Files
skills/docs/identity/auth/webauthn/src/attestation/fido-u2f/fido-u2f.md
2026-05-29 08:20:56 +01:00

2.4 KiB

fido-u2f attestation verifier

(no submodules)

Purpose

Implements the W3C WebAuthn L3 §8.6 fido-u2f attestation format, retained from the legacy CTAP1/U2F protocol so that existing U2F-only authenticators (early Yubikeys, hardware tokens predating CTAP2) remain interoperable with WebAuthn relying parties. The format is intentionally rigid: a single ECDSA-P256 attestation certificate, a SHA-256-then-sign signature over a fixed five-segment byte string, and a credential public key constrained to EC2 P-256.

Features

  • Strict single-element x5c enforcement.
  • Credential-key type check: P-256 EC2 only.
  • Fixed-format signed payload: 0x00 || rpIdHash || clientDataHash || credentialId || (0x04 || x || y) per W3C §8.6 step 3.
  • Constant-time rpIdHash compare.
  • Attestation cert's public key extracted via @suaveplan/x509#parseCertificate — no inline ASN.1 walking.
  • DER-encoded ECDSA signature converted to compact r||s via decodeEcdsaSignature from @suaveplan/x509.

Usage: Basic Example

import { verifyFidoU2fAttestation } from "@suaveplan/webauthn/attestation/fido-u2f";

const result = await verifyFidoU2fAttestation({
    attestationObject,
    clientDataHash,
    expectedRpIdHash,
});

Usage: Advanced Example

import {
    type AttestationFormatRegistry,
    verifyFidoU2fAttestation,
} from "@suaveplan/webauthn";

function registryWithFidoOnly(): AttestationFormatRegistry {
    return new Map([["fido-u2f", verifyFidoU2fAttestation]]);
}

API Reference

  • verifyFidoU2fAttestation: AttestationFormatVerifier — the format verifier.

Implementation Notes

  • The format pre-dates WebAuthn and shipped with one specific signature variant; we reject any payload that does not conform rather than trying to be lenient.
  • x5c.length === 1 is enforced because the U2F spec issues exactly one attestation cert per device; multi-cert chains in this slot indicate either a mis-bundled response or an attempt to chain-validate via a non-U2F format.
  • The package does NOT bind the attestation cert back to the FIDO U2F attestation-root pool — that policy belongs to the caller via FIDO MDS3 lookup on the returned trustPath.
  • The function is synchronous-shaped (no awaits inside) but typed as Promise-returning to match the AttestationFormatVerifier contract so callers can register either variant uniformly.