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))
.digest();
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));
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';
function generateData(namespace) {
@ -73,17 +66,23 @@ export const CURVES = {
secp256k1_old: ({ msg, priv }) => old_secp.signSync(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: {
samples: 1000,
secp256k1_old: ({ sig, 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)
},
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: {

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

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

@ -308,49 +308,55 @@ const WYCHEPROOF_ECDSA = {
},
};
function runWycheproof(name, CURVE, group, index) {
const pubKey = CURVE.Point.fromHex(group.key.uncompressed);
deepStrictEqual(pubKey.x, BigInt(`0x${group.key.wx}`));
deepStrictEqual(pubKey.y, BigInt(`0x${group.key.wy}`));
for (const test of group.tests) {
const m = CURVE.CURVE.hash(hexToBytes(test.msg));
if (test.result === 'valid' || test.result === 'acceptable') {
try {
CURVE.Signature.fromDER(test.sig);
} catch (e) {
// Some tests has invalid signature which we don't accept
if (e.message.includes('Invalid signature: incorrect length')) continue;
throw e;
}
const verified = CURVE.verify(test.sig, m, pubKey);
if (name === 'secp256k1') {
// lowS: true for secp256k1
deepStrictEqual(verified, !CURVE.Signature.fromDER(test.sig).hasHighS(), `${index}: valid`);
} else {
deepStrictEqual(verified, true, `${index}: valid`);
}
} else if (test.result === 'invalid') {
let failed = false;
try {
failed = !CURVE.verify(test.sig, m, pubKey);
} catch (error) {
failed = true;
}
deepStrictEqual(failed, true, `${index}: invalid`);
} 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);
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);
deepStrictEqual(pubKey.x, BigInt(`0x${group.key.wx}`));
deepStrictEqual(pubKey.y, BigInt(`0x${group.key.wy}`));
for (const test of group.tests) {
const m = CURVE.CURVE.hash(hexToBytes(test.msg));
if (test.result === 'valid' || test.result === 'acceptable') {
try {
CURVE.Signature.fromDER(test.sig);
} catch (e) {
// Some tests has invalid signature which we don't accept
if (e.message.includes('Invalid signature: incorrect length')) continue;
throw e;
}
const verified = CURVE.verify(test.sig, m, pubKey);
if (name === 'secp256k1') {
// lowS: true for secp256k1
deepStrictEqual(verified, !CURVE.Signature.fromDER(test.sig).hasHighS());
} else {
deepStrictEqual(verified, true, 'valid');
}
} else if (test.result === 'invalid') {
let failed = false;
try {
failed = !CURVE.verify(test.sig, m, pubKey);
} catch (error) {
failed = true;
}
deepStrictEqual(failed, true, 'invalid');
} else throw new Error('unknown test result');
}
});
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}`);
}
}
}
});
}
}