@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/ed448.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.x448 = exports.ed448ph = exports.ed448 = void 0;
|
|
3
|
+
exports.encodeToCurve = exports.hashToCurve = exports.x448 = exports.ed448ph = exports.ed448 = void 0;
|
|
4
4
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
5
5
|
const sha3_1 = require("@noble/hashes/sha3");
|
|
6
6
|
const utils_1 = require("@noble/hashes/utils");
|
|
7
7
|
const edwards_js_1 = require("./abstract/edwards.js");
|
|
8
8
|
const modular_js_1 = require("./abstract/modular.js");
|
|
9
9
|
const montgomery_js_1 = require("./abstract/montgomery.js");
|
|
10
|
+
const htf = require("./abstract/hash-to-curve.js");
|
|
10
11
|
/**
|
|
11
12
|
* Edwards448 (not Ed448-Goldilocks) curve with following addons:
|
|
12
13
|
* * X448 ECDH
|
|
@@ -49,79 +50,6 @@ function adjustScalarBytes(bytes) {
|
|
|
49
50
|
return bytes;
|
|
50
51
|
}
|
|
51
52
|
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
|
-
}
|
|
125
53
|
const ED448_DEF = {
|
|
126
54
|
// Param: a
|
|
127
55
|
a: BigInt(1),
|
|
@@ -169,15 +97,6 @@ const ED448_DEF = {
|
|
|
169
97
|
// square root exists, and the decoding fails.
|
|
170
98
|
return { isValid: (0, modular_js_1.mod)(x2 * v, P) === u, value: x };
|
|
171
99
|
},
|
|
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]),
|
|
181
100
|
};
|
|
182
101
|
exports.ed448 = (0, edwards_js_1.twistedEdwards)(ED448_DEF);
|
|
183
102
|
// NOTE: there is no ed448ctx, since ed448 supports ctx by default
|
|
@@ -210,3 +129,87 @@ exports.x448 = (0, montgomery_js_1.montgomery)({
|
|
|
210
129
|
// return numberToBytesLE(u, 56);
|
|
211
130
|
// },
|
|
212
131
|
});
|
|
132
|
+
// Hash To Curve Elligator2 Map
|
|
133
|
+
const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic
|
|
134
|
+
const ELL2_J = BigInt(156326);
|
|
135
|
+
function map_to_curve_elligator2_curve448(u) {
|
|
136
|
+
let tv1 = Fp.sqr(u); // 1. tv1 = u^2
|
|
137
|
+
let e1 = Fp.eql(tv1, Fp.ONE); // 2. e1 = tv1 == 1
|
|
138
|
+
tv1 = Fp.cmov(tv1, Fp.ZERO, e1); // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0
|
|
139
|
+
let xd = Fp.sub(Fp.ONE, tv1); // 4. xd = 1 - tv1
|
|
140
|
+
let x1n = Fp.neg(ELL2_J); // 5. x1n = -J
|
|
141
|
+
let tv2 = Fp.sqr(xd); // 6. tv2 = xd^2
|
|
142
|
+
let gxd = Fp.mul(tv2, xd); // 7. gxd = tv2 * xd # gxd = xd^3
|
|
143
|
+
let gx1 = Fp.mul(tv1, Fp.neg(ELL2_J)); // 8. gx1 = -J * tv1 # x1n + J * xd
|
|
144
|
+
gx1 = Fp.mul(gx1, x1n); // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
|
|
145
|
+
gx1 = Fp.add(gx1, tv2); // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
|
|
146
|
+
gx1 = Fp.mul(gx1, x1n); // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
|
|
147
|
+
let tv3 = Fp.sqr(gxd); // 12. tv3 = gxd^2
|
|
148
|
+
tv2 = Fp.mul(gx1, gxd); // 13. tv2 = gx1 * gxd # gx1 * gxd
|
|
149
|
+
tv3 = Fp.mul(tv3, tv2); // 14. tv3 = tv3 * tv2 # gx1 * gxd^3
|
|
150
|
+
let y1 = Fp.pow(tv3, ELL2_C1); // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4)
|
|
151
|
+
y1 = Fp.mul(y1, tv2); // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4)
|
|
152
|
+
let x2n = Fp.mul(x1n, Fp.neg(tv1)); // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd
|
|
153
|
+
let y2 = Fp.mul(y1, u); // 18. y2 = y1 * u
|
|
154
|
+
y2 = Fp.cmov(y2, Fp.ZERO, e1); // 19. y2 = CMOV(y2, 0, e1)
|
|
155
|
+
tv2 = Fp.sqr(y1); // 20. tv2 = y1^2
|
|
156
|
+
tv2 = Fp.mul(tv2, gxd); // 21. tv2 = tv2 * gxd
|
|
157
|
+
let e2 = Fp.eql(tv2, gx1); // 22. e2 = tv2 == gx1
|
|
158
|
+
let xn = Fp.cmov(x2n, x1n, e2); // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2
|
|
159
|
+
let y = Fp.cmov(y2, y1, e2); // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2
|
|
160
|
+
let e3 = Fp.isOdd(y); // 25. e3 = sgn0(y) == 1 # Fix sign of y
|
|
161
|
+
y = Fp.cmov(y, Fp.neg(y), e2 !== e3); // 26. y = CMOV(y, -y, e2 XOR e3)
|
|
162
|
+
return { xn, xd, yn: y, yd: Fp.ONE }; // 27. return (xn, xd, y, 1)
|
|
163
|
+
}
|
|
164
|
+
function map_to_curve_elligator2_edwards448(u) {
|
|
165
|
+
let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u); // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)
|
|
166
|
+
let xn2 = Fp.sqr(xn); // 2. xn2 = xn^2
|
|
167
|
+
let xd2 = Fp.sqr(xd); // 3. xd2 = xd^2
|
|
168
|
+
let xd4 = Fp.sqr(xd2); // 4. xd4 = xd2^2
|
|
169
|
+
let yn2 = Fp.sqr(yn); // 5. yn2 = yn^2
|
|
170
|
+
let yd2 = Fp.sqr(yd); // 6. yd2 = yd^2
|
|
171
|
+
let xEn = Fp.sub(xn2, xd2); // 7. xEn = xn2 - xd2
|
|
172
|
+
let tv2 = Fp.sub(xEn, xd2); // 8. tv2 = xEn - xd2
|
|
173
|
+
xEn = Fp.mul(xEn, xd2); // 9. xEn = xEn * xd2
|
|
174
|
+
xEn = Fp.mul(xEn, yd); // 10. xEn = xEn * yd
|
|
175
|
+
xEn = Fp.mul(xEn, yn); // 11. xEn = xEn * yn
|
|
176
|
+
xEn = Fp.mul(xEn, 4n); // 12. xEn = xEn * 4
|
|
177
|
+
tv2 = Fp.mul(tv2, xn2); // 13. tv2 = tv2 * xn2
|
|
178
|
+
tv2 = Fp.mul(tv2, yd2); // 14. tv2 = tv2 * yd2
|
|
179
|
+
let tv3 = Fp.mul(yn2, 4n); // 15. tv3 = 4 * yn2
|
|
180
|
+
let tv1 = Fp.add(tv3, yd2); // 16. tv1 = tv3 + yd2
|
|
181
|
+
tv1 = Fp.mul(tv1, xd4); // 17. tv1 = tv1 * xd4
|
|
182
|
+
let xEd = Fp.add(tv1, tv2); // 18. xEd = tv1 + tv2
|
|
183
|
+
tv2 = Fp.mul(tv2, xn); // 19. tv2 = tv2 * xn
|
|
184
|
+
let tv4 = Fp.mul(xn, xd4); // 20. tv4 = xn * xd4
|
|
185
|
+
let yEn = Fp.sub(tv3, yd2); // 21. yEn = tv3 - yd2
|
|
186
|
+
yEn = Fp.mul(yEn, tv4); // 22. yEn = yEn * tv4
|
|
187
|
+
yEn = Fp.sub(yEn, tv2); // 23. yEn = yEn - tv2
|
|
188
|
+
tv1 = Fp.add(xn2, xd2); // 24. tv1 = xn2 + xd2
|
|
189
|
+
tv1 = Fp.mul(tv1, xd2); // 25. tv1 = tv1 * xd2
|
|
190
|
+
tv1 = Fp.mul(tv1, xd); // 26. tv1 = tv1 * xd
|
|
191
|
+
tv1 = Fp.mul(tv1, yn2); // 27. tv1 = tv1 * yn2
|
|
192
|
+
tv1 = Fp.mul(tv1, BigInt(-2)); // 28. tv1 = -2 * tv1
|
|
193
|
+
let yEd = Fp.add(tv2, tv1); // 29. yEd = tv2 + tv1
|
|
194
|
+
tv4 = Fp.mul(tv4, yd2); // 30. tv4 = tv4 * yd2
|
|
195
|
+
yEd = Fp.add(yEd, tv4); // 31. yEd = yEd + tv4
|
|
196
|
+
tv1 = Fp.mul(xEd, yEd); // 32. tv1 = xEd * yEd
|
|
197
|
+
let e = Fp.eql(tv1, Fp.ZERO); // 33. e = tv1 == 0
|
|
198
|
+
xEn = Fp.cmov(xEn, Fp.ZERO, e); // 34. xEn = CMOV(xEn, 0, e)
|
|
199
|
+
xEd = Fp.cmov(xEd, Fp.ONE, e); // 35. xEd = CMOV(xEd, 1, e)
|
|
200
|
+
yEn = Fp.cmov(yEn, Fp.ONE, e); // 36. yEn = CMOV(yEn, 1, e)
|
|
201
|
+
yEd = Fp.cmov(yEd, Fp.ONE, e); // 37. yEd = CMOV(yEd, 1, e)
|
|
202
|
+
const inv = Fp.invertBatch([xEd, yEd]); // batch division
|
|
203
|
+
return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) }; // 38. return (xEn, xEd, yEn, yEd)
|
|
204
|
+
}
|
|
205
|
+
const { hashToCurve, encodeToCurve } = htf.hashToCurve(exports.ed448.ExtendedPoint, (scalars) => map_to_curve_elligator2_edwards448(scalars[0]), {
|
|
206
|
+
DST: 'edwards448_XOF:SHAKE256_ELL2_RO_',
|
|
207
|
+
encodeDST: 'edwards448_XOF:SHAKE256_ELL2_NU_',
|
|
208
|
+
p: Fp.ORDER,
|
|
209
|
+
m: 1,
|
|
210
|
+
k: 224,
|
|
211
|
+
expand: 'xof',
|
|
212
|
+
hash: sha3_1.shake256,
|
|
213
|
+
});
|
|
214
|
+
exports.hashToCurve = hashToCurve;
|
|
215
|
+
exports.encodeToCurve = encodeToCurve;
|
package/lib/esm/abstract/bls.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import { hashToPrivateScalar } from './modular.js';
|
|
2
|
+
import { bitLen, bitGet, hexToBytes, bytesToHex } from './utils.js';
|
|
3
|
+
import * as htf from './hash-to-curve.js';
|
|
4
|
+
import { weierstrassPoints, } from './weierstrass.js';
|
|
4
5
|
export function bls(CURVE) {
|
|
5
6
|
// Fields looks pretty specific for curve, so for now we need to pass them with options
|
|
6
7
|
const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE;
|
|
7
|
-
const BLS_X_LEN =
|
|
8
|
+
const BLS_X_LEN = bitLen(CURVE.x);
|
|
8
9
|
const groupLen = 32; // TODO: calculate; hardcoded for now
|
|
9
10
|
// Pre-compute coefficients for sparse multiplication
|
|
10
11
|
// Point addition and point double calculations is reused for coefficients
|
|
11
|
-
function calcPairingPrecomputes(
|
|
12
|
+
function calcPairingPrecomputes(p) {
|
|
13
|
+
const { x, y } = p;
|
|
12
14
|
// prettier-ignore
|
|
13
15
|
const Qx = x, Qy = y, Qz = Fp2.ONE;
|
|
14
16
|
// prettier-ignore
|
|
@@ -16,32 +18,32 @@ export function bls(CURVE) {
|
|
|
16
18
|
let ell_coeff = [];
|
|
17
19
|
for (let i = BLS_X_LEN - 2; i >= 0; i--) {
|
|
18
20
|
// Double
|
|
19
|
-
let t0 = Fp2.
|
|
20
|
-
let t1 = Fp2.
|
|
21
|
+
let t0 = Fp2.sqr(Ry); // Ry²
|
|
22
|
+
let t1 = Fp2.sqr(Rz); // Rz²
|
|
21
23
|
let t2 = Fp2.multiplyByB(Fp2.mul(t1, 3n)); // 3 * T1 * B
|
|
22
24
|
let t3 = Fp2.mul(t2, 3n); // 3 * T2
|
|
23
|
-
let t4 = Fp2.sub(Fp2.sub(Fp2.
|
|
25
|
+
let t4 = Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(Ry, Rz)), t1), t0); // (Ry + Rz)² - T1 - T0
|
|
24
26
|
ell_coeff.push([
|
|
25
27
|
Fp2.sub(t2, t0),
|
|
26
|
-
Fp2.mul(Fp2.
|
|
27
|
-
Fp2.
|
|
28
|
+
Fp2.mul(Fp2.sqr(Rx), 3n),
|
|
29
|
+
Fp2.neg(t4), // -T4
|
|
28
30
|
]);
|
|
29
31
|
Rx = Fp2.div(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), 2n); // ((T0 - T3) * Rx * Ry) / 2
|
|
30
|
-
Ry = Fp2.sub(Fp2.
|
|
32
|
+
Ry = Fp2.sub(Fp2.sqr(Fp2.div(Fp2.add(t0, t3), 2n)), Fp2.mul(Fp2.sqr(t2), 3n)); // ((T0 + T3) / 2)² - 3 * T2²
|
|
31
33
|
Rz = Fp2.mul(t0, t4); // T0 * T4
|
|
32
|
-
if (
|
|
34
|
+
if (bitGet(CURVE.x, i)) {
|
|
33
35
|
// Addition
|
|
34
36
|
let t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)); // Ry - Qy * Rz
|
|
35
37
|
let t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)); // Rx - Qx * Rz
|
|
36
38
|
ell_coeff.push([
|
|
37
39
|
Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)),
|
|
38
|
-
Fp2.
|
|
40
|
+
Fp2.neg(t0),
|
|
39
41
|
t1, // T1
|
|
40
42
|
]);
|
|
41
|
-
let t2 = Fp2.
|
|
43
|
+
let t2 = Fp2.sqr(t1); // T1²
|
|
42
44
|
let t3 = Fp2.mul(t2, t1); // T2 * T1
|
|
43
45
|
let t4 = Fp2.mul(t2, Rx); // T2 * Rx
|
|
44
|
-
let t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, 2n)), Fp2.mul(Fp2.
|
|
46
|
+
let t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, 2n)), Fp2.mul(Fp2.sqr(t0), Rz)); // T3 - 2 * T4 + T0² * Rz
|
|
45
47
|
Rx = Fp2.mul(t1, t5); // T1 * T5
|
|
46
48
|
Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)); // (T4 - T5) * T0 - T3 * Ry
|
|
47
49
|
Rz = Fp2.mul(Rz, t3); // Rz * T3
|
|
@@ -57,115 +59,114 @@ export function bls(CURVE) {
|
|
|
57
59
|
for (let j = 0, i = BLS_X_LEN - 2; i >= 0; i--, j++) {
|
|
58
60
|
const E = ell[j];
|
|
59
61
|
f12 = Fp12.multiplyBy014(f12, E[0], Fp2.mul(E[1], Px), Fp2.mul(E[2], Py));
|
|
60
|
-
if (
|
|
62
|
+
if (bitGet(x, i)) {
|
|
61
63
|
j += 1;
|
|
62
64
|
const F = ell[j];
|
|
63
65
|
f12 = Fp12.multiplyBy014(f12, F[0], Fp2.mul(F[1], Px), Fp2.mul(F[2], Py));
|
|
64
66
|
}
|
|
65
67
|
if (i !== 0)
|
|
66
|
-
f12 = Fp12.
|
|
68
|
+
f12 = Fp12.sqr(f12);
|
|
67
69
|
}
|
|
68
70
|
return Fp12.conjugate(f12);
|
|
69
71
|
}
|
|
70
72
|
const utils = {
|
|
71
|
-
hexToBytes:
|
|
72
|
-
bytesToHex:
|
|
73
|
-
stringToBytes: stringToBytes,
|
|
73
|
+
hexToBytes: hexToBytes,
|
|
74
|
+
bytesToHex: bytesToHex,
|
|
75
|
+
stringToBytes: htf.stringToBytes,
|
|
74
76
|
// TODO: do we need to export it here?
|
|
75
|
-
hashToField: (msg, count, options = {}) =>
|
|
76
|
-
expandMessageXMD: (msg, DST, lenInBytes, H = CURVE.hash) =>
|
|
77
|
-
hashToPrivateKey: (hash) => Fr.toBytes(
|
|
77
|
+
hashToField: (msg, count, options = {}) => htf.hash_to_field(msg, count, { ...CURVE.htfDefaults, ...options }),
|
|
78
|
+
expandMessageXMD: (msg, DST, lenInBytes, H = CURVE.hash) => htf.expand_message_xmd(msg, DST, lenInBytes, H),
|
|
79
|
+
hashToPrivateKey: (hash) => Fr.toBytes(hashToPrivateScalar(hash, CURVE.r)),
|
|
78
80
|
randomBytes: (bytesLength = groupLen) => CURVE.randomBytes(bytesLength),
|
|
79
81
|
randomPrivateKey: () => utils.hashToPrivateKey(utils.randomBytes(groupLen + 8)),
|
|
80
|
-
getDSTLabel: () => CURVE.htfDefaults.DST,
|
|
81
|
-
setDSTLabel(newLabel) {
|
|
82
|
-
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
|
|
83
|
-
if (typeof newLabel !== 'string' || newLabel.length > 2048 || newLabel.length === 0) {
|
|
84
|
-
throw new TypeError('Invalid DST');
|
|
85
|
-
}
|
|
86
|
-
CURVE.htfDefaults.DST = newLabel;
|
|
87
|
-
},
|
|
88
82
|
};
|
|
89
83
|
// Point on G1 curve: (x, y)
|
|
90
84
|
const G1 = weierstrassPoints({
|
|
91
85
|
n: Fr.ORDER,
|
|
92
86
|
...CURVE.G1,
|
|
93
87
|
});
|
|
88
|
+
const G1HashToCurve = htf.hashToCurve(G1.ProjectivePoint, CURVE.G1.mapToCurve, {
|
|
89
|
+
...CURVE.htfDefaults,
|
|
90
|
+
...CURVE.G1.htfDefaults,
|
|
91
|
+
});
|
|
94
92
|
function pairingPrecomputes(point) {
|
|
95
93
|
const p = point;
|
|
96
94
|
if (p._PPRECOMPUTES)
|
|
97
95
|
return p._PPRECOMPUTES;
|
|
98
|
-
p._PPRECOMPUTES = calcPairingPrecomputes(
|
|
96
|
+
p._PPRECOMPUTES = calcPairingPrecomputes(point.toAffine());
|
|
99
97
|
return p._PPRECOMPUTES;
|
|
100
98
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
function millerLoopG1(Q, P) {
|
|
107
|
-
return millerLoop(pairingPrecomputes(P), [Q.x, Q.y]);
|
|
108
|
-
}
|
|
99
|
+
// TODO: export
|
|
100
|
+
// function clearPairingPrecomputes(point: G2) {
|
|
101
|
+
// const p = point as G2 & withPairingPrecomputes;
|
|
102
|
+
// p._PPRECOMPUTES = undefined;
|
|
103
|
+
// }
|
|
109
104
|
// Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i)
|
|
110
105
|
const G2 = weierstrassPoints({
|
|
111
106
|
n: Fr.ORDER,
|
|
112
107
|
...CURVE.G2,
|
|
113
108
|
});
|
|
109
|
+
const C = G2.ProjectivePoint; // TODO: fix
|
|
110
|
+
const G2HashToCurve = htf.hashToCurve(C, CURVE.G2.mapToCurve, {
|
|
111
|
+
...CURVE.htfDefaults,
|
|
112
|
+
...CURVE.G2.htfDefaults,
|
|
113
|
+
});
|
|
114
114
|
const { Signature } = CURVE.G2;
|
|
115
115
|
// Calculates bilinear pairing
|
|
116
|
-
function pairing(
|
|
117
|
-
if (
|
|
118
|
-
throw new Error('
|
|
119
|
-
P.assertValidity();
|
|
116
|
+
function pairing(Q, P, withFinalExponent = true) {
|
|
117
|
+
if (Q.equals(G1.ProjectivePoint.ZERO) || P.equals(G2.ProjectivePoint.ZERO))
|
|
118
|
+
throw new Error('pairing is not available for ZERO point');
|
|
120
119
|
Q.assertValidity();
|
|
120
|
+
P.assertValidity();
|
|
121
121
|
// Performance: 9ms for millerLoop and ~14ms for exp.
|
|
122
|
-
const
|
|
122
|
+
const Qa = Q.toAffine();
|
|
123
|
+
const looped = millerLoop(pairingPrecomputes(P), [Qa.x, Qa.y]);
|
|
123
124
|
return withFinalExponent ? Fp12.finalExponentiate(looped) : looped;
|
|
124
125
|
}
|
|
125
126
|
function normP1(point) {
|
|
126
|
-
return point instanceof G1.
|
|
127
|
+
return point instanceof G1.ProjectivePoint ? point : G1.ProjectivePoint.fromHex(point);
|
|
127
128
|
}
|
|
128
129
|
function normP2(point) {
|
|
129
|
-
return point instanceof G2.
|
|
130
|
+
return point instanceof G2.ProjectivePoint ? point : Signature.decode(point);
|
|
130
131
|
}
|
|
131
|
-
function normP2Hash(point) {
|
|
132
|
-
return point instanceof G2.
|
|
132
|
+
function normP2Hash(point, htfOpts) {
|
|
133
|
+
return point instanceof G2.ProjectivePoint
|
|
134
|
+
? point
|
|
135
|
+
: G2HashToCurve.hashToCurve(point, htfOpts);
|
|
133
136
|
}
|
|
134
137
|
// Multiplies generator by private key.
|
|
135
138
|
// P = pk x G
|
|
136
139
|
function getPublicKey(privateKey) {
|
|
137
|
-
return G1.
|
|
140
|
+
return G1.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true);
|
|
138
141
|
}
|
|
139
|
-
function sign(message, privateKey) {
|
|
140
|
-
const msgPoint = normP2Hash(message);
|
|
142
|
+
function sign(message, privateKey, htfOpts) {
|
|
143
|
+
const msgPoint = normP2Hash(message, htfOpts);
|
|
141
144
|
msgPoint.assertValidity();
|
|
142
145
|
const sigPoint = msgPoint.multiply(G1.normalizePrivateKey(privateKey));
|
|
143
|
-
if (message instanceof G2.
|
|
146
|
+
if (message instanceof G2.ProjectivePoint)
|
|
144
147
|
return sigPoint;
|
|
145
148
|
return Signature.encode(sigPoint);
|
|
146
149
|
}
|
|
147
150
|
// Checks if pairing of public key & hash is equal to pairing of generator & signature.
|
|
148
151
|
// e(P, H(m)) == e(G, S)
|
|
149
|
-
function verify(signature, message, publicKey) {
|
|
152
|
+
function verify(signature, message, publicKey, htfOpts) {
|
|
150
153
|
const P = normP1(publicKey);
|
|
151
|
-
const Hm = normP2Hash(message);
|
|
152
|
-
const G = G1.
|
|
154
|
+
const Hm = normP2Hash(message, htfOpts);
|
|
155
|
+
const G = G1.ProjectivePoint.BASE;
|
|
153
156
|
const S = normP2(signature);
|
|
154
157
|
// Instead of doing 2 exponentiations, we use property of billinear maps
|
|
155
158
|
// and do one exp after multiplying 2 points.
|
|
156
159
|
const ePHm = pairing(P.negate(), Hm, false);
|
|
157
160
|
const eGS = pairing(G, S, false);
|
|
158
161
|
const exp = Fp12.finalExponentiate(Fp12.mul(eGS, ePHm));
|
|
159
|
-
return Fp12.
|
|
162
|
+
return Fp12.eql(exp, Fp12.ONE);
|
|
160
163
|
}
|
|
161
164
|
function aggregatePublicKeys(publicKeys) {
|
|
162
165
|
if (!publicKeys.length)
|
|
163
166
|
throw new Error('Expected non-empty array');
|
|
164
|
-
const agg = publicKeys
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const aggAffine = agg.toAffine();
|
|
168
|
-
if (publicKeys[0] instanceof G1.Point) {
|
|
167
|
+
const agg = publicKeys.map(normP1).reduce((sum, p) => sum.add(p), G1.ProjectivePoint.ZERO);
|
|
168
|
+
const aggAffine = agg; //.toAffine();
|
|
169
|
+
if (publicKeys[0] instanceof G1.ProjectivePoint) {
|
|
169
170
|
aggAffine.assertValidity();
|
|
170
171
|
return aggAffine;
|
|
171
172
|
}
|
|
@@ -175,11 +176,9 @@ export function bls(CURVE) {
|
|
|
175
176
|
function aggregateSignatures(signatures) {
|
|
176
177
|
if (!signatures.length)
|
|
177
178
|
throw new Error('Expected non-empty array');
|
|
178
|
-
const agg = signatures
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const aggAffine = agg.toAffine();
|
|
182
|
-
if (signatures[0] instanceof G2.Point) {
|
|
179
|
+
const agg = signatures.map(normP2).reduce((sum, s) => sum.add(s), G2.ProjectivePoint.ZERO);
|
|
180
|
+
const aggAffine = agg; //.toAffine();
|
|
181
|
+
if (signatures[0] instanceof G2.ProjectivePoint) {
|
|
183
182
|
aggAffine.assertValidity();
|
|
184
183
|
return aggAffine;
|
|
185
184
|
}
|
|
@@ -187,33 +186,34 @@ export function bls(CURVE) {
|
|
|
187
186
|
}
|
|
188
187
|
// https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407
|
|
189
188
|
// e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))
|
|
190
|
-
function verifyBatch(signature, messages, publicKeys) {
|
|
189
|
+
function verifyBatch(signature, messages, publicKeys, htfOpts) {
|
|
190
|
+
// @ts-ignore
|
|
191
|
+
// console.log('verifyBatch', bytesToHex(signature as any), messages, publicKeys.map(bytesToHex));
|
|
191
192
|
if (!messages.length)
|
|
192
193
|
throw new Error('Expected non-empty messages array');
|
|
193
194
|
if (publicKeys.length !== messages.length)
|
|
194
195
|
throw new Error('Pubkey count should equal msg count');
|
|
195
196
|
const sig = normP2(signature);
|
|
196
|
-
const nMessages = messages.map(normP2Hash);
|
|
197
|
+
const nMessages = messages.map((i) => normP2Hash(i, htfOpts));
|
|
197
198
|
const nPublicKeys = publicKeys.map(normP1);
|
|
198
199
|
try {
|
|
199
200
|
const paired = [];
|
|
200
201
|
for (const message of new Set(nMessages)) {
|
|
201
|
-
const groupPublicKey = nMessages.reduce((groupPublicKey, subMessage, i) => subMessage === message ? groupPublicKey.add(nPublicKeys[i]) : groupPublicKey, G1.
|
|
202
|
+
const groupPublicKey = nMessages.reduce((groupPublicKey, subMessage, i) => subMessage === message ? groupPublicKey.add(nPublicKeys[i]) : groupPublicKey, G1.ProjectivePoint.ZERO);
|
|
202
203
|
// const msg = message instanceof PointG2 ? message : await PointG2.hashToCurve(message);
|
|
203
204
|
// Possible to batch pairing for same msg with different groupPublicKey here
|
|
204
205
|
paired.push(pairing(groupPublicKey, message, false));
|
|
205
206
|
}
|
|
206
|
-
paired.push(pairing(G1.
|
|
207
|
+
paired.push(pairing(G1.ProjectivePoint.BASE.negate(), sig, false));
|
|
207
208
|
const product = paired.reduce((a, b) => Fp12.mul(a, b), Fp12.ONE);
|
|
208
209
|
const exp = Fp12.finalExponentiate(product);
|
|
209
|
-
return Fp12.
|
|
210
|
+
return Fp12.eql(exp, Fp12.ONE);
|
|
210
211
|
}
|
|
211
212
|
catch {
|
|
212
213
|
return false;
|
|
213
214
|
}
|
|
214
215
|
}
|
|
215
|
-
|
|
216
|
-
G1.Point.BASE._setWindowSize(4);
|
|
216
|
+
G1.ProjectivePoint.BASE._setWindowSize(4);
|
|
217
217
|
return {
|
|
218
218
|
CURVE,
|
|
219
219
|
Fr,
|
|
@@ -226,6 +226,7 @@ export function bls(CURVE) {
|
|
|
226
226
|
Signature,
|
|
227
227
|
millerLoop,
|
|
228
228
|
calcPairingPrecomputes,
|
|
229
|
+
hashToCurve: { G1: G1HashToCurve, G2: G2HashToCurve },
|
|
229
230
|
pairing,
|
|
230
231
|
getPublicKey,
|
|
231
232
|
sign,
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
2
2
|
// Abelian group utilities
|
|
3
|
+
import { validateField, nLength } from './modular.js';
|
|
4
|
+
import { validateObject } from './utils.js';
|
|
3
5
|
const _0n = BigInt(0);
|
|
4
6
|
const _1n = BigInt(1);
|
|
5
|
-
//
|
|
7
|
+
// Elliptic curve multiplication of Point by scalar. Complicated and fragile. Uses wNAF method.
|
|
8
|
+
// Windowed method is 10% faster, but takes 2x longer to generate & consumes 2x memory.
|
|
6
9
|
export function wNAF(c, bits) {
|
|
7
10
|
const constTimeNegate = (condition, item) => {
|
|
8
11
|
const neg = item.negate();
|
|
@@ -104,5 +107,32 @@ export function wNAF(c, bits) {
|
|
|
104
107
|
// which makes it less const-time: around 1 bigint multiply.
|
|
105
108
|
return { p, f };
|
|
106
109
|
},
|
|
110
|
+
wNAFCached(P, precomputesMap, n, transform) {
|
|
111
|
+
// @ts-ignore
|
|
112
|
+
const W = P._WINDOW_SIZE || 1;
|
|
113
|
+
// Calculate precomputes on a first run, reuse them after
|
|
114
|
+
let comp = precomputesMap.get(P);
|
|
115
|
+
if (!comp) {
|
|
116
|
+
comp = this.precomputeWindow(P, W);
|
|
117
|
+
if (W !== 1) {
|
|
118
|
+
precomputesMap.set(P, transform(comp));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return this.wNAF(W, comp, n);
|
|
122
|
+
},
|
|
107
123
|
};
|
|
108
124
|
}
|
|
125
|
+
export function validateBasic(curve) {
|
|
126
|
+
validateField(curve.Fp);
|
|
127
|
+
validateObject(curve, {
|
|
128
|
+
n: 'bigint',
|
|
129
|
+
h: 'bigint',
|
|
130
|
+
Gx: 'field',
|
|
131
|
+
Gy: 'field',
|
|
132
|
+
}, {
|
|
133
|
+
nBitLength: 'isSafeInteger',
|
|
134
|
+
nByteLength: 'isSafeInteger',
|
|
135
|
+
});
|
|
136
|
+
// Set defaults
|
|
137
|
+
return Object.freeze({ ...nLength(curve.n, curve.nBitLength), ...curve });
|
|
138
|
+
}
|