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

6 allow user add passkey as signer #9

Merged
merged 5 commits into from
Jun 20, 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
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/openzeppelin/openzeppelin-contracts
[submodule "lib/webauthn-sol"]
path = lib/webauthn-sol
url = https://github.com/base-org/webauthn-sol
1 change: 1 addition & 0 deletions lib/webauthn-sol
Submodule webauthn-sol added at 619f20
1 change: 1 addition & 0 deletions remappings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ forge-std/=lib/forge-std/src/
openzeppelin/=lib/openzeppelin-contracts/contracts/
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/
webauthn-sol/=lib/webauthn-sol/src/
120 changes: 120 additions & 0 deletions src/libraries/Base64.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.2) (utils/Base64.sol)

pragma solidity ^0.8.0;

/**
* @dev Provides a set of functions to operate with Base64 strings.
*/
library Base64 {
/**
* @dev Base64 Encoding/Decoding Table
* See sections 4 and 5 of https://datatracker.ietf.org/doc/html/rfc4648
*/
string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
string internal constant _TABLE_URL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";

/**
* @dev Converts a `bytes` to its Bytes64 `string` representation.
*/
function encode(bytes memory data) internal pure returns (string memory) {
return _encode(data, _TABLE, true);
}

/**
* @dev Converts a `bytes` to its Bytes64Url `string` representation.
*/
function encodeURL(bytes memory data) internal pure returns (string memory) {
return _encode(data, _TABLE_URL, false);
}

/**
* @dev Internal table-agnostic conversion
*/
function _encode(bytes memory data, string memory table, bool withPadding) private pure returns (string memory) {
/**
* Inspired by Brecht Devos (Brechtpd) implementation - MIT licence
* https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol
*/
if (data.length == 0) return "";

// If padding is enabled, the final length should be `bytes` data length divided by 3 rounded up and then
// multiplied by 4 so that it leaves room for padding the last chunk
// - `data.length + 2` -> Round up
// - `/ 3` -> Number of 3-bytes chunks
// - `4 *` -> 4 characters for each chunk
// If padding is disabled, the final length should be `bytes` data length multiplied by 4/3 rounded up as
// opposed to when padding is required to fill the last chunk.
// - `4 *` -> 4 characters for each chunk
// - `data.length + 2` -> Round up
// - `/ 3` -> Number of 3-bytes chunks
uint256 resultLength = withPadding ? 4 * ((data.length + 2) / 3) : (4 * data.length + 2) / 3;

string memory result = new string(resultLength);

/// @solidity memory-safe-assembly
assembly {
// Prepare the lookup table (skip the first "length" byte)
let tablePtr := add(table, 1)

// Prepare result pointer, jump over length
let resultPtr := add(result, 0x20)
let dataPtr := data
let endPtr := add(data, mload(data))

// In some cases, the last iteration will read bytes after the end of the data. We cache the value, and
// set it to zero to make sure no dirty bytes are read in that section.
let afterPtr := add(endPtr, 0x20)
let afterCache := mload(afterPtr)
mstore(afterPtr, 0x00)

// Run over the input, 3 bytes at a time
for {

} lt(dataPtr, endPtr) {

} {
// Advance 3 bytes
dataPtr := add(dataPtr, 3)
let input := mload(dataPtr)

// To write each character, shift the 3 byte (24 bits) chunk
// 4 times in blocks of 6 bits for each character (18, 12, 6, 0)
// and apply logical AND with 0x3F to bitmask the least significant 6 bits.
// Use this as an index into the lookup table, mload an entire word
// so the desired character is in the least significant byte, and
// mstore8 this least significant byte into the result and continue.

mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
resultPtr := add(resultPtr, 1) // Advance

mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
resultPtr := add(resultPtr, 1) // Advance

mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
resultPtr := add(resultPtr, 1) // Advance

mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
}

// Reset the value that was cached
mstore(afterPtr, afterCache)

if withPadding {
// When data `bytes` is not exactly 3 bytes long
// it is padded with `=` characters at the end
switch mod(mload(data), 3)
case 1 {
mstore8(sub(resultPtr, 1), 0x3d)
mstore8(sub(resultPtr, 2), 0x3d)
}
case 2 {
mstore8(sub(resultPtr, 1), 0x3d)
}
}
}

return result;
}
}
131 changes: 131 additions & 0 deletions src/libraries/FCL_ecdsa.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
//********************************************************************************************/
// ___ _ ___ _ _ _ _
// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__
// | _| '_/ -_|_-< ' \ | (__| '_| || | '_ \ _/ _ \ | |__| | '_ \
// |_||_| \___/__/_||_| \___|_| \_, | .__/\__\___/ |____|_|_.__/
// |__/|_|
///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project
///* License: This software is licensed under MIT License
///* This Code may be reused including license and copyright notice.
///* See LICENSE file at the root folder of the project.
///* FILE: FCL_ecdsa.sol
///*
///*
///* DESCRIPTION: ecdsa verification implementation
///*
//**************************************************************************************/
//* WARNING: this code SHALL not be used for non prime order curves for security reasons.
// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced
// if ever used for other curve than sec256R1
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;


import {FCL_Elliptic_ZZ} from "./FCL_elliptic.sol";



library FCL_ecdsa {
// Set parameters for curve sec256r1.public
//curve order (number of points)
uint256 constant n = FCL_Elliptic_ZZ.n;

/**
* @dev ECDSA verification, given , signature, and public key.
*/

/**
* @dev ECDSA verification, given , signature, and public key, no calldata version
*/
function ecdsa_verify(bytes32 message, uint256 r, uint256 s, uint256 Qx, uint256 Qy) internal view returns (bool){

if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {
return false;
}

if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {
return false;
}

uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);

uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);
uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);
uint256 x1;

x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);

x1= addmod(x1, n-r,n );

return x1 == 0;
}

function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)
{
if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {
return address(0);
}
uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);
uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);
uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1
uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1

uint256 Qx;
uint256 Qy;
(Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);

return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));
}

function ecdsa_precomputed_verify(bytes32 message, uint256 r, uint256 s, address Shamir8)
internal view
returns (bool)
{

if (r == 0 || r >= n || s == 0 || s >= n) {
return false;
}
/* Q is pushed via the contract at address Shamir8 assumed to be correct
if (!isOnCurve(Q[0], Q[1])) {
return false;
}*/

uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);

uint256 X;

//Shamir 8 dimensions
X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);

X= addmod(X, n-r,n );

return X == 0;
} //end ecdsa_precomputed_verify()

function ecdsa_precomputed_verify(bytes32 message, uint256[2] calldata rs, address Shamir8)
internal view
returns (bool)
{
uint256 r = rs[0];
uint256 s = rs[1];
if (r == 0 || r >= n || s == 0 || s >= n) {
return false;
}
/* Q is pushed via the contract at address Shamir8 assumed to be correct
if (!isOnCurve(Q[0], Q[1])) {
return false;
}*/

uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);

uint256 X;

//Shamir 8 dimensions
X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);

X= addmod(X, n-r,n );

return X == 0;
} //end ecdsa_precomputed_verify()

}
Loading
Loading