Skip to content

Commit

Permalink
allow longer line
Browse files Browse the repository at this point in the history
  • Loading branch information
wilsoncusack committed Apr 22, 2024
1 parent 593e2b8 commit 286cb31
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 47 deletions.
3 changes: 2 additions & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ optimizer_runs = 999999

[fmt]
sort_imports = true
wrap_comments = true
wrap_comments = true
line_length = 140
56 changes: 19 additions & 37 deletions src/WebAuthn.sol
Original file line number Diff line number Diff line change
Expand Up @@ -64,52 +64,35 @@ library WebAuthn {
///
/// Specifically, we do verify the following:
/// - Verify that authenticatorData (which comes from the authenticator, such as iCloud Keychain) indicates
/// a well-formed assertion with the user present bit set. If `requireUV` is set, checks that the
/// authenticator
/// enforced user verification. User verification should be required if, and only if,
/// options.userVerification
/// a well-formed assertion with the user present bit set. If `requireUV` is set, checks that the authenticator
/// enforced user verification. User verification should be required if, and only if, options.userVerification
/// is set to required in the request.
/// - Verifies that the client JSON is of type "webauthn.get", i.e. the client was responding to a request
/// to
/// - Verifies that the client JSON is of type "webauthn.get", i.e. the client was responding to a request to
/// assert authentication.
/// - Verifies that the client JSON contains the requested challenge.
/// - Verifies that (r, s) constitute a valid signature over both the authenicatorData and client JSON, for
/// public
/// - Verifies that (r, s) constitute a valid signature over both the authenicatorData and client JSON, for public
/// key (x, y).
///
/// We make some assumptions about the particular use case of this verifier, so we do NOT verify the following:
/// - Does NOT verify that the origin in the `clientDataJSON` matches the Relying Party's origin: tt is
/// considered
/// - Does NOT verify that the origin in the `clientDataJSON` matches the Relying Party's origin: tt is considered
/// the authenticator's responsibility to ensure that the user is interacting with the correct RP. This is
/// enforced by most high quality authenticators properly, particularly the iCloud Keychain and Google
/// Password
/// enforced by most high quality authenticators properly, particularly the iCloud Keychain and Google Password
/// Manager were tested.
/// - Does NOT verify That `topOrigin` in `clientDataJSON` is well-formed: We assume it would never be
/// present, i.e.
/// the credentials are never used in a cross-origin/iframe context. The website/app set up should
/// disallow
/// cross-origin usage of the credentials. This is the default behaviour for created credentials in common
/// settings.
/// - Does NOT verify that the `rpIdHash` in `authenticatorData` is the SHA-256 hash of the RP ID expected
/// by the Relying
/// Party: this means that we rely on the authenticator to properly enforce credentials to be used only by
/// the correct RP.
/// This is generally enforced with features like Apple App Site Association and Google Asset Links. To
/// protect from
/// edge cases in which a previously-linked RP ID is removed from the authorised RP IDs, we recommend that
/// messages
/// - Does NOT verify That `topOrigin` in `clientDataJSON` is well-formed: We assume it would never be present, i.e.
/// the credentials are never used in a cross-origin/iframe context. The website/app set up should disallow
/// cross-origin usage of the credentials. This is the default behaviour for created credentials in common settings.
/// - Does NOT verify that the `rpIdHash` in `authenticatorData` is the SHA-256 hash of the RP ID expected by the Relying
/// Party: this means that we rely on the authenticator to properly enforce credentials to be used only by the correct RP.
/// This is generally enforced with features like Apple App Site Association and Google Asset Links. To protect from
/// edge cases in which a previously-linked RP ID is removed from the authorised RP IDs, we recommend that messages
/// signed by the authenticator include some expiry mechanism.
/// - Does NOT verify the credential backup state: this assumes the credential backup state is NOT used as
/// part of Relying
/// - Does NOT verify the credential backup state: this assumes the credential backup state is NOT used as part of Relying
/// Party business logic or policy.
/// - Does NOT verify the values of the client extension outputs: this assumes that the Relying Party does
/// not use client
/// - Does NOT verify the values of the client extension outputs: this assumes that the Relying Party does not use client
/// extension outputs.
/// - Does NOT verify the signature counter: signature counters are intended to enable risk scoring for the
/// Relying Party.
/// - Does NOT verify the signature counter: signature counters are intended to enable risk scoring for the Relying Party.
/// This assumes risk scoring is not used as part of Relying Party business logic or policy.
/// - Does NOT verify the attestation object: this assumes that response.attestationObject is NOT present in
/// the response,
/// - Does NOT verify the attestation object: this assumes that response.attestationObject is NOT present in the response,
/// i.e. the RP does not intend to verify an attestation.
///
/// @param challenge The challenge that was provided by the relying party.
Expand Down Expand Up @@ -138,9 +121,8 @@ library WebAuthn {

// 12. Verify that the value of C.challenge equals the base64url encoding of options.challenge.
bytes memory expectedChallenge = bytes(string.concat('"challenge":"', Base64.encodeURL(challenge), '"'));
string memory actualChallenge = webAuthnAuth.clientDataJSON.slice(
webAuthnAuth.challengeIndex, webAuthnAuth.challengeIndex + expectedChallenge.length
);
string memory actualChallenge =
webAuthnAuth.clientDataJSON.slice(webAuthnAuth.challengeIndex, webAuthnAuth.challengeIndex + expectedChallenge.length);
if (keccak256(bytes(actualChallenge)) != keccak256(expectedChallenge)) {
return false;
}
Expand Down
4 changes: 1 addition & 3 deletions test/Utils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ library Utils {
string memory challengeb64url = Base64Url.encode(abi.encode(challenge));
string memory clientDataJSON = string(
abi.encodePacked(
'{"type":"webauthn.get","challenge":"',
challengeb64url,
'","origin":"https://sign.coinbase.com","crossOrigin":false}'
'{"type":"webauthn.get","challenge":"', challengeb64url, '","origin":"https://sign.coinbase.com","crossOrigin":false}'
)
);

Expand Down
4 changes: 1 addition & 3 deletions test/WebAuthn.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ contract WebAuthnTest is Test {
WebAuthn.WebAuthnAuth memory auth = WebAuthn.WebAuthnAuth({
authenticatorData: hex"49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763050000010a",
clientDataJSON: string.concat(
'{"type":"webauthn.get","challenge":"',
Base64Url.encode(challenge),
'","origin":"http://localhost:3005","crossOrigin":false}'
'{"type":"webauthn.get","challenge":"', Base64Url.encode(challenge), '","origin":"http://localhost:3005","crossOrigin":false}'
),
challengeIndex: 23,
typeIndex: 1,
Expand Down
4 changes: 1 addition & 3 deletions test/Webauthn.fuzz.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,7 @@ contract WebAuthnFuzzTest is Test {
webAuthnAuth = WebAuthn.WebAuthnAuth({
authenticatorData: abi.decode(json.parseRaw(string.concat(jsonCaseSelector, ".authenticator_data")), (bytes)),
clientDataJSON: abi.decode(json.parseRaw(string.concat(jsonCaseSelector, ".client_data_json.json")), (string)),
challengeIndex: abi.decode(
json.parseRaw(string.concat(jsonCaseSelector, ".client_data_json.challenge_index")), (uint256)
),
challengeIndex: abi.decode(json.parseRaw(string.concat(jsonCaseSelector, ".client_data_json.challenge_index")), (uint256)),
typeIndex: abi.decode(json.parseRaw(string.concat(jsonCaseSelector, ".client_data_json.type_index")), (uint256)),
r: abi.decode(json.parseRaw(string.concat(jsonCaseSelector, ".r")), (uint256)),
s: abi.decode(json.parseRaw(string.concat(jsonCaseSelector, ".s")), (uint256))
Expand Down

0 comments on commit 286cb31

Please sign in to comment.