NAME

Web::Authn::Attestation - Attestation statement format verifiers

SYNOPSIS

Web::Authn::Attestation::verify(
    fmt                   => $att->{fmt},
    att_stmt              => $att->{att_stmt},
    auth_raw              => $att->{auth_raw},
    client_data_json      => $client_data_bytes,
    credential_public_key => $cose_bytes,
    credential_id         => $cred_id,
    aaguid                => $aaguid,
    rp_id_hash            => $rp_hash,
    pem_root_certs        => \@pem,
    attestation_object    => $raw_att_obj,
);

DESCRIPTION

Called from "verify_registration_response" in Web::Authn after authenticator data and client data have been checked. Each fmt implements the verification procedure from WebAuthn §8.

You do not normally call this module yourself.

FUNCTIONS

You do not normally call these from application code. "verify_registration_response" in Web::Authn already does. On failure each routine throws Web::Authn::Exception::InvalidRegistration. On success it returns true.

sha384

my $digest = Web::Authn::Attestation::sha384( $bytes );

Returns the SHA-384 digest of the bytes you pass. This is used when checking TPM extraData.

sha512

my $digest = Web::Authn::Attestation::sha512( $bytes );

Returns the SHA-512 digest of the bytes you pass. This is used when checking TPM extraData.

verify

Web::Authn::Attestation::verify(
    fmt                   => $att->{fmt},
    att_stmt              => $att->{att_stmt},
    auth_raw              => $att->{auth_raw},
    client_data_json      => $client_data_bytes,
    credential_public_key => $cose_bytes,
    credential_id         => $cred_id,
    aaguid                => $aaguid,
    rp_id_hash            => $rp_hash,
    pem_root_certs        => \@pem,
    attestation_object    => $raw_att_obj,
);

Dispatches on fmt to "verify_none", "verify_packed", "verify_fido_u2f", "verify_apple", "verify_tpm", "verify_android_safetynet" or "verify_android_key". Throws if fmt is unknown.

The format-specific routines take the same named arguments. Unused keys are ignored.

aaguid

This argument is optional for most formats; "verify_fido_u2f" requires it and it must be 16 zero bytes. It is 16 raw bytes.

att_stmt

This argument is required. It is a hash: the decoded attestation statement (sig, alg, x5c, response, certInfo, pubArea, and so on).

attestation_object

This argument is optional. It is the raw bytes of the whole attestationObject. "verify_android_safetynet" uses it as one of the two nonce bases.

auth_raw

This argument is required. It is the raw bytes of authenticator data. They are concatenated with SHA-256(clientDataJSON) to form the signed payload.

client_data_json

This argument is required. It is the raw bytes of clientDataJSON.

credential_id

This argument is optional for most formats; "verify_fido_u2f" requires it. It is the raw bytes of the credential ID.

credential_public_key

This argument is optional for none. Packed self-attestation, Apple, and FIDO U2F require it. It is the raw COSE_Key bytes.

fmt

This argument is required by "verify". It is a string: the attestation format name, one of none, packed, fido-u2f, apple, tpm, android-safetynet, or android-key.

pem_root_certs

This argument is optional. It is an array of PEM strings or DER bytes: roots used to pin x5c chains. An empty array means “do not pin”, which is the same behaviour as py_webauthn.

rp_id_hash

This argument is optional for most formats; "verify_fido_u2f" requires it. It is the raw 32-byte SHA-256 of the RP ID.

verify_android_key

Web::Authn::Attestation::verify_android_key( %arg );

WebAuthn §8.4. Requires att_stmt.sig and att_stmt.x5c. Validates the chain when roots are supplied, then verifies sig over authData || SHA-256(clientDataJSON) with the leaf certificate key.

Named arguments: same as "verify".

verify_android_safetynet

Web::Authn::Attestation::verify_android_safetynet( %arg );

WebAuthn §8.5. attStmt.response is a JWS. Checks the JWT signature (RS256, x5c in the header), ctsProfileMatch, and that nonce matches SHA-256(authData || SHA-256(clientDataJSON)) or SHA-256(attestationObject || SHA-256(clientDataJSON)).

This format is deprecated in later WebAuthn drafts; it is still accepted for older authenticators.

Named arguments: same as "verify". attestation_object is used as an alternative nonce base.

verify_apple

Web::Authn::Attestation::verify_apple( %arg );

WebAuthn §8.8. Requires att_stmt.x5c. Validates the chain, checks Apple extension 1.2.840.113635.100.8.2 against SHA-256(authData || SHA-256(clientDataJSON)), and that the leaf subject public key equals the credential public key.

This distribution does not embed the Apple WebAuthn Root CA. Pass it in pem_root_certs for a pinned verification.

Named arguments: same as "verify".

verify_fido_u2f

Web::Authn::Attestation::verify_fido_u2f( %arg );

WebAuthn §8.6. Requires exactly one certificate in x5c, a signature, AAGUID all zeroes, and an EC2 credential key. Verifies ECDSA P-256 over 0x00 || rpIdHash || clientDataHash || credId || 0x04 || X || Y.

Named arguments: same as "verify". aaguid, credential_id, credential_public_key and rp_id_hash are required here.

verify_none

Web::Authn::Attestation::verify_none( %arg );

WebAuthn §8.7. attStmt must be empty. Typical for consumer passkeys when attestation was none.

Named arguments: same as "verify". Only att_stmt is inspected.

verify_packed

Web::Authn::Attestation::verify_packed( %arg );

WebAuthn §8.2. Requires att_stmt.sig and att_stmt.alg. Signed data is authData || SHA-256(clientDataJSON).

If x5c is present (basic attestation), the leaf key verifies sig after an optional chain check. If x5c is absent (self-attestation), the credential public key verifies sig and its COSE alg must equal attStmt.alg.

Named arguments: same as "verify". credential_public_key is required for self-attestation.

verify_tpm

Web::Authn::Attestation::verify_tpm( %arg );

WebAuthn §8.3. Requires att_stmt.sig, x5c, certInfo and pubArea.

Verifies sig over certInfo with the leaf key, then that certInfo contains a SHA-256, SHA-384 or SHA-512 of authData || SHA-256(clientDataJSON) (TPM extraData).

This is not a full TPMS_ATTEST parser. It is enough to reject a statement that was not signed by the attested key and does not bind the WebAuthn data.

Named arguments: same as "verify".

THREAD & PROCESS SAFETY

This module is designed to be fully thread-safe and process-safe, ensuring data integrity across Perl ithreads and mod_perl’s threaded Multi-Processing Modules (MPMs) such as Worker or Event.

AUTHOR

Jacques Deguest <jack@deguest.jp>

SEE ALSO

https://www.w3.org/TR/webauthn-3/#sctn-defined-attestation-formats, Web::Authn

COPYRIGHT & LICENSE

Copyright(c) 2026 DEGUEST Pte. Ltd.

All rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.