Skip to content

Commit

Permalink
[#289] Update WebAuthnVerifier in passkey package
Browse files Browse the repository at this point in the history
  • Loading branch information
akshay-ap committed Mar 13, 2024
1 parent f4c2e88 commit 530dcb2
Showing 1 changed file with 33 additions and 3 deletions.
36 changes: 33 additions & 3 deletions modules/passkey/contracts/verifiers/WebAuthnVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
pragma solidity >=0.8.0;

import {IP256Verifier, P256VerifierLib} from "./IP256Verifier.sol";
import {Base64Url} from "../vendor/FCL/utils/Base64Url.sol";

/**
* @title WebAuthnConstants
Expand Down Expand Up @@ -89,6 +88,9 @@ interface IWebAuthnVerifier {
*/
contract WebAuthnVerifier is IWebAuthnVerifier {
IP256Verifier internal immutable P256_VERIFIER;

string internal constant ENCODING_TABLE =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";

constructor(IP256Verifier verifier) {
P256_VERIFIER = verifier;
Expand All @@ -106,15 +108,43 @@ contract WebAuthnVerifier is IWebAuthnVerifier {
bytes32 challenge,
bytes calldata clientDataFields
) internal pure returns (bytes32 message) {
string memory encodedChallenge = Base64Url.encode(abi.encodePacked(challenge));
/* solhint-disable quotes */
// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA is placeholder for the encoded challenge
bytes memory clientDataJson = abi.encodePacked(
'{"type":"webauthn.get","challenge":"',
encodedChallenge,
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
'",',
clientDataFields,
"}"
);

string memory table = ENCODING_TABLE;

// solhint-disable-next-line no-inline-assembly
assembly {
// Skip first 32 bytes of the table containing the length
let tablePtr := add(table, 1)
// Skip first 36 bytes of the clientDataJson containing '{"type":"webauthn.get","challenge":"'
let resultPtr := add(clientDataJson, 68)

// Store group of 6 bits from the challenge to be encoded. Storing of 6 bits group can be removed but, kept here for readability.
let sixBitGroup

// Iterate over challenge in group of 6 bits, for each 6 bits lookup the ENCODING_TABLE, transform it and store it in the result
for {let i := 0} lt(i, 252)
{
i := add(i, 6)
} {
sixBitGroup := and(shr(sub(250, i), challenge), 0x3F)
mstore8(resultPtr, mload(add(tablePtr, sixBitGroup)))
resultPtr := add(resultPtr, 1)
}

// Load the remaining last 4 bits of challenge that are yet to be encoded and then shift left to add 2 bits at the end to make it a group of 6 bits.
sixBitGroup := shl(2, and(challenge, 0x0F))
mstore8(resultPtr, mload(add(tablePtr, sixBitGroup)))
}

/* solhint-enable quotes */
message = sha256(abi.encodePacked(authenticatorData, sha256(clientDataJson)));
}
Expand Down

0 comments on commit 530dcb2

Please sign in to comment.