WebAuthn256r1

Git Source

A library to verify ECDSA signature though WebAuthn on the secp256r1 curve

Functions

generateMessage

Validate the webauthn data and generate the signature message needed to recover

1. The signature counter is not checked in this implementation because we already have the nonce on-chain to prevent the anti-replay attack. The counter is 4-bytes long and it is located at bytes 33 of the authenticator data. 2. The RP.ID is not checked in this implementation as it is impossible to generate the same keys for different RP.IDs with a well formed authenticator. The hash of the id is 32-bytes long and it is located at bytes 0 of the authenticator data. 3. The length of the authenticator data is not fixed. It is at least 37 bytes (rpIdHash (32) + flags (1) + counter (4)) but it can be longer if there is an attested credential data and/or some extensions data. As we do not consider the counter in this implementation, we only require the authenticator data to be at least 32 bytes long in order to save some calldata gas. 4. You may probably ask why we encode the challenge in base64 on-chain instead of of sending it already encoded to save some gas. This library is opinionated and it assumes that it is used in the context of Account Abstraction. In this context, valuable informations required to proceed the transaction will be stored in the challenge meaning we need the challenge in clear to use it later in the flow. That's why we decided to add an extra encoding step during the validation. 5. It is assumed this is not the responsibility of this contract to check the value of the alg parameter. It is expected this contract will be extended by another contract that will redirect the message produced by this contract to the right recovery function. 6. Both extension data and attested credential data are out of scope of this implementation. 7. It is not the responsibility of this contract to validate the attestation statement formats This contract is based on the level 2 of the WebAuthn specification. and until proven otherwise compliant with the level 3 of the specification.

function generateMessage(
    bytes calldata authenticatorData,
    bytes calldata clientData,
    bytes calldata clientChallenge
)
    internal
    pure
    returns (bytes32 message);

Parameters

NameTypeDescription
authenticatorDatabytesThe authenticator data structure encodes contextual bindings made by the authenticator. Described here: https://www.w3.org/TR/webauthn-2/#authenticator-data
clientDatabytesThis is the client data that was signed. The client data represents the contextual bindings of both the WebAuthn Relying Party and the client. Described here: https://www.w3.org/TR/webauthn-2/#client-data
clientChallengebytesThis is the challenge that was sent to the client to sign. It is part of the client data. In a classic non-EVM flow, this challenge is generated by the server and sent to the client to avoid replay attack. In our context, as we already have the nonce for this purpose we use this field to pass the arbitrary execution order. This value is expected to not be encoded in Base64, the encoding is done during the verification.

Returns

NameTypeDescription
messagebytes32The signature message needed to recover

verify

Verify ECDSA signature though WebAuthn on the secp256r1 curve

function verify(
    bytes calldata authData,
    bytes calldata clientData,
    bytes calldata clientChallenge,
    uint256 r,
    uint256 s,
    uint256 qx,
    uint256 qy
)
    internal
    returns (bool);

Errors

InvalidAuthenticatorData

error InvalidAuthenticatorData();

InvalidClientData

error InvalidClientData();

InvalidChallenge

error InvalidChallenge();