Refactor tests slightly: group tests

This commit is contained in:
Paul Miller 2022-12-14 21:21:56 +00:00
parent fd75293334
commit 43b18ea13b
No known key found for this signature in database
GPG Key ID: 697079DA6878B89B
4 changed files with 99 additions and 94 deletions

@ -30,19 +30,12 @@ old_secp.utils.hmacSha256Sync = (key, ...msgs) =>
.update(concatBytes(...msgs)) .update(concatBytes(...msgs))
.digest(); .digest();
import * as noble_ed25519 from '@noble/ed25519'; import * as noble_ed25519 from '@noble/ed25519';
secp256k1.utils.precompute(8); // Not enabled by default?
ed25519.utils.precompute(8);
ed448.utils.precompute(8);
P256.utils.precompute(8);
P384.utils.precompute(8);
P521.utils.precompute(8);
noble_ed25519.utils.sha512Sync = (...m) => sha512(concatBytes(...m)); noble_ed25519.utils.sha512Sync = (...m) => sha512(concatBytes(...m));
old_secp.utils.precompute(8);
noble_ed25519.utils.precompute(8);
const wrapBuf = (arrayBuffer) => new Uint8Array(arrayBuffer); for (let item of [secp256k1, ed25519, ed448, P256, P384, P521, old_secp, noble_ed25519]) {
item.utils.precompute(8);
}
const ONLY_NOBLE = process.argv[2] === 'noble'; const ONLY_NOBLE = process.argv[2] === 'noble';
function generateData(namespace) { function generateData(namespace) {
@ -73,17 +66,23 @@ export const CURVES = {
secp256k1_old: ({ msg, priv }) => old_secp.signSync(msg, priv), secp256k1_old: ({ msg, priv }) => old_secp.signSync(msg, priv),
secp256k1: ({ msg, priv }) => secp256k1.sign(msg, priv), secp256k1: ({ msg, priv }) => secp256k1.sign(msg, priv),
}, },
getSharedSecret: {
samples: 1000,
secp256k1_old: ({ pub, priv }) => old_secp.getSharedSecret(priv, pub),
secp256k1: ({ pub, priv }) => secp256k1.getSharedSecret(priv, pub),
},
verify: { verify: {
samples: 1000, samples: 1000,
secp256k1_old: ({ sig, msg, pub }) => { secp256k1_old: ({ sig, msg, pub }) => {
return old_secp.verify((new old_secp.Signature(sig.r, sig.s)), msg, pub); return old_secp.verify((new old_secp.Signature(sig.r, sig.s)), msg, pub);
}, },
secp256k1: ({ sig, msg, pub }) => secp256k1.verify(sig, msg, pub) secp256k1: ({ sig, msg, pub }) => secp256k1.verify(sig, msg, pub)
},
getSharedSecret: {
samples: 1000,
secp256k1_old: ({ pub, priv }) => old_secp.getSharedSecret(priv, pub),
secp256k1: ({ pub, priv }) => secp256k1.getSharedSecret(priv, pub),
},
recoverPublicKey: {
samples: 1000,
secp256k1_old: ({ sig, msg }) =>
old_secp.recoverPublicKey(msg, (new old_secp.Signature(sig.r, sig.s)), sig.recovery),
secp256k1: ({ sig, msg }) => sig.recoverPublicKey(msg)
} }
}, },
ed25519: { ed25519: {

@ -508,13 +508,14 @@ should('RFC7748 getSharedKey', () => {
{ {
const group = x25519vectors.testGroups[0]; const group = x25519vectors.testGroups[0];
should(`Wycheproof/X25519`, () => {
for (let i = 0; i < group.tests.length; i++) { for (let i = 0; i < group.tests.length; i++) {
const v = group.tests[i]; const v = group.tests[i];
should(`Wycheproof/X25519(${i}, ${v.result}) ${v.comment}`, () => { const comment = `(${i}, ${v.result}) ${v.comment}`;
if (v.result === 'valid' || v.result === 'acceptable') { if (v.result === 'valid' || v.result === 'acceptable') {
try { try {
const shared = hex(x25519.scalarMult(v.public, v.private)); const shared = hex(x25519.scalarMult(v.public, v.private));
deepStrictEqual(shared, v.shared, 'valid'); deepStrictEqual(shared, v.shared, comment);
} catch (e) { } catch (e) {
// We are more strict // We are more strict
if (e.message.includes('Expected valid scalar')) return; if (e.message.includes('Expected valid scalar')) return;
@ -528,25 +529,23 @@ should('RFC7748 getSharedKey', () => {
} catch (error) { } catch (error) {
failed = true; failed = true;
} }
deepStrictEqual(failed, true, 'invalid'); deepStrictEqual(failed, true, comment);
} else throw new Error('unknown test result'); } else throw new Error('unknown test result');
});
} }
});
} }
{ should(`Wycheproof/ED25519`, () => {
for (let g = 0; g < ed25519vectors.testGroups.length; g++) { for (let g = 0; g < ed25519vectors.testGroups.length; g++) {
const group = ed25519vectors.testGroups[g]; const group = ed25519vectors.testGroups[g];
const key = group.key; const key = group.key;
should(`Wycheproof/ED25519(${g}, public)`, () => { deepStrictEqual(hex(ed.getPublicKey(key.sk)), key.pk, `(${g}, public)`);
deepStrictEqual(hex(ed.getPublicKey(key.sk)), key.pk);
});
for (let i = 0; i < group.tests.length; i++) { for (let i = 0; i < group.tests.length; i++) {
const v = group.tests[i]; const v = group.tests[i];
should(`Wycheproof/ED25519(${g}/${i}, ${v.result}): ${v.comment}`, () => { const comment = `(${g}/${i}, ${v.result}): ${v.comment}`;
if (v.result === 'valid' || v.result === 'acceptable') { if (v.result === 'valid' || v.result === 'acceptable') {
deepStrictEqual(hex(ed.sign(v.msg, key.sk)), v.sig); deepStrictEqual(hex(ed.sign(v.msg, key.sk)), v.sig, comment);
deepStrictEqual(ed.verify(v.sig, v.msg, key.pk), true); deepStrictEqual(ed.verify(v.sig, v.msg, key.pk), true, comment);
} else if (v.result === 'invalid') { } else if (v.result === 'invalid') {
let failed = false; let failed = false;
try { try {
@ -554,12 +553,11 @@ should('RFC7748 getSharedKey', () => {
} catch (error) { } catch (error) {
failed = true; failed = true;
} }
deepStrictEqual(failed, true, 'invalid'); deepStrictEqual(failed, true, comment);
} else throw new Error('unknown test result'); } else throw new Error('unknown test result');
});
} }
} }
} });
should('Property test issue #1', () => { should('Property test issue #1', () => {
const message = new Uint8Array([12, 12, 12]); const message = new Uint8Array([12, 12, 12]);

@ -439,12 +439,13 @@ should('input immutability: sign/verify are immutable', () => {
should(`Wycheproof/ED448(${g}, public)`, () => { should(`Wycheproof/ED448(${g}, public)`, () => {
deepStrictEqual(hex(ed.getPublicKey(key.sk)), key.pk); deepStrictEqual(hex(ed.getPublicKey(key.sk)), key.pk);
}); });
should(`Wycheproof/ED448`, () => {
for (let i = 0; i < group.tests.length; i++) { for (let i = 0; i < group.tests.length; i++) {
const v = group.tests[i]; const v = group.tests[i];
should(`Wycheproof/ED448(${g}/${i}, ${v.result}): ${v.comment}`, () => { const index = `${g}/${i} ${v.comment}`;
if (v.result === 'valid' || v.result === 'acceptable') { if (v.result === 'valid' || v.result === 'acceptable') {
deepStrictEqual(hex(ed.sign(v.msg, key.sk)), v.sig); deepStrictEqual(hex(ed.sign(v.msg, key.sk)), v.sig, index);
deepStrictEqual(ed.verify(v.sig, v.msg, key.pk), true); deepStrictEqual(ed.verify(v.sig, v.msg, key.pk), true, index);
} else if (v.result === 'invalid') { } else if (v.result === 'invalid') {
let failed = false; let failed = false;
try { try {
@ -452,10 +453,10 @@ should('input immutability: sign/verify are immutable', () => {
} catch (error) { } catch (error) {
failed = true; failed = true;
} }
deepStrictEqual(failed, true, 'invalid'); deepStrictEqual(failed, true, index);
} else throw new Error('unknown test result'); } else throw new Error('unknown test result');
});
} }
});
} }
} }
@ -524,13 +525,14 @@ should('RFC7748 getSharedKey', () => {
{ {
const group = x448vectors.testGroups[0]; const group = x448vectors.testGroups[0];
should(`Wycheproof/X448`, () => {
for (let i = 0; i < group.tests.length; i++) { for (let i = 0; i < group.tests.length; i++) {
const v = group.tests[i]; const v = group.tests[i];
should(`Wycheproof/X448(${i}, ${v.result}) ${v.comment}`, () => { const index = `(${i}, ${v.result}) ${v.comment}`;
if (v.result === 'valid' || v.result === 'acceptable') { if (v.result === 'valid' || v.result === 'acceptable') {
try { try {
const shared = hex(x448.scalarMult(v.public, v.private)); const shared = hex(x448.scalarMult(v.public, v.private));
deepStrictEqual(shared, v.shared, 'valid'); deepStrictEqual(shared, v.shared, index);
} catch (e) { } catch (e) {
// We are more strict // We are more strict
if (e.message.includes('Expected valid scalar')) return; if (e.message.includes('Expected valid scalar')) return;
@ -545,10 +547,10 @@ should('RFC7748 getSharedKey', () => {
} catch (error) { } catch (error) {
failed = true; failed = true;
} }
deepStrictEqual(failed, true, 'invalid'); deepStrictEqual(failed, true, index);
} else throw new Error('unknown test result'); } else throw new Error('unknown test result');
});
} }
});
} }
// should('X448: should convert base point to montgomery using fromPoint', () => { // should('X448: should convert base point to montgomery using fromPoint', () => {

@ -308,21 +308,13 @@ const WYCHEPROOF_ECDSA = {
}, },
}; };
for (const name in WYCHEPROOF_ECDSA) { function runWycheproof(name, CURVE, group, index) {
const { curve, hashes } = WYCHEPROOF_ECDSA[name];
for (const hName in hashes) {
const { hash, tests } = hashes[hName];
const CURVE = curve.create(hash);
for (let i = 0; i < tests.length; i++) {
const test = tests[i];
for (let j = 0; j < test.testGroups.length; j++) {
const group = test.testGroups[j];
should(`Wycheproof/WYCHEPROOF_ECDSA ${name}/${hName} (${i}/${j})`, () => {
const pubKey = CURVE.Point.fromHex(group.key.uncompressed); const pubKey = CURVE.Point.fromHex(group.key.uncompressed);
deepStrictEqual(pubKey.x, BigInt(`0x${group.key.wx}`)); deepStrictEqual(pubKey.x, BigInt(`0x${group.key.wx}`));
deepStrictEqual(pubKey.y, BigInt(`0x${group.key.wy}`)); deepStrictEqual(pubKey.y, BigInt(`0x${group.key.wy}`));
for (const test of group.tests) { for (const test of group.tests) {
const m = CURVE.CURVE.hash(hexToBytes(test.msg)); const m = CURVE.CURVE.hash(hexToBytes(test.msg));
if (test.result === 'valid' || test.result === 'acceptable') { if (test.result === 'valid' || test.result === 'acceptable') {
try { try {
CURVE.Signature.fromDER(test.sig); CURVE.Signature.fromDER(test.sig);
@ -334,10 +326,11 @@ for (const name in WYCHEPROOF_ECDSA) {
const verified = CURVE.verify(test.sig, m, pubKey); const verified = CURVE.verify(test.sig, m, pubKey);
if (name === 'secp256k1') { if (name === 'secp256k1') {
// lowS: true for secp256k1 // lowS: true for secp256k1
deepStrictEqual(verified, !CURVE.Signature.fromDER(test.sig).hasHighS()); deepStrictEqual(verified, !CURVE.Signature.fromDER(test.sig).hasHighS(), `${index}: valid`);
} else { } else {
deepStrictEqual(verified, true, 'valid'); deepStrictEqual(verified, true, `${index}: valid`);
} }
} else if (test.result === 'invalid') { } else if (test.result === 'invalid') {
let failed = false; let failed = false;
try { try {
@ -345,13 +338,26 @@ for (const name in WYCHEPROOF_ECDSA) {
} catch (error) { } catch (error) {
failed = true; failed = true;
} }
deepStrictEqual(failed, true, 'invalid'); deepStrictEqual(failed, true, `${index}: invalid`);
} else throw new Error('unknown test result'); } else throw new Error('unknown test result');
} }
}
for (const name in WYCHEPROOF_ECDSA) {
const { curve, hashes } = WYCHEPROOF_ECDSA[name];
for (const hName in hashes) {
const { hash, tests } = hashes[hName];
const CURVE = curve.create(hash);
should(`Wycheproof/WYCHEPROOF_ECDSA ${name}/${hName}`, () => {
for (let i = 0; i < tests.length; i++) {
const groups = tests[i].testGroups;
for (let j = 0; j < groups.length; j++) {
const group = groups[j];
runWycheproof(name, CURVE, group, `${i}/${j}`);
}
}
}); });
} }
}
}
} }
const hexToBigint = (hex) => BigInt(`0x${hex}`); const hexToBigint = (hex) => BigInt(`0x${hex}`);