Update tests

This commit is contained in:
Paul Miller 2023-01-24 03:02:45 +00:00
parent 7fda6de619
commit bfbcf733e6
No known key found for this signature in database
GPG Key ID: 697079DA6878B89B
4 changed files with 391 additions and 380 deletions

@ -342,7 +342,7 @@ for (const name in CURVES) {
if (!p) continue; if (!p) continue;
const G = [p.ZERO, p.BASE]; const G = [p.ZERO, p.BASE];
for (let i = 2; i < 10; i++) G.push(G[1].multiply(i)); for (let i = 2n; i < 10n; i++) G.push(G[1].multiply(i));
const title = `${name}/${pointName}`; const title = `${name}/${pointName}`;
describe(title, () => { describe(title, () => {
describe('basic group laws', () => { describe('basic group laws', () => {
@ -355,7 +355,7 @@ for (const name in CURVES) {
for (let i = 0; i < G.length; i++) { for (let i = 0; i < G.length; i++) {
const p = G[i]; const p = G[i];
equal(p, p.add(G[0]), '${i}*G + 0 = ${i}*G'); equal(p, p.add(G[0]), '${i}*G + 0 = ${i}*G');
equal(G[0].multiply(i + 1), G[0], '${i + 1}*0 = 0'); equal(G[0].multiply(BigInt(i + 1)), G[0], '${i + 1}*0 = 0');
} }
}); });
should('(one)', () => { should('(one)', () => {
@ -376,7 +376,7 @@ for (const name in CURVES) {
equal(G[3].double(), G[6], '(3*G).double() = 6*G'); equal(G[3].double(), G[6], '(3*G).double() = 6*G');
}); });
should('(multiply)', () => { should('(multiply)', () => {
equal(G[2].multiply(3), G[6], '(2*G).multiply(3) = 6*G'); equal(G[2].multiply(3n), G[6], '(2*G).multiply(3) = 6*G');
}); });
should('(same point addition)', () => { should('(same point addition)', () => {
equal(G[3].add(G[3]), G[6], '3*G + 3*G = 6*G'); equal(G[3].add(G[3]), G[6], '3*G + 3*G = 6*G');

@ -440,7 +440,7 @@ describe('ed25519', () => {
} catch (e) { } catch (e) {
noble = false; noble = false;
} }
deepStrictEqual(noble, v.valid_zip215); deepStrictEqual(noble, v.valid_zip215, JSON.stringify(v));
} }
}); });
should('ZIP-215 compliance tests/disallows sig.s >= CURVE.n', () => { should('ZIP-215 compliance tests/disallows sig.s >= CURVE.n', () => {

@ -8,7 +8,7 @@ import './ed25519.test.js';
import './secp256k1.test.js'; import './secp256k1.test.js';
import './stark/stark.test.js'; import './stark/stark.test.js';
import './jubjub.test.js'; import './jubjub.test.js';
import './bls12-381.test.js'; // import './bls12-381.test.js';
import './hash-to-curve.test.js'; import './hash-to-curve.test.js';
should.run(); should.run();

@ -76,7 +76,8 @@ describe('secp256k1', () => {
} }
}); });
should('Point.isValidPoint()', () => { describe('Point', () => {
should('fromHex() assertValidity', () => {
for (const vector of points.valid.isPoint) { for (const vector of points.valid.isPoint) {
const { P, expected } = vector; const { P, expected } = vector;
if (expected) { if (expected) {
@ -87,7 +88,7 @@ describe('secp256k1', () => {
} }
}); });
should('Point.fromPrivateKey()', () => { should('.fromPrivateKey()', () => {
for (const vector of points.valid.pointFromScalar) { for (const vector of points.valid.pointFromScalar) {
const { d, expected } = vector; const { d, expected } = vector;
let p = secp.Point.fromPrivateKey(d); let p = secp.Point.fromPrivateKey(d);
@ -95,7 +96,7 @@ describe('secp256k1', () => {
} }
}); });
should('Point#toHex(compressed)', () => { should('#toHex(compressed)', () => {
for (const vector of points.valid.pointCompress) { for (const vector of points.valid.pointCompress) {
const { P, compress, expected } = vector; const { P, compress, expected } = vector;
let p = secp.Point.fromHex(P); let p = secp.Point.fromHex(P);
@ -103,7 +104,7 @@ describe('secp256k1', () => {
} }
}); });
should('Point#toHex() roundtrip (failed case)', () => { should('#toHex() roundtrip (failed case)', () => {
const point1 = const point1 =
secp.Point.fromPrivateKey( secp.Point.fromPrivateKey(
88572218780422190464634044548753414301110513745532121983949500266768436236425n 88572218780422190464634044548753414301110513745532121983949500266768436236425n
@ -112,7 +113,7 @@ describe('secp256k1', () => {
// deepStrictEqual(secp.Point.fromHex(hex).toHex(true), hex); // deepStrictEqual(secp.Point.fromHex(hex).toHex(true), hex);
}); });
should('Point#toHex() roundtrip', () => { should('#toHex() roundtrip', () => {
fc.assert( fc.assert(
fc.property(FC_BIGINT, (x) => { fc.property(FC_BIGINT, (x) => {
const point1 = secp.Point.fromPrivateKey(x); const point1 = secp.Point.fromPrivateKey(x);
@ -122,7 +123,7 @@ describe('secp256k1', () => {
); );
}); });
should('Point#add(other)', () => { should('#add(other)', () => {
for (const vector of points.valid.pointAdd) { for (const vector of points.valid.pointAdd) {
const { P, Q, expected } = vector; const { P, Q, expected } = vector;
let p = secp.Point.fromHex(P); let p = secp.Point.fromHex(P);
@ -137,7 +138,7 @@ describe('secp256k1', () => {
} }
}); });
should('Point#multiply(privateKey)', () => { should('#multiply(privateKey)', () => {
for (const vector of points.valid.pointMultiply) { for (const vector of points.valid.pointMultiply) {
const { P, d, expected } = vector; const { P, d, expected } = vector;
const p = secp.Point.fromHex(P); const p = secp.Point.fromHex(P);
@ -163,6 +164,7 @@ describe('secp256k1', () => {
throws(() => secp.Point.BASE.multiply(num)); throws(() => secp.Point.BASE.multiply(num));
} }
}); });
});
// multiply() should equal multiplyUnsafe() // multiply() should equal multiplyUnsafe()
// should('ProjectivePoint#multiplyUnsafe', () => { // should('ProjectivePoint#multiplyUnsafe', () => {
@ -175,8 +177,8 @@ describe('secp256k1', () => {
// console.log(p0.multiply(z)); // console.log(p0.multiply(z));
// console.log(secp.ProjectivePoint.normalizeZ([p0.multiplyUnsafe(z)])[0]) // console.log(secp.ProjectivePoint.normalizeZ([p0.multiplyUnsafe(z)])[0])
// }); // });
describe('Signature', () => {
should('Signature.fromCompactHex() roundtrip', () => { should('.fromCompactHex() roundtrip', () => {
fc.assert( fc.assert(
fc.property(FC_BIGINT, FC_BIGINT, (r, s) => { fc.property(FC_BIGINT, FC_BIGINT, (r, s) => {
const sig = new secp.Signature(r, s); const sig = new secp.Signature(r, s);
@ -185,7 +187,7 @@ describe('secp256k1', () => {
); );
}); });
should('Signature.fromDERHex() roundtrip', () => { should('.fromDERHex() roundtrip', () => {
fc.assert( fc.assert(
fc.property(FC_BIGINT, FC_BIGINT, (r, s) => { fc.property(FC_BIGINT, FC_BIGINT, (r, s) => {
const sig = new secp.Signature(r, s); const sig = new secp.Signature(r, s);
@ -193,8 +195,10 @@ describe('secp256k1', () => {
}) })
); );
}); });
});
should('sign()/should create deterministic signatures with RFC 6979', () => { describe('sign()', () => {
should('create deterministic signatures with RFC 6979', () => {
for (const vector of ecdsa.valid) { for (const vector of ecdsa.valid) {
let usig = secp.sign(vector.m, vector.d); let usig = secp.sign(vector.m, vector.d);
let sig = usig.toCompactHex(); let sig = usig.toCompactHex();
@ -204,21 +208,18 @@ describe('secp256k1', () => {
} }
}); });
should( should('not create invalid deterministic signatures with RFC 6979', () => {
'secp256k1.sign()/should not create invalid deterministic signatures with RFC 6979',
() => {
for (const vector of ecdsa.invalid.sign) { for (const vector of ecdsa.invalid.sign) {
throws(() => secp.sign(vector.m, vector.d)); throws(() => secp.sign(vector.m, vector.d));
} }
} });
);
should('sign()/edge cases', () => { should('edge cases', () => {
throws(() => secp.sign()); throws(() => secp.sign());
throws(() => secp.sign('')); throws(() => secp.sign(''));
}); });
should('sign()/should create correct DER encoding against libsecp256k1', () => { should('create correct DER encoding against libsecp256k1', () => {
const CASES = [ const CASES = [
[ [
'd1a9dc8ed4e46a6a3e5e594615ca351d7d7ef44df1e4c94c1802f3592183794b', 'd1a9dc8ed4e46a6a3e5e594615ca351d7d7ef44df1e4c94c1802f3592183794b',
@ -233,7 +234,9 @@ describe('secp256k1', () => {
'3045022100d18990bba7832bb283e3ecf8700b67beb39acc73f4200ed1c331247c46edccc602202e5c8bbfe47ae159512c583b30a3fa86575cddc62527a03de7756517ae4c6c73', '3045022100d18990bba7832bb283e3ecf8700b67beb39acc73f4200ed1c331247c46edccc602202e5c8bbfe47ae159512c583b30a3fa86575cddc62527a03de7756517ae4c6c73',
], ],
]; ];
const privKey = hexToBytes('0101010101010101010101010101010101010101010101010101010101010101'); const privKey = hexToBytes(
'0101010101010101010101010101010101010101010101010101010101010101'
);
for (const [msg, exp] of CASES) { for (const [msg, exp] of CASES) {
const res = secp.sign(msg, privKey, { extraEntropy: undefined }); const res = secp.sign(msg, privKey, { extraEntropy: undefined });
deepStrictEqual(res.toDERHex(), exp); deepStrictEqual(res.toDERHex(), exp);
@ -241,7 +244,7 @@ describe('secp256k1', () => {
deepStrictEqual(secp.Signature.fromCompact(rs).toDERHex(), exp); deepStrictEqual(secp.Signature.fromCompact(rs).toDERHex(), exp);
} }
}); });
should('sign()/sign ecdsa extraData', () => { should('handle {extraData} option', () => {
const ent1 = '0000000000000000000000000000000000000000000000000000000000000000'; const ent1 = '0000000000000000000000000000000000000000000000000000000000000000';
const ent2 = '0000000000000000000000000000000000000000000000000000000000000001'; const ent2 = '0000000000000000000000000000000000000000000000000000000000000001';
const ent3 = '6e723d3fd94ed5d2b6bdd4f123364b0f3ca52af829988a63f8afe91d29db1c33'; const ent3 = '6e723d3fd94ed5d2b6bdd4f123364b0f3ca52af829988a63f8afe91d29db1c33';
@ -261,34 +264,36 @@ describe('secp256k1', () => {
deepStrictEqual(sign(ent5), e.extraEntropyMax); deepStrictEqual(sign(ent5), e.extraEntropyMax);
} }
}); });
});
should('verify()/should verify signature', () => { describe('verify()', () => {
should('verify signature', () => {
const MSG = '01'.repeat(32); const MSG = '01'.repeat(32);
const PRIV_KEY = 0x2n; const PRIV_KEY = 0x2n;
const signature = secp.sign(MSG, PRIV_KEY); const signature = secp.sign(MSG, PRIV_KEY);
const publicKey = secp.getPublicKey(PRIV_KEY); const publicKey = secp.getPublicKey(PRIV_KEY);
deepStrictEqual(publicKey.length, 65); deepStrictEqual(publicKey.length, 33);
deepStrictEqual(secp.verify(signature, MSG, publicKey), true); deepStrictEqual(secp.verify(signature, MSG, publicKey), true);
}); });
should('verify()/should not verify signature with wrong public key', () => { should(' not verify signature with wrong public key', () => {
const MSG = '01'.repeat(32); const MSG = '01'.repeat(32);
const PRIV_KEY = 0x2n; const PRIV_KEY = 0x2n;
const WRONG_PRIV_KEY = 0x22n; const WRONG_PRIV_KEY = 0x22n;
const signature = secp.sign(MSG, PRIV_KEY); const signature = secp.sign(MSG, PRIV_KEY);
const publicKey = secp.Point.fromPrivateKey(WRONG_PRIV_KEY).toHex(); const publicKey = secp.Point.fromPrivateKey(WRONG_PRIV_KEY).toHex();
deepStrictEqual(publicKey.length, 130); deepStrictEqual(publicKey.length, 66);
deepStrictEqual(secp.verify(signature, MSG, publicKey), false); deepStrictEqual(secp.verify(signature, MSG, publicKey), false);
}); });
should('verify()/should not verify signature with wrong hash', () => { should('not verify signature with wrong hash', () => {
const MSG = '01'.repeat(32); const MSG = '01'.repeat(32);
const PRIV_KEY = 0x2n; const PRIV_KEY = 0x2n;
const WRONG_MSG = '11'.repeat(32); const WRONG_MSG = '11'.repeat(32);
const signature = secp.sign(MSG, PRIV_KEY); const signature = secp.sign(MSG, PRIV_KEY);
const publicKey = secp.getPublicKey(PRIV_KEY); const publicKey = secp.getPublicKey(PRIV_KEY);
deepStrictEqual(publicKey.length, 65); deepStrictEqual(publicKey.length, 33);
deepStrictEqual(secp.verify(signature, WRONG_MSG, publicKey), false); deepStrictEqual(secp.verify(signature, WRONG_MSG, publicKey), false);
}); });
should('verify()/should verify random signatures', () => should('verify random signatures', () =>
fc.assert( fc.assert(
fc.property(FC_BIGINT, fc.hexaString({ minLength: 64, maxLength: 64 }), (privKey, msg) => { fc.property(FC_BIGINT, fc.hexaString({ minLength: 64, maxLength: 64 }), (privKey, msg) => {
const pub = secp.getPublicKey(privKey); const pub = secp.getPublicKey(privKey);
@ -297,7 +302,7 @@ describe('secp256k1', () => {
}) })
) )
); );
should('verify()/should not verify signature with invalid r/s', () => { should('not verify signature with invalid r/s', () => {
const msg = new Uint8Array([ const msg = new Uint8Array([
0xbb, 0x5a, 0x52, 0xf4, 0x2f, 0x9c, 0x92, 0x61, 0xed, 0x43, 0x61, 0xf5, 0x94, 0x22, 0xa1, 0xbb, 0x5a, 0x52, 0xf4, 0x2f, 0x9c, 0x92, 0x61, 0xed, 0x43, 0x61, 0xf5, 0x94, 0x22, 0xa1,
0xe3, 0x00, 0x36, 0xe7, 0xc3, 0x2b, 0x27, 0x0c, 0x88, 0x07, 0xa4, 0x19, 0xfe, 0xca, 0x60, 0xe3, 0x00, 0x36, 0xe7, 0xc3, 0x2b, 0x27, 0x0c, 0x88, 0x07, 0xa4, 0x19, 0xfe, 0xca, 0x60,
@ -317,7 +322,7 @@ describe('secp256k1', () => {
// Verifies, but it shouldn't, because signature S > curve order // Verifies, but it shouldn't, because signature S > curve order
deepStrictEqual(verified, false); deepStrictEqual(verified, false);
}); });
should('verify()/should not verify msg = curve order', () => { should('not verify msg = curve order', () => {
const msg = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'; const msg = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141';
const x = 55066263022277343669578718895168534326250603453777594175500187360389116729240n; const x = 55066263022277343669578718895168534326250603453777594175500187360389116729240n;
const y = 32670510020758816978083085130507043184471273380659243275938904335757337482424n; const y = 32670510020758816978083085130507043184471273380659243275938904335757337482424n;
@ -327,7 +332,7 @@ describe('secp256k1', () => {
const sig = new secp.Signature(r, s); const sig = new secp.Signature(r, s);
deepStrictEqual(secp.verify(sig, msg, pub), false); deepStrictEqual(secp.verify(sig, msg, pub), false);
}); });
should('verify()/should verify non-strict msg bb5a...', () => { should('verify non-strict msg bb5a...', () => {
const msg = 'bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023'; const msg = 'bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023';
const x = 3252872872578928810725465493269682203671229454553002637820453004368632726370n; const x = 3252872872578928810725465493269682203671229454553002637820453004368632726370n;
const y = 17482644437196207387910659778872952193236850502325156318830589868678978890912n; const y = 17482644437196207387910659778872952193236850502325156318830589868678978890912n;
@ -337,16 +342,15 @@ describe('secp256k1', () => {
const sig = new secp.Signature(r, s); const sig = new secp.Signature(r, s);
deepStrictEqual(secp.verify(sig, msg, pub, { strict: false }), true); deepStrictEqual(secp.verify(sig, msg, pub, { strict: false }), true);
}); });
should( should('not verify invalid deterministic signatures with RFC 6979', () => {
'secp256k1.verify()/should not verify invalid deterministic signatures with RFC 6979',
() => {
for (const vector of ecdsa.invalid.verify) { for (const vector of ecdsa.invalid.verify) {
const res = secp.verify(vector.signature, vector.m, vector.Q); const res = secp.verify(vector.signature, vector.m, vector.Q);
deepStrictEqual(res, false); deepStrictEqual(res, false);
} }
} });
); });
describe('schnorr.sign()', () => {
// index,secret key,public key,aux_rand,message,signature,verification result,comment // index,secret key,public key,aux_rand,message,signature,verification result,comment
const vectors = schCsv const vectors = schCsv
.split('\n') .split('\n')
@ -354,7 +358,7 @@ describe('secp256k1', () => {
.slice(1, -1); .slice(1, -1);
for (let vec of vectors) { for (let vec of vectors) {
const [index, sec, pub, rnd, msg, expSig, passes, comment] = vec; const [index, sec, pub, rnd, msg, expSig, passes, comment] = vec;
should(`sign with Schnorr scheme vector ${index}`, () => { should(`${comment || 'vector ' + index}`, () => {
if (sec) { if (sec) {
deepStrictEqual(hex(schnorr.getPublicKey(sec)), pub.toLowerCase()); deepStrictEqual(hex(schnorr.getPublicKey(sec)), pub.toLowerCase());
const sig = schnorr.sign(msg, sec, rnd); const sig = schnorr.sign(msg, sec, rnd);
@ -366,8 +370,10 @@ describe('secp256k1', () => {
} }
}); });
} }
});
should('recoverPublicKey()/should recover public key from recovery bit', () => { describe('recoverPublicKey()', () => {
should('recover public key from recovery bit', () => {
const message = '00000000000000000000000000000000000000000000000000000000deadbeef'; const message = '00000000000000000000000000000000000000000000000000000000deadbeef';
const privateKey = 123456789n; const privateKey = 123456789n;
const publicKey = secp.Point.fromHex(secp.getPublicKey(privateKey)).toHex(false); const publicKey = secp.Point.fromHex(secp.getPublicKey(privateKey)).toHex(false);
@ -378,22 +384,22 @@ describe('secp256k1', () => {
deepStrictEqual(recoveredPubkey.toHex(false), publicKey); deepStrictEqual(recoveredPubkey.toHex(false), publicKey);
deepStrictEqual(secp.verify(sig, message, publicKey), true); deepStrictEqual(secp.verify(sig, message, publicKey), true);
}); });
should('recoverPublicKey()/should not recover zero points', () => { should('not recover zero points', () => {
const msgHash = '6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9'; const msgHash = '6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9';
const sig = const sig =
'79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817986b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9'; '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817986b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9';
const recovery = 0; const recovery = 0;
throws(() => secp.recoverPublicKey(msgHash, sig, recovery)); throws(() => secp.recoverPublicKey(msgHash, sig, recovery));
}); });
should('recoverPublicKey()/should handle all-zeros msghash', () => { should('handle all-zeros msghash', () => {
const privKey = secp.utils.randomPrivateKey(); const privKey = secp.utils.randomPrivateKey();
const pub = secp.getPublicKey(privKey); const pub = secp.getPublicKey(privKey);
const zeros = '0000000000000000000000000000000000000000000000000000000000000000'; const zeros = '0000000000000000000000000000000000000000000000000000000000000000';
const sig = secp.sign(zeros, privKey, { recovered: true }); const sig = secp.sign(zeros, privKey);
const recoveredKey = sig.recoverPublicKey(zeros); const recoveredKey = sig.recoverPublicKey(zeros);
deepStrictEqual(recoveredKey.toRawBytes(), pub); deepStrictEqual(recoveredKey.toRawBytes(), pub);
}); });
should('recoverPublicKey()/should handle RFC 6979 vectors', () => { should('handle RFC 6979 vectors', () => {
for (const vector of ecdsa.valid) { for (const vector of ecdsa.valid) {
let usig = secp.sign(vector.m, vector.d); let usig = secp.sign(vector.m, vector.d);
let sig = usig.toDERHex(); let sig = usig.toDERHex();
@ -402,12 +408,14 @@ describe('secp256k1', () => {
deepStrictEqual(recovered.toHex(), hex(vpub)); deepStrictEqual(recovered.toHex(), hex(vpub));
} }
}); });
});
describe('getSharedSecret()', () => {
// TODO: Real implementation. // TODO: Real implementation.
function derToPub(der) { function derToPub(der) {
return der.slice(46); return der.slice(46);
} }
should('getSharedSecret()/should produce correct results', () => { should('produce correct results', () => {
// TODO: Once der is there, run all tests. // TODO: Once der is there, run all tests.
for (const vector of ecdh.testGroups[0].tests.slice(0, 230)) { for (const vector of ecdh.testGroups[0].tests.slice(0, 230)) {
if (vector.result === 'invalid' || vector.private.length !== 64) { if (vector.result === 'invalid' || vector.private.length !== 64) {
@ -420,7 +428,7 @@ describe('secp256k1', () => {
} }
} }
}); });
should('getSharedSecret()/priv/pub order matters', () => { should('priv/pub order matters', () => {
for (const vector of ecdh.testGroups[0].tests.slice(0, 100)) { for (const vector of ecdh.testGroups[0].tests.slice(0, 100)) {
if (vector.result === 'valid') { if (vector.result === 'valid') {
let priv = vector.private; let priv = vector.private;
@ -429,9 +437,10 @@ describe('secp256k1', () => {
} }
} }
}); });
should('getSharedSecret()/rejects invalid keys', () => { should('reject invalid keys', () => {
throws(() => secp.getSharedSecret('01', '02')); throws(() => secp.getSharedSecret('01', '02'));
}); });
});
should('utils.isValidPrivateKey()', () => { should('utils.isValidPrivateKey()', () => {
for (const vector of privates.valid.isPrivate) { for (const vector of privates.valid.isPrivate) {
@ -447,6 +456,7 @@ describe('secp256k1', () => {
}); });
}); });
describe('tweak utilities (legacy)', () => {
const Fn = Fp(secp.CURVE.n); const Fn = Fp(secp.CURVE.n);
const normal = secp.utils._normalizePrivateKey; const normal = secp.utils._normalizePrivateKey;
const tweakUtils = { const tweakUtils = {
@ -514,6 +524,7 @@ describe('secp256k1', () => {
throws(() => tweakUtils.pointMultiply(P, d)); throws(() => tweakUtils.pointMultiply(P, d));
} }
}); });
});
should('wychenproof vectors', () => { should('wychenproof vectors', () => {
for (let group of wp.testGroups) { for (let group of wp.testGroups) {