Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to latest FCL + fmt and CI improvement #16

Merged
merged 7 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
WebAuthnFuzzTest:test_Verify_ShoulReturnFalse_WhenSAboveP256_N_DIV_2() (gas: 429635068)
WebAuthnFuzzTest:test_Verify_ShoulReturnFalse_WhenTheUpFlagIsNotSet() (gas: 435310864)
WebAuthnFuzzTest:test_Verify_ShoulReturnFalse_WhenUserVerifictionIsRequiredButTestWasNotPerformed() (gas: 432573571)
WebAuthnFuzzTest:test_Verify_ShoulReturnTrue_WhenSBelowP256_N_DIV_2() (gas: 456300088)
WebAuthnTest:test_chrome() (gas: 225627)
WebAuthnTest:test_safari() (gas: 221874)
WebAuthnFuzzTest:test_Verify_ShoulReturnTrue_WhenSBelowP256_N_DIV_2() (gas: 456301488)
WebAuthnTest:test_chrome() (gas: 225641)
WebAuthnTest:test_safari() (gas: 221888)
5 changes: 5 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,8 @@ jobs:
run: |
forge fmt --check
id: fmt

- name: Check snapshot
run: |
forge snapshot --check
id: snapshot
7 changes: 5 additions & 2 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ src = "src"
out = "out"
libs = ["lib"]
optimizer_runs = 999999

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
fs_permissions = [{ access = "read", path = "test/fixtures" }]

[fmt]
sort_imports = true
wrap_comments = true
line_length = 140
13 changes: 7 additions & 6 deletions src/WebAuthn.sol
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,16 @@ library WebAuthn {
}

// 11. Verify that the value of C.type is the string webauthn.get.
// bytes("type":"webauthn.get").length = 21
// bytes("type":"webauthn.get").length = 21
string memory _type = webAuthnAuth.clientDataJSON.slice(webAuthnAuth.typeIndex, webAuthnAuth.typeIndex + 21);
if (keccak256(bytes(_type)) != _EXPECTED_TYPE_HASH) {
return false;
}

// 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 All @@ -135,7 +134,8 @@ library WebAuthn {
return false;
}

// 17. If user verification is required for this assertion, verify that the User Verified bit of the flags in authData is set.
// 17. If user verification is required for this assertion, verify that the User Verified bit of the flags in
// authData is set.
if (requireUV && (webAuthnAuth.authenticatorData[32] & _AUTH_DATA_FLAGS_UV) != _AUTH_DATA_FLAGS_UV) {
return false;
}
Expand All @@ -145,7 +145,8 @@ library WebAuthn {
// 19. Let hash be the result of computing a hash over the cData using SHA-256.
bytes32 clientDataJSONHash = sha256(bytes(webAuthnAuth.clientDataJSON));

// 20. Using credentialPublicKey, verify that sig is a valid signature over the binary concatenation of authData and hash.
// 20. Using credentialPublicKey, verify that sig is a valid signature over the binary concatenation of authData
// and hash.
bytes32 messageHash = sha256(abi.encodePacked(webAuthnAuth.authenticatorData, clientDataJSONHash));
bytes memory args = abi.encode(messageHash, webAuthnAuth.r, webAuthnAuth.s, x, y);
// try the RIP-7212 precompile address
Expand Down
6 changes: 2 additions & 4 deletions test/Utils.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {Base64Url} from "FreshCryptoLib/utils/Base64Url.sol";
import {FCL_Elliptic_ZZ} from "FreshCryptoLib/FCL_elliptic.sol";
import {Base64Url} from "FreshCryptoLib/utils/Base64Url.sol";

struct WebAuthnInfo {
bytes authenticatorData;
Expand All @@ -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
11 changes: 5 additions & 6 deletions test/WebAuthn.t.sol
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {Base64Url} from "FreshCryptoLib/utils/Base64Url.sol";
import {Test, console2} from "forge-std/Test.sol";

import {WebAuthn} from "../src/WebAuthn.sol";
import {Base64Url} from "FreshCryptoLib/utils/Base64Url.sol";

contract WebAuthnTest is Test {
bytes challenge = abi.encode(0xf631058a3ba1116acce12396fad0a125b5041c43f8e15723709f81aa8d5f4ccf);
Expand All @@ -15,7 +16,7 @@ contract WebAuthnTest is Test {
authenticatorData: hex"49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000101",
clientDataJSON: string.concat(
'{"type":"webauthn.get","challenge":"', Base64Url.encode(challenge), '","origin":"http://localhost:3005"}'
),
),
challengeIndex: 23,
typeIndex: 1,
r: 43684192885701841787131392247364253107519555363555461570655060745499568693242,
Expand All @@ -30,10 +31,8 @@ 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,
r: 29739767516584490820047863506833955097567272713519339793744591468032609909569,
Expand Down
9 changes: 4 additions & 5 deletions test/Webauthn.fuzz.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
pragma solidity ^0.8.0;

import {FCL_ecdsa} from "FreshCryptoLib/FCL_ecdsa.sol";
import {Test, Vm, console, stdJson} from "forge-std/Test.sol";

import {WebAuthn} from "../src/WebAuthn.sol";

import "forge-std/Test.sol";
import "./Utils.sol";

contract WebAuthnFuzzTest is Test {
Expand Down Expand Up @@ -114,7 +114,8 @@ contract WebAuthnFuzzTest is Test {
y: y
});

// Assert the verification failed because user verification was required but not performed by the authenticator.
// Assert the verification failed because user verification was required but not performed by the
// authenticator.
assertEq(res, false, string.concat("Failed on ", jsonCaseSelector));

console.log("------------------------------------");
Expand Down Expand Up @@ -174,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