forked from tornado-packages/noble-curves
ECDH tests: quick and dirty ASN1 parsing
This commit is contained in:
parent
c19373a0b5
commit
a4abd8a202
@ -95,32 +95,43 @@ should('fields', () => {
|
|||||||
for (const n in vectors) deepStrictEqual(NIST[n].CURVE.Fp.ORDER, vectors[n]);
|
for (const n in vectors) deepStrictEqual(NIST[n].CURVE.Fp.ORDER, vectors[n]);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('wycheproof ECDH', () => {
|
// 1. We don't support ASN.1 encoding of points, so we ignore these vectors
|
||||||
for (const group of ecdh.testGroups) {
|
// 2. Overall our parser is very strict, so we ignore padded (invalid) private keys, etc.
|
||||||
const CURVE = NIST[group.curve];
|
function verifyECDHVector(test, curve) {
|
||||||
if (!CURVE) continue;
|
if (test.flags.includes('InvalidAsn')) return; // Ignore invalid ASN
|
||||||
should(group.curve, () => {
|
|
||||||
for (const test of group.tests) {
|
|
||||||
if (test.result === 'valid' || test.result === 'acceptable') {
|
if (test.result === 'valid' || test.result === 'acceptable') {
|
||||||
|
const fpLen = curve.CURVE.Fp.BYTES; // 32 for P256
|
||||||
|
const encodedHexLen = fpLen * 2 * 2 + 2; // 130 (65 * 2) for P256
|
||||||
|
const privA = test.private;
|
||||||
|
const pubB = test.public.slice(-encodedHexLen); // slice(-130) for P256
|
||||||
|
if (!curve.utils.isValidPrivateKey(privA)) return; // Ignore invalid private key size
|
||||||
try {
|
try {
|
||||||
const pub = CURVE.ProjectivePoint.fromHex(test.public);
|
curve.ProjectivePoint.fromHex(pubB);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Our strict validation filter doesn't let weird-length DER vectors
|
if (e.message.startsWith('Point of length')) return; // Ignore
|
||||||
if (e.message.startsWith('Point of length')) continue;
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
const shared = CURVE.getSharedSecret(test.private, test.public);
|
const shared = curve.getSharedSecret(privA, pubB).subarray(1);
|
||||||
deepStrictEqual(shared, test.shared, 'valid');
|
deepStrictEqual(hex(shared), test.shared, 'valid');
|
||||||
} else if (test.result === 'invalid') {
|
} else if (test.result === 'invalid') {
|
||||||
let failed = false;
|
let failed = false;
|
||||||
try {
|
try {
|
||||||
CURVE.getSharedSecret(test.private, test.public);
|
curve.getSharedSecret(test.private, test.public);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
failed = true;
|
failed = true;
|
||||||
}
|
}
|
||||||
deepStrictEqual(failed, true, 'invalid');
|
deepStrictEqual(failed, true, 'invalid');
|
||||||
} else throw new Error('unknown test result');
|
} else throw new Error('unknown test result');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
describe('wycheproof ECDH', () => {
|
||||||
|
for (const group of ecdh.testGroups) {
|
||||||
|
const curve = NIST[group.curve];
|
||||||
|
if (!curve) continue;
|
||||||
|
should(group.curve, () => {
|
||||||
|
for (const test of group.tests) {
|
||||||
|
verifyECDHVector(test, curve);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,30 +162,12 @@ describe('wycheproof ECDH', () => {
|
|||||||
for (const name in WYCHEPROOF_ECDH) {
|
for (const name in WYCHEPROOF_ECDH) {
|
||||||
const { curve, tests } = WYCHEPROOF_ECDH[name];
|
const { curve, tests } = WYCHEPROOF_ECDH[name];
|
||||||
for (let i = 0; i < tests.length; i++) {
|
for (let i = 0; i < tests.length; i++) {
|
||||||
const test = tests[i];
|
const curveTests = tests[i];
|
||||||
for (let j = 0; j < test.testGroups.length; j++) {
|
for (let j = 0; j < curveTests.testGroups.length; j++) {
|
||||||
const group = test.testGroups[j];
|
const group = curveTests.testGroups[j];
|
||||||
should(`additional ${name} (${i}/${j})`, () => {
|
should(`additional ${name} (${group.tests.length})`, () => {
|
||||||
for (const test of group.tests) {
|
for (const test of group.tests) {
|
||||||
if (test.result === 'valid' || test.result === 'acceptable') {
|
verifyECDHVector(test, curve);
|
||||||
try {
|
|
||||||
const pub = curve.ProjectivePoint.fromHex(test.public);
|
|
||||||
} catch (e) {
|
|
||||||
// Our strict validation filter doesn't let weird-length DER vectors
|
|
||||||
if (e.message.includes('Point of length')) continue;
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
const shared = curve.getSharedSecret(test.private, test.public);
|
|
||||||
deepStrictEqual(hex(shared), test.shared, 'valid');
|
|
||||||
} else if (test.result === 'invalid') {
|
|
||||||
let failed = false;
|
|
||||||
try {
|
|
||||||
curve.getSharedSecret(test.private, test.public);
|
|
||||||
} catch (error) {
|
|
||||||
failed = true;
|
|
||||||
}
|
|
||||||
deepStrictEqual(failed, true, 'invalid');
|
|
||||||
} else throw new Error('unknown test result');
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user