@noble/curves 0.5.2 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -41
- package/lib/_shortw_utils.d.ts +13 -24
- package/lib/abstract/bls.d.ts +39 -32
- package/lib/abstract/bls.js +74 -73
- package/lib/abstract/{group.d.ts → curve.d.ts} +30 -1
- package/lib/abstract/{group.js → curve.js} +33 -2
- package/lib/abstract/edwards.d.ts +30 -72
- package/lib/abstract/edwards.js +206 -389
- package/lib/abstract/hash-to-curve.d.ts +25 -6
- package/lib/abstract/hash-to-curve.js +40 -12
- package/lib/abstract/modular.d.ts +21 -8
- package/lib/abstract/modular.js +72 -48
- package/lib/abstract/montgomery.js +23 -68
- package/lib/abstract/poseidon.d.ts +29 -0
- package/lib/abstract/poseidon.js +115 -0
- package/lib/abstract/utils.d.ts +9 -37
- package/lib/abstract/utils.js +61 -87
- package/lib/abstract/weierstrass.d.ts +58 -81
- package/lib/abstract/weierstrass.js +485 -679
- package/lib/bls12-381.js +63 -58
- package/lib/bn.js +1 -1
- package/lib/ed25519.d.ts +7 -5
- package/lib/ed25519.js +82 -79
- package/lib/ed448.d.ts +3 -0
- package/lib/ed448.js +86 -83
- package/lib/esm/abstract/bls.js +75 -74
- package/lib/esm/abstract/{group.js → curve.js} +31 -1
- package/lib/esm/abstract/edwards.js +204 -387
- package/lib/esm/abstract/hash-to-curve.js +38 -11
- package/lib/esm/abstract/modular.js +69 -47
- package/lib/esm/abstract/montgomery.js +24 -69
- package/lib/esm/abstract/poseidon.js +109 -0
- package/lib/esm/abstract/utils.js +58 -82
- package/lib/esm/abstract/weierstrass.js +484 -678
- package/lib/esm/bls12-381.js +75 -70
- package/lib/esm/bn.js +1 -1
- package/lib/esm/ed25519.js +80 -78
- package/lib/esm/ed448.js +84 -82
- package/lib/esm/jubjub.js +1 -1
- package/lib/esm/p224.js +1 -1
- package/lib/esm/p256.js +11 -9
- package/lib/esm/p384.js +11 -9
- package/lib/esm/p521.js +12 -23
- package/lib/esm/secp256k1.js +124 -162
- package/lib/esm/stark.js +105 -41
- package/lib/jubjub.d.ts +2 -2
- package/lib/jubjub.js +1 -1
- package/lib/p192.d.ts +26 -48
- package/lib/p224.d.ts +26 -48
- package/lib/p224.js +1 -1
- package/lib/p256.d.ts +29 -48
- package/lib/p256.js +13 -10
- package/lib/p384.d.ts +29 -48
- package/lib/p384.js +13 -10
- package/lib/p521.d.ts +37 -57
- package/lib/p521.js +14 -24
- package/lib/secp256k1.d.ts +37 -46
- package/lib/secp256k1.js +124 -162
- package/lib/stark.d.ts +39 -22
- package/lib/stark.js +108 -41
- package/package.json +15 -10
package/lib/esm/bls12-381.js
CHANGED
|
@@ -13,7 +13,7 @@ import { sha256 } from '@noble/hashes/sha256';
|
|
|
13
13
|
import { randomBytes } from '@noble/hashes/utils';
|
|
14
14
|
import { bls } from './abstract/bls.js';
|
|
15
15
|
import * as mod from './abstract/modular.js';
|
|
16
|
-
import { concatBytes, ensureBytes, numberToBytesBE, bytesToNumberBE, bitLen, bitSet, bitGet, bitMask, } from './abstract/utils.js';
|
|
16
|
+
import { concatBytes as concatB, ensureBytes, numberToBytesBE, bytesToNumberBE, bitLen, bitSet, bitGet, bitMask, } from './abstract/utils.js';
|
|
17
17
|
// Types
|
|
18
18
|
import { mapToCurveSimpleSWU, } from './abstract/weierstrass.js';
|
|
19
19
|
import { isogenyMap } from './abstract/hash-to-curve.js';
|
|
@@ -65,24 +65,24 @@ const Fp2 = {
|
|
|
65
65
|
ONE: { c0: Fp.ONE, c1: Fp.ZERO },
|
|
66
66
|
create: (num) => num,
|
|
67
67
|
isValid: ({ c0, c1 }) => typeof c0 === 'bigint' && typeof c1 === 'bigint',
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
is0: ({ c0, c1 }) => Fp.is0(c0) && Fp.is0(c1),
|
|
69
|
+
eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp.eql(c0, r0) && Fp.eql(c1, r1),
|
|
70
|
+
neg: ({ c0, c1 }) => ({ c0: Fp.neg(c0), c1: Fp.neg(c1) }),
|
|
71
71
|
pow: (num, power) => mod.FpPow(Fp2, num, power),
|
|
72
72
|
invertBatch: (nums) => mod.FpInvertBatch(Fp2, nums),
|
|
73
73
|
// Normalized
|
|
74
74
|
add: Fp2Add,
|
|
75
75
|
sub: Fp2Subtract,
|
|
76
76
|
mul: Fp2Multiply,
|
|
77
|
-
|
|
77
|
+
sqr: Fp2Square,
|
|
78
78
|
// NonNormalized stuff
|
|
79
79
|
addN: Fp2Add,
|
|
80
80
|
subN: Fp2Subtract,
|
|
81
81
|
mulN: Fp2Multiply,
|
|
82
|
-
|
|
82
|
+
sqrN: Fp2Square,
|
|
83
83
|
// Why inversion for bigint inside Fp instead of Fp2? it is even used in that context?
|
|
84
|
-
div: (lhs, rhs) => Fp2.mul(lhs, typeof rhs === 'bigint' ? Fp.
|
|
85
|
-
|
|
84
|
+
div: (lhs, rhs) => Fp2.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp2.inv(rhs)),
|
|
85
|
+
inv: ({ c0: a, c1: b }) => {
|
|
86
86
|
// We wish to find the multiplicative inverse of a nonzero
|
|
87
87
|
// element a + bu in Fp2. We leverage an identity
|
|
88
88
|
//
|
|
@@ -96,11 +96,11 @@ const Fp2 = {
|
|
|
96
96
|
// This gives that (a - bu)/(a² + b²) is the inverse
|
|
97
97
|
// of (a + bu). Importantly, this can be computing using
|
|
98
98
|
// only a single inversion in Fp.
|
|
99
|
-
const factor = Fp.
|
|
99
|
+
const factor = Fp.inv(Fp.create(a * a + b * b));
|
|
100
100
|
return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) };
|
|
101
101
|
},
|
|
102
102
|
sqrt: (num) => {
|
|
103
|
-
if (Fp2.
|
|
103
|
+
if (Fp2.eql(num, Fp2.ZERO))
|
|
104
104
|
return Fp2.ZERO; // Algo doesn't handles this case
|
|
105
105
|
// TODO: Optimize this line. It's extremely slow.
|
|
106
106
|
// Speeding this up would boost aggregateSignatures.
|
|
@@ -109,9 +109,9 @@ const Fp2 = {
|
|
|
109
109
|
// https://github.com/supranational/blst/blob/aae0c7d70b799ac269ff5edf29d8191dbd357876/src/exp2.c#L1
|
|
110
110
|
// Inspired by https://github.com/dalek-cryptography/curve25519-dalek/blob/17698df9d4c834204f83a3574143abacb4fc81a5/src/field.rs#L99
|
|
111
111
|
const candidateSqrt = Fp2.pow(num, (Fp2.ORDER + 8n) / 16n);
|
|
112
|
-
const check = Fp2.div(Fp2.
|
|
112
|
+
const check = Fp2.div(Fp2.sqr(candidateSqrt), num); // candidateSqrt.square().div(this);
|
|
113
113
|
const R = FP2_ROOTS_OF_UNITY;
|
|
114
|
-
const divisor = [R[0], R[2], R[4], R[6]].find((r) => Fp2.
|
|
114
|
+
const divisor = [R[0], R[2], R[4], R[6]].find((r) => Fp2.eql(r, check));
|
|
115
115
|
if (!divisor)
|
|
116
116
|
throw new Error('No root');
|
|
117
117
|
const index = R.indexOf(divisor);
|
|
@@ -119,7 +119,7 @@ const Fp2 = {
|
|
|
119
119
|
if (!root)
|
|
120
120
|
throw new Error('Invalid root');
|
|
121
121
|
const x1 = Fp2.div(candidateSqrt, root);
|
|
122
|
-
const x2 = Fp2.
|
|
122
|
+
const x2 = Fp2.neg(x1);
|
|
123
123
|
const { re: re1, im: im1 } = Fp2.reim(x1);
|
|
124
124
|
const { re: re2, im: im2 } = Fp2.reim(x2);
|
|
125
125
|
if (im1 > im2 || (im1 === im2 && re1 > re2))
|
|
@@ -140,7 +140,7 @@ const Fp2 = {
|
|
|
140
140
|
throw new Error(`fromBytes wrong length=${b.length}`);
|
|
141
141
|
return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) };
|
|
142
142
|
},
|
|
143
|
-
toBytes: ({ c0, c1 }) =>
|
|
143
|
+
toBytes: ({ c0, c1 }) => concatB(Fp.toBytes(c0), Fp.toBytes(c1)),
|
|
144
144
|
cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({
|
|
145
145
|
c0: Fp.cmov(c0, r0, c),
|
|
146
146
|
c1: Fp.cmov(c1, r1, c),
|
|
@@ -230,15 +230,15 @@ const Fp6Multiply = ({ c0, c1, c2 }, rhs) => {
|
|
|
230
230
|
};
|
|
231
231
|
};
|
|
232
232
|
const Fp6Square = ({ c0, c1, c2 }) => {
|
|
233
|
-
let t0 = Fp2.
|
|
233
|
+
let t0 = Fp2.sqr(c0); // c0²
|
|
234
234
|
let t1 = Fp2.mul(Fp2.mul(c0, c1), 2n); // 2 * c0 * c1
|
|
235
235
|
let t3 = Fp2.mul(Fp2.mul(c1, c2), 2n); // 2 * c1 * c2
|
|
236
|
-
let t4 = Fp2.
|
|
236
|
+
let t4 = Fp2.sqr(c2); // c2²
|
|
237
237
|
return {
|
|
238
238
|
c0: Fp2.add(Fp2.mulByNonresidue(t3), t0),
|
|
239
239
|
c1: Fp2.add(Fp2.mulByNonresidue(t4), t1),
|
|
240
240
|
// T1 + (c0 - c1 + c2)² + T3 - T0 - T4
|
|
241
|
-
c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.
|
|
241
|
+
c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4),
|
|
242
242
|
};
|
|
243
243
|
};
|
|
244
244
|
const Fp6 = {
|
|
@@ -250,32 +250,32 @@ const Fp6 = {
|
|
|
250
250
|
ONE: { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO },
|
|
251
251
|
create: (num) => num,
|
|
252
252
|
isValid: ({ c0, c1, c2 }) => Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2),
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
253
|
+
is0: ({ c0, c1, c2 }) => Fp2.is0(c0) && Fp2.is0(c1) && Fp2.is0(c2),
|
|
254
|
+
neg: ({ c0, c1, c2 }) => ({ c0: Fp2.neg(c0), c1: Fp2.neg(c1), c2: Fp2.neg(c2) }),
|
|
255
|
+
eql: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => Fp2.eql(c0, r0) && Fp2.eql(c1, r1) && Fp2.eql(c2, r2),
|
|
256
256
|
sqrt: () => {
|
|
257
257
|
throw new Error('Not implemented');
|
|
258
258
|
},
|
|
259
259
|
// Do we need division by bigint at all? Should be done via order:
|
|
260
|
-
div: (lhs, rhs) => Fp6.mul(lhs, typeof rhs === 'bigint' ? Fp.
|
|
260
|
+
div: (lhs, rhs) => Fp6.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp6.inv(rhs)),
|
|
261
261
|
pow: (num, power) => mod.FpPow(Fp6, num, power),
|
|
262
262
|
invertBatch: (nums) => mod.FpInvertBatch(Fp6, nums),
|
|
263
263
|
// Normalized
|
|
264
264
|
add: Fp6Add,
|
|
265
265
|
sub: Fp6Subtract,
|
|
266
266
|
mul: Fp6Multiply,
|
|
267
|
-
|
|
267
|
+
sqr: Fp6Square,
|
|
268
268
|
// NonNormalized stuff
|
|
269
269
|
addN: Fp6Add,
|
|
270
270
|
subN: Fp6Subtract,
|
|
271
271
|
mulN: Fp6Multiply,
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
let t0 = Fp2.sub(Fp2.
|
|
275
|
-
let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.
|
|
276
|
-
let t2 = Fp2.sub(Fp2.
|
|
272
|
+
sqrN: Fp6Square,
|
|
273
|
+
inv: ({ c0, c1, c2 }) => {
|
|
274
|
+
let t0 = Fp2.sub(Fp2.sqr(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))); // c0² - c2 * c1 * (u + 1)
|
|
275
|
+
let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.sqr(c2)), Fp2.mul(c0, c1)); // c2² * (u + 1) - c0 * c1
|
|
276
|
+
let t2 = Fp2.sub(Fp2.sqr(c1), Fp2.mul(c0, c2)); // c1² - c0 * c2
|
|
277
277
|
// 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0)
|
|
278
|
-
let t4 = Fp2.
|
|
278
|
+
let t4 = Fp2.inv(Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0)));
|
|
279
279
|
return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) };
|
|
280
280
|
},
|
|
281
281
|
// Bytes utils
|
|
@@ -288,7 +288,7 @@ const Fp6 = {
|
|
|
288
288
|
c2: Fp2.fromBytes(b.subarray(2 * Fp2.BYTES)),
|
|
289
289
|
};
|
|
290
290
|
},
|
|
291
|
-
toBytes: ({ c0, c1, c2 }) =>
|
|
291
|
+
toBytes: ({ c0, c1, c2 }) => concatB(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2)),
|
|
292
292
|
cmov: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }, c) => ({
|
|
293
293
|
c0: Fp2.cmov(c0, r0, c),
|
|
294
294
|
c1: Fp2.cmov(c1, r1, c),
|
|
@@ -416,11 +416,11 @@ const Fp12Square = ({ c0, c1 }) => {
|
|
|
416
416
|
}; // AB + AB
|
|
417
417
|
};
|
|
418
418
|
function Fp4Square(a, b) {
|
|
419
|
-
const a2 = Fp2.
|
|
420
|
-
const b2 = Fp2.
|
|
419
|
+
const a2 = Fp2.sqr(a);
|
|
420
|
+
const b2 = Fp2.sqr(b);
|
|
421
421
|
return {
|
|
422
422
|
first: Fp2.add(Fp2.mulByNonresidue(b2), a2),
|
|
423
|
-
second: Fp2.sub(Fp2.sub(Fp2.
|
|
423
|
+
second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b²
|
|
424
424
|
};
|
|
425
425
|
}
|
|
426
426
|
const Fp12 = {
|
|
@@ -432,29 +432,29 @@ const Fp12 = {
|
|
|
432
432
|
ONE: { c0: Fp6.ONE, c1: Fp6.ZERO },
|
|
433
433
|
create: (num) => num,
|
|
434
434
|
isValid: ({ c0, c1 }) => Fp6.isValid(c0) && Fp6.isValid(c1),
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
435
|
+
is0: ({ c0, c1 }) => Fp6.is0(c0) && Fp6.is0(c1),
|
|
436
|
+
neg: ({ c0, c1 }) => ({ c0: Fp6.neg(c0), c1: Fp6.neg(c1) }),
|
|
437
|
+
eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp6.eql(c0, r0) && Fp6.eql(c1, r1),
|
|
438
438
|
sqrt: () => {
|
|
439
439
|
throw new Error('Not implemented');
|
|
440
440
|
},
|
|
441
|
-
|
|
442
|
-
let t = Fp6.
|
|
443
|
-
return { c0: Fp6.mul(c0, t), c1: Fp6.
|
|
441
|
+
inv: ({ c0, c1 }) => {
|
|
442
|
+
let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1)))); // 1 / (c0² - c1² * v)
|
|
443
|
+
return { c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) }; // ((C0 * T) * T) + (-C1 * T) * w
|
|
444
444
|
},
|
|
445
|
-
div: (lhs, rhs) => Fp12.mul(lhs, typeof rhs === 'bigint' ? Fp.
|
|
445
|
+
div: (lhs, rhs) => Fp12.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp12.inv(rhs)),
|
|
446
446
|
pow: (num, power) => mod.FpPow(Fp12, num, power),
|
|
447
447
|
invertBatch: (nums) => mod.FpInvertBatch(Fp12, nums),
|
|
448
448
|
// Normalized
|
|
449
449
|
add: Fp12Add,
|
|
450
450
|
sub: Fp12Subtract,
|
|
451
451
|
mul: Fp12Multiply,
|
|
452
|
-
|
|
452
|
+
sqr: Fp12Square,
|
|
453
453
|
// NonNormalized stuff
|
|
454
454
|
addN: Fp12Add,
|
|
455
455
|
subN: Fp12Subtract,
|
|
456
456
|
mulN: Fp12Multiply,
|
|
457
|
-
|
|
457
|
+
sqrN: Fp12Square,
|
|
458
458
|
// Bytes utils
|
|
459
459
|
fromBytes: (b) => {
|
|
460
460
|
if (b.length !== Fp12.BYTES)
|
|
@@ -464,7 +464,7 @@ const Fp12 = {
|
|
|
464
464
|
c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)),
|
|
465
465
|
};
|
|
466
466
|
},
|
|
467
|
-
toBytes: ({ c0, c1 }) =>
|
|
467
|
+
toBytes: ({ c0, c1 }) => concatB(Fp6.toBytes(c0), Fp6.toBytes(c1)),
|
|
468
468
|
cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({
|
|
469
469
|
c0: Fp6.cmov(c0, r0, c),
|
|
470
470
|
c1: Fp6.cmov(c1, r1, c),
|
|
@@ -508,7 +508,7 @@ const Fp12 = {
|
|
|
508
508
|
c0: Fp6.multiplyByFp2(c0, rhs),
|
|
509
509
|
c1: Fp6.multiplyByFp2(c1, rhs),
|
|
510
510
|
}),
|
|
511
|
-
conjugate: ({ c0, c1 }) => ({ c0, c1: Fp6.
|
|
511
|
+
conjugate: ({ c0, c1 }) => ({ c0, c1: Fp6.neg(c1) }),
|
|
512
512
|
// A cyclotomic group is a subgroup of Fp^n defined by
|
|
513
513
|
// GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1}
|
|
514
514
|
// The result of any pairing is in a cyclotomic subgroup
|
|
@@ -787,7 +787,7 @@ function G2psi(c, P) {
|
|
|
787
787
|
// 1 / F2(2)^((p-1)/3) in GF(p²)
|
|
788
788
|
const PSI2_C1 = 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn;
|
|
789
789
|
function psi2(x, y) {
|
|
790
|
-
return [Fp2.mul(x, PSI2_C1), Fp2.
|
|
790
|
+
return [Fp2.mul(x, PSI2_C1), Fp2.neg(y)];
|
|
791
791
|
}
|
|
792
792
|
function G2psi2(c, P) {
|
|
793
793
|
const affine = P.toAffine();
|
|
@@ -809,6 +809,7 @@ const htfDefaults = {
|
|
|
809
809
|
// defined in section 2.2.5
|
|
810
810
|
// Use utils.getDSTLabel(), utils.setDSTLabel(value)
|
|
811
811
|
DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_',
|
|
812
|
+
encodeDST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_',
|
|
812
813
|
// p: the characteristic of F
|
|
813
814
|
// where F is a finite field of characteristic p and order q = p^m
|
|
814
815
|
p: Fp.ORDER,
|
|
@@ -875,7 +876,7 @@ export const bls12_381 = bls({
|
|
|
875
876
|
isTorsionFree: (c, point) => {
|
|
876
877
|
// φ endomorphism
|
|
877
878
|
const cubicRootOfUnityModP = 0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen;
|
|
878
|
-
const phi = new c(Fp.mul(point.
|
|
879
|
+
const phi = new c(Fp.mul(point.px, cubicRootOfUnityModP), point.py, point.pz);
|
|
879
880
|
// todo: unroll
|
|
880
881
|
const xP = point.multiplyUnsafe(bls12_381.CURVE.x).negate(); // [x]P
|
|
881
882
|
const u2P = xP.multiplyUnsafe(bls12_381.CURVE.x); // [u2]P
|
|
@@ -917,13 +918,13 @@ export const bls12_381 = bls({
|
|
|
917
918
|
throw new Error('Invalid compressed G1 point');
|
|
918
919
|
const aflag = bitGet(compressedValue, C_BIT_POS);
|
|
919
920
|
if ((y * 2n) / P !== aflag)
|
|
920
|
-
y = Fp.
|
|
921
|
+
y = Fp.neg(y);
|
|
921
922
|
return { x: Fp.create(x), y: Fp.create(y) };
|
|
922
923
|
}
|
|
923
924
|
else if (bytes.length === 96) {
|
|
924
925
|
// Check if the infinity flag is set
|
|
925
926
|
if ((bytes[0] & (1 << 6)) !== 0)
|
|
926
|
-
return bls12_381.G1.
|
|
927
|
+
return bls12_381.G1.ProjectivePoint.ZERO.toAffine();
|
|
927
928
|
const x = bytesToNumberBE(bytes.slice(0, Fp.BYTES));
|
|
928
929
|
const y = bytesToNumberBE(bytes.slice(Fp.BYTES));
|
|
929
930
|
return { x: Fp.create(x), y: Fp.create(y) };
|
|
@@ -934,7 +935,7 @@ export const bls12_381 = bls({
|
|
|
934
935
|
},
|
|
935
936
|
toBytes: (c, point, isCompressed) => {
|
|
936
937
|
const isZero = point.equals(c.ZERO);
|
|
937
|
-
const { x, y } = point;
|
|
938
|
+
const { x, y } = point.toAffine();
|
|
938
939
|
if (isCompressed) {
|
|
939
940
|
if (isZero)
|
|
940
941
|
return COMPRESSED_ZERO.slice();
|
|
@@ -947,11 +948,11 @@ export const bls12_381 = bls({
|
|
|
947
948
|
else {
|
|
948
949
|
if (isZero) {
|
|
949
950
|
// 2x PUBLIC_KEY_LENGTH
|
|
950
|
-
const x =
|
|
951
|
+
const x = concatB(new Uint8Array([0x40]), new Uint8Array(2 * Fp.BYTES - 1));
|
|
951
952
|
return x;
|
|
952
953
|
}
|
|
953
954
|
else {
|
|
954
|
-
return
|
|
955
|
+
return concatB(numberToBytesBE(x, Fp.BYTES), numberToBytesBE(y, Fp.BYTES));
|
|
955
956
|
}
|
|
956
957
|
}
|
|
957
958
|
},
|
|
@@ -1021,6 +1022,8 @@ export const bls12_381 = bls({
|
|
|
1021
1022
|
const bitC = m_byte & 0x80; // compression bit
|
|
1022
1023
|
const bitI = m_byte & 0x40; // point at infinity bit
|
|
1023
1024
|
const bitS = m_byte & 0x20; // sign bit
|
|
1025
|
+
const L = Fp.BYTES;
|
|
1026
|
+
const slc = (b, from, to) => bytesToNumberBE(b.slice(from, to));
|
|
1024
1027
|
if (bytes.length === 96 && bitC) {
|
|
1025
1028
|
const { b } = bls12_381.CURVE.G2;
|
|
1026
1029
|
const P = Fp.ORDER;
|
|
@@ -1032,13 +1035,13 @@ export const bls12_381 = bls({
|
|
|
1032
1035
|
}
|
|
1033
1036
|
return { x: Fp2.ZERO, y: Fp2.ZERO };
|
|
1034
1037
|
}
|
|
1035
|
-
const x_1 =
|
|
1036
|
-
const x_0 =
|
|
1038
|
+
const x_1 = slc(bytes, 0, L);
|
|
1039
|
+
const x_0 = slc(bytes, L, 2 * L);
|
|
1037
1040
|
const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) });
|
|
1038
1041
|
const right = Fp2.add(Fp2.pow(x, 3n), b); // y² = x³ + 4 * (u+1) = x³ + b
|
|
1039
1042
|
let y = Fp2.sqrt(right);
|
|
1040
1043
|
const Y_bit = y.c1 === 0n ? (y.c0 * 2n) / P : (y.c1 * 2n) / P ? 1n : 0n;
|
|
1041
|
-
y = bitS > 0 && Y_bit > 0 ? y : Fp2.
|
|
1044
|
+
y = bitS > 0 && Y_bit > 0 ? y : Fp2.neg(y);
|
|
1042
1045
|
return { x, y };
|
|
1043
1046
|
}
|
|
1044
1047
|
else if (bytes.length === 192 && !bitC) {
|
|
@@ -1046,10 +1049,10 @@ export const bls12_381 = bls({
|
|
|
1046
1049
|
if ((bytes[0] & (1 << 6)) !== 0) {
|
|
1047
1050
|
return { x: Fp2.ZERO, y: Fp2.ZERO };
|
|
1048
1051
|
}
|
|
1049
|
-
const x1 =
|
|
1050
|
-
const x0 =
|
|
1051
|
-
const y1 =
|
|
1052
|
-
const y0 =
|
|
1052
|
+
const x1 = slc(bytes, 0, L);
|
|
1053
|
+
const x0 = slc(bytes, L, 2 * L);
|
|
1054
|
+
const y1 = slc(bytes, 2 * L, 3 * L);
|
|
1055
|
+
const y0 = slc(bytes, 3 * L, 4 * L);
|
|
1053
1056
|
return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) };
|
|
1054
1057
|
}
|
|
1055
1058
|
else {
|
|
@@ -1058,23 +1061,23 @@ export const bls12_381 = bls({
|
|
|
1058
1061
|
},
|
|
1059
1062
|
toBytes: (c, point, isCompressed) => {
|
|
1060
1063
|
const isZero = point.equals(c.ZERO);
|
|
1061
|
-
const { x, y } = point;
|
|
1064
|
+
const { x, y } = point.toAffine();
|
|
1062
1065
|
if (isCompressed) {
|
|
1063
1066
|
const P = Fp.ORDER;
|
|
1064
1067
|
if (isZero)
|
|
1065
|
-
return
|
|
1068
|
+
return concatB(COMPRESSED_ZERO, numberToBytesBE(0n, Fp.BYTES));
|
|
1066
1069
|
const flag = Boolean(y.c1 === 0n ? (y.c0 * 2n) / P : (y.c1 * 2n) / P);
|
|
1067
1070
|
// set compressed & sign bits (looks like different offsets than for G1/Fp?)
|
|
1068
1071
|
let x_1 = bitSet(x.c1, C_BIT_POS, flag);
|
|
1069
1072
|
x_1 = bitSet(x_1, S_BIT_POS, true);
|
|
1070
|
-
return
|
|
1073
|
+
return concatB(numberToBytesBE(x_1, Fp.BYTES), numberToBytesBE(x.c0, Fp.BYTES));
|
|
1071
1074
|
}
|
|
1072
1075
|
else {
|
|
1073
1076
|
if (isZero)
|
|
1074
|
-
return
|
|
1077
|
+
return concatB(new Uint8Array([0x40]), new Uint8Array(4 * Fp.BYTES - 1)); // bytes[0] |= 1 << 6;
|
|
1075
1078
|
const { re: x0, im: x1 } = Fp2.reim(x);
|
|
1076
1079
|
const { re: y0, im: y1 } = Fp2.reim(y);
|
|
1077
|
-
return
|
|
1080
|
+
return concatB(numberToBytesBE(x1, Fp.BYTES), numberToBytesBE(x0, Fp.BYTES), numberToBytesBE(y1, Fp.BYTES), numberToBytesBE(y0, Fp.BYTES));
|
|
1078
1081
|
}
|
|
1079
1082
|
},
|
|
1080
1083
|
Signature: {
|
|
@@ -1090,7 +1093,7 @@ export const bls12_381 = bls({
|
|
|
1090
1093
|
// Indicates the infinity point
|
|
1091
1094
|
const bflag1 = bitGet(z1, I_BIT_POS);
|
|
1092
1095
|
if (bflag1 === 1n)
|
|
1093
|
-
return bls12_381.G2.
|
|
1096
|
+
return bls12_381.G2.ProjectivePoint.ZERO;
|
|
1094
1097
|
const x1 = Fp.create(z1 & Fp.MASK);
|
|
1095
1098
|
const x2 = Fp.create(z2);
|
|
1096
1099
|
const x = Fp2.create({ c0: x2, c1: x1 });
|
|
@@ -1106,23 +1109,25 @@ export const bls12_381 = bls({
|
|
|
1106
1109
|
const isGreater = y1 > 0n && (y1 * 2n) / P !== aflag1;
|
|
1107
1110
|
const isZero = y1 === 0n && (y0 * 2n) / P !== aflag1;
|
|
1108
1111
|
if (isGreater || isZero)
|
|
1109
|
-
y = Fp2.
|
|
1110
|
-
const point =
|
|
1112
|
+
y = Fp2.neg(y);
|
|
1113
|
+
const point = bls12_381.G2.ProjectivePoint.fromAffine({ x, y });
|
|
1114
|
+
// console.log('Signature.decode', point);
|
|
1111
1115
|
point.assertValidity();
|
|
1112
1116
|
return point;
|
|
1113
1117
|
},
|
|
1114
1118
|
encode(point) {
|
|
1115
1119
|
// NOTE: by some reasons it was missed in bls12-381, looks like bug
|
|
1116
1120
|
point.assertValidity();
|
|
1117
|
-
if (point.equals(bls12_381.G2.
|
|
1118
|
-
return
|
|
1119
|
-
const
|
|
1120
|
-
const { re:
|
|
1121
|
+
if (point.equals(bls12_381.G2.ProjectivePoint.ZERO))
|
|
1122
|
+
return concatB(COMPRESSED_ZERO, numberToBytesBE(0n, Fp.BYTES));
|
|
1123
|
+
const a = point.toAffine();
|
|
1124
|
+
const { re: x0, im: x1 } = Fp2.reim(a.x);
|
|
1125
|
+
const { re: y0, im: y1 } = Fp2.reim(a.y);
|
|
1121
1126
|
const tmp = y1 > 0n ? y1 * 2n : y0 * 2n;
|
|
1122
1127
|
const aflag1 = Boolean((tmp / Fp.ORDER) & 1n);
|
|
1123
1128
|
const z1 = bitSet(bitSet(x1, 381, aflag1), S_BIT_POS, true);
|
|
1124
1129
|
const z2 = x0;
|
|
1125
|
-
return
|
|
1130
|
+
return concatB(numberToBytesBE(z1, Fp.BYTES), numberToBytesBE(z2, Fp.BYTES));
|
|
1126
1131
|
},
|
|
1127
1132
|
},
|
|
1128
1133
|
},
|
package/lib/esm/bn.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
2
|
-
import { weierstrass } from './abstract/weierstrass.js';
|
|
3
2
|
import { sha256 } from '@noble/hashes/sha256';
|
|
3
|
+
import { weierstrass } from './abstract/weierstrass.js';
|
|
4
4
|
import { getHash } from './_shortw_utils.js';
|
|
5
5
|
import { Fp } from './abstract/modular.js';
|
|
6
6
|
/**
|
package/lib/esm/ed25519.js
CHANGED
|
@@ -5,6 +5,7 @@ import { twistedEdwards } from './abstract/edwards.js';
|
|
|
5
5
|
import { montgomery } from './abstract/montgomery.js';
|
|
6
6
|
import { mod, pow2, isNegativeLE, Fp as Field, FpSqrtEven } from './abstract/modular.js';
|
|
7
7
|
import { ensureBytes, equalBytes, bytesToHex, bytesToNumberLE, numberToBytesLE, } from './abstract/utils.js';
|
|
8
|
+
import * as htf from './abstract/hash-to-curve.js';
|
|
8
9
|
/**
|
|
9
10
|
* ed25519 Twisted Edwards curve with following addons:
|
|
10
11
|
* - X25519 ECDH
|
|
@@ -79,57 +80,107 @@ export const ED25519_TORSION_SUBGROUP = [
|
|
|
79
80
|
'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa',
|
|
80
81
|
];
|
|
81
82
|
const Fp = Field(ED25519_P, undefined, true);
|
|
83
|
+
const ED25519_DEF = {
|
|
84
|
+
// Param: a
|
|
85
|
+
a: BigInt(-1),
|
|
86
|
+
// Equal to -121665/121666 over finite field.
|
|
87
|
+
// Negative number is P - number, and division is invert(number, P)
|
|
88
|
+
d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'),
|
|
89
|
+
// Finite field 𝔽p over which we'll do calculations; 2n ** 255n - 19n
|
|
90
|
+
Fp,
|
|
91
|
+
// Subgroup order: how many points ed25519 has
|
|
92
|
+
// 2n ** 252n + 27742317777372353535851937790883648493n;
|
|
93
|
+
n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'),
|
|
94
|
+
// Cofactor
|
|
95
|
+
h: BigInt(8),
|
|
96
|
+
// Base point (x, y) aka generator point
|
|
97
|
+
Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'),
|
|
98
|
+
Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'),
|
|
99
|
+
hash: sha512,
|
|
100
|
+
randomBytes,
|
|
101
|
+
adjustScalarBytes,
|
|
102
|
+
// dom2
|
|
103
|
+
// Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3.
|
|
104
|
+
// Constant-time, u/√v
|
|
105
|
+
uvRatio,
|
|
106
|
+
};
|
|
107
|
+
export const ed25519 = twistedEdwards(ED25519_DEF);
|
|
108
|
+
function ed25519_domain(data, ctx, phflag) {
|
|
109
|
+
if (ctx.length > 255)
|
|
110
|
+
throw new Error('Context is too big');
|
|
111
|
+
return concatBytes(utf8ToBytes('SigEd25519 no Ed25519 collisions'), new Uint8Array([phflag ? 1 : 0, ctx.length]), ctx, data);
|
|
112
|
+
}
|
|
113
|
+
export const ed25519ctx = twistedEdwards({ ...ED25519_DEF, domain: ed25519_domain });
|
|
114
|
+
export const ed25519ph = twistedEdwards({
|
|
115
|
+
...ED25519_DEF,
|
|
116
|
+
domain: ed25519_domain,
|
|
117
|
+
preHash: sha512,
|
|
118
|
+
});
|
|
119
|
+
export const x25519 = montgomery({
|
|
120
|
+
P: ED25519_P,
|
|
121
|
+
a24: BigInt('121665'),
|
|
122
|
+
montgomeryBits: 255,
|
|
123
|
+
nByteLength: 32,
|
|
124
|
+
Gu: '0900000000000000000000000000000000000000000000000000000000000000',
|
|
125
|
+
powPminus2: (x) => {
|
|
126
|
+
const P = ED25519_P;
|
|
127
|
+
// x^(p-2) aka x^(2^255-21)
|
|
128
|
+
const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x);
|
|
129
|
+
return mod(pow2(pow_p_5_8, BigInt(3), P) * b2, P);
|
|
130
|
+
},
|
|
131
|
+
adjustScalarBytes,
|
|
132
|
+
});
|
|
82
133
|
// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator)
|
|
83
134
|
// NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since
|
|
84
135
|
// SageMath returns different root first and everything falls apart
|
|
85
136
|
const ELL2_C1 = (Fp.ORDER + BigInt(3)) / BigInt(8); // 1. c1 = (q + 3) / 8 # Integer arithmetic
|
|
86
137
|
const ELL2_C2 = Fp.pow(_2n, ELL2_C1); // 2. c2 = 2^c1
|
|
87
|
-
const ELL2_C3 = Fp.sqrt(Fp.
|
|
138
|
+
const ELL2_C3 = Fp.sqrt(Fp.neg(Fp.ONE)); // 3. c3 = sqrt(-1)
|
|
88
139
|
const ELL2_C4 = (Fp.ORDER - BigInt(5)) / BigInt(8); // 4. c4 = (q - 5) / 8 # Integer arithmetic
|
|
89
140
|
const ELL2_J = BigInt(486662);
|
|
90
141
|
// prettier-ignore
|
|
91
142
|
function map_to_curve_elligator2_curve25519(u) {
|
|
92
|
-
let tv1 = Fp.
|
|
143
|
+
let tv1 = Fp.sqr(u); // 1. tv1 = u^2
|
|
93
144
|
tv1 = Fp.mul(tv1, _2n); // 2. tv1 = 2 * tv1
|
|
94
145
|
let xd = Fp.add(tv1, Fp.ONE); // 3. xd = tv1 + 1 # Nonzero: -1 is square (mod p), tv1 is not
|
|
95
|
-
let x1n = Fp.
|
|
96
|
-
let tv2 = Fp.
|
|
146
|
+
let x1n = Fp.neg(ELL2_J); // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2)
|
|
147
|
+
let tv2 = Fp.sqr(xd); // 5. tv2 = xd^2
|
|
97
148
|
let gxd = Fp.mul(tv2, xd); // 6. gxd = tv2 * xd # gxd = xd^3
|
|
98
149
|
let gx1 = Fp.mul(tv1, ELL2_J); // 7. gx1 = J * tv1 # x1n + J * xd
|
|
99
150
|
gx1 = Fp.mul(gx1, x1n); // 8. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
|
|
100
151
|
gx1 = Fp.add(gx1, tv2); // 9. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
|
|
101
152
|
gx1 = Fp.mul(gx1, x1n); // 10. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
|
|
102
|
-
let tv3 = Fp.
|
|
103
|
-
tv2 = Fp.
|
|
153
|
+
let tv3 = Fp.sqr(gxd); // 11. tv3 = gxd^2
|
|
154
|
+
tv2 = Fp.sqr(tv3); // 12. tv2 = tv3^2 # gxd^4
|
|
104
155
|
tv3 = Fp.mul(tv3, gxd); // 13. tv3 = tv3 * gxd # gxd^3
|
|
105
156
|
tv3 = Fp.mul(tv3, gx1); // 14. tv3 = tv3 * gx1 # gx1 * gxd^3
|
|
106
157
|
tv2 = Fp.mul(tv2, tv3); // 15. tv2 = tv2 * tv3 # gx1 * gxd^7
|
|
107
158
|
let y11 = Fp.pow(tv2, ELL2_C4); // 16. y11 = tv2^c4 # (gx1 * gxd^7)^((p - 5) / 8)
|
|
108
159
|
y11 = Fp.mul(y11, tv3); // 17. y11 = y11 * tv3 # gx1*gxd^3*(gx1*gxd^7)^((p-5)/8)
|
|
109
160
|
let y12 = Fp.mul(y11, ELL2_C3); // 18. y12 = y11 * c3
|
|
110
|
-
tv2 = Fp.
|
|
161
|
+
tv2 = Fp.sqr(y11); // 19. tv2 = y11^2
|
|
111
162
|
tv2 = Fp.mul(tv2, gxd); // 20. tv2 = tv2 * gxd
|
|
112
|
-
let e1 = Fp.
|
|
163
|
+
let e1 = Fp.eql(tv2, gx1); // 21. e1 = tv2 == gx1
|
|
113
164
|
let y1 = Fp.cmov(y12, y11, e1); // 22. y1 = CMOV(y12, y11, e1) # If g(x1) is square, this is its sqrt
|
|
114
165
|
let x2n = Fp.mul(x1n, tv1); // 23. x2n = x1n * tv1 # x2 = x2n / xd = 2 * u^2 * x1n / xd
|
|
115
166
|
let y21 = Fp.mul(y11, u); // 24. y21 = y11 * u
|
|
116
167
|
y21 = Fp.mul(y21, ELL2_C2); // 25. y21 = y21 * c2
|
|
117
168
|
let y22 = Fp.mul(y21, ELL2_C3); // 26. y22 = y21 * c3
|
|
118
169
|
let gx2 = Fp.mul(gx1, tv1); // 27. gx2 = gx1 * tv1 # g(x2) = gx2 / gxd = 2 * u^2 * g(x1)
|
|
119
|
-
tv2 = Fp.
|
|
170
|
+
tv2 = Fp.sqr(y21); // 28. tv2 = y21^2
|
|
120
171
|
tv2 = Fp.mul(tv2, gxd); // 29. tv2 = tv2 * gxd
|
|
121
|
-
let e2 = Fp.
|
|
172
|
+
let e2 = Fp.eql(tv2, gx2); // 30. e2 = tv2 == gx2
|
|
122
173
|
let y2 = Fp.cmov(y22, y21, e2); // 31. y2 = CMOV(y22, y21, e2) # If g(x2) is square, this is its sqrt
|
|
123
|
-
tv2 = Fp.
|
|
174
|
+
tv2 = Fp.sqr(y1); // 32. tv2 = y1^2
|
|
124
175
|
tv2 = Fp.mul(tv2, gxd); // 33. tv2 = tv2 * gxd
|
|
125
|
-
let e3 = Fp.
|
|
176
|
+
let e3 = Fp.eql(tv2, gx1); // 34. e3 = tv2 == gx1
|
|
126
177
|
let xn = Fp.cmov(x2n, x1n, e3); // 35. xn = CMOV(x2n, x1n, e3) # If e3, x = x1, else x = x2
|
|
127
178
|
let y = Fp.cmov(y2, y1, e3); // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2
|
|
128
179
|
let e4 = Fp.isOdd(y); // 37. e4 = sgn0(y) == 1 # Fix sign of y
|
|
129
|
-
y = Fp.cmov(y, Fp.
|
|
180
|
+
y = Fp.cmov(y, Fp.neg(y), e3 !== e4); // 38. y = CMOV(y, -y, e3 XOR e4)
|
|
130
181
|
return { xMn: xn, xMd: xd, yMn: y, yMd: 1n }; // 39. return (xn, xd, y, 1)
|
|
131
182
|
}
|
|
132
|
-
const ELL2_C1_EDWARDS = FpSqrtEven(Fp, Fp.
|
|
183
|
+
const ELL2_C1_EDWARDS = FpSqrtEven(Fp, Fp.neg(BigInt(486664))); // sgn0(c1) MUST equal 0
|
|
133
184
|
function map_to_curve_elligator2_edwards25519(u) {
|
|
134
185
|
const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u); // 1. (xMn, xMd, yMn, yMd) = map_to_curve_elligator2_curve25519(u)
|
|
135
186
|
let xn = Fp.mul(xMn, yMd); // 2. xn = xMn * yMd
|
|
@@ -138,7 +189,7 @@ function map_to_curve_elligator2_edwards25519(u) {
|
|
|
138
189
|
let yn = Fp.sub(xMn, xMd); // 5. yn = xMn - xMd
|
|
139
190
|
let yd = Fp.add(xMn, xMd); // 6. yd = xMn + xMd # (n / d - 1) / (n / d + 1) = (n - d) / (n + d)
|
|
140
191
|
let tv1 = Fp.mul(xd, yd); // 7. tv1 = xd * yd
|
|
141
|
-
let e = Fp.
|
|
192
|
+
let e = Fp.eql(tv1, Fp.ZERO); // 8. e = tv1 == 0
|
|
142
193
|
xn = Fp.cmov(xn, Fp.ZERO, e); // 9. xn = CMOV(xn, 0, e)
|
|
143
194
|
xd = Fp.cmov(xd, Fp.ONE, e); // 10. xd = CMOV(xd, 1, e)
|
|
144
195
|
yn = Fp.cmov(yn, Fp.ONE, e); // 11. yn = CMOV(yn, 1, e)
|
|
@@ -146,68 +197,19 @@ function map_to_curve_elligator2_edwards25519(u) {
|
|
|
146
197
|
const inv = Fp.invertBatch([xd, yd]); // batch division
|
|
147
198
|
return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) }; // 13. return (xn, xd, yn, yd)
|
|
148
199
|
}
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
Fp,
|
|
157
|
-
// Subgroup order: how many points ed25519 has
|
|
158
|
-
// 2n ** 252n + 27742317777372353535851937790883648493n;
|
|
159
|
-
n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'),
|
|
160
|
-
// Cofactor
|
|
161
|
-
h: BigInt(8),
|
|
162
|
-
// Base point (x, y) aka generator point
|
|
163
|
-
Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'),
|
|
164
|
-
Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'),
|
|
200
|
+
const { hashToCurve, encodeToCurve } = htf.hashToCurve(ed25519.ExtendedPoint, (scalars) => map_to_curve_elligator2_edwards25519(scalars[0]), {
|
|
201
|
+
DST: 'edwards25519_XMD:SHA-512_ELL2_RO_',
|
|
202
|
+
encodeDST: 'edwards25519_XMD:SHA-512_ELL2_NU_',
|
|
203
|
+
p: Fp.ORDER,
|
|
204
|
+
m: 1,
|
|
205
|
+
k: 128,
|
|
206
|
+
expand: 'xmd',
|
|
165
207
|
hash: sha512,
|
|
166
|
-
randomBytes,
|
|
167
|
-
adjustScalarBytes,
|
|
168
|
-
// dom2
|
|
169
|
-
// Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3.
|
|
170
|
-
// Constant-time, u/√v
|
|
171
|
-
uvRatio,
|
|
172
|
-
htfDefaults: {
|
|
173
|
-
DST: 'edwards25519_XMD:SHA-512_ELL2_RO_',
|
|
174
|
-
p: Fp.ORDER,
|
|
175
|
-
m: 1,
|
|
176
|
-
k: 128,
|
|
177
|
-
expand: 'xmd',
|
|
178
|
-
hash: sha512,
|
|
179
|
-
},
|
|
180
|
-
mapToCurve: (scalars) => map_to_curve_elligator2_edwards25519(scalars[0]),
|
|
181
|
-
};
|
|
182
|
-
export const ed25519 = twistedEdwards(ED25519_DEF);
|
|
183
|
-
function ed25519_domain(data, ctx, phflag) {
|
|
184
|
-
if (ctx.length > 255)
|
|
185
|
-
throw new Error('Context is too big');
|
|
186
|
-
return concatBytes(utf8ToBytes('SigEd25519 no Ed25519 collisions'), new Uint8Array([phflag ? 1 : 0, ctx.length]), ctx, data);
|
|
187
|
-
}
|
|
188
|
-
export const ed25519ctx = twistedEdwards({ ...ED25519_DEF, domain: ed25519_domain });
|
|
189
|
-
export const ed25519ph = twistedEdwards({
|
|
190
|
-
...ED25519_DEF,
|
|
191
|
-
domain: ed25519_domain,
|
|
192
|
-
preHash: sha512,
|
|
193
|
-
});
|
|
194
|
-
export const x25519 = montgomery({
|
|
195
|
-
P: ED25519_P,
|
|
196
|
-
a24: BigInt('121665'),
|
|
197
|
-
montgomeryBits: 255,
|
|
198
|
-
nByteLength: 32,
|
|
199
|
-
Gu: '0900000000000000000000000000000000000000000000000000000000000000',
|
|
200
|
-
powPminus2: (x) => {
|
|
201
|
-
const P = ED25519_P;
|
|
202
|
-
// x^(p-2) aka x^(2^255-21)
|
|
203
|
-
const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x);
|
|
204
|
-
return mod(pow2(pow_p_5_8, BigInt(3), P) * b2, P);
|
|
205
|
-
},
|
|
206
|
-
adjustScalarBytes,
|
|
207
208
|
});
|
|
209
|
+
export { hashToCurve, encodeToCurve };
|
|
208
210
|
function assertRstPoint(other) {
|
|
209
211
|
if (!(other instanceof RistrettoPoint))
|
|
210
|
-
throw new
|
|
212
|
+
throw new Error('RistrettoPoint expected');
|
|
211
213
|
}
|
|
212
214
|
// √(-1) aka √(a) aka 2^((p-1)/4)
|
|
213
215
|
const SQRT_M1 = BigInt('19681161376707505956807079304988542015446066515923890162744021073123829784752');
|
|
@@ -316,7 +318,7 @@ export class RistrettoPoint {
|
|
|
316
318
|
* https://ristretto.group/formulas/encoding.html
|
|
317
319
|
*/
|
|
318
320
|
toRawBytes() {
|
|
319
|
-
let { x, y, z, t } = this.ep;
|
|
321
|
+
let { ex: x, ey: y, ez: z, et: t } = this.ep;
|
|
320
322
|
const P = ed25519.CURVE.Fp.ORDER;
|
|
321
323
|
const mod = ed25519.CURVE.Fp.create;
|
|
322
324
|
const u1 = mod(mod(z + y) * mod(z - y)); // 1
|
|
@@ -354,12 +356,12 @@ export class RistrettoPoint {
|
|
|
354
356
|
// Compare one point to another.
|
|
355
357
|
equals(other) {
|
|
356
358
|
assertRstPoint(other);
|
|
357
|
-
const
|
|
358
|
-
const
|
|
359
|
+
const { ex: X1, ey: Y1 } = this.ep;
|
|
360
|
+
const { ex: X2, ey: Y2 } = this.ep;
|
|
359
361
|
const mod = ed25519.CURVE.Fp.create;
|
|
360
362
|
// (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2)
|
|
361
|
-
const one = mod(
|
|
362
|
-
const two = mod(
|
|
363
|
+
const one = mod(X1 * Y2) === mod(Y1 * X2);
|
|
364
|
+
const two = mod(Y1 * Y2) === mod(X1 * X2);
|
|
363
365
|
return one || two;
|
|
364
366
|
}
|
|
365
367
|
add(other) {
|