forked from tornado-packages/noble-curves
tests: Use describe()
This commit is contained in:
parent
5312d92b2c
commit
f4cf21b9c8
@ -31,7 +31,7 @@
|
||||
"@types/node": "18.11.3",
|
||||
"fast-check": "3.0.0",
|
||||
"micro-bmark": "0.2.0",
|
||||
"micro-should": "0.2.0",
|
||||
"micro-should": "0.3.0",
|
||||
"prettier": "2.6.2",
|
||||
"rollup": "2.75.5",
|
||||
"typescript": "4.7.3"
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { deepStrictEqual, throws } from 'assert';
|
||||
import { should } from 'micro-should';
|
||||
import { should, describe } from 'micro-should';
|
||||
import * as fc from 'fast-check';
|
||||
import * as mod from '../lib/esm/abstract/modular.js';
|
||||
import { bytesToHex as toHex } from '../lib/esm/abstract/utils.js';
|
||||
@ -62,7 +62,8 @@ for (const c in FIELDS) {
|
||||
const FC_BIGINT = curve[f][1] ? curve[f][1] : fc.bigInt(1n, Fp.ORDER - 1n);
|
||||
|
||||
const create = curve[f][2] ? curve[f][2].bind(null, Fp) : (num) => Fp.create(num);
|
||||
should(`${name} equality`, () => {
|
||||
describe(name, () => {
|
||||
should('equality', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, (num) => {
|
||||
const a = create(num);
|
||||
@ -72,7 +73,7 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
should(`${name} non-equality`, () => {
|
||||
should('non-equality', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, FC_BIGINT, (num1, num2) => {
|
||||
const a = create(num1);
|
||||
@ -82,7 +83,7 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
should(`${name} add/subtract/commutativity`, () => {
|
||||
should('add/subtract/commutativity', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, FC_BIGINT, (num1, num2) => {
|
||||
const a = create(num1);
|
||||
@ -91,7 +92,7 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
should(`${name} add/subtract/associativity`, () => {
|
||||
should('add/subtract/associativity', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, FC_BIGINT, FC_BIGINT, (num1, num2, num3) => {
|
||||
const a = create(num1);
|
||||
@ -101,7 +102,7 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
should(`${name} add/subtract/x+0=x`, () => {
|
||||
should('add/subtract/x+0=x', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, (num) => {
|
||||
const a = create(num);
|
||||
@ -109,7 +110,7 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
should(`${name} add/subtract/x-0=x`, () => {
|
||||
should('add/subtract/x-0=x', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, (num) => {
|
||||
const a = create(num);
|
||||
@ -118,7 +119,7 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
should(`${name} add/subtract/negate equality`, () => {
|
||||
should('add/subtract/negate equality', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, (num1) => {
|
||||
const a = create(num1);
|
||||
@ -129,7 +130,7 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
should(`${name} add/subtract/negate`, () => {
|
||||
should('add/subtract/negate', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, (num) => {
|
||||
const a = create(num);
|
||||
@ -138,11 +139,11 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
should(`${name} negate(0)`, () => {
|
||||
should('negate(0)', () => {
|
||||
deepStrictEqual(Fp.negate(Fp.ZERO), Fp.ZERO);
|
||||
});
|
||||
|
||||
should(`${name} multiply/commutativity`, () => {
|
||||
should('multiply/commutativity', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, FC_BIGINT, (num1, num2) => {
|
||||
const a = create(num1);
|
||||
@ -151,7 +152,7 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
should(`${name} multiply/associativity`, () => {
|
||||
should('multiply/associativity', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, FC_BIGINT, FC_BIGINT, (num1, num2, num3) => {
|
||||
const a = create(num1);
|
||||
@ -161,7 +162,7 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
should(`${name} multiply/distributivity`, () => {
|
||||
should('multiply/distributivity', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, FC_BIGINT, FC_BIGINT, (num1, num2, num3) => {
|
||||
const a = create(num1);
|
||||
@ -171,7 +172,7 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
should(`${name} multiply/add equality`, () => {
|
||||
should('multiply/add equality', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, (num) => {
|
||||
const a = create(num);
|
||||
@ -185,7 +186,7 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
should(`${name} multiply/square equality`, () => {
|
||||
should('multiply/square equality', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, (num) => {
|
||||
const a = create(num);
|
||||
@ -193,7 +194,7 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
should(`${name} multiply/pow equality`, () => {
|
||||
should('multiply/pow equality', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, (num) => {
|
||||
const a = create(num);
|
||||
@ -205,17 +206,17 @@ for (const c in FIELDS) {
|
||||
);
|
||||
});
|
||||
|
||||
should(`${name} square(0)`, () => {
|
||||
should('square(0)', () => {
|
||||
deepStrictEqual(Fp.square(Fp.ZERO), Fp.ZERO);
|
||||
deepStrictEqual(Fp.mul(Fp.ZERO, Fp.ZERO), Fp.ZERO);
|
||||
});
|
||||
|
||||
should(`${name} square(1)`, () => {
|
||||
should('square(1)', () => {
|
||||
deepStrictEqual(Fp.square(Fp.ONE), Fp.ONE);
|
||||
deepStrictEqual(Fp.mul(Fp.ONE, Fp.ONE), Fp.ONE);
|
||||
});
|
||||
|
||||
should(`${name} square(-1)`, () => {
|
||||
should('square(-1)', () => {
|
||||
const minus1 = Fp.negate(Fp.ONE);
|
||||
deepStrictEqual(Fp.square(minus1), Fp.ONE);
|
||||
deepStrictEqual(Fp.mul(minus1, minus1), Fp.ONE);
|
||||
@ -224,7 +225,7 @@ for (const c in FIELDS) {
|
||||
const isSquare = mod.FpIsSquare(Fp);
|
||||
// Not implemented
|
||||
if (Fp !== bls12_381.CURVE.Fp12) {
|
||||
should(`${name} multiply/sqrt`, () => {
|
||||
should('multiply/sqrt', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, (num) => {
|
||||
const a = create(num);
|
||||
@ -242,7 +243,7 @@ for (const c in FIELDS) {
|
||||
);
|
||||
});
|
||||
|
||||
should(`${name} sqrt(0)`, () => {
|
||||
should('sqrt(0)', () => {
|
||||
deepStrictEqual(Fp.sqrt(Fp.ZERO), Fp.ZERO);
|
||||
const sqrt1 = Fp.sqrt(Fp.ONE);
|
||||
deepStrictEqual(
|
||||
@ -253,7 +254,7 @@ for (const c in FIELDS) {
|
||||
});
|
||||
}
|
||||
|
||||
should(`${name} div/division by one equality`, () => {
|
||||
should('div/division by one equality', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, (num) => {
|
||||
const a = create(num);
|
||||
@ -263,7 +264,7 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
should(`${name} zero division equality`, () => {
|
||||
should('zero division equality', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, (num) => {
|
||||
const a = create(num);
|
||||
@ -271,7 +272,7 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
should(`${name} div/division distributivity`, () => {
|
||||
should('div/division distributivity', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, FC_BIGINT, FC_BIGINT, (num1, num2, num3) => {
|
||||
const a = create(num1);
|
||||
@ -281,7 +282,7 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
should(`${name} div/division and multiplication equality`, () => {
|
||||
should('div/division and multiplication equality', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, FC_BIGINT, (num1, num2) => {
|
||||
const a = create(num1);
|
||||
@ -290,6 +291,7 @@ for (const c in FIELDS) {
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -311,12 +313,12 @@ const NUM_RUNS = 5;
|
||||
const getXY = (p) => ({ x: p.x, y: p.y });
|
||||
|
||||
function equal(a, b, comment) {
|
||||
deepStrictEqual(a.equals(b), true, `eq(${comment})`);
|
||||
deepStrictEqual(a.equals(b), true, 'eq(${comment})');
|
||||
if (a.toAffine && b.toAffine) {
|
||||
deepStrictEqual(getXY(a.toAffine()), getXY(b.toAffine()), `eqToAffine(${comment})`);
|
||||
deepStrictEqual(getXY(a.toAffine()), getXY(b.toAffine()), 'eqToAffine(${comment})');
|
||||
} else if (!a.toAffine && !b.toAffine) {
|
||||
// Already affine
|
||||
deepStrictEqual(getXY(a), getXY(b), `eqAffine(${comment})`);
|
||||
deepStrictEqual(getXY(a), getXY(b), 'eqAffine(${comment})');
|
||||
} else throw new Error('Different point types');
|
||||
}
|
||||
|
||||
@ -341,46 +343,49 @@ for (const name in CURVES) {
|
||||
|
||||
const G = [p.ZERO, p.BASE];
|
||||
for (let i = 2; i < 10; i++) G.push(G[1].multiply(i));
|
||||
const title = `${name}/${pointName}`;
|
||||
describe(title, () => {
|
||||
describe('basic group laws', () => {
|
||||
// Here we check basic group laws, to verify that points works as group
|
||||
should(`${name}/${pointName}/Basic group laws (zero)`, () => {
|
||||
should('(zero)', () => {
|
||||
equal(G[0].double(), G[0], '(0*G).double() = 0');
|
||||
equal(G[0].add(G[0]), G[0], '0*G + 0*G = 0');
|
||||
equal(G[0].subtract(G[0]), G[0], '0*G - 0*G = 0');
|
||||
equal(G[0].negate(), G[0], '-0 = 0');
|
||||
for (let i = 0; i < G.length; i++) {
|
||||
const p = G[i];
|
||||
equal(p, p.add(G[0]), `${i}*G + 0 = ${i}*G`);
|
||||
equal(G[0].multiply(i + 1), G[0], `${i + 1}*0 = 0`);
|
||||
equal(p, p.add(G[0]), '${i}*G + 0 = ${i}*G');
|
||||
equal(G[0].multiply(i + 1), G[0], '${i + 1}*0 = 0');
|
||||
}
|
||||
});
|
||||
should(`${name}/${pointName}/Basic group laws (one)`, () => {
|
||||
should('(one)', () => {
|
||||
equal(G[1].double(), G[2], '(1*G).double() = 2*G');
|
||||
equal(G[1].subtract(G[1]), G[0], '1*G - 1*G = 0');
|
||||
equal(G[1].add(G[1]), G[2], '1*G + 1*G = 2*G');
|
||||
});
|
||||
should(`${name}/${pointName}/Basic group laws (sanity tests)`, () => {
|
||||
equal(G[2].double(), G[4], `(2*G).double() = 4*G`);
|
||||
equal(G[2].add(G[2]), G[4], `2*G + 2*G = 4*G`);
|
||||
equal(G[7].add(G[3].negate()), G[4], `7*G - 3*G = 4*G`);
|
||||
should('(sanity tests)', () => {
|
||||
equal(G[2].double(), G[4], '(2*G).double() = 4*G');
|
||||
equal(G[2].add(G[2]), G[4], '2*G + 2*G = 4*G');
|
||||
equal(G[7].add(G[3].negate()), G[4], '7*G - 3*G = 4*G');
|
||||
});
|
||||
should(`${name}/${pointName}/Basic group laws (addition commutativity)`, () => {
|
||||
equal(G[4].add(G[3]), G[3].add(G[4]), `4*G + 3*G = 3*G + 4*G`);
|
||||
equal(G[4].add(G[3]), G[3].add(G[2]).add(G[2]), `4*G + 3*G = 3*G + 2*G + 2*G`);
|
||||
should('(addition commutativity)', () => {
|
||||
equal(G[4].add(G[3]), G[3].add(G[4]), '4*G + 3*G = 3*G + 4*G');
|
||||
equal(G[4].add(G[3]), G[3].add(G[2]).add(G[2]), '4*G + 3*G = 3*G + 2*G + 2*G');
|
||||
});
|
||||
should(`${name}/${pointName}/Basic group laws (double)`, () => {
|
||||
should('(double)', () => {
|
||||
equal(G[3].double(), G[6], '(3*G).double() = 6*G');
|
||||
});
|
||||
should(`${name}/${pointName}/Basic group laws (multiply)`, () => {
|
||||
should('(multiply)', () => {
|
||||
equal(G[2].multiply(3), G[6], '(2*G).multiply(3) = 6*G');
|
||||
});
|
||||
should(`${name}/${pointName}/Basic group laws (same point addition)`, () => {
|
||||
equal(G[3].add(G[3]), G[6], `3*G + 3*G = 6*G`);
|
||||
should('(same point addition)', () => {
|
||||
equal(G[3].add(G[3]), G[6], '3*G + 3*G = 6*G');
|
||||
});
|
||||
should(`${name}/${pointName}/Basic group laws (same point (negative) addition)`, () => {
|
||||
should('(same point (negative) addition)', () => {
|
||||
equal(G[3].add(G[3].negate()), G[0], '3*G + (- 3*G) = 0*G');
|
||||
equal(G[3].subtract(G[3]), G[0], '3*G - 3*G = 0*G');
|
||||
});
|
||||
should(`${name}/${pointName}/Basic group laws (curve order)`, () => {
|
||||
should('(curve order)', () => {
|
||||
equal(G[1].multiply(CURVE_ORDER - 1n).add(G[1]), G[0], '(N-1)*G + G = 0');
|
||||
equal(G[1].multiply(CURVE_ORDER - 1n).add(G[2]), G[1], '(N-1)*G + 2*G = 1*G');
|
||||
equal(G[1].multiply(CURVE_ORDER - 2n).add(G[2]), G[0], '(N-2)*G + 2*G = 0');
|
||||
@ -388,7 +393,7 @@ for (const name in CURVES) {
|
||||
const carry = CURVE_ORDER % 2n === 1n ? G[1] : G[0];
|
||||
equal(G[1].multiply(half).double().add(carry), G[0], '((N/2) * G).double() = 0');
|
||||
});
|
||||
should(`${name}/${pointName}/Basic group laws (inversion)`, () => {
|
||||
should('(inversion)', () => {
|
||||
const a = 1234n;
|
||||
const b = 5678n;
|
||||
const c = a * b;
|
||||
@ -396,7 +401,7 @@ for (const name in CURVES) {
|
||||
const inv = mod.invert(b, CURVE_ORDER);
|
||||
equal(G[1].multiply(c).multiply(inv), G[1].multiply(a), 'c*G * (1/b)*G = a*G');
|
||||
});
|
||||
should(`${name}/${pointName}/Basic group laws (multiply, rand)`, () =>
|
||||
should('(multiply, rand)', () =>
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, FC_BIGINT, (a, b) => {
|
||||
const c = mod.mod(a + b, CURVE_ORDER);
|
||||
@ -404,27 +409,29 @@ for (const name in CURVES) {
|
||||
const pA = G[1].multiply(a);
|
||||
const pB = G[1].multiply(b);
|
||||
const pC = G[1].multiply(c);
|
||||
equal(pA.add(pB), pB.add(pA), `pA + pB = pB + pA`);
|
||||
equal(pA.add(pB), pC, `pA + pB = pC`);
|
||||
equal(pA.add(pB), pB.add(pA), 'pA + pB = pB + pA');
|
||||
equal(pA.add(pB), pC, 'pA + pB = pC');
|
||||
}),
|
||||
{ numRuns: NUM_RUNS }
|
||||
)
|
||||
);
|
||||
should(`${name}/${pointName}/Basic group laws (multiply2, rand)`, () =>
|
||||
should('(multiply2, rand)', () =>
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, FC_BIGINT, (a, b) => {
|
||||
const c = mod.mod(a * b, CURVE_ORDER);
|
||||
const pA = G[1].multiply(a);
|
||||
const pB = G[1].multiply(b);
|
||||
equal(pA.multiply(b), pB.multiply(a), `b*pA = a*pB`);
|
||||
equal(pA.multiply(b), G[1].multiply(c), `b*pA = c*G`);
|
||||
equal(pA.multiply(b), pB.multiply(a), 'b*pA = a*pB');
|
||||
equal(pA.multiply(b), G[1].multiply(c), 'b*pA = c*G');
|
||||
}),
|
||||
{ numRuns: NUM_RUNS }
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
for (const op of ['add', 'subtract']) {
|
||||
should(`${name}/${pointName}/${op} type check`, () => {
|
||||
describe(op, () => {
|
||||
should('type check', () => {
|
||||
throws(() => G[1][op](0), '0');
|
||||
throws(() => G[1][op](0n), '0n');
|
||||
G[1][op](G[2]);
|
||||
@ -432,17 +439,21 @@ for (const name in CURVES) {
|
||||
throws(() => G[1][op](123.456), '123.456');
|
||||
throws(() => G[1][op](true), 'true');
|
||||
throws(() => G[1][op]('1'), "'1'");
|
||||
throws(() => G[1][op]({ x: 1n, y: 1n, z: 1n, t: 1n }), '{ x: 1n, y: 1n, z: 1n, t: 1n }');
|
||||
throws(
|
||||
() => G[1][op]({ x: 1n, y: 1n, z: 1n, t: 1n }),
|
||||
'{ x: 1n, y: 1n, z: 1n, t: 1n }'
|
||||
);
|
||||
throws(() => G[1][op](new Uint8Array([])), 'ui8a([])');
|
||||
throws(() => G[1][op](new Uint8Array([0])), 'ui8a([0])');
|
||||
throws(() => G[1][op](new Uint8Array([1])), 'ui8a([1])');
|
||||
throws(() => G[1][op](new Uint8Array(4096).fill(1)), 'ui8a(4096*[1])');
|
||||
if (G[1].toAffine) throws(() => G[1][op](C.Point.BASE), `Point ${op} ${pointName}`);
|
||||
throws(() => G[1][op](o.BASE), `${op}/other curve point`);
|
||||
if (G[1].toAffine) throws(() => G[1][op](C.Point.BASE), 'Point ${op} ${pointName}');
|
||||
throws(() => G[1][op](o.BASE), '${op}/other curve point');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
should(`${name}/${pointName}/equals type check`, () => {
|
||||
should('equals type check', () => {
|
||||
throws(() => G[1].equals(0), '0');
|
||||
throws(() => G[1].equals(0n), '0n');
|
||||
deepStrictEqual(G[1].equals(G[2]), false, '1*G != 2*G');
|
||||
@ -457,13 +468,14 @@ for (const name in CURVES) {
|
||||
throws(() => G[1].equals(new Uint8Array([0])), 'ui8a([0])');
|
||||
throws(() => G[1].equals(new Uint8Array([1])), 'ui8a([1])');
|
||||
throws(() => G[1].equals(new Uint8Array(4096).fill(1)), 'ui8a(4096*[1])');
|
||||
if (G[1].toAffine) throws(() => G[1].equals(C.Point.BASE), `Point.equals(${pointName})`);
|
||||
if (G[1].toAffine) throws(() => G[1].equals(C.Point.BASE), 'Point.equals(${pointName})');
|
||||
throws(() => G[1].equals(o.BASE), 'other curve point');
|
||||
});
|
||||
|
||||
for (const op of ['multiply', 'multiplyUnsafe']) {
|
||||
if (!p.BASE[op]) continue;
|
||||
should(`${name}/${pointName}/${op} type check`, () => {
|
||||
describe(op, () => {
|
||||
should('type check', () => {
|
||||
if (op !== 'multiplyUnsafe') {
|
||||
throws(() => G[1][op](0), '0');
|
||||
throws(() => G[1][op](0n), '0n');
|
||||
@ -482,23 +494,24 @@ for (const name in CURVES) {
|
||||
throws(() => G[1][op](new Uint8Array(4096).fill(1)), 'ui8a(4096*[1])');
|
||||
throws(() => G[1][op](o.BASE), 'other curve point');
|
||||
});
|
||||
});
|
||||
}
|
||||
// Complex point (Extended/Jacobian/Projective?)
|
||||
if (p.BASE.toAffine) {
|
||||
should(`${name}/${pointName}/toAffine()`, () => {
|
||||
equal(p.ZERO.toAffine(), C.Point.ZERO, `0 = 0`);
|
||||
equal(p.BASE.toAffine(), C.Point.BASE, `1 = 1`);
|
||||
should('toAffine()', () => {
|
||||
equal(p.ZERO.toAffine(), C.Point.ZERO, '0 = 0');
|
||||
equal(p.BASE.toAffine(), C.Point.BASE, '1 = 1');
|
||||
});
|
||||
}
|
||||
if (p.fromAffine) {
|
||||
should(`${name}/${pointName}/fromAffine()`, () => {
|
||||
equal(p.ZERO, p.fromAffine(C.Point.ZERO), `0 = 0`);
|
||||
equal(p.BASE, p.fromAffine(C.Point.BASE), `1 = 1`);
|
||||
should('fromAffine()', () => {
|
||||
equal(p.ZERO, p.fromAffine(C.Point.ZERO), '0 = 0');
|
||||
equal(p.BASE, p.fromAffine(C.Point.BASE), '1 = 1');
|
||||
});
|
||||
}
|
||||
// toHex/fromHex (if available)
|
||||
if (p.fromHex && p.BASE.toHex) {
|
||||
should(`${name}/${pointName}/fromHex(toHex()) roundtrip`, () => {
|
||||
should('fromHex(toHex()) roundtrip', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, (x) => {
|
||||
const hex = p.BASE.multiply(x).toHex();
|
||||
@ -507,9 +520,11 @@ for (const name in CURVES) {
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
describe(name, () => {
|
||||
// Generic complex things (getPublicKey/sign/verify/getSharedSecret)
|
||||
should(`${name}/getPublicKey type check`, () => {
|
||||
should('getPublicKey type check', () => {
|
||||
throws(() => C.getPublicKey(0), '0');
|
||||
throws(() => C.getPublicKey(0n), '0n');
|
||||
throws(() => C.getPublicKey(false), 'false');
|
||||
@ -524,7 +539,7 @@ for (const name in CURVES) {
|
||||
throws(() => C.getPublicKey(new Uint8Array([1])));
|
||||
throws(() => C.getPublicKey(new Uint8Array(4096).fill(1)));
|
||||
});
|
||||
should(`${name}.verify()/should verify random signatures`, () =>
|
||||
should('.verify() should verify random signatures', () =>
|
||||
fc.assert(
|
||||
fc.property(fc.hexaString({ minLength: 64, maxLength: 64 }), (msg) => {
|
||||
const priv = C.utils.randomPrivateKey();
|
||||
@ -533,18 +548,18 @@ for (const name in CURVES) {
|
||||
deepStrictEqual(
|
||||
C.verify(sig, msg, pub),
|
||||
true,
|
||||
`priv=${toHex(priv)},pub=${toHex(pub)},msg=${msg}`
|
||||
'priv=${toHex(priv)},pub=${toHex(pub)},msg=${msg}'
|
||||
);
|
||||
}),
|
||||
{ numRuns: NUM_RUNS }
|
||||
)
|
||||
);
|
||||
should(`${name}.sign()/edge cases`, () => {
|
||||
should('.sign() edge cases', () => {
|
||||
throws(() => C.sign());
|
||||
throws(() => C.sign(''));
|
||||
});
|
||||
|
||||
should(`${name}.verify()/should not verify signature with wrong hash`, () => {
|
||||
should('.verify() should not verify signature with wrong hash', () => {
|
||||
const MSG = '01'.repeat(32);
|
||||
const PRIV_KEY = 0x2n;
|
||||
const WRONG_MSG = '11'.repeat(32);
|
||||
@ -554,7 +569,7 @@ for (const name in CURVES) {
|
||||
});
|
||||
// NOTE: fails for ed, because of empty message. Since we convert it to scalar,
|
||||
// need to check what other implementations do. Empty message != new Uint8Array([0]), but what scalar should be in that case?
|
||||
// should(`${name}/should not verify signature with wrong message`, () => {
|
||||
// should('should not verify signature with wrong message', () => {
|
||||
// fc.assert(
|
||||
// fc.property(
|
||||
// fc.array(fc.integer({ min: 0x00, max: 0xff })),
|
||||
@ -576,7 +591,7 @@ for (const name in CURVES) {
|
||||
// });
|
||||
|
||||
if (C.getSharedSecret) {
|
||||
should(`${name}/getSharedSecret() should be commutative`, () => {
|
||||
should('getSharedSecret() should be commutative', () => {
|
||||
for (let i = 0; i < NUM_RUNS; i++) {
|
||||
const asec = C.utils.randomPrivateKey();
|
||||
const apub = C.getPublicKey(asec);
|
||||
@ -591,6 +606,7 @@ for (const name in CURVES) {
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
should('secp224k1 sqrt bug', () => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { bls12_381 } from '../lib/esm/bls12-381.js';
|
||||
import { should } from 'micro-should';
|
||||
import { describe, should } from 'micro-should';
|
||||
import { deepStrictEqual, notDeepStrictEqual, throws } from 'assert';
|
||||
import { sha512 } from '@noble/hashes/sha512';
|
||||
import * as fc from 'fast-check';
|
||||
@ -38,11 +38,11 @@ const B_384_40 = '40'.padEnd(384, '0'); // [0x40, 0, 0...]
|
||||
const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
|
||||
// Fp
|
||||
{
|
||||
describe('bls12-381 Fp', () => {
|
||||
const Fp = bls.Fp;
|
||||
const FC_BIGINT = fc.bigInt(1n, Fp.ORDER - 1n);
|
||||
|
||||
should('bls12-381/Fp/multiply/sqrt', () => {
|
||||
should('multiply/sqrt', () => {
|
||||
let sqr1 = Fp.sqrt(Fp.create(300855555557n));
|
||||
deepStrictEqual(
|
||||
sqr1 && sqr1.toString(),
|
||||
@ -50,16 +50,16 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
);
|
||||
throws(() => Fp.sqrt(Fp.create(72057594037927816n)));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Fp2
|
||||
{
|
||||
describe('bls12-381 Fp2', () => {
|
||||
const Fp = bls.Fp;
|
||||
const Fp2 = bls.Fp2;
|
||||
const FC_BIGINT = fc.bigInt(1n, Fp.ORDER - 1n);
|
||||
const FC_BIGINT_2 = fc.array(FC_BIGINT, { minLength: 2, maxLength: 2 });
|
||||
|
||||
should('bls12-381 Fp2/non-equality', () => {
|
||||
should('non-equality', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT_2, FC_BIGINT_2, (num1, num2) => {
|
||||
const a = Fp2.fromBigTuple([num1[0], num1[1]]);
|
||||
@ -70,7 +70,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
);
|
||||
});
|
||||
|
||||
should('bls12-381 Fp2/div/x/1=x', () => {
|
||||
should('div/x/1=x', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT_2, (num) => {
|
||||
const a = Fp2.fromBigTuple([num[0], num[1]]);
|
||||
@ -81,7 +81,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
);
|
||||
});
|
||||
|
||||
should('bls12-381 Fp2/frobenius', () => {
|
||||
should('frobenius', () => {
|
||||
// expect(Fp2.FROBENIUS_COEFFICIENTS[0].equals(Fp.ONE)).toBe(true);
|
||||
// expect(
|
||||
// Fp2.FROBENIUS_COEFFICIENTS[1].equals(
|
||||
@ -139,16 +139,17 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
true
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Point
|
||||
{
|
||||
describe('bls12-381 Point', () => {
|
||||
const Fp = bls.Fp;
|
||||
const FC_BIGINT = fc.bigInt(1n, Fp.ORDER - 1n);
|
||||
const PointG1 = bls.G1.Point;
|
||||
const PointG2 = bls.G2.Point;
|
||||
|
||||
should('bls12-381 Point/Point with Fp coordinates/Point equality', () => {
|
||||
describe('with Fp coordinates', () => {
|
||||
should('Point equality', () => {
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.array(FC_BIGINT, { minLength: 3, maxLength: 3 }),
|
||||
@ -164,16 +165,16 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
)
|
||||
);
|
||||
});
|
||||
should('bls12-381 Point/Point with Fp coordinates/should be placed on curve vector 1', () => {
|
||||
should('be placed on curve vector 1', () => {
|
||||
const a = new PointG1(Fp.create(0n), Fp.create(0n));
|
||||
a.assertValidity();
|
||||
});
|
||||
should('bls12-381 Point/Point with Fp coordinates/should not be placed on curve vector 1', () => {
|
||||
should('not be placed on curve vector 1', () => {
|
||||
const a = new PointG1(Fp.create(0n), Fp.create(1n));
|
||||
throws(() => a.assertValidity());
|
||||
});
|
||||
|
||||
should('bls12-381 Point/Point with Fp coordinates/should be placed on curve vector 2', () => {
|
||||
should('be placed on curve vector 2', () => {
|
||||
const a = new PointG1(
|
||||
Fp.create(
|
||||
0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bbn
|
||||
@ -184,7 +185,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
);
|
||||
a.assertValidity();
|
||||
});
|
||||
should('bls12-381 Point/Point with Fp coordinates/should be placed on curve vector 3', () => {
|
||||
should('be placed on curve vector 3', () => {
|
||||
const a = new PointG1(
|
||||
Fp.create(
|
||||
3971675556538908004130084773503021351583407620890695272226385332452194486153316625183061567093226342405194446632851n
|
||||
@ -196,7 +197,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
|
||||
a.assertValidity();
|
||||
});
|
||||
should('bls12-381 Point/Point with Fp coordinates/should not be placed on curve vector 3', () => {
|
||||
should('not be placed on curve vector 3', () => {
|
||||
const a = new PointG1(
|
||||
Fp.create(
|
||||
622186380008502900120948444810967255157373993223369845903602988014033704418470621816206856882891545628885272576827n
|
||||
@ -207,7 +208,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
);
|
||||
throws(() => a.assertValidity());
|
||||
});
|
||||
should('bls12-381 Point/Point with Fp coordinates/should not be placed on curve vector 2', () => {
|
||||
should('not be placed on curve vector 2', () => {
|
||||
const a = new PointG1(
|
||||
Fp.create(
|
||||
0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6ban
|
||||
@ -219,9 +220,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
throws(() => a.assertValidity());
|
||||
});
|
||||
|
||||
should(
|
||||
'bls12-381 Point/Point with Fp coordinates/should be doubled and placed on curve vector 1',
|
||||
() => {
|
||||
should('be doubled and placed on curve vector 1', () => {
|
||||
const a = new PointG1(
|
||||
Fp.create(
|
||||
0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bbn
|
||||
@ -245,11 +244,8 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
);
|
||||
deepStrictEqual(double, a.multiply(2n));
|
||||
deepStrictEqual(double, a.add(a));
|
||||
}
|
||||
);
|
||||
should(
|
||||
'bls12-381 Point/Point with Fp coordinates/should be pdoubled and placed on curve vector 2',
|
||||
() => {
|
||||
});
|
||||
should('be pdoubled and placed on curve vector 2', () => {
|
||||
const a = new PointG1(
|
||||
Fp.create(
|
||||
3971675556538908004130084773503021351583407620890695272226385332452194486153316625183061567093226342405194446632851n
|
||||
@ -273,9 +269,8 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
);
|
||||
deepStrictEqual(double, a.multiply(2n));
|
||||
deepStrictEqual(double, a.add(a));
|
||||
}
|
||||
);
|
||||
should('bls12-381 Point/Point with Fp coordinates/should not validate incorrect point', () => {
|
||||
});
|
||||
should('not validate incorrect point', () => {
|
||||
const x =
|
||||
499001545268060011619089734015590154568173930614466321429631711131511181286230338880376679848890024401335766847607n;
|
||||
const y =
|
||||
@ -284,8 +279,10 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
const p = new PointG1(Fp.create(x), Fp.create(y));
|
||||
throws(() => p.assertValidity());
|
||||
});
|
||||
});
|
||||
|
||||
should('bls12-381 Point/Point with Fp2 coordinates/Point equality', () => {
|
||||
describe('with Fp2 coordinates', () => {
|
||||
should('Point equality', () => {
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.array(fc.array(FC_BIGINT, { minLength: 2, maxLength: 2 }), {
|
||||
@ -297,8 +294,16 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
maxLength: 3,
|
||||
}),
|
||||
([x1, y1, z1], [x2, y2, z2]) => {
|
||||
const p1 = new PointG2(Fp2.fromBigTuple(x1), Fp2.fromBigTuple(y1), Fp2.fromBigTuple(z1));
|
||||
const p2 = new PointG2(Fp2.fromBigTuple(x2), Fp2.fromBigTuple(y2), Fp2.fromBigTuple(z2));
|
||||
const p1 = new PointG2(
|
||||
Fp2.fromBigTuple(x1),
|
||||
Fp2.fromBigTuple(y1),
|
||||
Fp2.fromBigTuple(z1)
|
||||
);
|
||||
const p2 = new PointG2(
|
||||
Fp2.fromBigTuple(x2),
|
||||
Fp2.fromBigTuple(y2),
|
||||
Fp2.fromBigTuple(z2)
|
||||
);
|
||||
deepStrictEqual(p1.equals(p1), true);
|
||||
deepStrictEqual(p2.equals(p2), true);
|
||||
deepStrictEqual(p1.equals(p2), false);
|
||||
@ -307,11 +312,11 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
)
|
||||
);
|
||||
});
|
||||
// should('bls12-381 Point/Point with Fp2 coordinates/should be placed on curve vector 1', () => {
|
||||
// should('be placed on curve vector 1', () => {
|
||||
// const a = new PointG2(Fp2.fromBigTuple([0n, 0n]), Fp2.fromBigTuple([0n, 0n]));
|
||||
// a.assertValidity();
|
||||
// });
|
||||
should('bls12-381 Point/Point with Fp2 coordinates/should be placed on curve vector 2', () => {
|
||||
should('be placed on curve vector 2', () => {
|
||||
const a = new PointG2(
|
||||
Fp2.fromBigTuple([
|
||||
0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8n,
|
||||
@ -325,7 +330,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
);
|
||||
a.assertValidity();
|
||||
});
|
||||
should('bls12-381 Point/Point with Fp2 coordinates/should be placed on curve vector 3', () => {
|
||||
should('be placed on curve vector 3', () => {
|
||||
const a = new PointG2(
|
||||
Fp2.fromBigTuple([
|
||||
233289878585407360737561818812172281900488265436962145913969074168503452745466655442125797664134009339799716079103n,
|
||||
@ -338,20 +343,15 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
);
|
||||
a.assertValidity();
|
||||
});
|
||||
should(
|
||||
'bls12-381 Point/Point with Fp2 coordinates/should not be placed on curve vector 1',
|
||||
() => {
|
||||
should('not be placed on curve vector 1', () => {
|
||||
const a = new PointG2(
|
||||
Fp2.fromBigTuple([0n, 0n]),
|
||||
Fp2.fromBigTuple([1n, 0n]),
|
||||
Fp2.fromBigTuple([1n, 0n])
|
||||
);
|
||||
throws(() => a.assertValidity());
|
||||
}
|
||||
);
|
||||
should(
|
||||
'bls12-381 Point/Point with Fp2 coordinates/should not be placed on curve vector 2',
|
||||
() => {
|
||||
});
|
||||
should('not be placed on curve vector 2', () => {
|
||||
const a = new PointG2(
|
||||
Fp2.fromBigTuple([
|
||||
0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4410b647ae3d1770bac0326a805bbefd48056c8c121bdb8n,
|
||||
@ -364,11 +364,8 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
Fp2.fromBigTuple([1n, 0n])
|
||||
);
|
||||
throws(() => a.assertValidity());
|
||||
}
|
||||
);
|
||||
should(
|
||||
'bls12-381 Point/Point with Fp2 coordinates/should not be placed on curve vector 3',
|
||||
() => {
|
||||
});
|
||||
should('not be placed on curve vector 3', () => {
|
||||
const a = new PointG2(
|
||||
Fp2.fromBigTuple([
|
||||
0x877d52dd65245f8908a03288adcd396f489ef87ae23fe110c5aa48bc208fbd1a0ed403df5b1ac137922b915f1f38ec37n,
|
||||
@ -384,10 +381,10 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
])
|
||||
);
|
||||
throws(() => a.assertValidity());
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
should('bls12-381 Point/should be doubled and placed on curve vector 1', () => {
|
||||
should('be doubled and placed on curve vector 1', () => {
|
||||
const a = new PointG2(
|
||||
Fp2.fromBigTuple([
|
||||
0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8n,
|
||||
@ -417,7 +414,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
deepStrictEqual(double, a.multiply(2n));
|
||||
deepStrictEqual(double, a.add(a));
|
||||
});
|
||||
should('bls12-381 Point/should be doubled and placed on curve vector 2', () => {
|
||||
should('be doubled and placed on curve vector 2', () => {
|
||||
const a = new PointG2(
|
||||
Fp2.fromBigTuple([
|
||||
233289878585407360737561818812172281900488265436962145913969074168503452745466655442125797664134009339799716079103n,
|
||||
@ -455,49 +452,51 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
0x53eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001n,
|
||||
0x63eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000n,
|
||||
];
|
||||
should('bls12-381 Point/wNAF multiplication same as unsafe (G1, W=1)', () => {
|
||||
describe('wNAF multiplication same as unsafe', () => {
|
||||
should('(G1, W=1)', () => {
|
||||
let G = PointG1.BASE.negate().negate(); // create new point
|
||||
G._setWindowSize(1);
|
||||
for (let k of wNAF_VECTORS) {
|
||||
deepStrictEqual(G.multiply(k).equals(G.multiplyUnsafe(k)), true);
|
||||
}
|
||||
});
|
||||
should('bls12-381 Point/wNAF multiplication same as unsafe (G1, W=4)', () => {
|
||||
should('(G1, W=4)', () => {
|
||||
let G = PointG1.BASE.negate().negate();
|
||||
G._setWindowSize(4);
|
||||
for (let k of wNAF_VECTORS) {
|
||||
deepStrictEqual(G.multiply(k).equals(G.multiplyUnsafe(k)), true);
|
||||
}
|
||||
});
|
||||
should('bls12-381 Point/wNAF multiplication same as unsafe (G1, W=5)', () => {
|
||||
should('(G1, W=5)', () => {
|
||||
let G = PointG1.BASE.negate().negate();
|
||||
G._setWindowSize(5);
|
||||
for (let k of wNAF_VECTORS) {
|
||||
deepStrictEqual(G.multiply(k).equals(G.multiplyUnsafe(k)), true);
|
||||
}
|
||||
});
|
||||
should('bls12-381 Point/wNAF multiplication same as unsafe (G2, W=1)', () => {
|
||||
should('(G2, W=1)', () => {
|
||||
let G = PointG2.BASE.negate().negate();
|
||||
G._setWindowSize(1);
|
||||
for (let k of wNAF_VECTORS) {
|
||||
deepStrictEqual(G.multiply(k).equals(G.multiplyUnsafe(k)), true);
|
||||
}
|
||||
});
|
||||
should('bls12-381 Point/wNAF multiplication same as unsafe (G2, W=4)', () => {
|
||||
should('(G2, W=4)', () => {
|
||||
let G = PointG2.BASE.negate().negate();
|
||||
G._setWindowSize(4);
|
||||
for (let k of wNAF_VECTORS) {
|
||||
deepStrictEqual(G.multiply(k).equals(G.multiplyUnsafe(k)), true);
|
||||
}
|
||||
});
|
||||
should('bls12-381 Point/wNAF multiplication same as unsafe (G2, W=5)', () => {
|
||||
should('(G2, W=5)', () => {
|
||||
let G = PointG2.BASE.negate().negate();
|
||||
G._setWindowSize(5);
|
||||
for (let k of wNAF_VECTORS) {
|
||||
deepStrictEqual(G.multiply(k).equals(G.multiplyUnsafe(k)), true);
|
||||
}
|
||||
});
|
||||
should('bls12-381 Point/PSI cofactor cleaning same as multiplication', () => {
|
||||
});
|
||||
should('PSI cofactor cleaning same as multiplication', () => {
|
||||
const points = [
|
||||
new PointG2(
|
||||
Fp2.fromBigTuple([
|
||||
@ -558,14 +557,15 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
|
||||
deepStrictEqual(ours.equals(shouldBe), true, 'clearLast');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// index.ts
|
||||
|
||||
// bls.PointG1.BASE.clearMultiplyPrecomputes();
|
||||
// bls.PointG1.BASE.calcMultiplyPrecomputes(4);
|
||||
|
||||
should('bls12-381/basic/should construct point G1 from its uncompressed form (Raw Bytes)', () => {
|
||||
describe('bls12-381/basic', () => {
|
||||
should('construct point G1 from its uncompressed form (Raw Bytes)', () => {
|
||||
// Test Zero
|
||||
const g1 = bls.G1.Point.fromHex(B_192_40);
|
||||
deepStrictEqual(g1.x, bls.G1.Point.ZERO.x);
|
||||
@ -590,7 +590,7 @@ should('bls12-381/basic/should construct point G1 from its uncompressed form (Ra
|
||||
deepStrictEqual(g1_.y, y);
|
||||
});
|
||||
|
||||
should('bls12-381/basic/should construct point G1 from its uncompressed form (Hex)', () => {
|
||||
should('construct point G1 from its uncompressed form (Hex)', () => {
|
||||
// Test Zero
|
||||
const g1 = bls.G1.Point.fromHex(B_192_40);
|
||||
|
||||
@ -616,7 +616,7 @@ should('bls12-381/basic/should construct point G1 from its uncompressed form (He
|
||||
deepStrictEqual(g1_.y, y);
|
||||
});
|
||||
|
||||
should('bls12-381/basic/should construct point G2 from its uncompressed form (Raw Bytes)', () => {
|
||||
should('construct point G2 from its uncompressed form (Raw Bytes)', () => {
|
||||
// Test Zero
|
||||
const g2 = bls.G2.Point.fromHex(B_384_40);
|
||||
deepStrictEqual(g2.x, bls.G2.Point.ZERO.x, 'zero(x)');
|
||||
@ -647,7 +647,7 @@ should('bls12-381/basic/should construct point G2 from its uncompressed form (Ra
|
||||
deepStrictEqual(g2_.y, y);
|
||||
});
|
||||
|
||||
should('bls12-381/basic/should construct point G2 from its uncompressed form (Hex)', () => {
|
||||
should('construct point G2 from its uncompressed form (Hex)', () => {
|
||||
// Test Zero
|
||||
const g2 = bls.G2.Point.fromHex(B_384_40);
|
||||
|
||||
@ -679,7 +679,7 @@ should('bls12-381/basic/should construct point G2 from its uncompressed form (He
|
||||
deepStrictEqual(g2_.y, y);
|
||||
});
|
||||
|
||||
should('bls12-381/basic/should get uncompressed form of point G1 (Raw Bytes)', () => {
|
||||
should('get uncompressed form of point G1 (Raw Bytes)', () => {
|
||||
// Test Zero
|
||||
deepStrictEqual(bls.G1.Point.ZERO.toHex(false), B_192_40);
|
||||
// Test Non-Zero
|
||||
@ -700,7 +700,7 @@ should('bls12-381/basic/should get uncompressed form of point G1 (Raw Bytes)', (
|
||||
);
|
||||
});
|
||||
|
||||
should('bls12-381/basic/should get uncompressed form of point G1 (Hex)', () => {
|
||||
should('get uncompressed form of point G1 (Hex)', () => {
|
||||
// Test Zero
|
||||
deepStrictEqual(bls.G1.Point.ZERO.toHex(false), B_192_40);
|
||||
// Test Non-Zero
|
||||
@ -721,7 +721,7 @@ should('bls12-381/basic/should get uncompressed form of point G1 (Hex)', () => {
|
||||
);
|
||||
});
|
||||
|
||||
should('bls12-381/basic/should get uncompressed form of point G2 (Raw Bytes)', () => {
|
||||
should('get uncompressed form of point G2 (Raw Bytes)', () => {
|
||||
// Test Zero
|
||||
deepStrictEqual(bls.G2.Point.ZERO.toHex(false), B_384_40);
|
||||
// Test Non-Zero
|
||||
@ -748,7 +748,7 @@ should('bls12-381/basic/should get uncompressed form of point G2 (Raw Bytes)', (
|
||||
);
|
||||
});
|
||||
|
||||
should('bls12-381/basic/should get uncompressed form of point G2 (Hex)', () => {
|
||||
should('get uncompressed form of point G2 (Hex)', () => {
|
||||
// Test Zero
|
||||
deepStrictEqual(bls.G2.Point.ZERO.toHex(false), B_384_40);
|
||||
|
||||
@ -776,22 +776,22 @@ should('bls12-381/basic/should get uncompressed form of point G2 (Hex)', () => {
|
||||
);
|
||||
});
|
||||
|
||||
should('bls12-381/basic/should compress and decompress G1 points', async () => {
|
||||
should('compress and decompress G1 points', async () => {
|
||||
const priv = bls.G1.Point.fromPrivateKey(42n);
|
||||
const publicKey = priv.toHex(true);
|
||||
const decomp = bls.G1.Point.fromHex(publicKey);
|
||||
deepStrictEqual(publicKey, decomp.toHex(true));
|
||||
});
|
||||
should('bls12-381/basic/should not compress and decompress zero G1 point', () => {
|
||||
should('not compress and decompress zero G1 point', () => {
|
||||
throws(() => bls.G1.Point.fromPrivateKey(0n));
|
||||
});
|
||||
should('bls12-381/basic/should compress and decompress G2 points', () => {
|
||||
should('compress and decompress G2 points', () => {
|
||||
const priv = bls.G2.Point.fromPrivateKey(42n);
|
||||
const publicKey = priv.toHex(true);
|
||||
const decomp = bls.G2.Point.fromHex(publicKey);
|
||||
deepStrictEqual(publicKey, decomp.toHex(true));
|
||||
});
|
||||
should('bls12-381/basic/should not compress and decompress zero G2 point', () => {
|
||||
should('not compress and decompress zero G2 point', () => {
|
||||
throws(() => bls.G2.Point.fromPrivateKey(0n));
|
||||
});
|
||||
const VALID_G1 = new bls.G1.Point(
|
||||
@ -820,7 +820,7 @@ const INVALID_G1 = new bls.G1.Point(
|
||||
)
|
||||
);
|
||||
|
||||
should('bls12-381/basic/should aggregate pubkeys', () => {
|
||||
should('aggregate pubkeys', () => {
|
||||
const agg = bls.aggregatePublicKeys([VALID_G1, VALID_G1_2]);
|
||||
deepStrictEqual(
|
||||
agg.x,
|
||||
@ -832,19 +832,19 @@ should('bls12-381/basic/should aggregate pubkeys', () => {
|
||||
);
|
||||
});
|
||||
|
||||
should('bls12-381/basic/should not aggregate invalid pubkeys', () => {
|
||||
should('not aggregate invalid pubkeys', () => {
|
||||
throws(() => bls.aggregatePublicKeys([VALID_G1, INVALID_G1]));
|
||||
});
|
||||
// should aggregate signatures
|
||||
|
||||
should(`should produce correct signatures (${G2_VECTORS.length} vectors)`, async () => {
|
||||
should(`produce correct signatures (${G2_VECTORS.length} vectors)`, async () => {
|
||||
for (let vector of G2_VECTORS) {
|
||||
const [priv, msg, expected] = vector;
|
||||
const sig = await bls.sign(msg, priv);
|
||||
deepStrictEqual(bls.utils.bytesToHex(sig), expected);
|
||||
}
|
||||
});
|
||||
should(`should produce correct scalars (${SCALAR_VECTORS.length} vectors)`, async () => {
|
||||
should(`produce correct scalars (${SCALAR_VECTORS.length} vectors)`, async () => {
|
||||
const options = {
|
||||
p: bls.CURVE.r,
|
||||
m: 1,
|
||||
@ -858,7 +858,7 @@ should(`should produce correct scalars (${SCALAR_VECTORS.length} vectors)`, asyn
|
||||
deepStrictEqual(scalars[0][0], expected);
|
||||
}
|
||||
});
|
||||
should('bls12-381/basic/should verify signed message', async () => {
|
||||
should('verify signed message', async () => {
|
||||
for (let i = 0; i < NUM_RUNS; i++) {
|
||||
const [priv, msg] = G2_VECTORS[i];
|
||||
const sig = await bls.sign(msg, priv);
|
||||
@ -867,7 +867,7 @@ should('bls12-381/basic/should verify signed message', async () => {
|
||||
deepStrictEqual(res, true);
|
||||
}
|
||||
});
|
||||
should('bls12-381/basic/should not verify signature with wrong message', async () => {
|
||||
should('not verify signature with wrong message', async () => {
|
||||
for (let i = 0; i < NUM_RUNS; i++) {
|
||||
const [priv, msg] = G2_VECTORS[i];
|
||||
const invMsg = G2_VECTORS[i + 1][1];
|
||||
@ -877,7 +877,7 @@ should('bls12-381/basic/should not verify signature with wrong message', async (
|
||||
deepStrictEqual(res, false);
|
||||
}
|
||||
});
|
||||
should('bls12-381/basic/should not verify signature with wrong key', async () => {
|
||||
should('not verify signature with wrong key', async () => {
|
||||
for (let i = 0; i < NUM_RUNS; i++) {
|
||||
const [priv, msg] = G2_VECTORS[i];
|
||||
const sig = await bls.sign(msg, priv);
|
||||
@ -887,7 +887,7 @@ should('bls12-381/basic/should not verify signature with wrong key', async () =>
|
||||
deepStrictEqual(res, false);
|
||||
}
|
||||
});
|
||||
should('bls12-381/basic/should verify multi-signature', async () => {
|
||||
should('verify multi-signature', async () => {
|
||||
await fc.assert(
|
||||
fc.asyncProperty(FC_MSG_5, FC_BIGINT_5, async (messages, privateKeys) => {
|
||||
privateKeys = privateKeys.slice(0, messages.length);
|
||||
@ -901,7 +901,7 @@ should('bls12-381/basic/should verify multi-signature', async () => {
|
||||
})
|
||||
);
|
||||
});
|
||||
should('bls12-381/basic/should batch verify multi-signatures', async () => {
|
||||
should('batch verify multi-signatures', async () => {
|
||||
await fc.assert(
|
||||
fc.asyncProperty(
|
||||
FC_MSG_5,
|
||||
@ -926,7 +926,7 @@ should('bls12-381/basic/should batch verify multi-signatures', async () => {
|
||||
)
|
||||
);
|
||||
});
|
||||
should('bls12-381/basic/should not verify multi-signature with wrong public keys', async () => {
|
||||
should('not verify multi-signature with wrong public keys', async () => {
|
||||
await fc.assert(
|
||||
fc.asyncProperty(
|
||||
FC_MSG_5,
|
||||
@ -951,7 +951,7 @@ should('bls12-381/basic/should not verify multi-signature with wrong public keys
|
||||
)
|
||||
);
|
||||
});
|
||||
should('bls12-381/basic/should verify multi-signature as simple signature', async () => {
|
||||
should('verify multi-signature as simple signature', async () => {
|
||||
await fc.assert(
|
||||
fc.asyncProperty(FC_MSG, FC_BIGINT_5, async (message, privateKeys) => {
|
||||
const publicKey = await Promise.all(privateKeys.map(getPubKey));
|
||||
@ -964,7 +964,7 @@ should('bls12-381/basic/should verify multi-signature as simple signature', asyn
|
||||
})
|
||||
);
|
||||
});
|
||||
should('bls12-381/basic/should not verify wrong multi-signature as simple signature', async () => {
|
||||
should('not verify wrong multi-signature as simple signature', async () => {
|
||||
await fc.assert(
|
||||
fc.asyncProperty(FC_MSG, FC_MSG, FC_BIGINT_5, async (message, wrongMessage, privateKeys) => {
|
||||
const publicKey = await Promise.all(privateKeys.map(getPubKey));
|
||||
@ -980,34 +980,35 @@ should('bls12-381/basic/should not verify wrong multi-signature as simple signat
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// Pairing
|
||||
{
|
||||
describe('pairing', () => {
|
||||
const { pairing, Fp12 } = bls;
|
||||
const G1 = bls.G1.Point.BASE;
|
||||
const G2 = bls.G2.Point.BASE;
|
||||
|
||||
should('pairing/creates negative G1 pairing', () => {
|
||||
should('creates negative G1 pairing', () => {
|
||||
const p1 = pairing(G1, G2);
|
||||
const p2 = pairing(G1.negate(), G2);
|
||||
deepStrictEqual(Fp12.mul(p1, p2), Fp12.ONE);
|
||||
});
|
||||
should('pairing/creates negative G2 pairing', () => {
|
||||
should('creates negative G2 pairing', () => {
|
||||
const p2 = pairing(G1.negate(), G2);
|
||||
const p3 = pairing(G1, G2.negate());
|
||||
deepStrictEqual(p2, p3);
|
||||
});
|
||||
should('pairing/creates proper pairing output order', () => {
|
||||
should('creates proper pairing output order', () => {
|
||||
const p1 = pairing(G1, G2);
|
||||
const p2 = Fp12.pow(p1, CURVE_ORDER);
|
||||
deepStrictEqual(p2, Fp12.ONE);
|
||||
});
|
||||
should('pairing/G1 billinearity', () => {
|
||||
should('G1 billinearity', () => {
|
||||
const p1 = pairing(G1, G2);
|
||||
const p2 = pairing(G1.multiply(2n), G2);
|
||||
deepStrictEqual(Fp12.mul(p1, p1), p2);
|
||||
});
|
||||
should('pairing/should not degenerate', () => {
|
||||
should('should not degenerate', () => {
|
||||
const p1 = pairing(G1, G2);
|
||||
const p2 = pairing(G1.multiply(2n), G2);
|
||||
const p3 = pairing(G1, G2.negate());
|
||||
@ -1015,17 +1016,17 @@ should('bls12-381/basic/should not verify wrong multi-signature as simple signat
|
||||
notDeepStrictEqual(p1, p3);
|
||||
notDeepStrictEqual(p2, p3);
|
||||
});
|
||||
should('pairing/G2 billinearity', () => {
|
||||
should('G2 billinearity', () => {
|
||||
const p1 = pairing(G1, G2);
|
||||
const p2 = pairing(G1, G2.multiply(2n));
|
||||
deepStrictEqual(Fp12.mul(p1, p1), p2);
|
||||
});
|
||||
should('pairing/proper pairing composite check', () => {
|
||||
should('proper pairing composite check', () => {
|
||||
const p1 = pairing(G1.multiply(37n), G2.multiply(27n));
|
||||
const p2 = pairing(G1.multiply(999n), G2);
|
||||
deepStrictEqual(p1, p2);
|
||||
});
|
||||
should('pairing/vectors from https://github.com/zkcrypto/pairing', () => {
|
||||
should('vectors from https://github.com/zkcrypto/pairing', () => {
|
||||
const p1 = pairing(G1, G2);
|
||||
deepStrictEqual(
|
||||
p1,
|
||||
@ -1045,7 +1046,7 @@ should('bls12-381/basic/should not verify wrong multi-signature as simple signat
|
||||
])
|
||||
);
|
||||
});
|
||||
should('pairing/finalExponentiate is correct', () => {
|
||||
should('finalExponentiate is correct', () => {
|
||||
const p1 = Fp12.fromBigTwelve([
|
||||
690392658038414015999440694435086329841032295415825549843130960252222448232974816207293269712691075396080336239827n,
|
||||
1673244384695948045466836192250093912021245353707563547917201356526057153141766171738038843400145227470982267854187n,
|
||||
@ -1078,9 +1079,9 @@ should('bls12-381/basic/should not verify wrong multi-signature as simple signat
|
||||
])
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
// hashToCurve
|
||||
{
|
||||
describe('hash-to-curve', () => {
|
||||
const DST = 'QUUX-V01-CS02-with-expander-SHA256-128';
|
||||
const VECTORS = [
|
||||
{
|
||||
@ -1824,9 +1825,9 @@ should('bls12-381/basic/should not verify wrong multi-signature as simple signat
|
||||
deepStrictEqual(p.toHex(), t.expected);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
// Deterministic
|
||||
{
|
||||
describe('bls12-381 deterministic', () => {
|
||||
// NOTE: Killic returns all items in reversed order, which looks strange:
|
||||
// instead of `Fp2(${this.c0} + ${this.c1}×i)`; it returns `Fp2(${this.c0}×i + ${this.c1})`;
|
||||
const killicHex = (lst) =>
|
||||
@ -1934,7 +1935,7 @@ should('bls12-381/basic/should not verify wrong multi-signature as simple signat
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// ESM is broken.
|
||||
import url from 'url';
|
||||
|
@ -1,7 +1,14 @@
|
||||
import { deepStrictEqual, throws } from 'assert';
|
||||
import { should } from 'micro-should';
|
||||
import { deepEqual, deepStrictEqual, strictEqual, throws } from 'assert';
|
||||
import { describe, should } from 'micro-should';
|
||||
import * as fc from 'fast-check';
|
||||
import { ed25519, ed25519ctx, ed25519ph, x25519, RistrettoPoint } from '../lib/esm/ed25519.js';
|
||||
import {
|
||||
ed25519,
|
||||
ed25519ctx,
|
||||
ed25519ph,
|
||||
x25519,
|
||||
RistrettoPoint,
|
||||
ED25519_TORSION_SUBGROUP,
|
||||
} from '../lib/esm/ed25519.js';
|
||||
import { readFileSync } from 'fs';
|
||||
import { default as zip215 } from './ed25519/zip215.json' assert { type: 'json' };
|
||||
import { hexToBytes, bytesToHex, randomBytes } from '@noble/hashes/utils';
|
||||
@ -10,6 +17,7 @@ import { sha512 } from '@noble/hashes/sha512';
|
||||
import { default as ed25519vectors } from './wycheproof/eddsa_test.json' assert { type: 'json' };
|
||||
import { default as x25519vectors } from './wycheproof/x25519_test.json' assert { type: 'json' };
|
||||
|
||||
describe('ed25519', () => {
|
||||
const ed = ed25519;
|
||||
const hex = bytesToHex;
|
||||
|
||||
@ -27,12 +35,12 @@ function utf8ToBytes(str) {
|
||||
|
||||
ed.utils.precompute(8);
|
||||
|
||||
should('ed25519/should not accept >32byte private keys', () => {
|
||||
should('not accept >32byte private keys', () => {
|
||||
const invalidPriv =
|
||||
100000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800073278156000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n;
|
||||
throws(() => ed.getPublicKey(invalidPriv));
|
||||
});
|
||||
should('ed25519/should verify recent signature', () => {
|
||||
should('verify recent signature', () => {
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.hexaString({ minLength: 2, maxLength: 32 }),
|
||||
@ -48,7 +56,7 @@ should('ed25519/should verify recent signature', () => {
|
||||
{ numRuns: 5 }
|
||||
);
|
||||
});
|
||||
should('ed25519/should not verify signature with wrong message', () => {
|
||||
should('not verify signature with wrong message', () => {
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.array(fc.integer({ min: 0x00, max: 0xff })),
|
||||
@ -72,38 +80,40 @@ should('ed25519/should not verify signature with wrong message', () => {
|
||||
const privKey = to32Bytes('a665a45920422f9d417e4867ef');
|
||||
const msg = hexToBytes('874f9960c5d2b7a9b5fad383e1ba44719ebb743a');
|
||||
const wrongMsg = hexToBytes('589d8c7f1da0a24bc07b7381ad48b1cfc211af1c');
|
||||
should('ed25519/basic methods/should sign and verify', () => {
|
||||
describe('basic methods', () => {
|
||||
should('sign and verify', () => {
|
||||
const publicKey = ed.getPublicKey(privKey);
|
||||
const signature = ed.sign(msg, privKey);
|
||||
deepStrictEqual(ed.verify(signature, msg, publicKey), true);
|
||||
});
|
||||
should('ed25519/basic methods/should not verify signature with wrong public key', () => {
|
||||
should('not verify signature with wrong public key', () => {
|
||||
const publicKey = ed.getPublicKey(12);
|
||||
const signature = ed.sign(msg, privKey);
|
||||
deepStrictEqual(ed.verify(signature, msg, publicKey), false);
|
||||
});
|
||||
should('ed25519/basic methods/should not verify signature with wrong hash', () => {
|
||||
should('not verify signature with wrong hash', () => {
|
||||
const publicKey = ed.getPublicKey(privKey);
|
||||
const signature = ed.sign(msg, privKey);
|
||||
deepStrictEqual(ed.verify(signature, wrongMsg, publicKey), false);
|
||||
});
|
||||
|
||||
should('ed25519/sync methods/should sign and verify', () => {
|
||||
});
|
||||
describe('sync methods', () => {
|
||||
should('sign and verify', () => {
|
||||
const publicKey = ed.getPublicKey(privKey);
|
||||
const signature = ed.sign(msg, privKey);
|
||||
deepStrictEqual(ed.verify(signature, msg, publicKey), true);
|
||||
});
|
||||
should('ed25519/sync methods/should not verify signature with wrong public key', () => {
|
||||
should('not verify signature with wrong public key', () => {
|
||||
const publicKey = ed.getPublicKey(12);
|
||||
const signature = ed.sign(msg, privKey);
|
||||
deepStrictEqual(ed.verify(signature, msg, publicKey), false);
|
||||
});
|
||||
should('ed25519/sync methods/should not verify signature with wrong hash', () => {
|
||||
should('not verify signature with wrong hash', () => {
|
||||
const publicKey = ed.getPublicKey(privKey);
|
||||
const signature = ed.sign(msg, privKey);
|
||||
deepStrictEqual(ed.verify(signature, wrongMsg, publicKey), false);
|
||||
});
|
||||
|
||||
});
|
||||
// https://xmr.llcoins.net/addresstests.html
|
||||
should(
|
||||
'ed25519/BASE_POINT.multiply()/should create right publicKey without SHA-512 hashing TEST 1',
|
||||
@ -651,6 +661,18 @@ should('X25519 base point', () => {
|
||||
deepStrictEqual(hex(numberToBytesLE(u, 32)), x25519.Gu);
|
||||
});
|
||||
|
||||
should('isTorsionFree()', () => {
|
||||
const orig = ed.utils.getExtendedPublicKey(ed.utils.randomPrivateKey()).point;
|
||||
for (const hex of ED25519_TORSION_SUBGROUP.slice(1)) {
|
||||
const dirty = orig.add(ed.Point.fromHex(hex));
|
||||
const cleared = dirty.clearCofactor();
|
||||
strictEqual(orig.isTorsionFree(), true, `orig must be torsionFree: ${hex}`);
|
||||
strictEqual(dirty.isTorsionFree(), false, `dirty must not be torsionFree: ${hex}`);
|
||||
strictEqual(cleared.isTorsionFree(), true, `cleared must be torsionFree: ${hex}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ESM is broken.
|
||||
import url from 'url';
|
||||
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { deepStrictEqual, throws } from 'assert';
|
||||
import { should } from 'micro-should';
|
||||
import { describe, should } from 'micro-should';
|
||||
import * as fc from 'fast-check';
|
||||
import { ed448, ed448ph, x448 } from '../lib/esm/ed448.js';
|
||||
import { hexToBytes, bytesToHex, randomBytes } from '@noble/hashes/utils';
|
||||
@ -7,6 +7,7 @@ import { numberToBytesLE } from '../lib/esm/abstract/utils.js';
|
||||
import { default as ed448vectors } from './wycheproof/ed448_test.json' assert { type: 'json' };
|
||||
import { default as x448vectors } from './wycheproof/x448_test.json' assert { type: 'json' };
|
||||
|
||||
describe('ed448', () => {
|
||||
const ed = ed448;
|
||||
const hex = bytesToHex;
|
||||
ed.utils.precompute(4);
|
||||
@ -323,7 +324,7 @@ for (let i = 0; i < VECTORS_RFC8032.length; i++) {
|
||||
});
|
||||
}
|
||||
|
||||
should('ed448/should not accept >57byte private keys', async () => {
|
||||
should('not accept >57byte private keys', async () => {
|
||||
const invalidPriv =
|
||||
100000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800073278156000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n;
|
||||
throws(() => ed.getPublicKey(invalidPriv));
|
||||
@ -334,7 +335,7 @@ function to57Bytes(numOrStr) {
|
||||
return hexToBytes(hex.padStart(114, '0'));
|
||||
}
|
||||
|
||||
should('ed448/should verify recent signature', () => {
|
||||
should('verify recent signature', () => {
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.hexaString({ minLength: 2, maxLength: 57 }),
|
||||
@ -350,7 +351,7 @@ should('ed448/should verify recent signature', () => {
|
||||
{ numRuns: 5 }
|
||||
);
|
||||
});
|
||||
should('ed448/should not verify signature with wrong message', () => {
|
||||
should('not verify signature with wrong message', () => {
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.array(fc.integer({ min: 0x00, max: 0xff })),
|
||||
@ -374,39 +375,43 @@ should('ed448/should not verify signature with wrong message', () => {
|
||||
const privKey = to57Bytes('a665a45920422f9d417e4867ef');
|
||||
const msg = hexToBytes('874f9960c5d2b7a9b5fad383e1ba44719ebb743a');
|
||||
const wrongMsg = hexToBytes('589d8c7f1da0a24bc07b7381ad48b1cfc211af1c');
|
||||
should('ed25519/basic methods/should sign and verify', () => {
|
||||
describe('basic methods', () => {
|
||||
should('sign and verify', () => {
|
||||
const publicKey = ed.getPublicKey(privKey);
|
||||
const signature = ed.sign(msg, privKey);
|
||||
deepStrictEqual(ed.verify(signature, msg, publicKey), true);
|
||||
});
|
||||
should('ed25519/basic methods/should not verify signature with wrong public key', () => {
|
||||
should('not verify signature with wrong public key', () => {
|
||||
const publicKey = ed.getPublicKey(12);
|
||||
const signature = ed.sign(msg, privKey);
|
||||
deepStrictEqual(ed.verify(signature, msg, publicKey), false);
|
||||
});
|
||||
should('ed25519/basic methods/should not verify signature with wrong hash', () => {
|
||||
should('not verify signature with wrong hash', () => {
|
||||
const publicKey = ed.getPublicKey(privKey);
|
||||
const signature = ed.sign(msg, privKey);
|
||||
deepStrictEqual(ed.verify(signature, wrongMsg, publicKey), false);
|
||||
});
|
||||
});
|
||||
|
||||
should('ed25519/sync methods/should sign and verify', () => {
|
||||
describe('sync methods', () => {
|
||||
should('sign and verify', () => {
|
||||
const publicKey = ed.getPublicKey(privKey);
|
||||
const signature = ed.sign(msg, privKey);
|
||||
deepStrictEqual(ed.verify(signature, msg, publicKey), true);
|
||||
});
|
||||
should('ed25519/sync methods/should not verify signature with wrong public key', async () => {
|
||||
should('not verify signature with wrong public key', async () => {
|
||||
const publicKey = ed.getPublicKey(12);
|
||||
const signature = ed.sign(msg, privKey);
|
||||
deepStrictEqual(ed.verify(signature, msg, publicKey), false);
|
||||
});
|
||||
should('ed25519/sync methods/should not verify signature with wrong hash', async () => {
|
||||
should('not verify signature with wrong hash', async () => {
|
||||
const publicKey = ed.getPublicKey(privKey);
|
||||
const signature = ed.sign(msg, privKey);
|
||||
deepStrictEqual(ed.verify(signature, wrongMsg, publicKey), false);
|
||||
});
|
||||
});
|
||||
|
||||
should('ed25519/BASE_POINT.multiply()/should throw Point#multiply on TEST 5', () => {
|
||||
should('BASE_POINT.multiply() throws in Point#multiply on TEST 5', () => {
|
||||
for (const num of [0n, 0, -1n, -1, 1.1]) {
|
||||
throws(() => ed.Point.BASE.multiply(num));
|
||||
}
|
||||
@ -657,6 +662,7 @@ should('X448 base point', () => {
|
||||
// const u = Fp.create(y * y * invX);
|
||||
deepStrictEqual(hex(numberToBytesLE(u, 56)), x448.Gu);
|
||||
});
|
||||
});
|
||||
|
||||
// ESM is broken.
|
||||
import url from 'url';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { deepStrictEqual } from 'assert';
|
||||
import { should } from 'micro-should';
|
||||
import { describe, should } from 'micro-should';
|
||||
import { bytesToHex } from '@noble/hashes/utils';
|
||||
// Generic tests for all curves in package
|
||||
import { sha256 } from '@noble/hashes/sha256';
|
||||
@ -51,9 +51,10 @@ import { default as ed448_ro } from './hash-to-curve/edwards448_XOF:SHAKE256_ELL
|
||||
import { default as ed448_nu } from './hash-to-curve/edwards448_XOF:SHAKE256_ELL2_NU_.json' assert { type: 'json' };
|
||||
|
||||
function testExpandXMD(hash, vectors) {
|
||||
describe(`${vectors.hash}/${vectors.DST.length}`, () => {
|
||||
for (let i = 0; i < vectors.tests.length; i++) {
|
||||
const t = vectors.tests[i];
|
||||
should(`expand_message_xmd/${vectors.hash}/${vectors.DST.length}/${i}`, () => {
|
||||
should(`${vectors.hash}/${vectors.DST.length}/${i}`, () => {
|
||||
const p = expand_message_xmd(
|
||||
stringToBytes(t.msg),
|
||||
stringToBytes(vectors.DST),
|
||||
@ -63,16 +64,20 @@ function testExpandXMD(hash, vectors) {
|
||||
deepStrictEqual(bytesToHex(p), t.uniform_bytes);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
describe('expand_message_xmd', () => {
|
||||
testExpandXMD(sha256, xmd_sha256_38);
|
||||
testExpandXMD(sha256, xmd_sha256_256);
|
||||
testExpandXMD(sha512, xmd_sha512_38);
|
||||
});
|
||||
|
||||
function testExpandXOF(hash, vectors) {
|
||||
describe(`${vectors.hash}/${vectors.DST.length}`, () => {
|
||||
for (let i = 0; i < vectors.tests.length; i++) {
|
||||
const t = vectors.tests[i];
|
||||
should(`expand_message_xof/${vectors.hash}/${vectors.DST.length}/${i}`, () => {
|
||||
should(`${i}`, () => {
|
||||
const p = expand_message_xof(
|
||||
stringToBytes(t.msg),
|
||||
stringToBytes(vectors.DST),
|
||||
@ -83,11 +88,14 @@ function testExpandXOF(hash, vectors) {
|
||||
deepStrictEqual(bytesToHex(p), t.uniform_bytes);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
describe('expand_message_xof', () => {
|
||||
testExpandXOF(shake128, xof_shake128_36);
|
||||
testExpandXOF(shake128, xof_shake128_256);
|
||||
testExpandXOF(shake256, xof_shake256_36);
|
||||
});
|
||||
|
||||
function stringToFp(s) {
|
||||
// bls-G2 support
|
||||
@ -99,9 +107,10 @@ function stringToFp(s) {
|
||||
}
|
||||
|
||||
function testCurve(curve, ro, nu) {
|
||||
describe(`${ro.curve}/${ro.ciphersuite}`, () => {
|
||||
for (let i = 0; i < ro.vectors.length; i++) {
|
||||
const t = ro.vectors[i];
|
||||
should(`${ro.curve}/${ro.ciphersuite}(${i})`, () => {
|
||||
should(`(${i})`, () => {
|
||||
const p = curve.Point.hashToCurve(stringToBytes(t.msg), {
|
||||
DST: ro.dst,
|
||||
});
|
||||
@ -109,9 +118,11 @@ function testCurve(curve, ro, nu) {
|
||||
deepStrictEqual(p.y, stringToFp(t.P.y), 'Py');
|
||||
});
|
||||
}
|
||||
});
|
||||
describe(`${nu.curve}/${nu.ciphersuite}`, () => {
|
||||
for (let i = 0; i < nu.vectors.length; i++) {
|
||||
const t = nu.vectors[i];
|
||||
should(`${nu.curve}/${nu.ciphersuite}(${i})`, () => {
|
||||
should(`(${i})`, () => {
|
||||
const p = curve.Point.encodeToCurve(stringToBytes(t.msg), {
|
||||
DST: nu.dst,
|
||||
});
|
||||
@ -119,6 +130,7 @@ function testCurve(curve, ro, nu) {
|
||||
deepStrictEqual(p.y, stringToFp(t.P.y), 'Py');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
testCurve(secp256r1, p256_ro, p256_nu);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { jubjub, findGroupHash } from '../lib/esm/jubjub.js';
|
||||
import { should } from 'micro-should';
|
||||
import { describe, should } from 'micro-should';
|
||||
import { deepStrictEqual, throws } from 'assert';
|
||||
import { hexToBytes, bytesToHex } from '@noble/hashes/utils';
|
||||
|
||||
@ -18,6 +18,7 @@ const G_PROOF = new jubjub.ExtendedPoint(
|
||||
|
||||
const getXY = (p) => ({ x: p.x, y: p.y });
|
||||
|
||||
describe('jubjub', () => {
|
||||
should('toHex/fromHex', () => {
|
||||
// More than field
|
||||
throws(() =>
|
||||
@ -66,6 +67,7 @@ should('Find generators', () => {
|
||||
deepStrictEqual(getXY(spend.toAffine()), getXY(G_SPEND.toAffine()));
|
||||
deepStrictEqual(getXY(proof.toAffine()), getXY(G_PROOF.toAffine()));
|
||||
});
|
||||
});
|
||||
|
||||
// ESM is broken.
|
||||
import url from 'url';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { deepStrictEqual, throws } from 'assert';
|
||||
import { should } from 'micro-should';
|
||||
import { describe, should } from 'micro-should';
|
||||
import { secp192r1, P192 } from '../lib/esm/p192.js';
|
||||
import { secp224r1, P224 } from '../lib/esm/p224.js';
|
||||
import { secp256r1, P256 } from '../lib/esm/p256.js';
|
||||
@ -344,10 +344,11 @@ function runWycheproof(name, CURVE, group, index) {
|
||||
|
||||
for (const name in WYCHEPROOF_ECDSA) {
|
||||
const { curve, hashes } = WYCHEPROOF_ECDSA[name];
|
||||
describe('Wycheproof/WYCHEPROOF_ECDSA', () => {
|
||||
for (const hName in hashes) {
|
||||
const { hash, tests } = hashes[hName];
|
||||
const CURVE = curve.create(hash);
|
||||
should(`Wycheproof/WYCHEPROOF_ECDSA ${name}/${hName}`, () => {
|
||||
should(`${name}/${hName}`, () => {
|
||||
for (let i = 0; i < tests.length; i++) {
|
||||
const groups = tests[i].testGroups;
|
||||
for (let j = 0; j < groups.length; j++) {
|
||||
@ -357,6 +358,7 @@ for (const name in WYCHEPROOF_ECDSA) {
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const hexToBigint = (hex) => BigInt(`0x${hex}`);
|
||||
|
@ -7,7 +7,7 @@ import { default as ecdh } from './vectors/ecdh.json' assert { type: 'json' };
|
||||
import { default as privates } from './vectors/privates.json' assert { type: 'json' };
|
||||
import { default as points } from './vectors/points.json' assert { type: 'json' };
|
||||
import { default as wp } from './vectors/wychenproof.json' assert { type: 'json' };
|
||||
import { should } from 'micro-should';
|
||||
import { should, describe } from 'micro-should';
|
||||
import { deepStrictEqual, throws } from 'assert';
|
||||
import { hexToBytes, bytesToHex } from '@noble/hashes/utils';
|
||||
|
||||
@ -30,7 +30,8 @@ function hexToNumber(hex) {
|
||||
return BigInt(`0x${hex}`);
|
||||
}
|
||||
|
||||
should('secp256k1.getPublicKey()', () => {
|
||||
describe('secp256k1', () => {
|
||||
should('getPublicKey()', () => {
|
||||
const data = privatesTxt
|
||||
.split('\n')
|
||||
.filter((line) => line)
|
||||
@ -49,12 +50,12 @@ should('secp256k1.getPublicKey()', () => {
|
||||
deepStrictEqual(toBEHex(point3.y), y);
|
||||
}
|
||||
});
|
||||
should('secp256k1.getPublicKey() rejects invalid keys', () => {
|
||||
should('getPublicKey() rejects invalid keys', () => {
|
||||
for (const item of INVALID_ITEMS) {
|
||||
throws(() => secp.getPublicKey(item));
|
||||
}
|
||||
});
|
||||
should('secp256k1.precompute', () => {
|
||||
should('precompute', () => {
|
||||
secp.utils.precompute(4);
|
||||
const data = privatesTxt
|
||||
.split('\n')
|
||||
@ -75,7 +76,7 @@ should('secp256k1.precompute', () => {
|
||||
}
|
||||
});
|
||||
|
||||
should('secp256k1.Point.isValidPoint()', () => {
|
||||
should('Point.isValidPoint()', () => {
|
||||
for (const vector of points.valid.isPoint) {
|
||||
const { P, expected } = vector;
|
||||
if (expected) {
|
||||
@ -86,7 +87,7 @@ should('secp256k1.Point.isValidPoint()', () => {
|
||||
}
|
||||
});
|
||||
|
||||
should('secp256k1.Point.fromPrivateKey()', () => {
|
||||
should('Point.fromPrivateKey()', () => {
|
||||
for (const vector of points.valid.pointFromScalar) {
|
||||
const { d, expected } = vector;
|
||||
let p = secp.Point.fromPrivateKey(d);
|
||||
@ -94,7 +95,7 @@ should('secp256k1.Point.fromPrivateKey()', () => {
|
||||
}
|
||||
});
|
||||
|
||||
should('secp256k1.Point#toHex(compressed)', () => {
|
||||
should('Point#toHex(compressed)', () => {
|
||||
for (const vector of points.valid.pointCompress) {
|
||||
const { P, compress, expected } = vector;
|
||||
let p = secp.Point.fromHex(P);
|
||||
@ -102,7 +103,7 @@ should('secp256k1.Point#toHex(compressed)', () => {
|
||||
}
|
||||
});
|
||||
|
||||
should('secp256k1.Point#toHex() roundtrip (failed case)', () => {
|
||||
should('Point#toHex() roundtrip (failed case)', () => {
|
||||
const point1 =
|
||||
secp.Point.fromPrivateKey(
|
||||
88572218780422190464634044548753414301110513745532121983949500266768436236425n
|
||||
@ -111,7 +112,7 @@ should('secp256k1.Point#toHex() roundtrip (failed case)', () => {
|
||||
// deepStrictEqual(secp.Point.fromHex(hex).toHex(true), hex);
|
||||
});
|
||||
|
||||
should('secp256k1.Point#toHex() roundtrip', () => {
|
||||
should('Point#toHex() roundtrip', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, (x) => {
|
||||
const point1 = secp.Point.fromPrivateKey(x);
|
||||
@ -121,7 +122,7 @@ should('secp256k1.Point#toHex() roundtrip', () => {
|
||||
);
|
||||
});
|
||||
|
||||
should('secp256k1.Point#add(other)', () => {
|
||||
should('Point#add(other)', () => {
|
||||
for (const vector of points.valid.pointAdd) {
|
||||
const { P, Q, expected } = vector;
|
||||
let p = secp.Point.fromHex(P);
|
||||
@ -136,7 +137,7 @@ should('secp256k1.Point#add(other)', () => {
|
||||
}
|
||||
});
|
||||
|
||||
should('secp256k1.Point#multiply(privateKey)', () => {
|
||||
should('Point#multiply(privateKey)', () => {
|
||||
for (const vector of points.valid.pointMultiply) {
|
||||
const { P, d, expected } = vector;
|
||||
const p = secp.Point.fromHex(P);
|
||||
@ -175,7 +176,7 @@ should('secp256k1.Point#multiply(privateKey)', () => {
|
||||
// console.log(secp.ProjectivePoint.normalizeZ([p0.multiplyUnsafe(z)])[0])
|
||||
// });
|
||||
|
||||
should('secp256k1.Signature.fromCompactHex() roundtrip', () => {
|
||||
should('Signature.fromCompactHex() roundtrip', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, FC_BIGINT, (r, s) => {
|
||||
const sig = new secp.Signature(r, s);
|
||||
@ -184,7 +185,7 @@ should('secp256k1.Signature.fromCompactHex() roundtrip', () => {
|
||||
);
|
||||
});
|
||||
|
||||
should('secp256k1.Signature.fromDERHex() roundtrip', () => {
|
||||
should('Signature.fromDERHex() roundtrip', () => {
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, FC_BIGINT, (r, s) => {
|
||||
const sig = new secp.Signature(r, s);
|
||||
@ -193,7 +194,7 @@ should('secp256k1.Signature.fromDERHex() roundtrip', () => {
|
||||
);
|
||||
});
|
||||
|
||||
should('secp256k1.sign()/should create deterministic signatures with RFC 6979', () => {
|
||||
should('sign()/should create deterministic signatures with RFC 6979', () => {
|
||||
for (const vector of ecdsa.valid) {
|
||||
let usig = secp.sign(vector.m, vector.d);
|
||||
let sig = usig.toCompactHex();
|
||||
@ -203,18 +204,21 @@ should('secp256k1.sign()/should create deterministic signatures with RFC 6979',
|
||||
}
|
||||
});
|
||||
|
||||
should('secp256k1.sign()/should not create invalid deterministic signatures with RFC 6979', () => {
|
||||
should(
|
||||
'secp256k1.sign()/should not create invalid deterministic signatures with RFC 6979',
|
||||
() => {
|
||||
for (const vector of ecdsa.invalid.sign) {
|
||||
throws(() => secp.sign(vector.m, vector.d));
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
should('secp256k1.sign()/edge cases', () => {
|
||||
should('sign()/edge cases', () => {
|
||||
throws(() => secp.sign());
|
||||
throws(() => secp.sign(''));
|
||||
});
|
||||
|
||||
should('secp256k1.sign()/should create correct DER encoding against libsecp256k1', () => {
|
||||
should('sign()/should create correct DER encoding against libsecp256k1', () => {
|
||||
const CASES = [
|
||||
[
|
||||
'd1a9dc8ed4e46a6a3e5e594615ca351d7d7ef44df1e4c94c1802f3592183794b',
|
||||
@ -237,7 +241,7 @@ should('secp256k1.sign()/should create correct DER encoding against libsecp256k1
|
||||
deepStrictEqual(secp.Signature.fromCompact(rs).toDERHex(), exp);
|
||||
}
|
||||
});
|
||||
should('secp256k1.sign()/sign ecdsa extraData', () => {
|
||||
should('sign()/sign ecdsa extraData', () => {
|
||||
const ent1 = '0000000000000000000000000000000000000000000000000000000000000000';
|
||||
const ent2 = '0000000000000000000000000000000000000000000000000000000000000001';
|
||||
const ent3 = '6e723d3fd94ed5d2b6bdd4f123364b0f3ca52af829988a63f8afe91d29db1c33';
|
||||
@ -258,7 +262,7 @@ should('secp256k1.sign()/sign ecdsa extraData', () => {
|
||||
}
|
||||
});
|
||||
|
||||
should('secp256k1.verify()/should verify signature', () => {
|
||||
should('verify()/should verify signature', () => {
|
||||
const MSG = '01'.repeat(32);
|
||||
const PRIV_KEY = 0x2n;
|
||||
const signature = secp.sign(MSG, PRIV_KEY);
|
||||
@ -266,7 +270,7 @@ should('secp256k1.verify()/should verify signature', () => {
|
||||
deepStrictEqual(publicKey.length, 65);
|
||||
deepStrictEqual(secp.verify(signature, MSG, publicKey), true);
|
||||
});
|
||||
should('secp256k1.verify()/should not verify signature with wrong public key', () => {
|
||||
should('verify()/should not verify signature with wrong public key', () => {
|
||||
const MSG = '01'.repeat(32);
|
||||
const PRIV_KEY = 0x2n;
|
||||
const WRONG_PRIV_KEY = 0x22n;
|
||||
@ -275,7 +279,7 @@ should('secp256k1.verify()/should not verify signature with wrong public key', (
|
||||
deepStrictEqual(publicKey.length, 130);
|
||||
deepStrictEqual(secp.verify(signature, MSG, publicKey), false);
|
||||
});
|
||||
should('secp256k1.verify()/should not verify signature with wrong hash', () => {
|
||||
should('verify()/should not verify signature with wrong hash', () => {
|
||||
const MSG = '01'.repeat(32);
|
||||
const PRIV_KEY = 0x2n;
|
||||
const WRONG_MSG = '11'.repeat(32);
|
||||
@ -284,7 +288,7 @@ should('secp256k1.verify()/should not verify signature with wrong hash', () => {
|
||||
deepStrictEqual(publicKey.length, 65);
|
||||
deepStrictEqual(secp.verify(signature, WRONG_MSG, publicKey), false);
|
||||
});
|
||||
should('secp256k1.verify()/should verify random signatures', () =>
|
||||
should('verify()/should verify random signatures', () =>
|
||||
fc.assert(
|
||||
fc.property(FC_BIGINT, fc.hexaString({ minLength: 64, maxLength: 64 }), (privKey, msg) => {
|
||||
const pub = secp.getPublicKey(privKey);
|
||||
@ -293,10 +297,11 @@ should('secp256k1.verify()/should verify random signatures', () =>
|
||||
})
|
||||
)
|
||||
);
|
||||
should('secp256k1.verify()/should not verify signature with invalid r/s', () => {
|
||||
should('verify()/should not verify signature with invalid r/s', () => {
|
||||
const msg = new Uint8Array([
|
||||
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, 0x50, 0x23,
|
||||
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,
|
||||
0x50, 0x23,
|
||||
]);
|
||||
const x = 100260381870027870612475458630405506840396644859280795015145920502443964769584n;
|
||||
const y = 41096923727651821103518389640356553930186852801619204169823347832429067794568n;
|
||||
@ -312,7 +317,7 @@ should('secp256k1.verify()/should not verify signature with invalid r/s', () =>
|
||||
// Verifies, but it shouldn't, because signature S > curve order
|
||||
deepStrictEqual(verified, false);
|
||||
});
|
||||
should('secp256k1.verify()/should not verify msg = curve order', () => {
|
||||
should('verify()/should not verify msg = curve order', () => {
|
||||
const msg = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141';
|
||||
const x = 55066263022277343669578718895168534326250603453777594175500187360389116729240n;
|
||||
const y = 32670510020758816978083085130507043184471273380659243275938904335757337482424n;
|
||||
@ -322,7 +327,7 @@ should('secp256k1.verify()/should not verify msg = curve order', () => {
|
||||
const sig = new secp.Signature(r, s);
|
||||
deepStrictEqual(secp.verify(sig, msg, pub), false);
|
||||
});
|
||||
should('secp256k1.verify()/should verify non-strict msg bb5a...', () => {
|
||||
should('verify()/should verify non-strict msg bb5a...', () => {
|
||||
const msg = 'bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023';
|
||||
const x = 3252872872578928810725465493269682203671229454553002637820453004368632726370n;
|
||||
const y = 17482644437196207387910659778872952193236850502325156318830589868678978890912n;
|
||||
@ -362,7 +367,7 @@ for (let vec of vectors) {
|
||||
});
|
||||
}
|
||||
|
||||
should('secp256k1.recoverPublicKey()/should recover public key from recovery bit', () => {
|
||||
should('recoverPublicKey()/should recover public key from recovery bit', () => {
|
||||
const message = '00000000000000000000000000000000000000000000000000000000deadbeef';
|
||||
const privateKey = 123456789n;
|
||||
const publicKey = secp.Point.fromHex(secp.getPublicKey(privateKey)).toHex(false);
|
||||
@ -373,14 +378,14 @@ should('secp256k1.recoverPublicKey()/should recover public key from recovery bit
|
||||
deepStrictEqual(recoveredPubkey.toHex(false), publicKey);
|
||||
deepStrictEqual(secp.verify(sig, message, publicKey), true);
|
||||
});
|
||||
should('secp256k1.recoverPublicKey()/should not recover zero points', () => {
|
||||
should('recoverPublicKey()/should not recover zero points', () => {
|
||||
const msgHash = '6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9';
|
||||
const sig =
|
||||
'79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817986b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9';
|
||||
const recovery = 0;
|
||||
throws(() => secp.recoverPublicKey(msgHash, sig, recovery));
|
||||
});
|
||||
should('secp256k1.recoverPublicKey()/should handle all-zeros msghash', () => {
|
||||
should('recoverPublicKey()/should handle all-zeros msghash', () => {
|
||||
const privKey = secp.utils.randomPrivateKey();
|
||||
const pub = secp.getPublicKey(privKey);
|
||||
const zeros = '0000000000000000000000000000000000000000000000000000000000000000';
|
||||
@ -388,7 +393,7 @@ should('secp256k1.recoverPublicKey()/should handle all-zeros msghash', () => {
|
||||
const recoveredKey = sig.recoverPublicKey(zeros);
|
||||
deepStrictEqual(recoveredKey.toRawBytes(), pub);
|
||||
});
|
||||
should('secp256k1.recoverPublicKey()/should handle RFC 6979 vectors', () => {
|
||||
should('recoverPublicKey()/should handle RFC 6979 vectors', () => {
|
||||
for (const vector of ecdsa.valid) {
|
||||
let usig = secp.sign(vector.m, vector.d);
|
||||
let sig = usig.toDERHex();
|
||||
@ -402,7 +407,7 @@ should('secp256k1.recoverPublicKey()/should handle RFC 6979 vectors', () => {
|
||||
function derToPub(der) {
|
||||
return der.slice(46);
|
||||
}
|
||||
should('secp256k1.getSharedSecret()/should produce correct results', () => {
|
||||
should('getSharedSecret()/should produce correct results', () => {
|
||||
// TODO: Once der is there, run all tests.
|
||||
for (const vector of ecdh.testGroups[0].tests.slice(0, 230)) {
|
||||
if (vector.result === 'invalid' || vector.private.length !== 64) {
|
||||
@ -415,7 +420,7 @@ should('secp256k1.getSharedSecret()/should produce correct results', () => {
|
||||
}
|
||||
}
|
||||
});
|
||||
should('secp256k1.getSharedSecret()/priv/pub order matters', () => {
|
||||
should('getSharedSecret()/priv/pub order matters', () => {
|
||||
for (const vector of ecdh.testGroups[0].tests.slice(0, 100)) {
|
||||
if (vector.result === 'valid') {
|
||||
let priv = vector.private;
|
||||
@ -424,11 +429,11 @@ should('secp256k1.getSharedSecret()/priv/pub order matters', () => {
|
||||
}
|
||||
}
|
||||
});
|
||||
should('secp256k1.getSharedSecret()/rejects invalid keys', () => {
|
||||
should('getSharedSecret()/rejects invalid keys', () => {
|
||||
throws(() => secp.getSharedSecret('01', '02'));
|
||||
});
|
||||
|
||||
should('secp256k1.utils.isValidPrivateKey()', () => {
|
||||
should('utils.isValidPrivateKey()', () => {
|
||||
for (const vector of privates.valid.isPrivate) {
|
||||
const { d, expected } = vector;
|
||||
deepStrictEqual(secp.utils.isValidPrivateKey(d), expected);
|
||||
@ -472,45 +477,45 @@ const tweakUtils = {
|
||||
},
|
||||
};
|
||||
|
||||
should('secp256k1.privateAdd()', () => {
|
||||
should('privateAdd()', () => {
|
||||
for (const vector of privates.valid.add) {
|
||||
const { a, b, expected } = vector;
|
||||
deepStrictEqual(bytesToHex(tweakUtils.privateAdd(a, b)), expected);
|
||||
}
|
||||
});
|
||||
should('secp256k1.privateNegate()', () => {
|
||||
should('privateNegate()', () => {
|
||||
for (const vector of privates.valid.negate) {
|
||||
const { a, expected } = vector;
|
||||
deepStrictEqual(bytesToHex(tweakUtils.privateNegate(a)), expected);
|
||||
}
|
||||
});
|
||||
should('secp256k1.pointAddScalar()', () => {
|
||||
should('pointAddScalar()', () => {
|
||||
for (const vector of points.valid.pointAddScalar) {
|
||||
const { description, P, d, expected } = vector;
|
||||
const compressed = !!expected && expected.length === 66; // compressed === 33 bytes
|
||||
deepStrictEqual(bytesToHex(tweakUtils.pointAddScalar(P, d, compressed)), expected);
|
||||
}
|
||||
});
|
||||
should('secp256k1.pointAddScalar() invalid', () => {
|
||||
should('pointAddScalar() invalid', () => {
|
||||
for (const vector of points.invalid.pointAddScalar) {
|
||||
const { P, d, exception } = vector;
|
||||
throws(() => tweakUtils.pointAddScalar(P, d));
|
||||
}
|
||||
});
|
||||
should('secp256k1.pointMultiply()', () => {
|
||||
should('pointMultiply()', () => {
|
||||
for (const vector of points.valid.pointMultiply) {
|
||||
const { P, d, expected } = vector;
|
||||
deepStrictEqual(bytesToHex(tweakUtils.pointMultiply(P, d, true)), expected);
|
||||
}
|
||||
});
|
||||
should('secp256k1.pointMultiply() invalid', () => {
|
||||
should('pointMultiply() invalid', () => {
|
||||
for (const vector of points.invalid.pointMultiply) {
|
||||
const { P, d, exception } = vector;
|
||||
throws(() => tweakUtils.pointMultiply(P, d));
|
||||
}
|
||||
});
|
||||
|
||||
should('secp256k1.wychenproof vectors', () => {
|
||||
should('wychenproof vectors', () => {
|
||||
for (let group of wp.testGroups) {
|
||||
const pubKey = secp.Point.fromHex(group.key.uncompressed);
|
||||
for (let test of group.tests) {
|
||||
@ -537,6 +542,7 @@ should('secp256k1.wychenproof vectors', () => {
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ESM is broken.
|
||||
import url from 'url';
|
||||
|
Loading…
Reference in New Issue
Block a user