-
Notifications
You must be signed in to change notification settings - Fork 24
Add SignerERC7913 and verifiers for P256 and RSA #98
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
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
8825e22
Add an ERC-7913 based abstract signer and an ERC-7913 signature verif…
Amxx bd1184f
documentation
Amxx acf80ac
pragma
Amxx 722571c
spelling
Amxx 6a88076
pragma
Amxx 6878710
Update contracts/utils/cryptography/ERC7913SignatureVerifierP256.sol
Amxx 7c3bef2
add RSA signature verifier
Amxx a086759
doc
Amxx fb0e649
add changelog entry
Amxx cd9b527
Merge branch 'master' into aa/erc7913-signer
Amxx 18d70b6
Update contracts/utils/cryptography/ERC7913SignatureVerifierP256.sol
Amxx 87119a0
fix test
Amxx 1cdd64e
Merge branch 'master' into aa/erc7913-signer
ernestognw 67d5c39
Nit
ernestognw 1e3f120
Pragma
ernestognw c33ca98
Add docs
ernestognw a1d07fe
Improve docs
ernestognw d470aef
Pragma
ernestognw fa2c352
Update CHANGELOG
ernestognw File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.24; | ||
|
||
import {Account} from "../../account/Account.sol"; | ||
import {ERC721Holder} from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol"; | ||
import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; | ||
import {ERC7739} from "../../utils/cryptography/ERC7739.sol"; | ||
import {ERC7821} from "../../account/extensions/ERC7821.sol"; | ||
import {SignerERC7913} from "../../utils/cryptography/SignerERC7913.sol"; | ||
|
||
abstract contract AccountERC7913Mock is Account, SignerERC7913, ERC7739, ERC7821, ERC721Holder, ERC1155Holder { | ||
constructor(bytes memory _signer) { | ||
_setSigner(_signer); | ||
} | ||
|
||
/// @inheritdoc ERC7821 | ||
function _erc7821AuthorizedExecutor( | ||
address caller, | ||
bytes32 mode, | ||
bytes calldata executionData | ||
) internal view virtual override returns (bool) { | ||
return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// contracts/MyAccount.sol | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.24; | ||
|
||
import {Account} from "../../../account/Account.sol"; | ||
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; | ||
import {ERC721Holder} from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol"; | ||
import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; | ||
import {ERC7739} from "../../../utils/cryptography/ERC7739.sol"; | ||
import {ERC7821} from "../../../account/extensions/ERC7821.sol"; | ||
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; | ||
import {SignerERC7913} from "../../../utils/cryptography/SignerERC7913.sol"; | ||
|
||
contract MyAccount7913 is Account, SignerERC7913, ERC7739, ERC7821, ERC721Holder, ERC1155Holder, Initializable { | ||
constructor() EIP712("MyAccount7913", "1") {} | ||
|
||
function initialize(bytes memory signer) public initializer { | ||
_setSigner(signer); | ||
} | ||
|
||
/// @dev Allows the entry point as an authorized executor. | ||
function _erc7821AuthorizedExecutor( | ||
address caller, | ||
bytes32 mode, | ||
bytes calldata executionData | ||
) internal view virtual override returns (bool) { | ||
return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
contracts/utils/cryptography/ERC7913SignatureVerifierP256.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.20; | ||
|
||
import {P256} from "@openzeppelin/contracts/utils/cryptography/P256.sol"; | ||
import {IERC7913SignatureVerifier} from "../../interfaces/IERC7913.sol"; | ||
|
||
/** | ||
* @dev ERC-7913 signature verifier that support P256 (secp256r1) keys. | ||
*/ | ||
contract ERC7913SignatureVerifierP256 is IERC7913SignatureVerifier { | ||
/// @inheritdoc IERC7913SignatureVerifier | ||
function verify(bytes calldata key, bytes32 hash, bytes calldata signature) public view virtual returns (bytes4) { | ||
// Signature length may be 0x40 or 0x41. | ||
if (key.length == 0x40 && signature.length >= 0x40) { | ||
bytes32 qx = bytes32(key[0x00:0x20]); | ||
bytes32 qy = bytes32(key[0x20:0x40]); | ||
bytes32 r = bytes32(signature[0x00:0x20]); | ||
bytes32 s = bytes32(signature[0x20:0x40]); | ||
if (P256.verify(hash, r, s, qx, qy)) { | ||
return IERC7913SignatureVerifier.verify.selector; | ||
} | ||
} | ||
return 0xFFFFFFFF; | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
contracts/utils/cryptography/ERC7913SignatureVerifierRSA.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.20; | ||
|
||
import {RSA} from "@openzeppelin/contracts/utils/cryptography/RSA.sol"; | ||
import {IERC7913SignatureVerifier} from "../../interfaces/IERC7913.sol"; | ||
|
||
/** | ||
* @dev ERC-7913 signature verifier that support RSA keys. | ||
*/ | ||
contract ERC7913SignatureVerifierRSA is IERC7913SignatureVerifier { | ||
/// @inheritdoc IERC7913SignatureVerifier | ||
function verify(bytes calldata key, bytes32 hash, bytes calldata signature) public view virtual returns (bytes4) { | ||
(bytes memory e, bytes memory n) = abi.decode(key, (bytes, bytes)); | ||
return | ||
RSA.pkcs1Sha256(abi.encodePacked(hash), signature, e, n) | ||
? IERC7913SignatureVerifier.verify.selector | ||
: bytes4(0xFFFFFFFF); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.24; | ||
|
||
import {AbstractSigner} from "./AbstractSigner.sol"; | ||
import {ERC7913Utils} from "./ERC7913Utils.sol"; | ||
|
||
/** | ||
* @dev Implementation of {AbstractSigner} using | ||
* https://eips.ethereum.org/EIPS/eip-7913[ERC-7913] signature verification. | ||
* | ||
* For {Account} usage, a {_setSigner} function is provided to set the ERC-7913 formatted {signer}. | ||
* Doing so is easier for a factory, who is likely to use initializable clones of this contract. | ||
* | ||
* The signer is a `bytes` object that concatenates a verifier address and a key: `verifier || key`. | ||
* | ||
* Example of usage: | ||
* | ||
* ```solidity | ||
* contract MyAccountERC7913 is Account, SignerERC7913, Initializable { | ||
* constructor() EIP712("MyAccountERC7913", "1") {} | ||
* | ||
* function initialize(bytes memory signer_) public initializer { | ||
* _setSigner(signer_); | ||
* } | ||
* } | ||
* ``` | ||
* | ||
* IMPORTANT: Failing to call {_setSigner} either during construction (if used standalone) | ||
* or during initialization (if used as a clone) may leave the signer either front-runnable or unusable. | ||
*/ | ||
|
||
abstract contract SignerERC7913 is AbstractSigner { | ||
bytes private _signer; | ||
|
||
/// @dev Sets the signer (i.e. `verifier || key`) with an ERC-7913 formatted signer. | ||
function _setSigner(bytes memory signer_) internal { | ||
_signer = signer_; | ||
} | ||
|
||
/// @dev Return the ERC-7913 signer (i.e. `verifier || key`). | ||
function signer() public view virtual returns (bytes memory) { | ||
return _signer; | ||
} | ||
|
||
/// @dev Verifies a signature using {ERC7913Utils.isValidSignatureNow} with {signer}, `hash` and `signature`. | ||
function _rawSignatureValidation( | ||
bytes32 hash, | ||
bytes calldata signature | ||
) internal view virtual override returns (bool) { | ||
return ERC7913Utils.isValidSignatureNow(signer(), hash, signature); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I would prefer having just one implementation of the
isValidSignatureNow
function. The rationale is thatsignature
always ends up in memory for any valid verification, and a portion ofsigner
will be copied too. So I doubt there's actual benefits in having two versions. I'll simplify for now following #109Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The memory version uses a slice, that does a memory copy.
Overall, calldata versions are often cheaper because they don't copy to memory until the very last point (when the Abi call is encoded) contrary to the memory version that copy to memory at least once more (in this case 2 times)
Overall not a big deal. Having a single "memory" version is probably good enough. Just explaining the initial idea
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I saw the memory version is required, so I'd agree with just one "memory" version for now unless there are significant savings measured.
Thanks for answering though, now please you go 👨🍼