Skip to content

Commit

Permalink
♻️ modular the library
Browse files Browse the repository at this point in the history
Reorg the repository to improve the modularity of the library (accepting
more curves...).
  • Loading branch information
qd-qd committed Aug 7, 2023
1 parent 3d59ac7 commit ec30836
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 119 deletions.
33 changes: 2 additions & 31 deletions script/DeployWebAuthn.s.sol → script/DeployWebAuthn256r1.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,13 @@
pragma solidity >=0.8.19 <0.9.0;

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

contract LibraryWrapper {
function verify(
bytes1 authenticatorDataFlagMask,
bytes calldata authenticatorData,
bytes calldata clientData,
bytes calldata clientChallengeBase64,
uint256 clientChallengeOffset,
uint256 r,
uint256 s,
uint256 qx,
uint256 qy
)
external
returns (bool)
{
return WebAuthn.verify(
authenticatorDataFlagMask,
authenticatorData,
clientData,
clientChallengeBase64,
clientChallengeOffset,
r,
s,
qx,
qy
);
}
}
import { WebAuthn256r1 } from "../src/WebAuthn256r1.sol";

/// @notice This script deploys the ECDSA256r1 library
contract MyScript is BaseScript {
function run() external broadcast returns (address addr) {
// deploy the library contract and return the address
addr = address(new LibraryWrapper());
addr = address(new WebAuthn256r1());
}
}

Expand Down
29 changes: 2 additions & 27 deletions src/WebAuthn.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@
pragma solidity >=0.8.19 <0.9.0;

import { Base64 } from "../lib/solady/src/utils/Base64.sol";
import { ECDSA256r1 } from "../lib/secp256r1-verify/src/ECDSA256r1.sol";

error InvalidAuthenticatorData();
error InvalidClientData();

/// @title A library to verify ECDSA signature though WebAuthn on the secp256r1 curve
/// @title An abstract contract that validates the WebAuthn data and generates the message to recover
/// @dev This implementation assumes the caller check if User Presence (0x01) or User Verification (0x04) are set
library WebAuthn {
abstract contract WebAuthn {
/// @notice Validate the webauthn data and generate the signature message needed to recover
/// @dev 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 opiniated and
Expand Down Expand Up @@ -50,28 +49,4 @@ library WebAuthn {
return sha256(abi.encodePacked(authenticatorData, sha256(clientData)));
}
}

/// @notice Verify ECDSA signature though WebAuthn on the secp256r1 curve
function verify(
bytes1 authenticatorDataFlagMask,
bytes calldata authenticatorData,
bytes calldata clientData,
bytes calldata clientChallenge,
uint256 clientChallengeOffset,
uint256 r,
uint256 s,
uint256 qx,
uint256 qy
)
internal
returns (bool)
{
unchecked {
bytes32 message = generateMessage(
authenticatorDataFlagMask, authenticatorData, clientData, clientChallenge, clientChallengeOffset
);

return ECDSA256r1.verify(message, r, s, qx, qy);
}
}
}
32 changes: 32 additions & 0 deletions src/WebAuthn256r1.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19 <0.9.0;

import { ECDSA256r1 } from "../lib/secp256r1-verify/src/ECDSA256r1.sol";
import { WebAuthn } from "./WebAuthn.sol";

/// @title A library to verify ECDSA signature though WebAuthn on the secp256r1 curve
contract WebAuthn256r1 is WebAuthn {
/// @notice Verify ECDSA signature though WebAuthn on the secp256r1 curve
function verify(
bytes1 authenticatorDataFlagMask,
bytes calldata authenticatorData,
bytes calldata clientData,
bytes calldata clientChallenge,
uint256 clientChallengeOffset,
uint256 r,
uint256 s,
uint256 qx,
uint256 qy
)
external
returns (bool)
{
unchecked {
bytes32 message = generateMessage(
authenticatorDataFlagMask, authenticatorData, clientData, clientChallenge, clientChallengeOffset
);

return ECDSA256r1.verify(message, r, s, qx, qy);
}
}
}
67 changes: 6 additions & 61 deletions test/WebAuthn.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,20 @@ pragma solidity >=0.8.19 <0.9.0;
import { Test } from "../lib/forge-std/src/Test.sol";
import { WebAuthn } from "../src/WebAuthn.sol";

contract WebAuthnImplementation {
function generateMessage(
contract WebAuthnImplementation is WebAuthn {
function _generateMessage(
bytes1 authenticatorDataFlagMask,
bytes calldata authenticatorData,
bytes calldata clientData,
bytes calldata clientChallengeBase64,
bytes calldata clientChallenge,
uint256 clientChallengeOffset
)
external
pure
returns (bytes32)
{
return WebAuthn.generateMessage(
authenticatorDataFlagMask, authenticatorData, clientData, clientChallengeBase64, clientChallengeOffset
);
}

function verify(
bytes1 authenticatorDataFlagMask,
bytes calldata authenticatorData,
bytes calldata clientData,
bytes calldata clientChallengeBase64,
uint256 clientChallengeOffset,
uint256 r,
uint256 s,
uint256 qx,
uint256 qy
)
external
returns (bool)
{
return WebAuthn.verify(
authenticatorDataFlagMask,
authenticatorData,
clientData,
clientChallengeBase64,
clientChallengeOffset,
r,
s,
qx,
qy
return generateMessage(
authenticatorDataFlagMask, authenticatorData, clientData, clientChallenge, clientChallengeOffset
);
}
}
Expand All @@ -56,36 +29,8 @@ contract ContractTest is Test {
implem = new WebAuthnImplementation();
}

function test_Verify() public {
assertTrue(
implem.verify(
// authenticatorDataFlagMask
0x01,
// authenticatorData
hex"f8e4b678e1c62f7355266eaa4dc1148573440937063a46d848da1e25babbd20b010000004d",
// clientData
hex"7b2274797065223a22776562617574686e2e676574222c226368616c6c656e67"
hex"65223a224e546f2d3161424547526e78786a6d6b61544865687972444e583369"
hex"7a6c7169316f776d4f643955474a30222c226f726967696e223a226874747073"
hex"3a2f2f66726573682e6c65646765722e636f6d222c2263726f73734f726967696e223a66616c73657d",
// clientChallenge
hex"353a3ed5a0441919f1c639a46931de872ac3357de2ce5aa2d68c2639df54189d",
// clientChallengeOffset
0x24,
// r
45_847_212_378_479_006_099_766_816_358_861_726_414_873_720_355_505_495_069_909_394_794_949_093_093_607,
// s
55_835_259_151_215_769_394_881_684_156_457_977_412_783_812_617_123_006_733_908_193_526_332_337_539_398,
// qx
114_874_632_398_302_156_264_159_990_279_427_641_021_947_882_640_101_801_130_664_833_947_273_521_181_002,
// qy
32_136_952_818_958_550_240_756_825_111_900_051_564_117_520_891_182_470_183_735_244_184_006_536_587_423
)
);
}

function test_GenerateMessage() public {
bytes32 message = implem.generateMessage(
bytes32 message = implem._generateMessage(
// authenticatorDataFlagMask
0x01,
// authenticatorData
Expand Down
41 changes: 41 additions & 0 deletions test/WebAuthn256r1.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19 <0.9.0;

import { Test } from "../lib/forge-std/src/Test.sol";
import { WebAuthn256r1 } from "../src/WebAuthn256r1.sol";

contract ContractTest is Test {
WebAuthn256r1 internal implem;

function setUp() external {
implem = new WebAuthn256r1();
}

function test_Verify() public {
assertTrue(
implem.verify(
// authenticatorDataFlagMask
0x01,
// authenticatorData
hex"f8e4b678e1c62f7355266eaa4dc1148573440937063a46d848da1e25babbd20b010000004d",
// clientData
hex"7b2274797065223a22776562617574686e2e676574222c226368616c6c656e67"
hex"65223a224e546f2d3161424547526e78786a6d6b61544865687972444e583369"
hex"7a6c7169316f776d4f643955474a30222c226f726967696e223a226874747073"
hex"3a2f2f66726573682e6c65646765722e636f6d222c2263726f73734f726967696e223a66616c73657d",
// clientChallenge
hex"353a3ed5a0441919f1c639a46931de872ac3357de2ce5aa2d68c2639df54189d",
// clientChallengeOffset
0x24,
// r
45_847_212_378_479_006_099_766_816_358_861_726_414_873_720_355_505_495_069_909_394_794_949_093_093_607,
// s
55_835_259_151_215_769_394_881_684_156_457_977_412_783_812_617_123_006_733_908_193_526_332_337_539_398,
// qx
114_874_632_398_302_156_264_159_990_279_427_641_021_947_882_640_101_801_130_664_833_947_273_521_181_002,
// qy
32_136_952_818_958_550_240_756_825_111_900_051_564_117_520_891_182_470_183_735_244_184_006_536_587_423
)
);
}
}

0 comments on commit ec30836

Please sign in to comment.