forked from tornado-packages/noble-curves
edwards: affine Point removal tests
This commit is contained in:
parent
a49f0d266e
commit
17e5be5f1b
@ -96,10 +96,10 @@ export const CURVES = {
|
|||||||
old_secp.recoverPublicKey(msg, new old_secp.Signature(sig.r, sig.s), sig.recovery),
|
old_secp.recoverPublicKey(msg, new old_secp.Signature(sig.r, sig.s), sig.recovery),
|
||||||
secp256k1: ({ sig, msg }) => sig.recoverPublicKey(msg),
|
secp256k1: ({ sig, msg }) => sig.recoverPublicKey(msg),
|
||||||
},
|
},
|
||||||
hashToCurve: {
|
// hashToCurve: {
|
||||||
samples: 500,
|
// samples: 500,
|
||||||
noble: () => secp256k1.Point.hashToCurve('abcd'),
|
// noble: () => secp256k1.Point.hashToCurve('abcd'),
|
||||||
},
|
// },
|
||||||
},
|
},
|
||||||
ed25519: {
|
ed25519: {
|
||||||
data: () => {
|
data: () => {
|
||||||
@ -128,10 +128,10 @@ export const CURVES = {
|
|||||||
old: ({ sig, msg, pub }) => noble_ed25519.sync.verify(sig, msg, pub),
|
old: ({ sig, msg, pub }) => noble_ed25519.sync.verify(sig, msg, pub),
|
||||||
noble: ({ sig, msg, pub }) => ed25519.verify(sig, msg, pub),
|
noble: ({ sig, msg, pub }) => ed25519.verify(sig, msg, pub),
|
||||||
},
|
},
|
||||||
hashToCurve: {
|
// hashToCurve: {
|
||||||
samples: 500,
|
// samples: 500,
|
||||||
noble: () => ed25519.Point.hashToCurve('abcd'),
|
// noble: () => ed25519.Point.hashToCurve('abcd'),
|
||||||
},
|
// },
|
||||||
},
|
},
|
||||||
ed448: {
|
ed448: {
|
||||||
data: () => {
|
data: () => {
|
||||||
|
@ -61,7 +61,10 @@ function validateOpts(curve: CurveType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2d point in XY coords
|
// 2d point in XY coords
|
||||||
export interface AffinePoint { x: bigint; y: bigint };
|
export interface AffinePoint {
|
||||||
|
x: bigint;
|
||||||
|
y: bigint;
|
||||||
|
}
|
||||||
|
|
||||||
// Instance of Extended Point with coordinates in X, Y, Z, T
|
// Instance of Extended Point with coordinates in X, Y, Z, T
|
||||||
export interface ExtendedPointType extends Group<ExtendedPointType> {
|
export interface ExtendedPointType extends Group<ExtendedPointType> {
|
||||||
@ -384,7 +387,7 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const { BASE: G, ZERO: I } = ExtendedPoint;
|
const { BASE: G, ZERO: I } = ExtendedPoint;
|
||||||
let Gpows: ExtendedPoint[] | undefined = undefined; // precomputes for base point G
|
let Gpows: ExtendedPoint[] | undefined = undefined; // precomputes for base point G
|
||||||
const wnaf = wNAF(ExtendedPoint, CURVE.nByteLength * 8);
|
const wnaf = wNAF(ExtendedPoint, CURVE.nByteLength * 8);
|
||||||
function wNAF_TMP_FN(P: ExtendedPoint, n: bigint): ExtendedPoint {
|
function wNAF_TMP_FN(P: ExtendedPoint, n: bigint): ExtendedPoint {
|
||||||
if (P.equals(G)) {
|
if (P.equals(G)) {
|
||||||
|
@ -179,13 +179,16 @@ export function isogenyMap<T, F extends mod.Field<T>>(field: F, map: [T[], T[],
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Point<T> extends Group<Point<T>> {
|
export interface Point<T> extends Group<Point<T>> {
|
||||||
readonly x: T;
|
// readonly x: T;
|
||||||
readonly y: T;
|
// readonly y: T;
|
||||||
|
add(rhs: Point<T>): Point<T>;
|
||||||
|
toAffine(iz?: bigint): { x: T; y: T };
|
||||||
clearCofactor(): Point<T>;
|
clearCofactor(): Point<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PointConstructor<T> extends GroupConstructor<Point<T>> {
|
export interface PointConstructor<T> extends GroupConstructor<Point<T>> {
|
||||||
new (x: T, y: T): Point<T>;
|
// new (x: T, y: T): Point<T>;
|
||||||
|
fromAffine(ap: { x: T; y: T }): Point<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MapToCurve<T> = (scalar: bigint[]) => { x: T; y: T };
|
export type MapToCurve<T> = (scalar: bigint[]) => { x: T; y: T };
|
||||||
@ -207,9 +210,9 @@ export function hashToCurve<T>(Point: PointConstructor<T>, mapToCurve: MapToCurv
|
|||||||
if (!mapToCurve) throw new Error('CURVE.mapToCurve() has not been defined');
|
if (!mapToCurve) throw new Error('CURVE.mapToCurve() has not been defined');
|
||||||
msg = ut.ensureBytes(msg);
|
msg = ut.ensureBytes(msg);
|
||||||
const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options } as Opts);
|
const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options } as Opts);
|
||||||
const { x: x0, y: y0 } = mapToCurve(u[0]);
|
return Point.fromAffine(mapToCurve(u[0]))
|
||||||
const { x: x1, y: y1 } = mapToCurve(u[1]);
|
.add(Point.fromAffine(mapToCurve(u[1])))
|
||||||
return new Point(x0, y0).add(new Point(x1, y1)).clearCofactor();
|
.clearCofactor();
|
||||||
},
|
},
|
||||||
|
|
||||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3
|
||||||
@ -217,8 +220,7 @@ export function hashToCurve<T>(Point: PointConstructor<T>, mapToCurve: MapToCurv
|
|||||||
if (!mapToCurve) throw new Error('CURVE.mapToCurve() has not been defined');
|
if (!mapToCurve) throw new Error('CURVE.mapToCurve() has not been defined');
|
||||||
msg = ut.ensureBytes(msg);
|
msg = ut.ensureBytes(msg);
|
||||||
const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options } as Opts);
|
const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options } as Opts);
|
||||||
const { x, y } = mapToCurve(u[0]);
|
return Point.fromAffine(mapToCurve(u[0])).clearCofactor();
|
||||||
return new Point(x, y).clearCofactor();
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -137,10 +137,12 @@ export interface PointType<T> extends Group<PointType<T>> {
|
|||||||
assertValidity(): void;
|
assertValidity(): void;
|
||||||
multiplyAndAddUnsafe(Q: PointType<T>, a: bigint, b: bigint): PointType<T> | undefined;
|
multiplyAndAddUnsafe(Q: PointType<T>, a: bigint, b: bigint): PointType<T> | undefined;
|
||||||
clearCofactor(): PointType<T>;
|
clearCofactor(): PointType<T>;
|
||||||
|
toAffine(iz?: bigint): { x: T; y: T };
|
||||||
}
|
}
|
||||||
// Static methods for 2d XY points
|
// Static methods for 2d XY points
|
||||||
export interface PointConstructor<T> extends GroupConstructor<PointType<T>> {
|
export interface PointConstructor<T> extends GroupConstructor<PointType<T>> {
|
||||||
new (x: T, y: T): PointType<T>;
|
new (x: T, y: T): PointType<T>;
|
||||||
|
fromAffine(ap: { x: T; y: T }): PointType<T>;
|
||||||
fromHex(hex: Hex): PointType<T>;
|
fromHex(hex: Hex): PointType<T>;
|
||||||
fromPrivateKey(privateKey: PrivKey): PointType<T>;
|
fromPrivateKey(privateKey: PrivKey): PointType<T>;
|
||||||
}
|
}
|
||||||
@ -546,6 +548,12 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
|
|||||||
* Identity point aka point at infinity. p - p = zero_p; p + zero_p = p
|
* Identity point aka point at infinity. p - p = zero_p; p + zero_p = p
|
||||||
*/
|
*/
|
||||||
static ZERO: Point = new Point(Fp.ZERO, Fp.ZERO);
|
static ZERO: Point = new Point(Fp.ZERO, Fp.ZERO);
|
||||||
|
static fromAffine(ap: { x: T; y: T }) {
|
||||||
|
return new Point(ap.x, ap.y);
|
||||||
|
}
|
||||||
|
toAffine(iz?: bigint) {
|
||||||
|
return { x: this.x, y: this.y };
|
||||||
|
}
|
||||||
|
|
||||||
// We calculate precomputes for elliptic curve point multiplication
|
// We calculate precomputes for elliptic curve point multiplication
|
||||||
// using windowed method. This specifies window size and
|
// using windowed method. This specifies window size and
|
||||||
@ -1124,10 +1132,11 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|||||||
// Also it can be bigger for P224 + SHA256
|
// Also it can be bigger for P224 + SHA256
|
||||||
function prepSig(msgHash: Hex, privateKey: PrivKey, opts = defaultSigOpts) {
|
function prepSig(msgHash: Hex, privateKey: PrivKey, opts = defaultSigOpts) {
|
||||||
if (msgHash == null) throw new Error(`sign: expected valid message hash, not "${msgHash}"`);
|
if (msgHash == null) throw new Error(`sign: expected valid message hash, not "${msgHash}"`);
|
||||||
if (['recovered', 'canonical'].some(k => k in opts)) // Ban legacy options
|
if (['recovered', 'canonical'].some((k) => k in opts))
|
||||||
|
// Ban legacy options
|
||||||
throw new Error('sign() legacy options not supported');
|
throw new Error('sign() legacy options not supported');
|
||||||
let { lowS } = opts; // generates low-s sigs by default
|
let { lowS } = opts; // generates low-s sigs by default
|
||||||
if (lowS == null) lowS = true; // RFC6979 3.2: we skip step A, because
|
if (lowS == null) lowS = true; // RFC6979 3.2: we skip step A, because
|
||||||
// Step A is ignored, since we already provide hash instead of msg
|
// Step A is ignored, since we already provide hash instead of msg
|
||||||
|
|
||||||
// NOTE: instead of bits2int, we calling here truncateHash, since we need
|
// NOTE: instead of bits2int, we calling here truncateHash, since we need
|
||||||
@ -1141,7 +1150,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|||||||
const d = normalizePrivateKey(privateKey);
|
const d = normalizePrivateKey(privateKey);
|
||||||
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
|
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
|
||||||
const seedArgs = [int2octets(d), h1octets];
|
const seedArgs = [int2octets(d), h1octets];
|
||||||
let ent = opts.extraEntropy; // RFC6979 3.6: additional k' (optional)
|
let ent = opts.extraEntropy; // RFC6979 3.6: additional k' (optional)
|
||||||
if (ent != null) {
|
if (ent != null) {
|
||||||
if (ent === true) ent = CURVE.randomBytes(Fp.BYTES);
|
if (ent === true) ent = CURVE.randomBytes(Fp.BYTES);
|
||||||
const e = ut.ensureBytes(ent);
|
const e = ut.ensureBytes(ent);
|
||||||
|
@ -210,7 +210,7 @@ export const ed25519ph = twistedEdwards({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
||||||
ed25519.Point,
|
ed25519.ExtendedPoint,
|
||||||
(scalars: bigint[]) => map_to_curve_elligator2_edwards25519(scalars[0]),
|
(scalars: bigint[]) => map_to_curve_elligator2_edwards25519(scalars[0]),
|
||||||
{
|
{
|
||||||
DST: 'edwards25519_XMD:SHA-512_ELL2_RO_',
|
DST: 'edwards25519_XMD:SHA-512_ELL2_RO_',
|
||||||
|
@ -197,7 +197,7 @@ export const ed448 = twistedEdwards(ED448_DEF);
|
|||||||
export const ed448ph = twistedEdwards({ ...ED448_DEF, preHash: shake256_64 });
|
export const ed448ph = twistedEdwards({ ...ED448_DEF, preHash: shake256_64 });
|
||||||
|
|
||||||
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
||||||
ed448.Point,
|
ed448.ExtendedPoint,
|
||||||
(scalars: bigint[]) => map_to_curve_elligator2_edwards448(scalars[0]),
|
(scalars: bigint[]) => map_to_curve_elligator2_edwards448(scalars[0]),
|
||||||
{
|
{
|
||||||
DST: 'edwards448_XOF:SHAKE256_ELL2_RO_',
|
DST: 'edwards448_XOF:SHAKE256_ELL2_RO_',
|
||||||
|
@ -39,7 +39,7 @@ export function groupHash(tag: Uint8Array, personalization: Uint8Array) {
|
|||||||
h.update(GH_FIRST_BLOCK);
|
h.update(GH_FIRST_BLOCK);
|
||||||
h.update(tag);
|
h.update(tag);
|
||||||
// NOTE: returns ExtendedPoint, in case it will be multiplied later
|
// NOTE: returns ExtendedPoint, in case it will be multiplied later
|
||||||
let p = jubjub.ExtendedPoint.fromAffine(jubjub.Point.fromHex(h.digest()));
|
let p = jubjub.ExtendedPoint.fromAffine(jubjub.ExtendedPoint.fromHex(h.digest()));
|
||||||
// NOTE: cannot replace with isSmallOrder, returns Point*8
|
// NOTE: cannot replace with isSmallOrder, returns Point*8
|
||||||
p = p.multiply(jubjub.CURVE.h);
|
p = p.multiply(jubjub.CURVE.h);
|
||||||
if (p.equals(jubjub.ExtendedPoint.ZERO)) throw new Error('Point has small order');
|
if (p.equals(jubjub.ExtendedPoint.ZERO)) throw new Error('Point has small order');
|
||||||
|
@ -313,12 +313,12 @@ const NUM_RUNS = 5;
|
|||||||
const getXY = (p) => ({ x: p.x, y: p.y });
|
const getXY = (p) => ({ x: p.x, y: p.y });
|
||||||
|
|
||||||
function equal(a, b, comment) {
|
function equal(a, b, comment) {
|
||||||
deepStrictEqual(a.equals(b), true, 'eq(${comment})');
|
deepStrictEqual(a.equals(b), true, `eq(${comment})`);
|
||||||
if (a.toAffine && b.toAffine) {
|
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) {
|
} else if (!a.toAffine && !b.toAffine) {
|
||||||
// Already affine
|
// Already affine
|
||||||
deepStrictEqual(getXY(a), getXY(b), 'eqAffine(${comment})');
|
deepStrictEqual(getXY(a), getXY(b), `eqAffine(${comment})`);
|
||||||
} else throw new Error('Different point types');
|
} else throw new Error('Different point types');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,8 +354,8 @@ for (const name in CURVES) {
|
|||||||
equal(G[0].negate(), G[0], '-0 = 0');
|
equal(G[0].negate(), G[0], '-0 = 0');
|
||||||
for (let i = 0; i < G.length; i++) {
|
for (let i = 0; i < G.length; i++) {
|
||||||
const p = G[i];
|
const p = G[i];
|
||||||
equal(p, p.add(G[0]), '${i}*G + 0 = ${i}*G');
|
equal(p, p.add(G[0]), `${i}*G + 0 = ${i}*G`);
|
||||||
equal(G[0].multiply(BigInt(i + 1)), G[0], '${i + 1}*0 = 0');
|
equal(G[0].multiply(BigInt(i + 1)), G[0], `${i + 1}*0 = 0`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
should('(one)', () => {
|
should('(one)', () => {
|
||||||
@ -447,8 +447,8 @@ for (const name in CURVES) {
|
|||||||
throws(() => G[1][op](new Uint8Array([0])), 'ui8a([0])');
|
throws(() => G[1][op](new Uint8Array([0])), 'ui8a([0])');
|
||||||
throws(() => G[1][op](new Uint8Array([1])), 'ui8a([1])');
|
throws(() => G[1][op](new Uint8Array([1])), 'ui8a([1])');
|
||||||
throws(() => G[1][op](new Uint8Array(4096).fill(1)), 'ui8a(4096*[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}');
|
// if (G[1].toAffine) throws(() => G[1][op](C.Point.BASE), `Point ${op} ${pointName}`);
|
||||||
throws(() => G[1][op](o.BASE), '${op}/other curve point');
|
throws(() => G[1][op](o.BASE), `${op}/other curve point`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -468,7 +468,7 @@ for (const name in CURVES) {
|
|||||||
throws(() => G[1].equals(new Uint8Array([0])), 'ui8a([0])');
|
throws(() => G[1].equals(new Uint8Array([0])), 'ui8a([0])');
|
||||||
throws(() => G[1].equals(new Uint8Array([1])), 'ui8a([1])');
|
throws(() => G[1].equals(new Uint8Array([1])), 'ui8a([1])');
|
||||||
throws(() => G[1].equals(new Uint8Array(4096).fill(1)), 'ui8a(4096*[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');
|
throws(() => G[1].equals(o.BASE), 'other curve point');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -497,18 +497,18 @@ for (const name in CURVES) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Complex point (Extended/Jacobian/Projective?)
|
// Complex point (Extended/Jacobian/Projective?)
|
||||||
if (p.BASE.toAffine) {
|
// if (p.BASE.toAffine && C.Point) {
|
||||||
should('toAffine()', () => {
|
// should('toAffine()', () => {
|
||||||
equal(p.ZERO.toAffine(), C.Point.ZERO, '0 = 0');
|
// equal(p.ZERO.toAffine(), C.Point.ZERO, '0 = 0');
|
||||||
equal(p.BASE.toAffine(), C.Point.BASE, '1 = 1');
|
// equal(p.BASE.toAffine(), C.Point.BASE, '1 = 1');
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
if (p.fromAffine) {
|
// if (p.fromAffine && C.Point) {
|
||||||
should('fromAffine()', () => {
|
// should('fromAffine()', () => {
|
||||||
equal(p.ZERO, p.fromAffine(C.Point.ZERO), '0 = 0');
|
// equal(p.ZERO, p.fromAffine(C.Point.ZERO), '0 = 0');
|
||||||
equal(p.BASE, p.fromAffine(C.Point.BASE), '1 = 1');
|
// equal(p.BASE, p.fromAffine(C.Point.BASE), '1 = 1');
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
// toHex/fromHex (if available)
|
// toHex/fromHex (if available)
|
||||||
if (p.fromHex && p.BASE.toHex) {
|
if (p.fromHex && p.BASE.toHex) {
|
||||||
should('fromHex(toHex()) roundtrip', () => {
|
should('fromHex(toHex()) roundtrip', () => {
|
||||||
|
@ -20,6 +20,7 @@ import { default as x25519vectors } from './wycheproof/x25519_test.json' assert
|
|||||||
describe('ed25519', () => {
|
describe('ed25519', () => {
|
||||||
const ed = ed25519;
|
const ed = ed25519;
|
||||||
const hex = bytesToHex;
|
const hex = bytesToHex;
|
||||||
|
const Point = ed.ExtendedPoint;
|
||||||
|
|
||||||
function to32Bytes(numOrStr) {
|
function to32Bytes(numOrStr) {
|
||||||
let hex = typeof numOrStr === 'string' ? numOrStr : numOrStr.toString(16);
|
let hex = typeof numOrStr === 'string' ? numOrStr : numOrStr.toString(16);
|
||||||
@ -114,55 +115,45 @@ describe('ed25519', () => {
|
|||||||
deepStrictEqual(ed.verify(signature, wrongMsg, publicKey), false);
|
deepStrictEqual(ed.verify(signature, wrongMsg, publicKey), false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// https://xmr.llcoins.net/addresstests.html
|
describe('BASE_POINT.multiply()', () => {
|
||||||
should(
|
// https://xmr.llcoins.net/addresstests.html
|
||||||
'ed25519/BASE_POINT.multiply()/should create right publicKey without SHA-512 hashing TEST 1',
|
should('create right publicKey without SHA-512 hashing TEST 1', () => {
|
||||||
() => {
|
|
||||||
const publicKey =
|
const publicKey =
|
||||||
ed.Point.BASE.multiply(0x90af56259a4b6bfbc4337980d5d75fbe3c074630368ff3804d33028e5dbfa77n);
|
Point.BASE.multiply(0x90af56259a4b6bfbc4337980d5d75fbe3c074630368ff3804d33028e5dbfa77n);
|
||||||
deepStrictEqual(
|
deepStrictEqual(
|
||||||
publicKey.toHex(),
|
publicKey.toHex(),
|
||||||
'0f3b913371411b27e646b537e888f685bf929ea7aab93c950ed84433f064480d'
|
'0f3b913371411b27e646b537e888f685bf929ea7aab93c950ed84433f064480d'
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
);
|
should('create right publicKey without SHA-512 hashing TEST 2', () => {
|
||||||
should(
|
|
||||||
'ed25519/BASE_POINT.multiply()/should create right publicKey without SHA-512 hashing TEST 2',
|
|
||||||
() => {
|
|
||||||
const publicKey =
|
const publicKey =
|
||||||
ed.Point.BASE.multiply(0x364e8711a60780382a5d57b061c126f039940f28a9e91fe039d4d3094d8b88n);
|
Point.BASE.multiply(0x364e8711a60780382a5d57b061c126f039940f28a9e91fe039d4d3094d8b88n);
|
||||||
deepStrictEqual(
|
deepStrictEqual(
|
||||||
publicKey.toHex(),
|
publicKey.toHex(),
|
||||||
'ad545340b58610f0cd62f17d55af1ab11ecde9c084d5476865ddb4dbda015349'
|
'ad545340b58610f0cd62f17d55af1ab11ecde9c084d5476865ddb4dbda015349'
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
);
|
should('create right publicKey without SHA-512 hashing TEST 3', () => {
|
||||||
should(
|
|
||||||
'ed25519/BASE_POINT.multiply()/should create right publicKey without SHA-512 hashing TEST 3',
|
|
||||||
() => {
|
|
||||||
const publicKey =
|
const publicKey =
|
||||||
ed.Point.BASE.multiply(0xb9bf90ff3abec042752cac3a07a62f0c16cfb9d32a3fc2305d676ec2d86e941n);
|
Point.BASE.multiply(0xb9bf90ff3abec042752cac3a07a62f0c16cfb9d32a3fc2305d676ec2d86e941n);
|
||||||
deepStrictEqual(
|
deepStrictEqual(
|
||||||
publicKey.toHex(),
|
publicKey.toHex(),
|
||||||
'e097c4415fe85724d522b2e449e8fd78dd40d20097bdc9ae36fe8ec6fe12cb8c'
|
'e097c4415fe85724d522b2e449e8fd78dd40d20097bdc9ae36fe8ec6fe12cb8c'
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
);
|
should('create right publicKey without SHA-512 hashing TEST 4', () => {
|
||||||
should(
|
|
||||||
'ed25519/BASE_POINT.multiply()/should create right publicKey without SHA-512 hashing TEST 4',
|
|
||||||
() => {
|
|
||||||
const publicKey =
|
const publicKey =
|
||||||
ed.Point.BASE.multiply(0x69d896f02d79524c9878e080308180e2859d07f9f54454e0800e8db0847a46en);
|
Point.BASE.multiply(0x69d896f02d79524c9878e080308180e2859d07f9f54454e0800e8db0847a46en);
|
||||||
deepStrictEqual(
|
deepStrictEqual(
|
||||||
publicKey.toHex(),
|
publicKey.toHex(),
|
||||||
'f12cb7c43b59971395926f278ce7c2eaded9444fbce62ca717564cb508a0db1d'
|
'f12cb7c43b59971395926f278ce7c2eaded9444fbce62ca717564cb508a0db1d'
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
);
|
should('throw Point#multiply on TEST 5', () => {
|
||||||
should('ed25519/BASE_POINT.multiply()/should throw Point#multiply on TEST 5', () => {
|
for (const num of [0n, 0, -1n, -1, 1.1]) {
|
||||||
for (const num of [0n, 0, -1n, -1, 1.1]) {
|
throws(() => Point.BASE.multiply(num));
|
||||||
throws(() => ed.Point.BASE.multiply(num));
|
}
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://ed25519.cr.yp.to/python/sign.py
|
// https://ed25519.cr.yp.to/python/sign.py
|
||||||
@ -184,7 +175,7 @@ describe('ed25519', () => {
|
|||||||
// Calculate
|
// Calculate
|
||||||
const pub = ed.getPublicKey(to32Bytes(priv));
|
const pub = ed.getPublicKey(to32Bytes(priv));
|
||||||
deepStrictEqual(hex(pub), expectedPub);
|
deepStrictEqual(hex(pub), expectedPub);
|
||||||
deepStrictEqual(pub, ed.Point.fromHex(pub).toRawBytes());
|
deepStrictEqual(pub, Point.fromHex(pub).toRawBytes());
|
||||||
|
|
||||||
const signature = hex(ed.sign(msg, priv));
|
const signature = hex(ed.sign(msg, priv));
|
||||||
// console.log('vector', i);
|
// console.log('vector', i);
|
||||||
@ -444,9 +435,10 @@ describe('ed25519', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
should('ZIP-215 compliance tests/disallows sig.s >= CURVE.n', () => {
|
should('ZIP-215 compliance tests/disallows sig.s >= CURVE.n', () => {
|
||||||
const sig = new ed.Signature(ed.Point.BASE, 1n);
|
// sig.R = BASE, sig.s = N+1
|
||||||
sig.s = ed.CURVE.n + 1n;
|
const sig =
|
||||||
throws(() => ed.verify(sig, 'deadbeef', ed.Point.BASE));
|
'5866666666666666666666666666666666666666666666666666666666666666eed3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010';
|
||||||
|
throws(() => ed.verify(sig, 'deadbeef', Point.BASE));
|
||||||
});
|
});
|
||||||
|
|
||||||
const rfc7748Mul = [
|
const rfc7748Mul = [
|
||||||
@ -511,7 +503,7 @@ describe('ed25519', () => {
|
|||||||
|
|
||||||
// should('X25519: should convert base point to montgomery using fromPoint', () => {
|
// should('X25519: should convert base point to montgomery using fromPoint', () => {
|
||||||
// deepStrictEqual(
|
// deepStrictEqual(
|
||||||
// hex(ed.montgomeryCurve.UfromPoint(ed.Point.BASE)),
|
// hex(ed.montgomeryCurve.UfromPoint(Point.BASE)),
|
||||||
// ed.montgomeryCurve.BASE_POINT_U
|
// ed.montgomeryCurve.BASE_POINT_U
|
||||||
// );
|
// );
|
||||||
// });
|
// });
|
||||||
@ -655,7 +647,7 @@ describe('ed25519', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
should('X25519 base point', () => {
|
should('X25519 base point', () => {
|
||||||
const { y } = ed25519.Point.BASE;
|
const { y } = ed25519.ExtendedPoint.BASE;
|
||||||
const { Fp } = ed25519.CURVE;
|
const { Fp } = ed25519.CURVE;
|
||||||
const u = Fp.create((y + 1n) * Fp.invert(1n - y));
|
const u = Fp.create((y + 1n) * Fp.invert(1n - y));
|
||||||
deepStrictEqual(hex(numberToBytesLE(u, 32)), x25519.Gu);
|
deepStrictEqual(hex(numberToBytesLE(u, 32)), x25519.Gu);
|
||||||
@ -664,7 +656,7 @@ describe('ed25519', () => {
|
|||||||
should('isTorsionFree()', () => {
|
should('isTorsionFree()', () => {
|
||||||
const orig = ed.utils.getExtendedPublicKey(ed.utils.randomPrivateKey()).point;
|
const orig = ed.utils.getExtendedPublicKey(ed.utils.randomPrivateKey()).point;
|
||||||
for (const hex of ED25519_TORSION_SUBGROUP.slice(1)) {
|
for (const hex of ED25519_TORSION_SUBGROUP.slice(1)) {
|
||||||
const dirty = orig.add(ed.Point.fromHex(hex));
|
const dirty = orig.add(Point.fromHex(hex));
|
||||||
const cleared = dirty.clearCofactor();
|
const cleared = dirty.clearCofactor();
|
||||||
strictEqual(orig.isTorsionFree(), true, `orig must be torsionFree: ${hex}`);
|
strictEqual(orig.isTorsionFree(), true, `orig must be torsionFree: ${hex}`);
|
||||||
strictEqual(dirty.isTorsionFree(), false, `dirty must not be torsionFree: ${hex}`);
|
strictEqual(dirty.isTorsionFree(), false, `dirty must not be torsionFree: ${hex}`);
|
||||||
|
@ -11,9 +11,10 @@ describe('ed448', () => {
|
|||||||
const ed = ed448;
|
const ed = ed448;
|
||||||
const hex = bytesToHex;
|
const hex = bytesToHex;
|
||||||
ed.utils.precompute(4);
|
ed.utils.precompute(4);
|
||||||
|
const Point = ed.ExtendedPoint;
|
||||||
|
|
||||||
should(`Basic`, () => {
|
should(`Basic`, () => {
|
||||||
const G1 = ed.Point.BASE;
|
const G1 = Point.BASE.toAffine();
|
||||||
deepStrictEqual(
|
deepStrictEqual(
|
||||||
G1.x,
|
G1.x,
|
||||||
224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710n
|
224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710n
|
||||||
@ -22,7 +23,7 @@ describe('ed448', () => {
|
|||||||
G1.y,
|
G1.y,
|
||||||
298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660n
|
298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660n
|
||||||
);
|
);
|
||||||
const G2 = ed.Point.BASE.multiply(2n);
|
const G2 = Point.BASE.multiply(2n).toAffine();
|
||||||
deepStrictEqual(
|
deepStrictEqual(
|
||||||
G2.x,
|
G2.x,
|
||||||
484559149530404593699549205258669689569094240458212040187660132787056912146709081364401144455726350866276831544947397859048262938744149n
|
484559149530404593699549205258669689569094240458212040187660132787056912146709081364401144455726350866276831544947397859048262938744149n
|
||||||
@ -31,7 +32,7 @@ describe('ed448', () => {
|
|||||||
G2.y,
|
G2.y,
|
||||||
494088759867433727674302672526735089350544552303727723746126484473087719117037293890093462157703888342865036477787453078312060500281069n
|
494088759867433727674302672526735089350544552303727723746126484473087719117037293890093462157703888342865036477787453078312060500281069n
|
||||||
);
|
);
|
||||||
const G3 = ed.Point.BASE.multiply(3n);
|
const G3 = Point.BASE.multiply(3n).toAffine();
|
||||||
deepStrictEqual(
|
deepStrictEqual(
|
||||||
G3.x,
|
G3.x,
|
||||||
23839778817283171003887799738662344287085130522697782688245073320169861206004018274567429238677677920280078599146891901463786155880335n
|
23839778817283171003887799738662344287085130522697782688245073320169861206004018274567429238677677920280078599146891901463786155880335n
|
||||||
@ -43,12 +44,12 @@ describe('ed448', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
should('Basic/decompress', () => {
|
should('Basic/decompress', () => {
|
||||||
const G1 = ed.Point.BASE;
|
const G1 = Point.BASE;
|
||||||
const G2 = ed.Point.BASE.multiply(2n);
|
const G2 = Point.BASE.multiply(2n);
|
||||||
const G3 = ed.Point.BASE.multiply(3n);
|
const G3 = Point.BASE.multiply(3n);
|
||||||
const points = [G1, G2, G3];
|
const points = [G1, G2, G3];
|
||||||
const getXY = (p) => ({ x: p.x, y: p.y });
|
const getXY = (p) => p.toAffine();
|
||||||
for (const p of points) deepStrictEqual(getXY(ed.Point.fromHex(p.toHex())), getXY(p));
|
for (const p of points) deepStrictEqual(getXY(Point.fromHex(p.toHex())), getXY(p));
|
||||||
});
|
});
|
||||||
|
|
||||||
const VECTORS_RFC8032 = [
|
const VECTORS_RFC8032 = [
|
||||||
@ -412,7 +413,7 @@ describe('ed448', () => {
|
|||||||
|
|
||||||
should('BASE_POINT.multiply() throws in 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]) {
|
for (const num of [0n, 0, -1n, -1, 1.1]) {
|
||||||
throws(() => ed.Point.BASE.multiply(num));
|
throws(() => ed.ExtendedPoint.BASE.multiply(num));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -559,7 +560,7 @@ describe('ed448', () => {
|
|||||||
|
|
||||||
// should('X448: should convert base point to montgomery using fromPoint', () => {
|
// should('X448: should convert base point to montgomery using fromPoint', () => {
|
||||||
// deepStrictEqual(
|
// deepStrictEqual(
|
||||||
// hex(ed.montgomeryCurve.UfromPoint(ed.Point.BASE)),
|
// hex(ed.montgomeryCurve.UfromPoint(Point.BASE)),
|
||||||
// ed.montgomeryCurve.BASE_POINT_U
|
// ed.montgomeryCurve.BASE_POINT_U
|
||||||
// );
|
// );
|
||||||
// });
|
// });
|
||||||
@ -654,7 +655,7 @@ describe('ed448', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
should('X448 base point', () => {
|
should('X448 base point', () => {
|
||||||
const { x, y } = ed448.Point.BASE;
|
const { x, y } = Point.BASE;
|
||||||
const { Fp } = ed448.CURVE;
|
const { Fp } = ed448.CURVE;
|
||||||
// const invX = Fp.invert(x * x); // x²
|
// const invX = Fp.invert(x * x); // x²
|
||||||
const u = Fp.div(Fp.create(y * y), Fp.create(x * x)); // (y²/x²)
|
const u = Fp.div(Fp.create(y * y), Fp.create(x * x)); // (y²/x²)
|
||||||
|
@ -111,9 +111,11 @@ function testCurve(curve, ro, nu) {
|
|||||||
for (let i = 0; i < ro.vectors.length; i++) {
|
for (let i = 0; i < ro.vectors.length; i++) {
|
||||||
const t = ro.vectors[i];
|
const t = ro.vectors[i];
|
||||||
should(`(${i})`, () => {
|
should(`(${i})`, () => {
|
||||||
const p = curve.hashToCurve(stringToBytes(t.msg), {
|
const p = curve
|
||||||
DST: ro.dst,
|
.hashToCurve(stringToBytes(t.msg), {
|
||||||
});
|
DST: ro.dst,
|
||||||
|
})
|
||||||
|
.toAffine();
|
||||||
deepStrictEqual(p.x, stringToFp(t.P.x), 'Px');
|
deepStrictEqual(p.x, stringToFp(t.P.x), 'Px');
|
||||||
deepStrictEqual(p.y, stringToFp(t.P.y), 'Py');
|
deepStrictEqual(p.y, stringToFp(t.P.y), 'Py');
|
||||||
});
|
});
|
||||||
@ -123,9 +125,11 @@ function testCurve(curve, ro, nu) {
|
|||||||
for (let i = 0; i < nu.vectors.length; i++) {
|
for (let i = 0; i < nu.vectors.length; i++) {
|
||||||
const t = nu.vectors[i];
|
const t = nu.vectors[i];
|
||||||
should(`(${i})`, () => {
|
should(`(${i})`, () => {
|
||||||
const p = curve.encodeToCurve(stringToBytes(t.msg), {
|
const p = curve
|
||||||
DST: nu.dst,
|
.encodeToCurve(stringToBytes(t.msg), {
|
||||||
});
|
DST: nu.dst,
|
||||||
|
})
|
||||||
|
.toAffine();
|
||||||
deepStrictEqual(p.x, stringToFp(t.P.x), 'Px');
|
deepStrictEqual(p.x, stringToFp(t.P.x), 'Px');
|
||||||
deepStrictEqual(p.y, stringToFp(t.P.y), 'Py');
|
deepStrictEqual(p.y, stringToFp(t.P.y), 'Py');
|
||||||
});
|
});
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import { jubjub, findGroupHash } from '../lib/esm/jubjub.js';
|
import { jubjub, findGroupHash } from '../lib/esm/jubjub.js';
|
||||||
import { describe, should } from 'micro-should';
|
import { describe, should } from 'micro-should';
|
||||||
import { deepStrictEqual, throws } from 'assert';
|
import { deepStrictEqual, throws } from 'assert';
|
||||||
import { hexToBytes, bytesToHex } from '@noble/hashes/utils';
|
const Point = jubjub.ExtendedPoint;
|
||||||
|
|
||||||
const G_SPEND = new jubjub.ExtendedPoint(
|
const G_SPEND = new Point(
|
||||||
0x055f1f24f0f0512287e51c3c5a0a6903fc0baf8711de9eafd7c0e66f69d8d2dbn,
|
0x055f1f24f0f0512287e51c3c5a0a6903fc0baf8711de9eafd7c0e66f69d8d2dbn,
|
||||||
0x566178b2505fdd52132a5007d80a04652842e78ffb376897588f406278214ed7n,
|
0x566178b2505fdd52132a5007d80a04652842e78ffb376897588f406278214ed7n,
|
||||||
0x0141fafa1f11088a3b2007c14d652375888f3b37838ba6bdffae096741ceddfen,
|
0x0141fafa1f11088a3b2007c14d652375888f3b37838ba6bdffae096741ceddfen,
|
||||||
0x12eada93c0b7d595f5f04f5ebfb4b7d033ef2884136475cab5e41ce17db5be9cn
|
0x12eada93c0b7d595f5f04f5ebfb4b7d033ef2884136475cab5e41ce17db5be9cn
|
||||||
);
|
);
|
||||||
const G_PROOF = new jubjub.ExtendedPoint(
|
const G_PROOF = new Point(
|
||||||
0x0174d54ce9fad258a2f8a86a1deabf15c7a2b51106b0fbcd9d29020f78936f71n,
|
0x0174d54ce9fad258a2f8a86a1deabf15c7a2b51106b0fbcd9d29020f78936f71n,
|
||||||
0x16871d6d877dcd222e4ec3bccb3f37cb1865a2d37dd3a5dcbc032a69b62b4445n,
|
0x16871d6d877dcd222e4ec3bccb3f37cb1865a2d37dd3a5dcbc032a69b62b4445n,
|
||||||
0x57a3cd31e496d82bd4aa78bd5ecd751cfb76d54a5d3f4560866379f9fc11c9b3n,
|
0x57a3cd31e496d82bd4aa78bd5ecd751cfb76d54a5d3f4560866379f9fc11c9b3n,
|
||||||
@ -22,7 +22,7 @@ describe('jubjub', () => {
|
|||||||
should('toHex/fromHex', () => {
|
should('toHex/fromHex', () => {
|
||||||
// More than field
|
// More than field
|
||||||
throws(() =>
|
throws(() =>
|
||||||
jubjub.Point.fromHex(
|
Point.fromHex(
|
||||||
new Uint8Array([
|
new Uint8Array([
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
@ -31,14 +31,14 @@ describe('jubjub', () => {
|
|||||||
);
|
);
|
||||||
// Multiplicative generator (sqrt == null), not on curve.
|
// Multiplicative generator (sqrt == null), not on curve.
|
||||||
throws(() =>
|
throws(() =>
|
||||||
jubjub.Point.fromHex(
|
Point.fromHex(
|
||||||
new Uint8Array([
|
new Uint8Array([
|
||||||
7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0,
|
0, 0,
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
const tmp = jubjub.Point.fromHex(
|
const tmp = Point.fromHex(
|
||||||
new Uint8Array([
|
new Uint8Array([
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0,
|
0,
|
||||||
@ -47,14 +47,14 @@ describe('jubjub', () => {
|
|||||||
deepStrictEqual(tmp.x, 0x8d51ccce760304d0ec030002760300000001000000000000n);
|
deepStrictEqual(tmp.x, 0x8d51ccce760304d0ec030002760300000001000000000000n);
|
||||||
deepStrictEqual(tmp.y, 0n);
|
deepStrictEqual(tmp.y, 0n);
|
||||||
|
|
||||||
const S = G_SPEND.toAffine().toRawBytes();
|
const S = G_SPEND.toRawBytes();
|
||||||
const S2 = G_SPEND.double().toAffine().toRawBytes();
|
const S2 = G_SPEND.double().toRawBytes();
|
||||||
const P = G_PROOF.toAffine().toRawBytes();
|
const P = G_PROOF.toRawBytes();
|
||||||
const P2 = G_PROOF.double().toAffine().toRawBytes();
|
const P2 = G_PROOF.double().toRawBytes();
|
||||||
const S_exp = jubjub.Point.fromHex(S);
|
const S_exp = Point.fromHex(S);
|
||||||
const S2_exp = jubjub.Point.fromHex(S2);
|
const S2_exp = Point.fromHex(S2);
|
||||||
const P_exp = jubjub.Point.fromHex(P);
|
const P_exp = Point.fromHex(P);
|
||||||
const P2_exp = jubjub.Point.fromHex(P2);
|
const P2_exp = Point.fromHex(P2);
|
||||||
deepStrictEqual(getXY(G_SPEND.toAffine()), getXY(S_exp));
|
deepStrictEqual(getXY(G_SPEND.toAffine()), getXY(S_exp));
|
||||||
deepStrictEqual(getXY(G_SPEND.double().toAffine()), getXY(S2_exp));
|
deepStrictEqual(getXY(G_SPEND.double().toAffine()), getXY(S2_exp));
|
||||||
deepStrictEqual(getXY(G_PROOF.toAffine()), getXY(P_exp));
|
deepStrictEqual(getXY(G_PROOF.toAffine()), getXY(P_exp));
|
||||||
|
Loading…
Reference in New Issue
Block a user