@noble/curves 0.5.1 → 0.6.0
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 +49 -8
- package/lib/_shortw_utils.d.ts +11 -26
- package/lib/abstract/bls.d.ts +51 -35
- package/lib/abstract/bls.js +77 -139
- package/lib/abstract/{group.d.ts → curve.d.ts} +31 -1
- package/lib/abstract/{group.js → curve.js} +39 -2
- package/lib/abstract/edwards.d.ts +30 -81
- package/lib/abstract/edwards.js +225 -420
- 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 +20 -7
- package/lib/abstract/modular.js +80 -51
- package/lib/abstract/montgomery.js +3 -4
- package/lib/abstract/poseidon.d.ts +29 -0
- package/lib/abstract/poseidon.js +115 -0
- package/lib/abstract/utils.d.ts +5 -34
- package/lib/abstract/utils.js +23 -63
- package/lib/abstract/weierstrass.d.ts +56 -79
- package/lib/abstract/weierstrass.js +509 -641
- package/lib/bls12-381.d.ts +1 -0
- package/lib/bls12-381.js +75 -65
- package/lib/bn.js +1 -1
- package/lib/ed25519.d.ts +7 -5
- package/lib/ed25519.js +87 -84
- package/lib/ed448.d.ts +3 -0
- package/lib/ed448.js +88 -84
- package/lib/esm/abstract/bls.js +77 -139
- package/lib/esm/abstract/{group.js → curve.js} +37 -1
- package/lib/esm/abstract/edwards.js +223 -418
- package/lib/esm/abstract/hash-to-curve.js +38 -11
- package/lib/esm/abstract/modular.js +77 -50
- package/lib/esm/abstract/montgomery.js +4 -7
- package/lib/esm/abstract/poseidon.js +109 -0
- package/lib/esm/abstract/utils.js +21 -59
- package/lib/esm/abstract/weierstrass.js +508 -640
- package/lib/esm/bls12-381.js +86 -76
- package/lib/esm/bn.js +1 -1
- package/lib/esm/ed25519.js +85 -83
- package/lib/esm/ed448.js +86 -83
- package/lib/esm/jubjub.js +6 -5
- package/lib/esm/p256.js +11 -9
- package/lib/esm/p384.js +11 -9
- package/lib/esm/p521.js +13 -12
- package/lib/esm/secp256k1.js +118 -157
- package/lib/esm/stark.js +104 -39
- package/lib/jubjub.d.ts +3 -2
- package/lib/jubjub.js +6 -5
- package/lib/p192.d.ts +22 -52
- package/lib/p224.d.ts +22 -52
- package/lib/p256.d.ts +25 -52
- package/lib/p256.js +13 -10
- package/lib/p384.d.ts +25 -52
- package/lib/p384.js +13 -10
- package/lib/p521.d.ts +25 -52
- package/lib/p521.js +15 -13
- package/lib/secp256k1.d.ts +26 -42
- package/lib/secp256k1.js +118 -157
- package/lib/stark.d.ts +36 -21
- package/lib/stark.js +107 -39
- package/package.json +14 -9
package/lib/esm/bls12-381.js
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
2
|
+
// The pairing-friendly Barreto-Lynn-Scott elliptic curve construction allows to:
|
|
3
|
+
// - Construct zk-SNARKs at the 128-bit security
|
|
4
|
+
// - Use threshold signatures, which allows a user to sign lots of messages with one signature and verify them swiftly in a batch, using Boneh-Lynn-Shacham signature scheme.
|
|
5
|
+
// Differences from @noble/bls12-381 1.4:
|
|
6
|
+
// - PointG1 -> G1.Point
|
|
7
|
+
// - PointG2 -> G2.Point
|
|
8
|
+
// - PointG2.fromSignature -> Signature.decode
|
|
9
|
+
// - PointG2.toSignature -> Signature.encode
|
|
10
|
+
// - Fixed Fp2 ORDER
|
|
11
|
+
// - Points now have only two coordinates
|
|
2
12
|
import { sha256 } from '@noble/hashes/sha256';
|
|
3
13
|
import { randomBytes } from '@noble/hashes/utils';
|
|
4
14
|
import { bls } from './abstract/bls.js';
|
|
5
15
|
import * as mod from './abstract/modular.js';
|
|
6
|
-
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';
|
|
7
17
|
// Types
|
|
8
18
|
import { mapToCurveSimpleSWU, } from './abstract/weierstrass.js';
|
|
9
19
|
import { isogenyMap } from './abstract/hash-to-curve.js';
|
|
10
|
-
// Differences from bls12-381:
|
|
11
|
-
// - PointG1 -> G1.Point
|
|
12
|
-
// - PointG2 -> G2.Point
|
|
13
|
-
// - PointG2.fromSignature -> Signature.decode
|
|
14
|
-
// - PointG2.toSignature -> Signature.encode
|
|
15
|
-
// - Fixed Fp2 ORDER
|
|
16
|
-
// Points now have only two coordinates
|
|
17
20
|
// CURVE FIELDS
|
|
18
21
|
// Finite field over p.
|
|
19
22
|
const Fp = mod.Fp(0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn);
|
|
@@ -62,24 +65,24 @@ const Fp2 = {
|
|
|
62
65
|
ONE: { c0: Fp.ONE, c1: Fp.ZERO },
|
|
63
66
|
create: (num) => num,
|
|
64
67
|
isValid: ({ c0, c1 }) => typeof c0 === 'bigint' && typeof c1 === 'bigint',
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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) }),
|
|
68
71
|
pow: (num, power) => mod.FpPow(Fp2, num, power),
|
|
69
72
|
invertBatch: (nums) => mod.FpInvertBatch(Fp2, nums),
|
|
70
73
|
// Normalized
|
|
71
74
|
add: Fp2Add,
|
|
72
75
|
sub: Fp2Subtract,
|
|
73
76
|
mul: Fp2Multiply,
|
|
74
|
-
|
|
77
|
+
sqr: Fp2Square,
|
|
75
78
|
// NonNormalized stuff
|
|
76
79
|
addN: Fp2Add,
|
|
77
80
|
subN: Fp2Subtract,
|
|
78
81
|
mulN: Fp2Multiply,
|
|
79
|
-
|
|
82
|
+
sqrN: Fp2Square,
|
|
80
83
|
// Why inversion for bigint inside Fp instead of Fp2? it is even used in that context?
|
|
81
|
-
div: (lhs, rhs) => Fp2.mul(lhs, typeof rhs === 'bigint' ? Fp.
|
|
82
|
-
|
|
84
|
+
div: (lhs, rhs) => Fp2.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp2.inv(rhs)),
|
|
85
|
+
inv: ({ c0: a, c1: b }) => {
|
|
83
86
|
// We wish to find the multiplicative inverse of a nonzero
|
|
84
87
|
// element a + bu in Fp2. We leverage an identity
|
|
85
88
|
//
|
|
@@ -93,10 +96,12 @@ const Fp2 = {
|
|
|
93
96
|
// This gives that (a - bu)/(a² + b²) is the inverse
|
|
94
97
|
// of (a + bu). Importantly, this can be computing using
|
|
95
98
|
// only a single inversion in Fp.
|
|
96
|
-
const factor = Fp.
|
|
99
|
+
const factor = Fp.inv(Fp.create(a * a + b * b));
|
|
97
100
|
return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) };
|
|
98
101
|
},
|
|
99
102
|
sqrt: (num) => {
|
|
103
|
+
if (Fp2.eql(num, Fp2.ZERO))
|
|
104
|
+
return Fp2.ZERO; // Algo doesn't handles this case
|
|
100
105
|
// TODO: Optimize this line. It's extremely slow.
|
|
101
106
|
// Speeding this up would boost aggregateSignatures.
|
|
102
107
|
// https://eprint.iacr.org/2012/685.pdf applicable?
|
|
@@ -104,9 +109,9 @@ const Fp2 = {
|
|
|
104
109
|
// https://github.com/supranational/blst/blob/aae0c7d70b799ac269ff5edf29d8191dbd357876/src/exp2.c#L1
|
|
105
110
|
// Inspired by https://github.com/dalek-cryptography/curve25519-dalek/blob/17698df9d4c834204f83a3574143abacb4fc81a5/src/field.rs#L99
|
|
106
111
|
const candidateSqrt = Fp2.pow(num, (Fp2.ORDER + 8n) / 16n);
|
|
107
|
-
const check = Fp2.div(Fp2.
|
|
112
|
+
const check = Fp2.div(Fp2.sqr(candidateSqrt), num); // candidateSqrt.square().div(this);
|
|
108
113
|
const R = FP2_ROOTS_OF_UNITY;
|
|
109
|
-
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));
|
|
110
115
|
if (!divisor)
|
|
111
116
|
throw new Error('No root');
|
|
112
117
|
const index = R.indexOf(divisor);
|
|
@@ -114,7 +119,7 @@ const Fp2 = {
|
|
|
114
119
|
if (!root)
|
|
115
120
|
throw new Error('Invalid root');
|
|
116
121
|
const x1 = Fp2.div(candidateSqrt, root);
|
|
117
|
-
const x2 = Fp2.
|
|
122
|
+
const x2 = Fp2.neg(x1);
|
|
118
123
|
const { re: re1, im: im1 } = Fp2.reim(x1);
|
|
119
124
|
const { re: re2, im: im2 } = Fp2.reim(x2);
|
|
120
125
|
if (im1 > im2 || (im1 === im2 && re1 > re2))
|
|
@@ -135,7 +140,7 @@ const Fp2 = {
|
|
|
135
140
|
throw new Error(`fromBytes wrong length=${b.length}`);
|
|
136
141
|
return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) };
|
|
137
142
|
},
|
|
138
|
-
toBytes: ({ c0, c1 }) =>
|
|
143
|
+
toBytes: ({ c0, c1 }) => concatB(Fp.toBytes(c0), Fp.toBytes(c1)),
|
|
139
144
|
cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({
|
|
140
145
|
c0: Fp.cmov(c0, r0, c),
|
|
141
146
|
c1: Fp.cmov(c1, r1, c),
|
|
@@ -225,15 +230,15 @@ const Fp6Multiply = ({ c0, c1, c2 }, rhs) => {
|
|
|
225
230
|
};
|
|
226
231
|
};
|
|
227
232
|
const Fp6Square = ({ c0, c1, c2 }) => {
|
|
228
|
-
let t0 = Fp2.
|
|
233
|
+
let t0 = Fp2.sqr(c0); // c0²
|
|
229
234
|
let t1 = Fp2.mul(Fp2.mul(c0, c1), 2n); // 2 * c0 * c1
|
|
230
235
|
let t3 = Fp2.mul(Fp2.mul(c1, c2), 2n); // 2 * c1 * c2
|
|
231
|
-
let t4 = Fp2.
|
|
236
|
+
let t4 = Fp2.sqr(c2); // c2²
|
|
232
237
|
return {
|
|
233
238
|
c0: Fp2.add(Fp2.mulByNonresidue(t3), t0),
|
|
234
239
|
c1: Fp2.add(Fp2.mulByNonresidue(t4), t1),
|
|
235
240
|
// T1 + (c0 - c1 + c2)² + T3 - T0 - T4
|
|
236
|
-
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),
|
|
237
242
|
};
|
|
238
243
|
};
|
|
239
244
|
const Fp6 = {
|
|
@@ -245,32 +250,32 @@ const Fp6 = {
|
|
|
245
250
|
ONE: { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO },
|
|
246
251
|
create: (num) => num,
|
|
247
252
|
isValid: ({ c0, c1, c2 }) => Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2),
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
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),
|
|
251
256
|
sqrt: () => {
|
|
252
257
|
throw new Error('Not implemented');
|
|
253
258
|
},
|
|
254
259
|
// Do we need division by bigint at all? Should be done via order:
|
|
255
|
-
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)),
|
|
256
261
|
pow: (num, power) => mod.FpPow(Fp6, num, power),
|
|
257
262
|
invertBatch: (nums) => mod.FpInvertBatch(Fp6, nums),
|
|
258
263
|
// Normalized
|
|
259
264
|
add: Fp6Add,
|
|
260
265
|
sub: Fp6Subtract,
|
|
261
266
|
mul: Fp6Multiply,
|
|
262
|
-
|
|
267
|
+
sqr: Fp6Square,
|
|
263
268
|
// NonNormalized stuff
|
|
264
269
|
addN: Fp6Add,
|
|
265
270
|
subN: Fp6Subtract,
|
|
266
271
|
mulN: Fp6Multiply,
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
let t0 = Fp2.sub(Fp2.
|
|
270
|
-
let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.
|
|
271
|
-
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
|
|
272
277
|
// 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0)
|
|
273
|
-
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)));
|
|
274
279
|
return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) };
|
|
275
280
|
},
|
|
276
281
|
// Bytes utils
|
|
@@ -283,7 +288,7 @@ const Fp6 = {
|
|
|
283
288
|
c2: Fp2.fromBytes(b.subarray(2 * Fp2.BYTES)),
|
|
284
289
|
};
|
|
285
290
|
},
|
|
286
|
-
toBytes: ({ c0, c1, c2 }) =>
|
|
291
|
+
toBytes: ({ c0, c1, c2 }) => concatB(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2)),
|
|
287
292
|
cmov: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }, c) => ({
|
|
288
293
|
c0: Fp2.cmov(c0, r0, c),
|
|
289
294
|
c1: Fp2.cmov(c1, r1, c),
|
|
@@ -411,11 +416,11 @@ const Fp12Square = ({ c0, c1 }) => {
|
|
|
411
416
|
}; // AB + AB
|
|
412
417
|
};
|
|
413
418
|
function Fp4Square(a, b) {
|
|
414
|
-
const a2 = Fp2.
|
|
415
|
-
const b2 = Fp2.
|
|
419
|
+
const a2 = Fp2.sqr(a);
|
|
420
|
+
const b2 = Fp2.sqr(b);
|
|
416
421
|
return {
|
|
417
422
|
first: Fp2.add(Fp2.mulByNonresidue(b2), a2),
|
|
418
|
-
second: Fp2.sub(Fp2.sub(Fp2.
|
|
423
|
+
second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b²
|
|
419
424
|
};
|
|
420
425
|
}
|
|
421
426
|
const Fp12 = {
|
|
@@ -427,29 +432,29 @@ const Fp12 = {
|
|
|
427
432
|
ONE: { c0: Fp6.ONE, c1: Fp6.ZERO },
|
|
428
433
|
create: (num) => num,
|
|
429
434
|
isValid: ({ c0, c1 }) => Fp6.isValid(c0) && Fp6.isValid(c1),
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
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),
|
|
433
438
|
sqrt: () => {
|
|
434
439
|
throw new Error('Not implemented');
|
|
435
440
|
},
|
|
436
|
-
|
|
437
|
-
let t = Fp6.
|
|
438
|
-
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
|
|
439
444
|
},
|
|
440
|
-
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)),
|
|
441
446
|
pow: (num, power) => mod.FpPow(Fp12, num, power),
|
|
442
447
|
invertBatch: (nums) => mod.FpInvertBatch(Fp12, nums),
|
|
443
448
|
// Normalized
|
|
444
449
|
add: Fp12Add,
|
|
445
450
|
sub: Fp12Subtract,
|
|
446
451
|
mul: Fp12Multiply,
|
|
447
|
-
|
|
452
|
+
sqr: Fp12Square,
|
|
448
453
|
// NonNormalized stuff
|
|
449
454
|
addN: Fp12Add,
|
|
450
455
|
subN: Fp12Subtract,
|
|
451
456
|
mulN: Fp12Multiply,
|
|
452
|
-
|
|
457
|
+
sqrN: Fp12Square,
|
|
453
458
|
// Bytes utils
|
|
454
459
|
fromBytes: (b) => {
|
|
455
460
|
if (b.length !== Fp12.BYTES)
|
|
@@ -459,7 +464,7 @@ const Fp12 = {
|
|
|
459
464
|
c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)),
|
|
460
465
|
};
|
|
461
466
|
},
|
|
462
|
-
toBytes: ({ c0, c1 }) =>
|
|
467
|
+
toBytes: ({ c0, c1 }) => concatB(Fp6.toBytes(c0), Fp6.toBytes(c1)),
|
|
463
468
|
cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({
|
|
464
469
|
c0: Fp6.cmov(c0, r0, c),
|
|
465
470
|
c1: Fp6.cmov(c1, r1, c),
|
|
@@ -503,7 +508,7 @@ const Fp12 = {
|
|
|
503
508
|
c0: Fp6.multiplyByFp2(c0, rhs),
|
|
504
509
|
c1: Fp6.multiplyByFp2(c1, rhs),
|
|
505
510
|
}),
|
|
506
|
-
conjugate: ({ c0, c1 }) => ({ c0, c1: Fp6.
|
|
511
|
+
conjugate: ({ c0, c1 }) => ({ c0, c1: Fp6.neg(c1) }),
|
|
507
512
|
// A cyclotomic group is a subgroup of Fp^n defined by
|
|
508
513
|
// GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1}
|
|
509
514
|
// The result of any pairing is in a cyclotomic subgroup
|
|
@@ -782,7 +787,7 @@ function G2psi(c, P) {
|
|
|
782
787
|
// 1 / F2(2)^((p-1)/3) in GF(p²)
|
|
783
788
|
const PSI2_C1 = 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn;
|
|
784
789
|
function psi2(x, y) {
|
|
785
|
-
return [Fp2.mul(x, PSI2_C1), Fp2.
|
|
790
|
+
return [Fp2.mul(x, PSI2_C1), Fp2.neg(y)];
|
|
786
791
|
}
|
|
787
792
|
function G2psi2(c, P) {
|
|
788
793
|
const affine = P.toAffine();
|
|
@@ -804,6 +809,7 @@ const htfDefaults = {
|
|
|
804
809
|
// defined in section 2.2.5
|
|
805
810
|
// Use utils.getDSTLabel(), utils.setDSTLabel(value)
|
|
806
811
|
DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_',
|
|
812
|
+
encodeDST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_',
|
|
807
813
|
// p: the characteristic of F
|
|
808
814
|
// where F is a finite field of characteristic p and order q = p^m
|
|
809
815
|
p: Fp.ORDER,
|
|
@@ -870,7 +876,7 @@ export const bls12_381 = bls({
|
|
|
870
876
|
isTorsionFree: (c, point) => {
|
|
871
877
|
// φ endomorphism
|
|
872
878
|
const cubicRootOfUnityModP = 0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen;
|
|
873
|
-
const phi = new c(Fp.mul(point.
|
|
879
|
+
const phi = new c(Fp.mul(point.px, cubicRootOfUnityModP), point.py, point.pz);
|
|
874
880
|
// todo: unroll
|
|
875
881
|
const xP = point.multiplyUnsafe(bls12_381.CURVE.x).negate(); // [x]P
|
|
876
882
|
const u2P = xP.multiplyUnsafe(bls12_381.CURVE.x); // [u2]P
|
|
@@ -912,13 +918,13 @@ export const bls12_381 = bls({
|
|
|
912
918
|
throw new Error('Invalid compressed G1 point');
|
|
913
919
|
const aflag = bitGet(compressedValue, C_BIT_POS);
|
|
914
920
|
if ((y * 2n) / P !== aflag)
|
|
915
|
-
y = Fp.
|
|
921
|
+
y = Fp.neg(y);
|
|
916
922
|
return { x: Fp.create(x), y: Fp.create(y) };
|
|
917
923
|
}
|
|
918
924
|
else if (bytes.length === 96) {
|
|
919
925
|
// Check if the infinity flag is set
|
|
920
926
|
if ((bytes[0] & (1 << 6)) !== 0)
|
|
921
|
-
return bls12_381.G1.
|
|
927
|
+
return bls12_381.G1.ProjectivePoint.ZERO.toAffine();
|
|
922
928
|
const x = bytesToNumberBE(bytes.slice(0, Fp.BYTES));
|
|
923
929
|
const y = bytesToNumberBE(bytes.slice(Fp.BYTES));
|
|
924
930
|
return { x: Fp.create(x), y: Fp.create(y) };
|
|
@@ -929,7 +935,7 @@ export const bls12_381 = bls({
|
|
|
929
935
|
},
|
|
930
936
|
toBytes: (c, point, isCompressed) => {
|
|
931
937
|
const isZero = point.equals(c.ZERO);
|
|
932
|
-
const { x, y } = point;
|
|
938
|
+
const { x, y } = point.toAffine();
|
|
933
939
|
if (isCompressed) {
|
|
934
940
|
if (isZero)
|
|
935
941
|
return COMPRESSED_ZERO.slice();
|
|
@@ -942,11 +948,11 @@ export const bls12_381 = bls({
|
|
|
942
948
|
else {
|
|
943
949
|
if (isZero) {
|
|
944
950
|
// 2x PUBLIC_KEY_LENGTH
|
|
945
|
-
const x =
|
|
951
|
+
const x = concatB(new Uint8Array([0x40]), new Uint8Array(2 * Fp.BYTES - 1));
|
|
946
952
|
return x;
|
|
947
953
|
}
|
|
948
954
|
else {
|
|
949
|
-
return
|
|
955
|
+
return concatB(numberToBytesBE(x, Fp.BYTES), numberToBytesBE(y, Fp.BYTES));
|
|
950
956
|
}
|
|
951
957
|
}
|
|
952
958
|
},
|
|
@@ -1016,6 +1022,8 @@ export const bls12_381 = bls({
|
|
|
1016
1022
|
const bitC = m_byte & 0x80; // compression bit
|
|
1017
1023
|
const bitI = m_byte & 0x40; // point at infinity bit
|
|
1018
1024
|
const bitS = m_byte & 0x20; // sign bit
|
|
1025
|
+
const L = Fp.BYTES;
|
|
1026
|
+
const slc = (b, from, to) => bytesToNumberBE(b.slice(from, to));
|
|
1019
1027
|
if (bytes.length === 96 && bitC) {
|
|
1020
1028
|
const { b } = bls12_381.CURVE.G2;
|
|
1021
1029
|
const P = Fp.ORDER;
|
|
@@ -1027,13 +1035,13 @@ export const bls12_381 = bls({
|
|
|
1027
1035
|
}
|
|
1028
1036
|
return { x: Fp2.ZERO, y: Fp2.ZERO };
|
|
1029
1037
|
}
|
|
1030
|
-
const x_1 =
|
|
1031
|
-
const x_0 =
|
|
1038
|
+
const x_1 = slc(bytes, 0, L);
|
|
1039
|
+
const x_0 = slc(bytes, L, 2 * L);
|
|
1032
1040
|
const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) });
|
|
1033
1041
|
const right = Fp2.add(Fp2.pow(x, 3n), b); // y² = x³ + 4 * (u+1) = x³ + b
|
|
1034
1042
|
let y = Fp2.sqrt(right);
|
|
1035
1043
|
const Y_bit = y.c1 === 0n ? (y.c0 * 2n) / P : (y.c1 * 2n) / P ? 1n : 0n;
|
|
1036
|
-
y = bitS > 0 && Y_bit > 0 ? y : Fp2.
|
|
1044
|
+
y = bitS > 0 && Y_bit > 0 ? y : Fp2.neg(y);
|
|
1037
1045
|
return { x, y };
|
|
1038
1046
|
}
|
|
1039
1047
|
else if (bytes.length === 192 && !bitC) {
|
|
@@ -1041,10 +1049,10 @@ export const bls12_381 = bls({
|
|
|
1041
1049
|
if ((bytes[0] & (1 << 6)) !== 0) {
|
|
1042
1050
|
return { x: Fp2.ZERO, y: Fp2.ZERO };
|
|
1043
1051
|
}
|
|
1044
|
-
const x1 =
|
|
1045
|
-
const x0 =
|
|
1046
|
-
const y1 =
|
|
1047
|
-
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);
|
|
1048
1056
|
return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) };
|
|
1049
1057
|
}
|
|
1050
1058
|
else {
|
|
@@ -1053,23 +1061,23 @@ export const bls12_381 = bls({
|
|
|
1053
1061
|
},
|
|
1054
1062
|
toBytes: (c, point, isCompressed) => {
|
|
1055
1063
|
const isZero = point.equals(c.ZERO);
|
|
1056
|
-
const { x, y } = point;
|
|
1064
|
+
const { x, y } = point.toAffine();
|
|
1057
1065
|
if (isCompressed) {
|
|
1058
1066
|
const P = Fp.ORDER;
|
|
1059
1067
|
if (isZero)
|
|
1060
|
-
return
|
|
1068
|
+
return concatB(COMPRESSED_ZERO, numberToBytesBE(0n, Fp.BYTES));
|
|
1061
1069
|
const flag = Boolean(y.c1 === 0n ? (y.c0 * 2n) / P : (y.c1 * 2n) / P);
|
|
1062
1070
|
// set compressed & sign bits (looks like different offsets than for G1/Fp?)
|
|
1063
1071
|
let x_1 = bitSet(x.c1, C_BIT_POS, flag);
|
|
1064
1072
|
x_1 = bitSet(x_1, S_BIT_POS, true);
|
|
1065
|
-
return
|
|
1073
|
+
return concatB(numberToBytesBE(x_1, Fp.BYTES), numberToBytesBE(x.c0, Fp.BYTES));
|
|
1066
1074
|
}
|
|
1067
1075
|
else {
|
|
1068
1076
|
if (isZero)
|
|
1069
|
-
return
|
|
1077
|
+
return concatB(new Uint8Array([0x40]), new Uint8Array(4 * Fp.BYTES - 1)); // bytes[0] |= 1 << 6;
|
|
1070
1078
|
const { re: x0, im: x1 } = Fp2.reim(x);
|
|
1071
1079
|
const { re: y0, im: y1 } = Fp2.reim(y);
|
|
1072
|
-
return
|
|
1080
|
+
return concatB(numberToBytesBE(x1, Fp.BYTES), numberToBytesBE(x0, Fp.BYTES), numberToBytesBE(y1, Fp.BYTES), numberToBytesBE(y0, Fp.BYTES));
|
|
1073
1081
|
}
|
|
1074
1082
|
},
|
|
1075
1083
|
Signature: {
|
|
@@ -1085,7 +1093,7 @@ export const bls12_381 = bls({
|
|
|
1085
1093
|
// Indicates the infinity point
|
|
1086
1094
|
const bflag1 = bitGet(z1, I_BIT_POS);
|
|
1087
1095
|
if (bflag1 === 1n)
|
|
1088
|
-
return bls12_381.G2.
|
|
1096
|
+
return bls12_381.G2.ProjectivePoint.ZERO;
|
|
1089
1097
|
const x1 = Fp.create(z1 & Fp.MASK);
|
|
1090
1098
|
const x2 = Fp.create(z2);
|
|
1091
1099
|
const x = Fp2.create({ c0: x2, c1: x1 });
|
|
@@ -1101,23 +1109,25 @@ export const bls12_381 = bls({
|
|
|
1101
1109
|
const isGreater = y1 > 0n && (y1 * 2n) / P !== aflag1;
|
|
1102
1110
|
const isZero = y1 === 0n && (y0 * 2n) / P !== aflag1;
|
|
1103
1111
|
if (isGreater || isZero)
|
|
1104
|
-
y = Fp2.
|
|
1105
|
-
const point =
|
|
1112
|
+
y = Fp2.neg(y);
|
|
1113
|
+
const point = bls12_381.G2.ProjectivePoint.fromAffine({ x, y });
|
|
1114
|
+
// console.log('Signature.decode', point);
|
|
1106
1115
|
point.assertValidity();
|
|
1107
1116
|
return point;
|
|
1108
1117
|
},
|
|
1109
1118
|
encode(point) {
|
|
1110
1119
|
// NOTE: by some reasons it was missed in bls12-381, looks like bug
|
|
1111
1120
|
point.assertValidity();
|
|
1112
|
-
if (point.equals(bls12_381.G2.
|
|
1113
|
-
return
|
|
1114
|
-
const
|
|
1115
|
-
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);
|
|
1116
1126
|
const tmp = y1 > 0n ? y1 * 2n : y0 * 2n;
|
|
1117
1127
|
const aflag1 = Boolean((tmp / Fp.ORDER) & 1n);
|
|
1118
1128
|
const z1 = bitSet(bitSet(x1, 381, aflag1), S_BIT_POS, true);
|
|
1119
1129
|
const z2 = x0;
|
|
1120
|
-
return
|
|
1130
|
+
return concatB(numberToBytesBE(z1, Fp.BYTES), numberToBytesBE(z2, Fp.BYTES));
|
|
1121
1131
|
},
|
|
1122
1132
|
},
|
|
1123
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
|
/**
|