@@ -60,11 +60,6 @@ library WebAuthn {
6060 /// @dev Bit 4 of the authenticator data flags: "Backup State" bit.
6161 bytes1 private constant AUTH_DATA_FLAGS_BS = 0x10 ;
6262
63- /// @dev The expected type string in the client data JSON when verifying assertion signatures.
64- /// https://www.w3.org/TR/webauthn-2/#dom-collectedclientdata-type
65- // solhint-disable-next-line quotes
66- bytes32 private constant EXPECTED_TYPE_HASH = keccak256 ('"type":"webauthn.get" ' );
67-
6863 /**
6964 * @dev Performs the absolute minimal verification of a WebAuthn Authentication Assertion.
7065 * This function includes only the essential checks required for basic WebAuthn security:
@@ -89,18 +84,16 @@ library WebAuthn {
8984 // - 32 bytes for rpIdHash
9085 // - 1 byte for flags
9186 // - 4 bytes for signature counter
92- if (auth.authenticatorData.length < 37 ) return false ;
93- bytes memory clientDataJSON = bytes (auth.clientDataJSON);
94-
9587 return
96- validateExpectedTypeHash (clientDataJSON, auth.typeIndex) && // 11
97- validateChallenge (clientDataJSON, auth.challengeIndex, challenge) && // 12
88+ auth.authenticatorData.length > 36 &&
89+ validateExpectedTypeHash (auth.clientDataJSON, auth.typeIndex) && // 11
90+ validateChallenge (auth.clientDataJSON, auth.challengeIndex, challenge) && // 12
9891 // Handles signature malleability internally
9992 P256.verify (
10093 sha256 (
10194 abi.encodePacked (
10295 auth.authenticatorData,
103- sha256 (clientDataJSON) // 19
96+ sha256 (bytes (auth. clientDataJSON) ) // 19
10497 )
10598 ),
10699 auth.r,
@@ -222,30 +215,27 @@ library WebAuthn {
222215 * @dev Validates that the https://www.w3.org/TR/webauthn-2/#type[Type] field in the client data JSON
223216 * is set to "webauthn.get".
224217 */
225- function validateExpectedTypeHash (bytes memory clientDataJSON , uint256 typeIndex ) internal pure returns (bool ) {
218+ function validateExpectedTypeHash (string memory clientDataJSON , uint256 typeIndex ) internal pure returns (bool ) {
226219 // 21 = length of '"type":"webauthn.get"'
227- bytes memory typeValueBytes = Bytes.slice (clientDataJSON, typeIndex, typeIndex + 21 );
228- return keccak256 (typeValueBytes) == EXPECTED_TYPE_HASH;
220+ bytes memory typeValueBytes = Bytes.slice (bytes (clientDataJSON), typeIndex, typeIndex + 21 );
221+
222+ // solhint-disable-next-line quotes
223+ return bytes21 (typeValueBytes) == bytes21 ('"type":"webauthn.get" ' );
229224 }
230225
231226 /// @dev Validates that the challenge in the client data JSON matches the `expectedChallenge`.
232227 function validateChallenge (
233- bytes memory clientDataJSON ,
228+ string memory clientDataJSON ,
234229 uint256 challengeIndex ,
235- bytes memory expectedChallenge
230+ bytes memory challenge
236231 ) internal pure returns (bool ) {
237- bytes memory expectedChallengeBytes = bytes (
238- // solhint-disable-next-line quotes
239- string .concat ('"challenge":" ' , Base64.encodeURL (expectedChallenge), '" ' )
240- );
241- if (challengeIndex + expectedChallengeBytes.length > clientDataJSON.length ) return false ;
242- bytes memory actualChallengeBytes = Bytes.slice (
243- clientDataJSON,
244- challengeIndex,
245- challengeIndex + expectedChallengeBytes.length
232+ // solhint-disable-next-line quotes
233+ string memory expectedChallenge = string .concat ('"challenge":" ' , Base64.encodeURL (challenge), '" ' );
234+ string memory actualChallenge = string (
235+ Bytes.slice (bytes (clientDataJSON), challengeIndex, challengeIndex + bytes (expectedChallenge).length )
246236 );
247237
248- return Strings.equal (string (actualChallengeBytes), string (expectedChallengeBytes) );
238+ return Strings.equal (actualChallenge, expectedChallenge );
249239 }
250240
251241 /**
0 commit comments