pub fn verify_webauthn_assertion(
spki_der: &[u8],
signing: &ContentHash,
sig: &Witness,
) -> Result<(), IdentityError>Expand description
Verifies a WebAuthn assertion and that it attests to signing
(D39).
This is the binding verify_es256 deliberately does not do. It
answers the whole question a caller actually has — “did the holder of
this credential approve this operation” — rather than the primitive’s
narrower “did this key sign these bytes”. D39 carries a tripwire for
getting this wrong, because an assertion accepted against the wrong
challenge is a real signature attesting to something nobody agreed to,
which is forgery rather than a bug.
spki_der is the enrolled credential’s public key in
SubjectPublicKeyInfo DER; sig must carry
choir_oplog::scheme::WEBAUTHN_ES256 together with the
authenticator data and client data JSON the browser returned.
The comparison is made in the encoded form: the expected challenge is base64url-encoded and compared to the string the browser sent, rather than decoding what the browser sent. That is deliberately the stricter direction — a non-canonical encoding that would decode to the right bytes is refused — and it means this path needs no base64 decoder that an attacker’s input reaches.
§Errors
IdentityError::UnsupportedScheme if sig names another scheme,
IdentityError::BadSignature for missing WebAuthn fields, an
unparseable clientDataJSON, a ceremony that is not webauthn.get, or
a signature that does not verify, IdentityError::ChallengeMismatch
when it verifies against a different challenge, and
IdentityError::Verifier when openssl could not be run.