first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
# `apple` attestation verifier
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Implements the W3C WebAuthn L3 §8.8 `apple` anonymous attestation format used by macOS Touch ID, iOS Face ID, and other Apple platform authenticators. Apple's format is unusual: there is no signed `attStmt` field; instead, the leaf certificate in `x5c` carries an Apple-specific extension whose value is the SHA-256 of `authData || clientDataHash`. The verifier confirms that nonce binding and surfaces the chain as `anonCA` attestation per W3C §6.5.3.
## Features
- Apple nonce extension OID `1.2.840.113635.100.8.2` enforced on the leaf cert.
- Extension content decoded via `@suaveplan/x509#decodeAsn1` — no inline ASN.1 walking.
- Constant-time compare of the extracted nonce against `sha256(authData || clientDataHash)`.
- Constant-time `rpIdHash` compare.
- Reports `attestationType: "anonCA"` — Apple deliberately uses anonymous CA attestation so the format does not leak per-device identity to the relying party.
## Usage: Basic Example
```ts
import { verifyAppleAttestation } from "@suaveplan/webauthn/attestation/apple";
const result = await verifyAppleAttestation({
attestationObject,
clientDataHash,
expectedRpIdHash,
});
// result.attestationType === "anonCA"
```
## Usage: Advanced Example
```ts
import {
defaultAttestationRegistry,
verifyAppleAttestation,
} from "@suaveplan/webauthn";
const registry = defaultAttestationRegistry();
registry.set("apple", async (input) => {
const r = await verifyAppleAttestation(input);
await validateAppleAttestationRoot(r.trustPath);
return r;
});
```
## API Reference
- `verifyAppleAttestation: AttestationFormatVerifier` — the format verifier.
## Implementation Notes
- The nonce extension is wrapped in `SEQUENCE { [1] EXPLICIT OCTET STRING <nonce> }` per Apple's documented schema; the verifier walks the decoded ASN.1 tree depth-first and grabs the first universal OCTET STRING it encounters, which is the documented contract.
- Chain validation against the Apple WebAuthn attestation root is intentionally NOT performed here — that root is environment-specific and the caller's metadata layer is the right place for it. The verifier surfaces the x5c chain via `trustPath`.
- `anonCA` is the only `attestationType` returned. RPs that need per-device telemetry MUST request a different attestation conveyance preference (`attestation: "direct"` does NOT produce per-device identity from Apple platform authenticators by design).