@noble/curves 0.5.0 → 0.5.2
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 +62 -14
- package/lib/_shortw_utils.d.ts +2 -6
- package/lib/abstract/bls.d.ts +17 -8
- package/lib/abstract/bls.js +15 -78
- package/lib/abstract/edwards.d.ts +7 -16
- package/lib/abstract/edwards.js +89 -106
- package/lib/abstract/hash-to-curve.d.ts +10 -1
- package/lib/abstract/hash-to-curve.js +32 -10
- package/lib/abstract/modular.d.ts +8 -17
- package/lib/abstract/modular.js +134 -152
- package/lib/abstract/montgomery.js +1 -1
- package/lib/abstract/utils.d.ts +8 -4
- package/lib/abstract/utils.js +22 -14
- package/lib/abstract/weierstrass.d.ts +8 -8
- package/lib/abstract/weierstrass.js +209 -168
- package/lib/bls12-381.d.ts +2 -1
- package/lib/bls12-381.js +14 -9
- package/lib/ed25519.js +75 -12
- package/lib/ed448.js +86 -2
- package/lib/esm/abstract/bls.js +19 -82
- package/lib/esm/abstract/edwards.js +90 -107
- package/lib/esm/abstract/hash-to-curve.js +30 -9
- package/lib/esm/abstract/modular.js +128 -148
- package/lib/esm/abstract/montgomery.js +2 -4
- package/lib/esm/abstract/utils.js +20 -13
- package/lib/esm/abstract/weierstrass.js +210 -169
- package/lib/esm/bls12-381.js +13 -8
- package/lib/esm/ed25519.js +76 -13
- package/lib/esm/ed448.js +87 -3
- package/lib/esm/jubjub.js +5 -4
- package/lib/esm/p256.js +1 -1
- package/lib/esm/p384.js +1 -1
- package/lib/esm/p521.js +1 -1
- package/lib/esm/secp256k1.js +27 -27
- package/lib/esm/stark.js +5 -2
- package/lib/jubjub.d.ts +1 -0
- package/lib/jubjub.js +5 -4
- package/lib/p192.d.ts +4 -12
- package/lib/p224.d.ts +4 -12
- package/lib/p256.d.ts +4 -12
- package/lib/p256.js +1 -1
- package/lib/p384.d.ts +4 -12
- package/lib/p384.js +1 -1
- package/lib/p521.d.ts +4 -12
- package/lib/p521.js +1 -1
- package/lib/secp256k1.d.ts +2 -6
- package/lib/secp256k1.js +27 -27
- package/lib/stark.d.ts +1 -3
- package/lib/stark.js +5 -2
- package/package.json +2 -2
package/lib/bls12-381.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
1
2
|
import { CurveFn } from './abstract/bls.js';
|
|
2
3
|
import * as mod from './abstract/modular.js';
|
|
3
|
-
declare const Fp: Readonly<mod.Field<bigint
|
|
4
|
+
declare const Fp: Readonly<mod.Field<bigint> & Required<Pick<mod.Field<bigint>, "isOdd">>>;
|
|
4
5
|
declare type Fp = bigint;
|
|
5
6
|
declare type BigintTuple = [bigint, bigint];
|
|
6
7
|
declare type Fp2 = {
|
package/lib/bls12-381.js
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
2
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
4
|
exports.bls12_381 = void 0;
|
|
4
|
-
|
|
5
|
+
// The pairing-friendly Barreto-Lynn-Scott elliptic curve construction allows to:
|
|
6
|
+
// - Construct zk-SNARKs at the 128-bit security
|
|
7
|
+
// - 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.
|
|
8
|
+
// Differences from @noble/bls12-381 1.4:
|
|
9
|
+
// - PointG1 -> G1.Point
|
|
10
|
+
// - PointG2 -> G2.Point
|
|
11
|
+
// - PointG2.fromSignature -> Signature.decode
|
|
12
|
+
// - PointG2.toSignature -> Signature.encode
|
|
13
|
+
// - Fixed Fp2 ORDER
|
|
14
|
+
// - Points now have only two coordinates
|
|
5
15
|
const sha256_1 = require("@noble/hashes/sha256");
|
|
6
16
|
const utils_1 = require("@noble/hashes/utils");
|
|
7
17
|
const bls_js_1 = require("./abstract/bls.js");
|
|
@@ -10,13 +20,6 @@ const utils_js_1 = require("./abstract/utils.js");
|
|
|
10
20
|
// Types
|
|
11
21
|
const weierstrass_js_1 = require("./abstract/weierstrass.js");
|
|
12
22
|
const hash_to_curve_js_1 = require("./abstract/hash-to-curve.js");
|
|
13
|
-
// Differences from bls12-381:
|
|
14
|
-
// - PointG1 -> G1.Point
|
|
15
|
-
// - PointG2 -> G2.Point
|
|
16
|
-
// - PointG2.fromSignature -> Signature.decode
|
|
17
|
-
// - PointG2.toSignature -> Signature.encode
|
|
18
|
-
// - Fixed Fp2 ORDER
|
|
19
|
-
// Points now have only two coordinates
|
|
20
23
|
// CURVE FIELDS
|
|
21
24
|
// Finite field over p.
|
|
22
25
|
const Fp = mod.Fp(0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn);
|
|
@@ -100,6 +103,8 @@ const Fp2 = {
|
|
|
100
103
|
return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) };
|
|
101
104
|
},
|
|
102
105
|
sqrt: (num) => {
|
|
106
|
+
if (Fp2.equals(num, Fp2.ZERO))
|
|
107
|
+
return Fp2.ZERO; // Algo doesn't handles this case
|
|
103
108
|
// TODO: Optimize this line. It's extremely slow.
|
|
104
109
|
// Speeding this up would boost aggregateSignatures.
|
|
105
110
|
// https://eprint.iacr.org/2012/685.pdf applicable?
|
|
@@ -818,7 +823,7 @@ const htfDefaults = {
|
|
|
818
823
|
k: 128,
|
|
819
824
|
// option to use a message that has already been processed by
|
|
820
825
|
// expand_message_xmd
|
|
821
|
-
expand:
|
|
826
|
+
expand: 'xmd',
|
|
822
827
|
// Hash functions for: expand_message_xmd is appropriate for use with a
|
|
823
828
|
// wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
|
|
824
829
|
// BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
|
package/lib/ed25519.js
CHANGED
|
@@ -81,7 +81,74 @@ exports.ED25519_TORSION_SUBGROUP = [
|
|
|
81
81
|
'0000000000000000000000000000000000000000000000000000000000000000',
|
|
82
82
|
'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa',
|
|
83
83
|
];
|
|
84
|
-
const Fp = (0, modular_js_1.Fp)(ED25519_P);
|
|
84
|
+
const Fp = (0, modular_js_1.Fp)(ED25519_P, undefined, true);
|
|
85
|
+
// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator)
|
|
86
|
+
// NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since
|
|
87
|
+
// SageMath returns different root first and everything falls apart
|
|
88
|
+
const ELL2_C1 = (Fp.ORDER + BigInt(3)) / BigInt(8); // 1. c1 = (q + 3) / 8 # Integer arithmetic
|
|
89
|
+
const ELL2_C2 = Fp.pow(_2n, ELL2_C1); // 2. c2 = 2^c1
|
|
90
|
+
const ELL2_C3 = Fp.sqrt(Fp.negate(Fp.ONE)); // 3. c3 = sqrt(-1)
|
|
91
|
+
const ELL2_C4 = (Fp.ORDER - BigInt(5)) / BigInt(8); // 4. c4 = (q - 5) / 8 # Integer arithmetic
|
|
92
|
+
const ELL2_J = BigInt(486662);
|
|
93
|
+
// prettier-ignore
|
|
94
|
+
function map_to_curve_elligator2_curve25519(u) {
|
|
95
|
+
let tv1 = Fp.square(u); // 1. tv1 = u^2
|
|
96
|
+
tv1 = Fp.mul(tv1, _2n); // 2. tv1 = 2 * tv1
|
|
97
|
+
let xd = Fp.add(tv1, Fp.ONE); // 3. xd = tv1 + 1 # Nonzero: -1 is square (mod p), tv1 is not
|
|
98
|
+
let x1n = Fp.negate(ELL2_J); // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2)
|
|
99
|
+
let tv2 = Fp.square(xd); // 5. tv2 = xd^2
|
|
100
|
+
let gxd = Fp.mul(tv2, xd); // 6. gxd = tv2 * xd # gxd = xd^3
|
|
101
|
+
let gx1 = Fp.mul(tv1, ELL2_J); // 7. gx1 = J * tv1 # x1n + J * xd
|
|
102
|
+
gx1 = Fp.mul(gx1, x1n); // 8. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
|
|
103
|
+
gx1 = Fp.add(gx1, tv2); // 9. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
|
|
104
|
+
gx1 = Fp.mul(gx1, x1n); // 10. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
|
|
105
|
+
let tv3 = Fp.square(gxd); // 11. tv3 = gxd^2
|
|
106
|
+
tv2 = Fp.square(tv3); // 12. tv2 = tv3^2 # gxd^4
|
|
107
|
+
tv3 = Fp.mul(tv3, gxd); // 13. tv3 = tv3 * gxd # gxd^3
|
|
108
|
+
tv3 = Fp.mul(tv3, gx1); // 14. tv3 = tv3 * gx1 # gx1 * gxd^3
|
|
109
|
+
tv2 = Fp.mul(tv2, tv3); // 15. tv2 = tv2 * tv3 # gx1 * gxd^7
|
|
110
|
+
let y11 = Fp.pow(tv2, ELL2_C4); // 16. y11 = tv2^c4 # (gx1 * gxd^7)^((p - 5) / 8)
|
|
111
|
+
y11 = Fp.mul(y11, tv3); // 17. y11 = y11 * tv3 # gx1*gxd^3*(gx1*gxd^7)^((p-5)/8)
|
|
112
|
+
let y12 = Fp.mul(y11, ELL2_C3); // 18. y12 = y11 * c3
|
|
113
|
+
tv2 = Fp.square(y11); // 19. tv2 = y11^2
|
|
114
|
+
tv2 = Fp.mul(tv2, gxd); // 20. tv2 = tv2 * gxd
|
|
115
|
+
let e1 = Fp.equals(tv2, gx1); // 21. e1 = tv2 == gx1
|
|
116
|
+
let y1 = Fp.cmov(y12, y11, e1); // 22. y1 = CMOV(y12, y11, e1) # If g(x1) is square, this is its sqrt
|
|
117
|
+
let x2n = Fp.mul(x1n, tv1); // 23. x2n = x1n * tv1 # x2 = x2n / xd = 2 * u^2 * x1n / xd
|
|
118
|
+
let y21 = Fp.mul(y11, u); // 24. y21 = y11 * u
|
|
119
|
+
y21 = Fp.mul(y21, ELL2_C2); // 25. y21 = y21 * c2
|
|
120
|
+
let y22 = Fp.mul(y21, ELL2_C3); // 26. y22 = y21 * c3
|
|
121
|
+
let gx2 = Fp.mul(gx1, tv1); // 27. gx2 = gx1 * tv1 # g(x2) = gx2 / gxd = 2 * u^2 * g(x1)
|
|
122
|
+
tv2 = Fp.square(y21); // 28. tv2 = y21^2
|
|
123
|
+
tv2 = Fp.mul(tv2, gxd); // 29. tv2 = tv2 * gxd
|
|
124
|
+
let e2 = Fp.equals(tv2, gx2); // 30. e2 = tv2 == gx2
|
|
125
|
+
let y2 = Fp.cmov(y22, y21, e2); // 31. y2 = CMOV(y22, y21, e2) # If g(x2) is square, this is its sqrt
|
|
126
|
+
tv2 = Fp.square(y1); // 32. tv2 = y1^2
|
|
127
|
+
tv2 = Fp.mul(tv2, gxd); // 33. tv2 = tv2 * gxd
|
|
128
|
+
let e3 = Fp.equals(tv2, gx1); // 34. e3 = tv2 == gx1
|
|
129
|
+
let xn = Fp.cmov(x2n, x1n, e3); // 35. xn = CMOV(x2n, x1n, e3) # If e3, x = x1, else x = x2
|
|
130
|
+
let y = Fp.cmov(y2, y1, e3); // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2
|
|
131
|
+
let e4 = Fp.isOdd(y); // 37. e4 = sgn0(y) == 1 # Fix sign of y
|
|
132
|
+
y = Fp.cmov(y, Fp.negate(y), e3 !== e4); // 38. y = CMOV(y, -y, e3 XOR e4)
|
|
133
|
+
return { xMn: xn, xMd: xd, yMn: y, yMd: 1n }; // 39. return (xn, xd, y, 1)
|
|
134
|
+
}
|
|
135
|
+
const ELL2_C1_EDWARDS = (0, modular_js_1.FpSqrtEven)(Fp, Fp.negate(BigInt(486664))); // sgn0(c1) MUST equal 0
|
|
136
|
+
function map_to_curve_elligator2_edwards25519(u) {
|
|
137
|
+
const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u); // 1. (xMn, xMd, yMn, yMd) = map_to_curve_elligator2_curve25519(u)
|
|
138
|
+
let xn = Fp.mul(xMn, yMd); // 2. xn = xMn * yMd
|
|
139
|
+
xn = Fp.mul(xn, ELL2_C1_EDWARDS); // 3. xn = xn * c1
|
|
140
|
+
let xd = Fp.mul(xMd, yMn); // 4. xd = xMd * yMn # xn / xd = c1 * xM / yM
|
|
141
|
+
let yn = Fp.sub(xMn, xMd); // 5. yn = xMn - xMd
|
|
142
|
+
let yd = Fp.add(xMn, xMd); // 6. yd = xMn + xMd # (n / d - 1) / (n / d + 1) = (n - d) / (n + d)
|
|
143
|
+
let tv1 = Fp.mul(xd, yd); // 7. tv1 = xd * yd
|
|
144
|
+
let e = Fp.equals(tv1, Fp.ZERO); // 8. e = tv1 == 0
|
|
145
|
+
xn = Fp.cmov(xn, Fp.ZERO, e); // 9. xn = CMOV(xn, 0, e)
|
|
146
|
+
xd = Fp.cmov(xd, Fp.ONE, e); // 10. xd = CMOV(xd, 1, e)
|
|
147
|
+
yn = Fp.cmov(yn, Fp.ONE, e); // 11. yn = CMOV(yn, 1, e)
|
|
148
|
+
yd = Fp.cmov(yd, Fp.ONE, e); // 12. yd = CMOV(yd, 1, e)
|
|
149
|
+
const inv = Fp.invertBatch([xd, yd]); // batch division
|
|
150
|
+
return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) }; // 13. return (xn, xd, yn, yd)
|
|
151
|
+
}
|
|
85
152
|
const ED25519_DEF = {
|
|
86
153
|
// Param: a
|
|
87
154
|
a: BigInt(-1),
|
|
@@ -110,14 +177,10 @@ const ED25519_DEF = {
|
|
|
110
177
|
p: Fp.ORDER,
|
|
111
178
|
m: 1,
|
|
112
179
|
k: 128,
|
|
113
|
-
expand:
|
|
180
|
+
expand: 'xmd',
|
|
114
181
|
hash: sha512_1.sha512,
|
|
115
182
|
},
|
|
116
|
-
mapToCurve: (scalars) =>
|
|
117
|
-
throw new Error('Not supported yet');
|
|
118
|
-
// const { x, y } = calcElligatorRistrettoMap(scalars[0]).toAffine();
|
|
119
|
-
// return { x, y };
|
|
120
|
-
},
|
|
183
|
+
mapToCurve: (scalars) => map_to_curve_elligator2_edwards25519(scalars[0]),
|
|
121
184
|
};
|
|
122
185
|
exports.ed25519 = (0, edwards_js_1.twistedEdwards)(ED25519_DEF);
|
|
123
186
|
function ed25519_domain(data, ctx, phflag) {
|
|
@@ -162,13 +225,13 @@ const D_MINUS_ONE_SQ = BigInt('4044083434630853685810104246932319082624839914623
|
|
|
162
225
|
// Calculates 1/√(number)
|
|
163
226
|
const invertSqrt = (number) => uvRatio(_1n, number);
|
|
164
227
|
const MAX_255B = BigInt('0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
|
|
165
|
-
const bytes255ToNumberLE = (bytes) => exports.ed25519.
|
|
228
|
+
const bytes255ToNumberLE = (bytes) => exports.ed25519.CURVE.Fp.create((0, utils_js_1.bytesToNumberLE)(bytes) & MAX_255B);
|
|
166
229
|
// Computes Elligator map for Ristretto
|
|
167
230
|
// https://ristretto.group/formulas/elligator.html
|
|
168
231
|
function calcElligatorRistrettoMap(r0) {
|
|
169
232
|
const { d } = exports.ed25519.CURVE;
|
|
170
233
|
const P = exports.ed25519.CURVE.Fp.ORDER;
|
|
171
|
-
const
|
|
234
|
+
const mod = exports.ed25519.CURVE.Fp.create;
|
|
172
235
|
const r = mod(SQRT_M1 * r0 * r0); // 1
|
|
173
236
|
const Ns = mod((r + _1n) * ONE_MINUS_D_SQ); // 2
|
|
174
237
|
let c = BigInt(-1); // 3
|
|
@@ -226,7 +289,7 @@ class RistrettoPoint {
|
|
|
226
289
|
hex = (0, utils_js_1.ensureBytes)(hex, 32);
|
|
227
290
|
const { a, d } = exports.ed25519.CURVE;
|
|
228
291
|
const P = exports.ed25519.CURVE.Fp.ORDER;
|
|
229
|
-
const
|
|
292
|
+
const mod = exports.ed25519.CURVE.Fp.create;
|
|
230
293
|
const emsg = 'RistrettoPoint.fromHex: the hex is not valid encoding of RistrettoPoint';
|
|
231
294
|
const s = bytes255ToNumberLE(hex);
|
|
232
295
|
// 1. Check that s_bytes is the canonical encoding of a field element, or else abort.
|
|
@@ -258,7 +321,7 @@ class RistrettoPoint {
|
|
|
258
321
|
toRawBytes() {
|
|
259
322
|
let { x, y, z, t } = this.ep;
|
|
260
323
|
const P = exports.ed25519.CURVE.Fp.ORDER;
|
|
261
|
-
const
|
|
324
|
+
const mod = exports.ed25519.CURVE.Fp.create;
|
|
262
325
|
const u1 = mod(mod(z + y) * mod(z - y)); // 1
|
|
263
326
|
const u2 = mod(x * y); // 2
|
|
264
327
|
// Square root always exists
|
|
@@ -296,7 +359,7 @@ class RistrettoPoint {
|
|
|
296
359
|
assertRstPoint(other);
|
|
297
360
|
const a = this.ep;
|
|
298
361
|
const b = other.ep;
|
|
299
|
-
const
|
|
362
|
+
const mod = exports.ed25519.CURVE.Fp.create;
|
|
300
363
|
// (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2)
|
|
301
364
|
const one = mod(a.x * b.y) === mod(a.y * b.x);
|
|
302
365
|
const two = mod(a.y * b.y) === mod(a.x * b.x);
|
package/lib/ed448.js
CHANGED
|
@@ -48,14 +48,89 @@ function adjustScalarBytes(bytes) {
|
|
|
48
48
|
bytes[56] = 0; // Byte outside of group (456 buts vs 448 bits)
|
|
49
49
|
return bytes;
|
|
50
50
|
}
|
|
51
|
+
const Fp = (0, modular_js_1.Fp)(ed448P, 456, true);
|
|
52
|
+
// Hash To Curve Elligator2 Map
|
|
53
|
+
const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic
|
|
54
|
+
const ELL2_J = BigInt(156326);
|
|
55
|
+
function map_to_curve_elligator2_curve448(u) {
|
|
56
|
+
let tv1 = Fp.square(u); // 1. tv1 = u^2
|
|
57
|
+
let e1 = Fp.equals(tv1, Fp.ONE); // 2. e1 = tv1 == 1
|
|
58
|
+
tv1 = Fp.cmov(tv1, Fp.ZERO, e1); // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0
|
|
59
|
+
let xd = Fp.sub(Fp.ONE, tv1); // 4. xd = 1 - tv1
|
|
60
|
+
let x1n = Fp.negate(ELL2_J); // 5. x1n = -J
|
|
61
|
+
let tv2 = Fp.square(xd); // 6. tv2 = xd^2
|
|
62
|
+
let gxd = Fp.mul(tv2, xd); // 7. gxd = tv2 * xd # gxd = xd^3
|
|
63
|
+
let gx1 = Fp.mul(tv1, Fp.negate(ELL2_J)); // 8. gx1 = -J * tv1 # x1n + J * xd
|
|
64
|
+
gx1 = Fp.mul(gx1, x1n); // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
|
|
65
|
+
gx1 = Fp.add(gx1, tv2); // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
|
|
66
|
+
gx1 = Fp.mul(gx1, x1n); // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
|
|
67
|
+
let tv3 = Fp.square(gxd); // 12. tv3 = gxd^2
|
|
68
|
+
tv2 = Fp.mul(gx1, gxd); // 13. tv2 = gx1 * gxd # gx1 * gxd
|
|
69
|
+
tv3 = Fp.mul(tv3, tv2); // 14. tv3 = tv3 * tv2 # gx1 * gxd^3
|
|
70
|
+
let y1 = Fp.pow(tv3, ELL2_C1); // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4)
|
|
71
|
+
y1 = Fp.mul(y1, tv2); // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4)
|
|
72
|
+
let x2n = Fp.mul(x1n, Fp.negate(tv1)); // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd
|
|
73
|
+
let y2 = Fp.mul(y1, u); // 18. y2 = y1 * u
|
|
74
|
+
y2 = Fp.cmov(y2, Fp.ZERO, e1); // 19. y2 = CMOV(y2, 0, e1)
|
|
75
|
+
tv2 = Fp.square(y1); // 20. tv2 = y1^2
|
|
76
|
+
tv2 = Fp.mul(tv2, gxd); // 21. tv2 = tv2 * gxd
|
|
77
|
+
let e2 = Fp.equals(tv2, gx1); // 22. e2 = tv2 == gx1
|
|
78
|
+
let xn = Fp.cmov(x2n, x1n, e2); // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2
|
|
79
|
+
let y = Fp.cmov(y2, y1, e2); // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2
|
|
80
|
+
let e3 = Fp.isOdd(y); // 25. e3 = sgn0(y) == 1 # Fix sign of y
|
|
81
|
+
y = Fp.cmov(y, Fp.negate(y), e2 !== e3); // 26. y = CMOV(y, -y, e2 XOR e3)
|
|
82
|
+
return { xn, xd, yn: y, yd: Fp.ONE }; // 27. return (xn, xd, y, 1)
|
|
83
|
+
}
|
|
84
|
+
function map_to_curve_elligator2_edwards448(u) {
|
|
85
|
+
let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u); // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)
|
|
86
|
+
let xn2 = Fp.square(xn); // 2. xn2 = xn^2
|
|
87
|
+
let xd2 = Fp.square(xd); // 3. xd2 = xd^2
|
|
88
|
+
let xd4 = Fp.square(xd2); // 4. xd4 = xd2^2
|
|
89
|
+
let yn2 = Fp.square(yn); // 5. yn2 = yn^2
|
|
90
|
+
let yd2 = Fp.square(yd); // 6. yd2 = yd^2
|
|
91
|
+
let xEn = Fp.sub(xn2, xd2); // 7. xEn = xn2 - xd2
|
|
92
|
+
let tv2 = Fp.sub(xEn, xd2); // 8. tv2 = xEn - xd2
|
|
93
|
+
xEn = Fp.mul(xEn, xd2); // 9. xEn = xEn * xd2
|
|
94
|
+
xEn = Fp.mul(xEn, yd); // 10. xEn = xEn * yd
|
|
95
|
+
xEn = Fp.mul(xEn, yn); // 11. xEn = xEn * yn
|
|
96
|
+
xEn = Fp.mul(xEn, 4n); // 12. xEn = xEn * 4
|
|
97
|
+
tv2 = Fp.mul(tv2, xn2); // 13. tv2 = tv2 * xn2
|
|
98
|
+
tv2 = Fp.mul(tv2, yd2); // 14. tv2 = tv2 * yd2
|
|
99
|
+
let tv3 = Fp.mul(yn2, 4n); // 15. tv3 = 4 * yn2
|
|
100
|
+
let tv1 = Fp.add(tv3, yd2); // 16. tv1 = tv3 + yd2
|
|
101
|
+
tv1 = Fp.mul(tv1, xd4); // 17. tv1 = tv1 * xd4
|
|
102
|
+
let xEd = Fp.add(tv1, tv2); // 18. xEd = tv1 + tv2
|
|
103
|
+
tv2 = Fp.mul(tv2, xn); // 19. tv2 = tv2 * xn
|
|
104
|
+
let tv4 = Fp.mul(xn, xd4); // 20. tv4 = xn * xd4
|
|
105
|
+
let yEn = Fp.sub(tv3, yd2); // 21. yEn = tv3 - yd2
|
|
106
|
+
yEn = Fp.mul(yEn, tv4); // 22. yEn = yEn * tv4
|
|
107
|
+
yEn = Fp.sub(yEn, tv2); // 23. yEn = yEn - tv2
|
|
108
|
+
tv1 = Fp.add(xn2, xd2); // 24. tv1 = xn2 + xd2
|
|
109
|
+
tv1 = Fp.mul(tv1, xd2); // 25. tv1 = tv1 * xd2
|
|
110
|
+
tv1 = Fp.mul(tv1, xd); // 26. tv1 = tv1 * xd
|
|
111
|
+
tv1 = Fp.mul(tv1, yn2); // 27. tv1 = tv1 * yn2
|
|
112
|
+
tv1 = Fp.mul(tv1, BigInt(-2)); // 28. tv1 = -2 * tv1
|
|
113
|
+
let yEd = Fp.add(tv2, tv1); // 29. yEd = tv2 + tv1
|
|
114
|
+
tv4 = Fp.mul(tv4, yd2); // 30. tv4 = tv4 * yd2
|
|
115
|
+
yEd = Fp.add(yEd, tv4); // 31. yEd = yEd + tv4
|
|
116
|
+
tv1 = Fp.mul(xEd, yEd); // 32. tv1 = xEd * yEd
|
|
117
|
+
let e = Fp.equals(tv1, Fp.ZERO); // 33. e = tv1 == 0
|
|
118
|
+
xEn = Fp.cmov(xEn, Fp.ZERO, e); // 34. xEn = CMOV(xEn, 0, e)
|
|
119
|
+
xEd = Fp.cmov(xEd, Fp.ONE, e); // 35. xEd = CMOV(xEd, 1, e)
|
|
120
|
+
yEn = Fp.cmov(yEn, Fp.ONE, e); // 36. yEn = CMOV(yEn, 1, e)
|
|
121
|
+
yEd = Fp.cmov(yEd, Fp.ONE, e); // 37. yEd = CMOV(yEd, 1, e)
|
|
122
|
+
const inv = Fp.invertBatch([xEd, yEd]); // batch division
|
|
123
|
+
return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) }; // 38. return (xEn, xEd, yEn, yEd)
|
|
124
|
+
}
|
|
51
125
|
const ED448_DEF = {
|
|
52
126
|
// Param: a
|
|
53
127
|
a: BigInt(1),
|
|
54
128
|
// -39081. Negative number is P - number
|
|
55
129
|
d: BigInt('726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358'),
|
|
56
130
|
// Finite field 𝔽p over which we'll do calculations; 2n ** 448n - 2n ** 224n - 1n
|
|
57
|
-
Fp
|
|
58
|
-
// Subgroup order: how many points
|
|
131
|
+
Fp,
|
|
132
|
+
// Subgroup order: how many points curve has;
|
|
133
|
+
// 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n
|
|
59
134
|
n: BigInt('181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779'),
|
|
60
135
|
nBitLength: 456,
|
|
61
136
|
// Cofactor
|
|
@@ -94,6 +169,15 @@ const ED448_DEF = {
|
|
|
94
169
|
// square root exists, and the decoding fails.
|
|
95
170
|
return { isValid: (0, modular_js_1.mod)(x2 * v, P) === u, value: x };
|
|
96
171
|
},
|
|
172
|
+
htfDefaults: {
|
|
173
|
+
DST: 'edwards448_XOF:SHAKE256_ELL2_RO_',
|
|
174
|
+
p: Fp.ORDER,
|
|
175
|
+
m: 1,
|
|
176
|
+
k: 224,
|
|
177
|
+
expand: 'xof',
|
|
178
|
+
hash: sha3_1.shake256,
|
|
179
|
+
},
|
|
180
|
+
mapToCurve: (scalars) => map_to_curve_elligator2_edwards448(scalars[0]),
|
|
97
181
|
};
|
|
98
182
|
exports.ed448 = (0, edwards_js_1.twistedEdwards)(ED448_DEF);
|
|
99
183
|
// NOTE: there is no ed448ctx, since ed448 supports ctx by default
|
package/lib/esm/abstract/bls.js
CHANGED
|
@@ -1,21 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// NOTE: only 12 supported for now
|
|
4
|
-
// Constructed from pair of weierstrass curves, based pairing logic
|
|
5
|
-
import * as mod from './modular.js';
|
|
6
|
-
import { ensureBytes, numberToBytesBE, bytesToNumberBE, bitLen, bitGet } from './utils.js';
|
|
7
|
-
// Types
|
|
8
|
-
import { hexToBytes, bytesToHex } from './utils.js';
|
|
9
|
-
import { stringToBytes, hash_to_field, expand_message_xmd } from './hash-to-curve.js';
|
|
1
|
+
import * as ut from './utils.js';
|
|
2
|
+
import { stringToBytes, hash_to_field as hashToField, expand_message_xmd as expandMessageXMD, } from './hash-to-curve.js';
|
|
10
3
|
import { weierstrassPoints } from './weierstrass.js';
|
|
11
4
|
export function bls(CURVE) {
|
|
12
5
|
// Fields looks pretty specific for curve, so for now we need to pass them with options
|
|
13
|
-
const Fp = CURVE
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const Fp6 = CURVE.Fp6;
|
|
17
|
-
const Fp12 = CURVE.Fp12;
|
|
18
|
-
const BLS_X_LEN = bitLen(CURVE.x);
|
|
6
|
+
const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE;
|
|
7
|
+
const BLS_X_LEN = ut.bitLen(CURVE.x);
|
|
8
|
+
const groupLen = 32; // TODO: calculate; hardcoded for now
|
|
19
9
|
// Pre-compute coefficients for sparse multiplication
|
|
20
10
|
// Point addition and point double calculations is reused for coefficients
|
|
21
11
|
function calcPairingPrecomputes(x, y) {
|
|
@@ -39,7 +29,7 @@ export function bls(CURVE) {
|
|
|
39
29
|
Rx = Fp2.div(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), 2n); // ((T0 - T3) * Rx * Ry) / 2
|
|
40
30
|
Ry = Fp2.sub(Fp2.square(Fp2.div(Fp2.add(t0, t3), 2n)), Fp2.mul(Fp2.square(t2), 3n)); // ((T0 + T3) / 2)² - 3 * T2²
|
|
41
31
|
Rz = Fp2.mul(t0, t4); // T0 * T4
|
|
42
|
-
if (bitGet(CURVE.x, i)) {
|
|
32
|
+
if (ut.bitGet(CURVE.x, i)) {
|
|
43
33
|
// Addition
|
|
44
34
|
let t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)); // Ry - Qy * Rz
|
|
45
35
|
let t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)); // Rx - Qx * Rz
|
|
@@ -60,13 +50,14 @@ export function bls(CURVE) {
|
|
|
60
50
|
return ell_coeff;
|
|
61
51
|
}
|
|
62
52
|
function millerLoop(ell, g1) {
|
|
53
|
+
const { x } = CURVE;
|
|
63
54
|
const Px = g1[0];
|
|
64
55
|
const Py = g1[1];
|
|
65
56
|
let f12 = Fp12.ONE;
|
|
66
57
|
for (let j = 0, i = BLS_X_LEN - 2; i >= 0; i--, j++) {
|
|
67
58
|
const E = ell[j];
|
|
68
59
|
f12 = Fp12.multiplyBy014(f12, E[0], Fp2.mul(E[1], Px), Fp2.mul(E[2], Py));
|
|
69
|
-
if (bitGet(
|
|
60
|
+
if (ut.bitGet(x, i)) {
|
|
70
61
|
j += 1;
|
|
71
62
|
const F = ell[j];
|
|
72
63
|
f12 = Fp12.multiplyBy014(f12, F[0], Fp2.mul(F[1], Px), Fp2.mul(F[2], Py));
|
|
@@ -76,79 +67,25 @@ export function bls(CURVE) {
|
|
|
76
67
|
}
|
|
77
68
|
return Fp12.conjugate(f12);
|
|
78
69
|
}
|
|
79
|
-
// bls12-381 is a construction of two curves:
|
|
80
|
-
// 1. Fp: (x, y)
|
|
81
|
-
// 2. Fp₂: ((x₁, x₂+i), (y₁, y₂+i)) - (complex numbers)
|
|
82
|
-
//
|
|
83
|
-
// Bilinear Pairing (ate pairing) is used to combine both elements into a paired one:
|
|
84
|
-
// Fp₁₂ = e(Fp, Fp2)
|
|
85
|
-
// where Fp₁₂ = 12-degree polynomial
|
|
86
|
-
// Pairing is used to verify signatures.
|
|
87
|
-
//
|
|
88
|
-
// We are using Fp for private keys (shorter) and Fp2 for signatures (longer).
|
|
89
|
-
// Some projects may prefer to swap this relation, it is not supported for now.
|
|
90
|
-
const htfDefaults = { ...CURVE.htfDefaults };
|
|
91
|
-
function isWithinCurveOrder(num) {
|
|
92
|
-
return 0 < num && num < CURVE.r;
|
|
93
|
-
}
|
|
94
70
|
const utils = {
|
|
95
|
-
hexToBytes: hexToBytes,
|
|
96
|
-
bytesToHex: bytesToHex,
|
|
97
|
-
|
|
98
|
-
stringToBytes,
|
|
71
|
+
hexToBytes: ut.hexToBytes,
|
|
72
|
+
bytesToHex: ut.bytesToHex,
|
|
73
|
+
stringToBytes: stringToBytes,
|
|
99
74
|
// TODO: do we need to export it here?
|
|
100
|
-
hashToField: (msg, count, options = {}) =>
|
|
101
|
-
expandMessageXMD: (msg, DST, lenInBytes, H = CURVE.hash) =>
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
* https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
|
|
107
|
-
* @param hash hash output from sha512, or a similar function
|
|
108
|
-
* @returns valid private key
|
|
109
|
-
*/
|
|
110
|
-
hashToPrivateKey: (hash) => {
|
|
111
|
-
hash = ensureBytes(hash);
|
|
112
|
-
if (hash.length < 40 || hash.length > 1024)
|
|
113
|
-
throw new Error('Expected 40-1024 bytes of private key as per FIPS 186');
|
|
114
|
-
// hashToPrivateScalar(hash, CURVE.r)
|
|
115
|
-
// NOTE: doesn't add +/-1
|
|
116
|
-
const num = mod.mod(bytesToNumberBE(hash), CURVE.r);
|
|
117
|
-
// This should never happen
|
|
118
|
-
if (num === 0n || num === 1n)
|
|
119
|
-
throw new Error('Invalid private key');
|
|
120
|
-
return numberToBytesBE(num, 32);
|
|
121
|
-
},
|
|
122
|
-
randomBytes: (bytesLength = 32) => CURVE.randomBytes(bytesLength),
|
|
123
|
-
// NIST SP 800-56A rev 3, section 5.6.1.2.2
|
|
124
|
-
// https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
|
|
125
|
-
randomPrivateKey: () => utils.hashToPrivateKey(utils.randomBytes(40)),
|
|
126
|
-
getDSTLabel: () => htfDefaults.DST,
|
|
75
|
+
hashToField: (msg, count, options = {}) => hashToField(msg, count, { ...CURVE.htfDefaults, ...options }),
|
|
76
|
+
expandMessageXMD: (msg, DST, lenInBytes, H = CURVE.hash) => expandMessageXMD(msg, DST, lenInBytes, H),
|
|
77
|
+
hashToPrivateKey: (hash) => Fr.toBytes(ut.hashToPrivateScalar(hash, CURVE.r)),
|
|
78
|
+
randomBytes: (bytesLength = groupLen) => CURVE.randomBytes(bytesLength),
|
|
79
|
+
randomPrivateKey: () => utils.hashToPrivateKey(utils.randomBytes(groupLen + 8)),
|
|
80
|
+
getDSTLabel: () => CURVE.htfDefaults.DST,
|
|
127
81
|
setDSTLabel(newLabel) {
|
|
128
82
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
|
|
129
83
|
if (typeof newLabel !== 'string' || newLabel.length > 2048 || newLabel.length === 0) {
|
|
130
84
|
throw new TypeError('Invalid DST');
|
|
131
85
|
}
|
|
132
|
-
htfDefaults.DST = newLabel;
|
|
86
|
+
CURVE.htfDefaults.DST = newLabel;
|
|
133
87
|
},
|
|
134
88
|
};
|
|
135
|
-
function normalizePrivKey(key) {
|
|
136
|
-
let int;
|
|
137
|
-
if (key instanceof Uint8Array && key.length === 32)
|
|
138
|
-
int = bytesToNumberBE(key);
|
|
139
|
-
else if (typeof key === 'string' && key.length === 64)
|
|
140
|
-
int = BigInt(`0x${key}`);
|
|
141
|
-
else if (typeof key === 'number' && key > 0 && Number.isSafeInteger(key))
|
|
142
|
-
int = BigInt(key);
|
|
143
|
-
else if (typeof key === 'bigint' && key > 0n)
|
|
144
|
-
int = key;
|
|
145
|
-
else
|
|
146
|
-
throw new TypeError('Expected valid private key');
|
|
147
|
-
int = mod.mod(int, CURVE.r);
|
|
148
|
-
if (!isWithinCurveOrder(int))
|
|
149
|
-
throw new Error('Private key must be 0 < key < CURVE.r');
|
|
150
|
-
return int;
|
|
151
|
-
}
|
|
152
89
|
// Point on G1 curve: (x, y)
|
|
153
90
|
const G1 = weierstrassPoints({
|
|
154
91
|
n: Fr.ORDER,
|
|
@@ -202,7 +139,7 @@ export function bls(CURVE) {
|
|
|
202
139
|
function sign(message, privateKey) {
|
|
203
140
|
const msgPoint = normP2Hash(message);
|
|
204
141
|
msgPoint.assertValidity();
|
|
205
|
-
const sigPoint = msgPoint.multiply(
|
|
142
|
+
const sigPoint = msgPoint.multiply(G1.normalizePrivateKey(privateKey));
|
|
206
143
|
if (message instanceof G2.Point)
|
|
207
144
|
return sigPoint;
|
|
208
145
|
return Signature.encode(sigPoint);
|