# `android-safetynet` attestation verifier _(no submodules)_ ## Purpose Implements the W3C WebAuthn L3 ยง8.5 `android-safetynet` attestation format. Google's SafetyNet API issues a JWS attestation token whose payload binds the credential creation challenge (`nonce = base64(sha256(authData || clientDataHash))`) to a Google-signed claim that the device passed the SafetyNet integrity checks. The verifier delegates JWS structural parsing to `@suaveplan/jws`, confirms the nonce, and surfaces the x5c chain for the caller to bind to the Google attestation root. ## Features - JWS parsing via `@suaveplan/jws` โ€” no inline JWT/JOSE decoding. - `nonce` claim cross-bind via constant-time compare against `base64(sha256(authData || clientDataHash))`. - `x5c` chain extracted from the JWS header, decoded into raw DER bytes, and surfaced via `trustPath`. - Constant-time `rpIdHash` compare. - Reports `attestationType: "basic"`. ## Usage: Basic Example ```ts import { verifyAndroidSafetynetAttestation } from "@suaveplan/webauthn/attestation/android-safetynet"; const result = await verifyAndroidSafetynetAttestation({ attestationObject, clientDataHash, expectedRpIdHash, }); ``` ## Usage: Advanced Example ```ts import { verifyAndroidSafetynetAttestation, type AttestationFormatRegistry, } from "@suaveplan/webauthn"; function strictSafetynetRegistry(): AttestationFormatRegistry { return new Map([ [ "android-safetynet", async (input) => { const r = await verifyAndroidSafetynetAttestation(input); await assertGoogleAttestationRoot(r.trustPath); return r; }, ], ]); } ``` ## API Reference - `verifyAndroidSafetynetAttestation: AttestationFormatVerifier` โ€” the format verifier. ## Implementation Notes - Google has deprecated SafetyNet in favour of the Play Integrity API. The format is retained because Android devices still emit it during the transition window; new deployments SHOULD NOT depend on it for new policy. - Full JWS signature verification against the Google attestation root is intentionally NOT performed here โ€” the root cert pool changes and the caller's metadata layer is the right place for it. The verifier surfaces the x5c chain via `trustPath` and confirms the nonce binding so the caller can do the full chain check with the correct trust anchor. - The `nonce` is base64 (not base64url) per the SafetyNet spec; the verifier explicitly encodes via `btoa` rather than via `toBase64Url` to match.