Update docs
This commit is contained in:
@ -26,7 +26,6 @@ describe('ECDSA', function () {
|
||||
|
||||
it('with long signature', async function () {
|
||||
await expect(
|
||||
// eslint-disable-next-line max-len
|
||||
this.mock.$recover(
|
||||
TEST_MESSAGE,
|
||||
'0x01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789',
|
||||
@ -61,7 +60,6 @@ describe('ECDSA', function () {
|
||||
});
|
||||
|
||||
it('reverts with invalid signature', async function () {
|
||||
// eslint-disable-next-line max-len
|
||||
const signature =
|
||||
'0x332ce75a821c982f9127538858900d87d3ec1f9f737338ad67cad133fa48feff48e6fa0c18abc62e42820f05943e47af3e9fbe306ce74d64094bdf1691ee53e01c';
|
||||
await expect(this.mock.$recover(TEST_MESSAGE, signature)).to.be.revertedWithCustomError(
|
||||
@ -73,7 +71,7 @@ describe('ECDSA', function () {
|
||||
|
||||
describe('with v=27 signature', function () {
|
||||
const signer = '0x2cc1166f6212628A0deEf2B33BEFB2187D35b86c';
|
||||
// eslint-disable-next-line max-len
|
||||
|
||||
const signatureWithoutV =
|
||||
'0x5d99b6f7f6d1f73d1a26497f2b1c89b24c0993913f86e9a2d02cd69887d9c94f3c880358579d811b21dd1b7fd9bb01c1d81d10e69f0384e675c32b39643be892';
|
||||
|
||||
@ -133,7 +131,7 @@ describe('ECDSA', function () {
|
||||
|
||||
describe('with v=28 signature', function () {
|
||||
const signer = '0x1E318623aB09Fe6de3C9b8672098464Aeda9100E';
|
||||
// eslint-disable-next-line max-len
|
||||
|
||||
const signatureWithoutV =
|
||||
'0x331fe75a821c982f9127538858900d87d3ec1f9f737338ad67cad133fa48feff48e6fa0c18abc62e42820f05943e47af3e9fbe306ce74d64094bdf1691ee53e0';
|
||||
|
||||
@ -193,7 +191,7 @@ describe('ECDSA', function () {
|
||||
|
||||
it('reverts with high-s value signature', async function () {
|
||||
const message = '0xb94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9';
|
||||
// eslint-disable-next-line max-len
|
||||
|
||||
const highSSignature =
|
||||
'0xe742ff452d41413616a5bf43fe15dd88294e983d3d36206c2712f39083d638bde0a0fc89be718fbc1033e1d30d78be1c68081562ed2e97af876f286f3453231d1b';
|
||||
|
||||
|
||||
@ -12,23 +12,23 @@ contract P256Test is Test {
|
||||
function testVerify(bytes32 digest, uint256 seed) public {
|
||||
uint256 privateKey = _asPrivateKey(seed);
|
||||
|
||||
(bytes32 x, bytes32 y) = P256PublicKey.getPublicKey(privateKey);
|
||||
(uint256 x, uint256 y) = vm.publicKeyP256(privateKey);
|
||||
(bytes32 r, bytes32 s) = vm.signP256(privateKey, digest);
|
||||
s = _ensureLowerS(s);
|
||||
assertTrue(P256.verify(digest, r, s, x, y));
|
||||
assertTrue(P256.verifySolidity(digest, r, s, x, y));
|
||||
assertTrue(P256.verify(digest, r, s, bytes32(x), bytes32(y)));
|
||||
assertTrue(P256.verifySolidity(digest, r, s, bytes32(x), bytes32(y)));
|
||||
}
|
||||
|
||||
/// forge-config: default.fuzz.runs = 512
|
||||
function testRecover(bytes32 digest, uint256 seed) public {
|
||||
uint256 privateKey = _asPrivateKey(seed);
|
||||
|
||||
(bytes32 x, bytes32 y) = P256PublicKey.getPublicKey(privateKey);
|
||||
(uint256 x, uint256 y) = vm.publicKeyP256(privateKey);
|
||||
(bytes32 r, bytes32 s) = vm.signP256(privateKey, digest);
|
||||
s = _ensureLowerS(s);
|
||||
(bytes32 qx0, bytes32 qy0) = P256.recovery(digest, 0, r, s);
|
||||
(bytes32 qx1, bytes32 qy1) = P256.recovery(digest, 1, r, s);
|
||||
assertTrue((qx0 == x && qy0 == y) || (qx1 == x && qy1 == y));
|
||||
assertTrue((qx0 == bytes32(x) && qy0 == bytes32(y)) || (qx1 == bytes32(x) && qy1 == bytes32(y)));
|
||||
}
|
||||
|
||||
function _asPrivateKey(uint256 seed) private pure returns (uint256) {
|
||||
@ -42,98 +42,3 @@ contract P256Test is Test {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Library to derive P256 public key from private key
|
||||
* Should be removed if Foundry adds this functionality
|
||||
* See https://github.com/foundry-rs/foundry/issues/7908
|
||||
*/
|
||||
library P256PublicKey {
|
||||
function getPublicKey(uint256 privateKey) internal view returns (bytes32, bytes32) {
|
||||
(uint256 x, uint256 y, uint256 z) = _jMult(P256.GX, P256.GY, 1, privateKey);
|
||||
return _affineFromJacobian(x, y, z);
|
||||
}
|
||||
|
||||
function _jMult(
|
||||
uint256 x,
|
||||
uint256 y,
|
||||
uint256 z,
|
||||
uint256 k
|
||||
) private pure returns (uint256 rx, uint256 ry, uint256 rz) {
|
||||
unchecked {
|
||||
for (uint256 i = 0; i < 256; ++i) {
|
||||
if (rz > 0) {
|
||||
(rx, ry, rz) = _jDouble(rx, ry, rz);
|
||||
}
|
||||
if (k >> 255 > 0) {
|
||||
if (rz == 0) {
|
||||
(rx, ry, rz) = (x, y, z);
|
||||
} else {
|
||||
(rx, ry, rz) = _jAdd(rx, ry, rz, x, y, z);
|
||||
}
|
||||
}
|
||||
k <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// From P256.sol
|
||||
|
||||
function _affineFromJacobian(uint256 jx, uint256 jy, uint256 jz) private view returns (bytes32 ax, bytes32 ay) {
|
||||
if (jz == 0) return (0, 0);
|
||||
uint256 zinv = Math.invModPrime(jz, P256.P);
|
||||
uint256 zzinv = mulmod(zinv, zinv, P256.P);
|
||||
uint256 zzzinv = mulmod(zzinv, zinv, P256.P);
|
||||
ax = bytes32(mulmod(jx, zzinv, P256.P));
|
||||
ay = bytes32(mulmod(jy, zzzinv, P256.P));
|
||||
}
|
||||
|
||||
function _jDouble(uint256 x, uint256 y, uint256 z) private pure returns (uint256 rx, uint256 ry, uint256 rz) {
|
||||
uint256 p = P256.P;
|
||||
uint256 a = P256.A;
|
||||
assembly ("memory-safe") {
|
||||
let yy := mulmod(y, y, p)
|
||||
let zz := mulmod(z, z, p)
|
||||
let s := mulmod(4, mulmod(x, yy, p), p) // s = 4*x*y²
|
||||
let m := addmod(mulmod(3, mulmod(x, x, p), p), mulmod(a, mulmod(zz, zz, p), p), p) // m = 3*x²+a*z⁴
|
||||
let t := addmod(mulmod(m, m, p), sub(p, mulmod(2, s, p)), p) // t = m²-2*s
|
||||
|
||||
// x' = t
|
||||
rx := t
|
||||
// y' = m*(s-t)-8*y⁴
|
||||
ry := addmod(mulmod(m, addmod(s, sub(p, t), p), p), sub(p, mulmod(8, mulmod(yy, yy, p), p)), p)
|
||||
// z' = 2*y*z
|
||||
rz := mulmod(2, mulmod(y, z, p), p)
|
||||
}
|
||||
}
|
||||
|
||||
function _jAdd(
|
||||
uint256 x1,
|
||||
uint256 y1,
|
||||
uint256 z1,
|
||||
uint256 x2,
|
||||
uint256 y2,
|
||||
uint256 z2
|
||||
) private pure returns (uint256 rx, uint256 ry, uint256 rz) {
|
||||
uint256 p = P256.P;
|
||||
assembly ("memory-safe") {
|
||||
let zz1 := mulmod(z1, z1, p) // zz1 = z1²
|
||||
let zz2 := mulmod(z2, z2, p) // zz2 = z2²
|
||||
let u1 := mulmod(x1, zz2, p) // u1 = x1*z2²
|
||||
let u2 := mulmod(x2, zz1, p) // u2 = x2*z1²
|
||||
let s1 := mulmod(y1, mulmod(zz2, z2, p), p) // s1 = y1*z2³
|
||||
let s2 := mulmod(y2, mulmod(zz1, z1, p), p) // s2 = y2*z1³
|
||||
let h := addmod(u2, sub(p, u1), p) // h = u2-u1
|
||||
let hh := mulmod(h, h, p) // h²
|
||||
let hhh := mulmod(h, hh, p) // h³
|
||||
let r := addmod(s2, sub(p, s1), p) // r = s2-s1
|
||||
|
||||
// x' = r²-h³-2*u1*h²
|
||||
rx := addmod(addmod(mulmod(r, r, p), sub(p, hhh), p), sub(p, mulmod(2, mulmod(u1, hh, p), p)), p)
|
||||
// y' = r*(u1*h²-x')-s1*h³
|
||||
ry := addmod(mulmod(r, addmod(mulmod(u1, hh, p), sub(p, rx), p), p), sub(p, mulmod(s1, hhh, p)), p)
|
||||
// z' = h*z1*z2
|
||||
rz := mulmod(h, mulmod(z1, z2, p), p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user