-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
secp256r1: Adds support for NIST's secp256r1 (p256) curve
- Loading branch information
1 parent
1a6a4ae
commit 197dcac
Showing
29 changed files
with
3,439 additions
and
232 deletions.
There are no files selected for viewing
This file contains 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 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 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 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 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,79 @@ | ||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
pragma solidity ^0.8.16; | ||
|
||
import {Script} from "forge-std/Script.sol"; | ||
import {console2 as console} from "forge-std/console2.sol"; | ||
|
||
import {Secp256r1Offchain} from "src/offchain/secp256r1/Secp256r1Offchain.sol"; | ||
import { | ||
Secp256r1, | ||
SecretKey, | ||
PublicKey | ||
} from "src/onchain/secp256r1/Secp256r1.sol"; | ||
import { | ||
Secp256r1Arithmetic, | ||
Point, | ||
ProjectivePoint | ||
} from "src/onchain/secp256r1/Secp256r1Arithmetic.sol"; | ||
|
||
/** | ||
* @title Secp256r1Example | ||
* | ||
* @dev Run via: | ||
* | ||
* ```bash | ||
* $ forge script examples/secp256r1/Secp256r1.sol:Secp256r1Example -vvvv | ||
* ``` | ||
* | ||
* @dev Note that some code is commented out to reduce compiler warnings | ||
* regarding unused variables. | ||
*/ | ||
contract Secp256r1Example is Script { | ||
using Secp256r1Offchain for SecretKey; | ||
using Secp256r1Offchain for PublicKey; | ||
using Secp256r1 for SecretKey; | ||
using Secp256r1 for PublicKey; | ||
using Secp256r1Arithmetic for Point; | ||
using Secp256r1Arithmetic for ProjectivePoint; | ||
|
||
function run() public { | ||
// Create new cryptographically sound secret key. | ||
SecretKey sk = Secp256r1Offchain.newSecretKey(); | ||
// assert(sk.isValid()); | ||
console.log("Created new secret key:"); | ||
console.log(sk.asUint()); | ||
console.log(""); | ||
|
||
// Derive public key. | ||
PublicKey memory pk = sk.toPublicKey(); | ||
// assert(pk.isValid()); | ||
console.log("Derived public key:"); | ||
console.log(pk.toString()); | ||
console.log(""); | ||
|
||
// Arithmetic types. | ||
// into___() -> overwrites memory, no allocation / memory expansion cost | ||
// to___() -> allocates new memory, may has expansion cost | ||
/* | ||
Point memory point = pk.intoPoint(); | ||
ProjectivePoint memory jPoint = pk.toProjectivePoint(); | ||
*/ | ||
|
||
// Derive common constructs. | ||
// bytes32 digest = pk.toHash(); | ||
// uint yParity = pk.yParity(); | ||
|
||
// Serialization. | ||
console.log("ABI serialized public key:"); | ||
console.logBytes(pk.toBytes()); | ||
console.log(""); | ||
|
||
console.log("SEC encoded public key:"); | ||
console.logBytes(pk.intoPoint().toEncoded()); | ||
console.log(""); | ||
|
||
console.log("SEC compressed encoded public key:"); | ||
console.logBytes(pk.intoPoint().toCompressedEncoded()); | ||
console.log(""); | ||
} | ||
} |
Submodule forge-std
updated
37 files
+1 −0 | .gitattributes | |
+6 −12 | .github/workflows/ci.yml | |
+3 −1 | .github/workflows/sync.yml | |
+0 −3 | .gitmodules | |
+1 −1 | README.md | |
+3 −3 | foundry.toml | |
+0 −1 | lib/ds-test | |
+1 −1 | package.json | |
+635 −0 | scripts/vm.py | |
+518 −225 | src/StdAssertions.sol | |
+25 −10 | src/StdChains.sol | |
+2 −2 | src/StdCheats.sol | |
+18 −3 | src/StdInvariant.sol | |
+7 −11 | src/StdJson.sol | |
+201 −106 | src/StdStorage.sol | |
+179 −0 | src/StdToml.sol | |
+61 −33 | src/StdUtils.sol | |
+4 −4 | src/Test.sol | |
+1,457 −462 | src/Vm.sol | |
+393 −382 | src/console.sol | |
+1 −1,555 | src/console2.sol | |
+234 −0 | src/mocks/MockERC20.sol | |
+231 −0 | src/mocks/MockERC721.sol | |
+39 −909 | test/StdAssertions.t.sol | |
+36 −26 | test/StdChains.t.sol | |
+19 −11 | test/StdCheats.t.sol | |
+3 −1 | test/StdError.t.sol | |
+49 −0 | test/StdJson.t.sol | |
+8 −8 | test/StdMath.t.sol | |
+159 −11 | test/StdStorage.t.sol | |
+49 −0 | test/StdToml.t.sol | |
+20 −20 | test/StdUtils.t.sol | |
+3 −3 | test/Vm.t.sol | |
+8 −0 | test/fixtures/test.json | |
+6 −0 | test/fixtures/test.toml | |
+441 −0 | test/mocks/MockERC20.t.sol | |
+721 −0 | test/mocks/MockERC721.t.sol |
This file contains 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,121 @@ | ||
/* | ||
██████ ██████ ██ ██ ███████ ██████ ██ | ||
██ ██ ██ ██ ██ ██ ██ ██ ██ | ||
██ ██████ ████ ███████ ██ ██ ██ | ||
██ ██ ██ ██ ██ ██ ██ ██ | ||
██████ ██ ██ ██ ███████ ██████ ███████ | ||
*/ | ||
|
||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
pragma solidity ^0.8.16; | ||
|
||
import {Vm} from "forge-std/Vm.sol"; | ||
|
||
import {RandomOffchain} from "../common/RandomOffchain.sol"; | ||
|
||
import { | ||
Secp256r1, | ||
SecretKey, | ||
PublicKey | ||
} from "../../onchain/secp256r1/Secp256r1.sol"; | ||
import { | ||
Secp256r1Arithmetic, | ||
Point, | ||
ProjectivePoint | ||
} from "../../onchain/secp256r1/Secp256r1Arithmetic.sol"; | ||
|
||
/** | ||
* @title Secp256r1Offchain | ||
* | ||
* @notice Providing offchain cryptography-related functionality for the secp256r1 | ||
* elliptic curve | ||
* | ||
* @author verklegarden | ||
* @custom:repository github.com/verklegarden/crysol | ||
*/ | ||
library Secp256r1Offchain { | ||
using Secp256r1Offchain for SecretKey; | ||
using Secp256r1 for SecretKey; | ||
using Secp256r1 for PublicKey; | ||
using Secp256r1 for Point; | ||
using Secp256r1Arithmetic for Point; | ||
using Secp256r1Arithmetic for ProjectivePoint; | ||
|
||
// ~~~~~~~ Prelude ~~~~~~~ | ||
// forgefmt: disable-start | ||
Vm private constant vm = Vm(address(uint160(uint(keccak256("hevm cheat code"))))); | ||
modifier vmed() { | ||
if (block.chainid != 31337) revert("requireVm"); | ||
_; | ||
} | ||
// forgefmt: disable-end | ||
// ~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
//-------------------------------------------------------------------------- | ||
// Secret Key | ||
|
||
/// @dev Returns a new cryptographically secure secret key. | ||
/// | ||
/// @custom:vm RandomOffchain::readUint()(uint) | ||
function newSecretKey() internal vmed returns (SecretKey) { | ||
// Note to not introduce potential bias via bounding operation. | ||
uint scalar; | ||
do { | ||
scalar = RandomOffchain.readUint(); | ||
} while (scalar == 0 || scalar >= Secp256r1Arithmetic.Q); | ||
|
||
return Secp256r1.secretKeyFromUint(scalar); | ||
} | ||
|
||
/// @dev Returns the public key of secret key `sk`. | ||
/// | ||
/// @dev Reverts if: | ||
/// Secret key invalid | ||
/// | ||
/// @custom:vm vm.createWallet(uint) | ||
function toPublicKey(SecretKey sk) | ||
internal | ||
view | ||
vmed | ||
returns (PublicKey memory) | ||
{ | ||
if (!sk.isValid()) { | ||
revert("SecretKeyInvalid()"); | ||
} | ||
|
||
// TODO: Need vm support for p256 public key derivation. | ||
// Note that this function, in its current form, does not actually | ||
// depend on vm. However, for performance an issue in foundry will | ||
// be created to provide vm functionality for secp256r1 public key | ||
// derivation. | ||
// Note that this function should for obvious reasons not be | ||
// executed onchain anyway. | ||
// forgefmt: disable-next-item | ||
Point memory p = Secp256r1.G().toProjectivePoint() | ||
.mul(sk.asUint()) | ||
.intoPoint(); | ||
|
||
return p.intoPublicKey(); | ||
} | ||
|
||
//-------------------------------------------------------------------------- | ||
// Public Key | ||
|
||
/// @dev Returns a string representation of public key `pk`. | ||
/// | ||
/// @custom:vm vm.toString(uint) | ||
function toString(PublicKey memory pk) | ||
internal | ||
view | ||
vmed | ||
returns (string memory) | ||
{ | ||
string memory str = "Secp256r1::PublicKey({"; | ||
str = string.concat(str, " x: ", vm.toString(pk.x), ","); | ||
str = string.concat(str, " y: ", vm.toString(pk.y)); | ||
str = string.concat(str, " })"); | ||
return str; | ||
} | ||
} |
Oops, something went wrong.