/** * App Attest receipt verifier — the core judgment function this * package exports. * * Flow (matches Apple's published verification recipe for App Attest, * plus the motebit-specific identity-key binding step): * * 1. Split the receipt into (attestationObjectBase64, * keyIdBase64, clientDataHashBase64). * 2. CBOR-decode the attestation object to {fmt, attStmt:{x5c, * receipt}, authData}. Assert fmt === "apple-appattest". * 3. Parse leaf + intermediate as X.509. Walk the chain from leaf to * a self-signed root and verify every signature, every CA bit, * every validity window. The terminal cert's DER must equal the * pinned Apple App Attest root. * 4. Extract OID `1.2.840.113635.100.8.2` from the leaf's * extensions. Assert its payload equals SHA256(authData || * clientDataHash) where clientDataHash is the transmitted hash. * (In App Attest parlance: the "nonce" binding.) * 5. Parse authData (WebAuthn format). First 32 bytes is * `rpIdHash`; assert it equals SHA256(bundleId). (The "bundle" * binding.) * 6. Reconstruct the JCS-canonical attestation body from * (motebit_id, device_id, identity_public_key, attested_at) the * caller supplies, SHA-256 it, and byte-compare against the * transmitted `clientDataHash`. This is the cross-stack binding * — without it, every other step would prove only that *some* * Apple-attested iOS device did something, not that the Ed25519 * key the credential subject claims is actually on that device. * * Apple's own inner `receipt` field is NOT verified here — that * requires Apple's server-side refresh endpoint and is out of scope * for v1. The outer chain + nonce binding + bundle binding + motebit * identity binding is enough for third-party self-verification of * device-attested identity. */ import type { HardwareAttestationClaim } from "@motebit/protocol"; export interface AppAttestVerifyOptions { /** iOS bundle identifier that minted the attestation (e.g. "com.motebit.app"). */ readonly expectedBundleId: string; /** * Ed25519 identity key (lowercase hex) the motebit VC claims. The * attested body MUST name this key. */ readonly expectedIdentityPublicKeyHex: string; /** * motebit_id from the credential subject. Part of the canonical * attestation body the Swift mint path signs; re-derived here and * byte-compared against the transmitted clientDataHash so a * malicious native client cannot substitute a different body. */ readonly expectedMotebitId?: string; /** * device_id from the credential subject. Same binding role as * `expectedMotebitId`. */ readonly expectedDeviceId?: string; /** * `attested_at` (unix ms) from the credential subject. Same binding * role as `expectedMotebitId`. */ readonly expectedAttestedAt?: number; /** * Override the pinned Apple root — tests fabricate their own root so * chain verification exercises the same code path without needing * real Apple-signed leaves. Defaults to the pinned * `APPLE_APPATTEST_ROOT_PEM`. */ readonly rootPem?: string; /** * Clock for chain-validity checks. Defaults to `Date.now`. Tests inject * a fixed clock to keep certificate validity windows deterministic. */ readonly now?: () => number; /** * Override the attestation format check. Defaults to `"apple-appattest"` * — the value Apple emits. Exposed only so test fabrications that * exercise chain-validation edge cases can still reach the code path. */ readonly expectedFmt?: string; } export interface AppAttestVerifyError { readonly message: string; } export interface AppAttestVerifyResult { readonly valid: boolean; readonly cert_chain_valid: boolean; readonly nonce_bound: boolean; readonly bundle_bound: boolean; readonly identity_bound: boolean; readonly errors: readonly AppAttestVerifyError[]; } /** * Apple App Attest attestation verifier. * * Pure. No network. No filesystem. Deterministic given `now()`. * * `claim` is the `HardwareAttestationClaim` as carried inside the * motebit AgentTrustCredential. For App Attest, the * `attestation_receipt` field is expected to be three base64url * segments separated by `.`: * * `{attestationObjectB64}.{keyIdB64}.{clientDataHashB64}` * * The mobile mint path constructs this shape; see * `apps/mobile/src/mint-hardware-credential.ts`. */ export declare function verifyAppAttestReceipt(claim: HardwareAttestationClaim, opts: AppAttestVerifyOptions): Promise; //# sourceMappingURL=verify.d.ts.map