@noble/curves 0.4.0 → 0.5.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 +254 -162
- package/lib/_shortw_utils.d.ts +75 -0
- package/lib/_shortw_utils.js +20 -0
- package/lib/{bls.d.ts → abstract/bls.d.ts} +2 -1
- package/lib/{bls.js → abstract/bls.js} +28 -27
- package/lib/{edwards.d.ts → abstract/edwards.d.ts} +17 -0
- package/lib/{edwards.js → abstract/edwards.js} +45 -4
- package/lib/{group.d.ts → abstract/group.d.ts} +2 -1
- package/lib/{group.js → abstract/group.js} +4 -3
- package/lib/abstract/hash-to-curve.d.ts +28 -0
- package/lib/{hashToCurve.js → abstract/hash-to-curve.js} +46 -11
- package/lib/{modular.d.ts → abstract/modular.d.ts} +13 -16
- package/lib/abstract/modular.js +337 -0
- package/lib/{montgomery.d.ts → abstract/montgomery.d.ts} +2 -1
- package/lib/{montgomery.js → abstract/montgomery.js} +17 -8
- package/lib/{utils.d.ts → abstract/utils.d.ts} +4 -2
- package/lib/{utils.js → abstract/utils.js} +1 -1
- package/lib/{weierstrass.d.ts → abstract/weierstrass.d.ts} +28 -16
- package/lib/{weierstrass.js → abstract/weierstrass.js} +261 -127
- package/lib/bls12-381.d.ts +66 -0
- package/lib/bls12-381.js +1132 -0
- package/lib/bn.d.ts +7 -0
- package/lib/bn.js +24 -0
- package/lib/ed25519.d.ts +48 -0
- package/lib/ed25519.js +385 -0
- package/lib/ed448.d.ts +3 -0
- package/lib/ed448.js +211 -0
- package/lib/esm/_shortw_utils.js +15 -0
- package/lib/esm/{bls.js → abstract/bls.js} +25 -24
- package/lib/esm/{edwards.js → abstract/edwards.js} +45 -4
- package/lib/esm/{group.js → abstract/group.js} +4 -3
- package/lib/esm/{hashToCurve.js → abstract/hash-to-curve.js} +43 -10
- package/lib/esm/abstract/modular.js +319 -0
- package/lib/esm/{montgomery.js → abstract/montgomery.js} +17 -8
- package/lib/esm/{utils.js → abstract/utils.js} +1 -1
- package/lib/esm/{weierstrass.js → abstract/weierstrass.js} +255 -123
- package/lib/esm/bls12-381.js +1129 -0
- package/lib/esm/bn.js +21 -0
- package/lib/esm/ed25519.js +381 -0
- package/lib/esm/ed448.js +208 -0
- package/lib/esm/index.js +2 -0
- package/lib/esm/jubjub.js +52 -0
- package/lib/esm/p192.js +21 -0
- package/lib/esm/p224.js +21 -0
- package/lib/esm/p256.js +39 -0
- package/lib/esm/p384.js +44 -0
- package/lib/esm/p521.js +58 -0
- package/lib/esm/pasta.js +29 -0
- package/lib/esm/secp256k1.js +293 -0
- package/lib/esm/stark.js +224 -0
- package/lib/index.d.ts +0 -0
- package/lib/index.js +2 -0
- package/lib/jubjub.d.ts +7 -0
- package/lib/jubjub.js +57 -0
- package/lib/p192.d.ts +130 -0
- package/lib/p192.js +24 -0
- package/lib/p224.d.ts +130 -0
- package/lib/p224.js +24 -0
- package/lib/p256.d.ts +130 -0
- package/lib/p256.js +42 -0
- package/lib/p384.d.ts +130 -0
- package/lib/p384.js +47 -0
- package/lib/p521.d.ts +131 -0
- package/lib/p521.js +61 -0
- package/lib/pasta.d.ts +4 -0
- package/lib/pasta.js +32 -0
- package/lib/secp256k1.d.ts +96 -0
- package/lib/secp256k1.js +297 -0
- package/lib/stark.d.ts +72 -0
- package/lib/stark.js +245 -0
- package/package.json +146 -50
- package/index.js +0 -1
- package/lib/esm/modular.js +0 -252
- package/lib/hashToCurve.d.ts +0 -13
- package/lib/modular.js +0 -267
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
3
|
-
//
|
|
3
|
+
// Short Weierstrass curve. The formula is: y² = x³ + ax + b
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.weierstrass = exports.weierstrassPoints = void 0;
|
|
5
|
+
exports.mapToCurveSimpleSWU = exports.SWUFpSqrtRatio = exports.weierstrass = exports.weierstrassPoints = void 0;
|
|
6
6
|
// TODO: sync vs async naming
|
|
7
7
|
// TODO: default randomBytes
|
|
8
8
|
// Differences from @noble/secp256k1 1.7:
|
|
@@ -13,7 +13,7 @@ exports.weierstrass = exports.weierstrassPoints = void 0;
|
|
|
13
13
|
const mod = require("./modular.js");
|
|
14
14
|
const utils_js_1 = require("./utils.js");
|
|
15
15
|
const utils = require("./utils.js");
|
|
16
|
-
const
|
|
16
|
+
const hash_to_curve_js_1 = require("./hash-to-curve.js");
|
|
17
17
|
const group_js_1 = require("./group.js");
|
|
18
18
|
// DER encoding utilities
|
|
19
19
|
class DERError extends Error {
|
|
@@ -58,9 +58,7 @@ function parseDERSignature(data) {
|
|
|
58
58
|
// Be friendly to bad ECMAScript parsers by not using bigint literals like 123n
|
|
59
59
|
const _0n = BigInt(0);
|
|
60
60
|
const _1n = BigInt(1);
|
|
61
|
-
const _2n = BigInt(2);
|
|
62
61
|
const _3n = BigInt(3);
|
|
63
|
-
const _8n = BigInt(8);
|
|
64
62
|
function validatePointOpts(curve) {
|
|
65
63
|
const opts = utils.validateOpts(curve);
|
|
66
64
|
const Fp = opts.Fp;
|
|
@@ -91,7 +89,7 @@ function validatePointOpts(curve) {
|
|
|
91
89
|
throw new Error('Invalid fromBytes function');
|
|
92
90
|
// Requires including hashToCurve file
|
|
93
91
|
if (opts.htfDefaults !== undefined)
|
|
94
|
-
(0,
|
|
92
|
+
(0, hash_to_curve_js_1.validateHTFOpts)(opts.htfDefaults);
|
|
95
93
|
// Set defaults
|
|
96
94
|
return Object.freeze({ ...opts });
|
|
97
95
|
}
|
|
@@ -117,8 +115,8 @@ function weierstrassPoints(opts) {
|
|
|
117
115
|
function weierstrassEquation(x) {
|
|
118
116
|
const { a, b } = CURVE;
|
|
119
117
|
const x2 = Fp.square(x); // x * x
|
|
120
|
-
const x3 = Fp.
|
|
121
|
-
return Fp.add(Fp.add(x3, Fp.
|
|
118
|
+
const x3 = Fp.mul(x2, x); // x2 * x
|
|
119
|
+
return Fp.add(Fp.add(x3, Fp.mul(x, a)), b); // x3 + a * x + b
|
|
122
120
|
}
|
|
123
121
|
function isWithinCurveOrder(num) {
|
|
124
122
|
return _0n < num && num < CURVE.n;
|
|
@@ -161,11 +159,11 @@ function weierstrassPoints(opts) {
|
|
|
161
159
|
throw new TypeError('Expected valid private scalar: 0 < scalar < curve.n');
|
|
162
160
|
}
|
|
163
161
|
/**
|
|
164
|
-
*
|
|
162
|
+
* Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z)
|
|
165
163
|
* Default Point works in 2d / affine coordinates: (x, y)
|
|
166
|
-
* We're doing calculations in
|
|
164
|
+
* We're doing calculations in projective, because its operations don't require costly inversion.
|
|
167
165
|
*/
|
|
168
|
-
class
|
|
166
|
+
class ProjectivePoint {
|
|
169
167
|
constructor(x, y, z) {
|
|
170
168
|
this.x = x;
|
|
171
169
|
this.y = y;
|
|
@@ -173,15 +171,15 @@ function weierstrassPoints(opts) {
|
|
|
173
171
|
}
|
|
174
172
|
static fromAffine(p) {
|
|
175
173
|
if (!(p instanceof Point)) {
|
|
176
|
-
throw new TypeError('
|
|
174
|
+
throw new TypeError('ProjectivePoint#fromAffine: expected Point');
|
|
177
175
|
}
|
|
178
176
|
// fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0)
|
|
179
177
|
if (p.equals(Point.ZERO))
|
|
180
|
-
return
|
|
181
|
-
return new
|
|
178
|
+
return ProjectivePoint.ZERO;
|
|
179
|
+
return new ProjectivePoint(p.x, p.y, Fp.ONE);
|
|
182
180
|
}
|
|
183
181
|
/**
|
|
184
|
-
* Takes a bunch of
|
|
182
|
+
* Takes a bunch of Projective Points but executes only one
|
|
185
183
|
* invert on all of them. invert is very slow operation,
|
|
186
184
|
* so this improves performance massively.
|
|
187
185
|
*/
|
|
@@ -190,98 +188,122 @@ function weierstrassPoints(opts) {
|
|
|
190
188
|
return points.map((p, i) => p.toAffine(toInv[i]));
|
|
191
189
|
}
|
|
192
190
|
static normalizeZ(points) {
|
|
193
|
-
return
|
|
191
|
+
return ProjectivePoint.toAffineBatch(points).map(ProjectivePoint.fromAffine);
|
|
194
192
|
}
|
|
195
193
|
/**
|
|
196
194
|
* Compare one point to another.
|
|
197
195
|
*/
|
|
198
196
|
equals(other) {
|
|
199
|
-
|
|
200
|
-
throw new TypeError('JacobianPoint expected');
|
|
197
|
+
assertPrjPoint(other);
|
|
201
198
|
const { x: X1, y: Y1, z: Z1 } = this;
|
|
202
199
|
const { x: X2, y: Y2, z: Z2 } = other;
|
|
203
|
-
const
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
const U2 = Fp.multiply(X2, Z1Z1); // X2 * Z1Z1
|
|
207
|
-
const S1 = Fp.multiply(Fp.multiply(Y1, Z2), Z2Z2); // Y1 * Z2 * Z2Z2
|
|
208
|
-
const S2 = Fp.multiply(Fp.multiply(Y2, Z1), Z1Z1); // Y2 * Z1 * Z1Z1
|
|
209
|
-
return Fp.equals(U1, U2) && Fp.equals(S1, S2);
|
|
200
|
+
const U1 = Fp.equals(Fp.mul(X1, Z2), Fp.mul(X2, Z1));
|
|
201
|
+
const U2 = Fp.equals(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1));
|
|
202
|
+
return U1 && U2;
|
|
210
203
|
}
|
|
211
204
|
/**
|
|
212
205
|
* Flips point to one corresponding to (x, -y) in Affine coordinates.
|
|
213
206
|
*/
|
|
214
207
|
negate() {
|
|
215
|
-
return new
|
|
208
|
+
return new ProjectivePoint(this.x, Fp.negate(this.y), this.z);
|
|
216
209
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
210
|
+
doubleAdd() {
|
|
211
|
+
return this.add(this);
|
|
212
|
+
}
|
|
213
|
+
// Renes-Costello-Batina exception-free doubling formula.
|
|
214
|
+
// There is 30% faster Jacobian formula, but it is not complete.
|
|
215
|
+
// https://eprint.iacr.org/2015/1060, algorithm 3
|
|
216
|
+
// Cost: 8M + 3S + 3*a + 2*b3 + 15add.
|
|
220
217
|
double() {
|
|
218
|
+
const { a, b } = CURVE;
|
|
219
|
+
const b3 = Fp.mul(b, 3n);
|
|
221
220
|
const { x: X1, y: Y1, z: Z1 } = this;
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
//
|
|
221
|
+
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
|
|
222
|
+
let t0 = Fp.mul(X1, X1); // step 1
|
|
223
|
+
let t1 = Fp.mul(Y1, Y1);
|
|
224
|
+
let t2 = Fp.mul(Z1, Z1);
|
|
225
|
+
let t3 = Fp.mul(X1, Y1);
|
|
226
|
+
t3 = Fp.add(t3, t3); // step 5
|
|
227
|
+
Z3 = Fp.mul(X1, Z1);
|
|
228
|
+
Z3 = Fp.add(Z3, Z3);
|
|
229
|
+
X3 = Fp.mul(a, Z3);
|
|
230
|
+
Y3 = Fp.mul(b3, t2);
|
|
231
|
+
Y3 = Fp.add(X3, Y3); // step 10
|
|
232
|
+
X3 = Fp.sub(t1, Y3);
|
|
233
|
+
Y3 = Fp.add(t1, Y3);
|
|
234
|
+
Y3 = Fp.mul(X3, Y3);
|
|
235
|
+
X3 = Fp.mul(t3, X3);
|
|
236
|
+
Z3 = Fp.mul(b3, Z3); // step 15
|
|
237
|
+
t2 = Fp.mul(a, t2);
|
|
238
|
+
t3 = Fp.sub(t0, t2);
|
|
239
|
+
t3 = Fp.mul(a, t3);
|
|
240
|
+
t3 = Fp.add(t3, Z3);
|
|
241
|
+
Z3 = Fp.add(t0, t0); // step 20
|
|
242
|
+
t0 = Fp.add(Z3, t0);
|
|
243
|
+
t0 = Fp.add(t0, t2);
|
|
244
|
+
t0 = Fp.mul(t0, t3);
|
|
245
|
+
Y3 = Fp.add(Y3, t0);
|
|
246
|
+
t2 = Fp.mul(Y1, Z1); // step 25
|
|
247
|
+
t2 = Fp.add(t2, t2);
|
|
248
|
+
t0 = Fp.mul(t2, t3);
|
|
249
|
+
X3 = Fp.sub(X3, t0);
|
|
250
|
+
Z3 = Fp.mul(t2, t1);
|
|
251
|
+
Z3 = Fp.add(Z3, Z3); // step 30
|
|
252
|
+
Z3 = Fp.add(Z3, Z3);
|
|
253
|
+
return new ProjectivePoint(X3, Y3, Z3);
|
|
254
|
+
}
|
|
255
|
+
// Renes-Costello-Batina exception-free addition formula.
|
|
256
|
+
// There is 30% faster Jacobian formula, but it is not complete.
|
|
257
|
+
// https://eprint.iacr.org/2015/1060, algorithm 1
|
|
258
|
+
// Cost: 12M + 0S + 3*a + 3*b3 + 23add.
|
|
257
259
|
add(other) {
|
|
258
|
-
|
|
259
|
-
throw new TypeError('JacobianPoint expected');
|
|
260
|
+
assertPrjPoint(other);
|
|
260
261
|
const { x: X1, y: Y1, z: Z1 } = this;
|
|
261
262
|
const { x: X2, y: Y2, z: Z2 } = other;
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
263
|
+
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
|
|
264
|
+
const a = CURVE.a;
|
|
265
|
+
const b3 = Fp.mul(CURVE.b, 3n);
|
|
266
|
+
let t0 = Fp.mul(X1, X2); // step 1
|
|
267
|
+
let t1 = Fp.mul(Y1, Y2);
|
|
268
|
+
let t2 = Fp.mul(Z1, Z2);
|
|
269
|
+
let t3 = Fp.add(X1, Y1);
|
|
270
|
+
let t4 = Fp.add(X2, Y2); // step 5
|
|
271
|
+
t3 = Fp.mul(t3, t4);
|
|
272
|
+
t4 = Fp.add(t0, t1);
|
|
273
|
+
t3 = Fp.sub(t3, t4);
|
|
274
|
+
t4 = Fp.add(X1, Z1);
|
|
275
|
+
let t5 = Fp.add(X2, Z2); // step 10
|
|
276
|
+
t4 = Fp.mul(t4, t5);
|
|
277
|
+
t5 = Fp.add(t0, t2);
|
|
278
|
+
t4 = Fp.sub(t4, t5);
|
|
279
|
+
t5 = Fp.add(Y1, Z1);
|
|
280
|
+
X3 = Fp.add(Y2, Z2); // step 15
|
|
281
|
+
t5 = Fp.mul(t5, X3);
|
|
282
|
+
X3 = Fp.add(t1, t2);
|
|
283
|
+
t5 = Fp.sub(t5, X3);
|
|
284
|
+
Z3 = Fp.mul(a, t4);
|
|
285
|
+
X3 = Fp.mul(b3, t2); // step 20
|
|
286
|
+
Z3 = Fp.add(X3, Z3);
|
|
287
|
+
X3 = Fp.sub(t1, Z3);
|
|
288
|
+
Z3 = Fp.add(t1, Z3);
|
|
289
|
+
Y3 = Fp.mul(X3, Z3);
|
|
290
|
+
t1 = Fp.add(t0, t0); // step 25
|
|
291
|
+
t1 = Fp.add(t1, t0);
|
|
292
|
+
t2 = Fp.mul(a, t2);
|
|
293
|
+
t4 = Fp.mul(b3, t4);
|
|
294
|
+
t1 = Fp.add(t1, t2);
|
|
295
|
+
t2 = Fp.sub(t0, t2); // step 30
|
|
296
|
+
t2 = Fp.mul(a, t2);
|
|
297
|
+
t4 = Fp.add(t4, t2);
|
|
298
|
+
t0 = Fp.mul(t1, t4);
|
|
299
|
+
Y3 = Fp.add(Y3, t0);
|
|
300
|
+
t0 = Fp.mul(t5, t4); // step 35
|
|
301
|
+
X3 = Fp.mul(t3, X3);
|
|
302
|
+
X3 = Fp.sub(X3, t0);
|
|
303
|
+
t0 = Fp.mul(t3, t1);
|
|
304
|
+
Z3 = Fp.mul(t5, Z3);
|
|
305
|
+
Z3 = Fp.add(Z3, t0); // step 40
|
|
306
|
+
return new ProjectivePoint(X3, Y3, Z3);
|
|
285
307
|
}
|
|
286
308
|
subtract(other) {
|
|
287
309
|
return this.add(other.negate());
|
|
@@ -292,7 +314,7 @@ function weierstrassPoints(opts) {
|
|
|
292
314
|
* an exposed private key e.g. sig verification, which works over *public* keys.
|
|
293
315
|
*/
|
|
294
316
|
multiplyUnsafe(scalar) {
|
|
295
|
-
const P0 =
|
|
317
|
+
const P0 = ProjectivePoint.ZERO;
|
|
296
318
|
if (typeof scalar === 'bigint' && scalar === _0n)
|
|
297
319
|
return P0;
|
|
298
320
|
// Will throw on 0
|
|
@@ -319,14 +341,14 @@ function weierstrassPoints(opts) {
|
|
|
319
341
|
k1p = k1p.negate();
|
|
320
342
|
if (k2neg)
|
|
321
343
|
k2p = k2p.negate();
|
|
322
|
-
k2p = new
|
|
344
|
+
k2p = new ProjectivePoint(Fp.mul(k2p.x, CURVE.endo.beta), k2p.y, k2p.z);
|
|
323
345
|
return k1p.add(k2p);
|
|
324
346
|
}
|
|
325
347
|
/**
|
|
326
348
|
* Implements w-ary non-adjacent form for calculating ec multiplication.
|
|
327
349
|
*/
|
|
328
350
|
wNAF(n, affinePoint) {
|
|
329
|
-
if (!affinePoint && this.equals(
|
|
351
|
+
if (!affinePoint && this.equals(ProjectivePoint.BASE))
|
|
330
352
|
affinePoint = Point.BASE;
|
|
331
353
|
const W = (affinePoint && affinePoint._WINDOW_SIZE) || 1;
|
|
332
354
|
// Calculate precomputes on a first run, reuse them after
|
|
@@ -334,7 +356,7 @@ function weierstrassPoints(opts) {
|
|
|
334
356
|
if (!precomputes) {
|
|
335
357
|
precomputes = wnaf.precomputeWindow(this, W);
|
|
336
358
|
if (affinePoint && W !== 1) {
|
|
337
|
-
precomputes =
|
|
359
|
+
precomputes = ProjectivePoint.normalizeZ(precomputes);
|
|
338
360
|
pointPrecomputes.set(affinePoint, precomputes);
|
|
339
361
|
}
|
|
340
362
|
}
|
|
@@ -360,7 +382,7 @@ function weierstrassPoints(opts) {
|
|
|
360
382
|
let { p: k2p, f: f2p } = this.wNAF(k2, affinePoint);
|
|
361
383
|
k1p = wnaf.constTimeNegate(k1neg, k1p);
|
|
362
384
|
k2p = wnaf.constTimeNegate(k2neg, k2p);
|
|
363
|
-
k2p = new
|
|
385
|
+
k2p = new ProjectivePoint(Fp.mul(k2p.x, CURVE.endo.beta), k2p.y, k2p.z);
|
|
364
386
|
point = k1p.add(k2p);
|
|
365
387
|
fake = f1p.add(f2p);
|
|
366
388
|
}
|
|
@@ -370,25 +392,21 @@ function weierstrassPoints(opts) {
|
|
|
370
392
|
fake = f;
|
|
371
393
|
}
|
|
372
394
|
// Normalize `z` for both points, but return only real one
|
|
373
|
-
return
|
|
395
|
+
return ProjectivePoint.normalizeZ([point, fake])[0];
|
|
374
396
|
}
|
|
375
|
-
// Converts
|
|
397
|
+
// Converts Projective point to affine (x, y) coordinates.
|
|
376
398
|
// Can accept precomputed Z^-1 - for example, from invertBatch.
|
|
377
|
-
// (x, y, z) ∋ (x=x/z
|
|
378
|
-
// https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#scaling-z
|
|
399
|
+
// (x, y, z) ∋ (x=x/z, y=y/z)
|
|
379
400
|
toAffine(invZ) {
|
|
380
401
|
const { x, y, z } = this;
|
|
381
|
-
const is0 = this.equals(
|
|
402
|
+
const is0 = this.equals(ProjectivePoint.ZERO);
|
|
382
403
|
// If invZ was 0, we return zero point. However we still want to execute
|
|
383
404
|
// all operations, so we replace invZ with a random number, 1.
|
|
384
405
|
if (invZ == null)
|
|
385
406
|
invZ = is0 ? Fp.ONE : Fp.invert(z);
|
|
386
|
-
const
|
|
387
|
-
const
|
|
388
|
-
const
|
|
389
|
-
const ax = Fp.multiply(x, iz2); // x * iz2
|
|
390
|
-
const ay = Fp.multiply(y, iz3); // y * iz3
|
|
391
|
-
const zz = Fp.multiply(z, iz1); // z * iz1
|
|
407
|
+
const ax = Fp.mul(x, invZ);
|
|
408
|
+
const ay = Fp.mul(y, invZ);
|
|
409
|
+
const zz = Fp.mul(z, invZ);
|
|
392
410
|
if (is0)
|
|
393
411
|
return Point.ZERO;
|
|
394
412
|
if (!Fp.equals(zz, Fp.ONE))
|
|
@@ -399,7 +417,7 @@ function weierstrassPoints(opts) {
|
|
|
399
417
|
if (CURVE.h === _1n)
|
|
400
418
|
return true; // No subgroups, always torsion fee
|
|
401
419
|
if (CURVE.isTorsionFree)
|
|
402
|
-
return CURVE.isTorsionFree(
|
|
420
|
+
return CURVE.isTorsionFree(ProjectivePoint, this);
|
|
403
421
|
// is multiplyUnsafe(CURVE.n) is always ok, same as for edwards?
|
|
404
422
|
throw new Error('Unsupported!');
|
|
405
423
|
}
|
|
@@ -409,13 +427,17 @@ function weierstrassPoints(opts) {
|
|
|
409
427
|
if (CURVE.h === _1n)
|
|
410
428
|
return this; // Fast-path
|
|
411
429
|
if (CURVE.clearCofactor)
|
|
412
|
-
return CURVE.clearCofactor(
|
|
430
|
+
return CURVE.clearCofactor(ProjectivePoint, this);
|
|
413
431
|
return this.multiplyUnsafe(CURVE.h);
|
|
414
432
|
}
|
|
415
433
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
const wnaf = (0, group_js_1.wNAF)(
|
|
434
|
+
ProjectivePoint.BASE = new ProjectivePoint(CURVE.Gx, CURVE.Gy, Fp.ONE);
|
|
435
|
+
ProjectivePoint.ZERO = new ProjectivePoint(Fp.ZERO, Fp.ONE, Fp.ZERO);
|
|
436
|
+
const wnaf = (0, group_js_1.wNAF)(ProjectivePoint, CURVE.endo ? nBitLength / 2 : nBitLength);
|
|
437
|
+
function assertPrjPoint(other) {
|
|
438
|
+
if (!(other instanceof ProjectivePoint))
|
|
439
|
+
throw new TypeError('ProjectivePoint expected');
|
|
440
|
+
}
|
|
419
441
|
// Stores precomputed values for points.
|
|
420
442
|
const pointPrecomputes = new WeakMap();
|
|
421
443
|
/**
|
|
@@ -490,27 +512,27 @@ function weierstrassPoints(opts) {
|
|
|
490
512
|
}
|
|
491
513
|
// Adds point to itself
|
|
492
514
|
double() {
|
|
493
|
-
return
|
|
515
|
+
return ProjectivePoint.fromAffine(this).double().toAffine();
|
|
494
516
|
}
|
|
495
517
|
// Adds point to other point
|
|
496
518
|
add(other) {
|
|
497
|
-
return
|
|
519
|
+
return ProjectivePoint.fromAffine(this).add(ProjectivePoint.fromAffine(other)).toAffine();
|
|
498
520
|
}
|
|
499
521
|
// Subtracts other point from the point
|
|
500
522
|
subtract(other) {
|
|
501
523
|
return this.add(other.negate());
|
|
502
524
|
}
|
|
503
525
|
multiply(scalar) {
|
|
504
|
-
return
|
|
526
|
+
return ProjectivePoint.fromAffine(this).multiply(scalar, this).toAffine();
|
|
505
527
|
}
|
|
506
528
|
multiplyUnsafe(scalar) {
|
|
507
|
-
return
|
|
529
|
+
return ProjectivePoint.fromAffine(this).multiplyUnsafe(scalar).toAffine();
|
|
508
530
|
}
|
|
509
531
|
clearCofactor() {
|
|
510
|
-
return
|
|
532
|
+
return ProjectivePoint.fromAffine(this).clearCofactor().toAffine();
|
|
511
533
|
}
|
|
512
534
|
isTorsionFree() {
|
|
513
|
-
return
|
|
535
|
+
return ProjectivePoint.fromAffine(this).isTorsionFree();
|
|
514
536
|
}
|
|
515
537
|
/**
|
|
516
538
|
* Efficiently calculate `aP + bQ`.
|
|
@@ -519,11 +541,11 @@ function weierstrassPoints(opts) {
|
|
|
519
541
|
* @returns non-zero affine point
|
|
520
542
|
*/
|
|
521
543
|
multiplyAndAddUnsafe(Q, a, b) {
|
|
522
|
-
const P =
|
|
544
|
+
const P = ProjectivePoint.fromAffine(this);
|
|
523
545
|
const aP = a === _0n || a === _1n || this !== Point.BASE ? P.multiplyUnsafe(a) : P.multiply(a);
|
|
524
|
-
const bQ =
|
|
546
|
+
const bQ = ProjectivePoint.fromAffine(Q).multiplyUnsafe(b);
|
|
525
547
|
const sum = aP.add(bQ);
|
|
526
|
-
return sum.equals(
|
|
548
|
+
return sum.equals(ProjectivePoint.ZERO) ? undefined : sum.toAffine();
|
|
527
549
|
}
|
|
528
550
|
// Encodes byte string to elliptic curve
|
|
529
551
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3
|
|
@@ -531,7 +553,7 @@ function weierstrassPoints(opts) {
|
|
|
531
553
|
if (!CURVE.mapToCurve)
|
|
532
554
|
throw new Error('No mapToCurve defined for curve');
|
|
533
555
|
msg = (0, utils_js_1.ensureBytes)(msg);
|
|
534
|
-
const u = (0,
|
|
556
|
+
const u = (0, hash_to_curve_js_1.hash_to_field)(msg, 2, { ...CURVE.htfDefaults, ...options });
|
|
535
557
|
const { x: x0, y: y0 } = CURVE.mapToCurve(u[0]);
|
|
536
558
|
const { x: x1, y: y1 } = CURVE.mapToCurve(u[1]);
|
|
537
559
|
const p = new Point(x0, y0).add(new Point(x1, y1)).clearCofactor();
|
|
@@ -542,7 +564,7 @@ function weierstrassPoints(opts) {
|
|
|
542
564
|
if (!CURVE.mapToCurve)
|
|
543
565
|
throw new Error('No mapToCurve defined for curve');
|
|
544
566
|
msg = (0, utils_js_1.ensureBytes)(msg);
|
|
545
|
-
const u = (0,
|
|
567
|
+
const u = (0, hash_to_curve_js_1.hash_to_field)(msg, 1, { ...CURVE.htfDefaults, ...options });
|
|
546
568
|
const { x, y } = CURVE.mapToCurve(u[0]);
|
|
547
569
|
return new Point(x, y).clearCofactor();
|
|
548
570
|
}
|
|
@@ -557,7 +579,7 @@ function weierstrassPoints(opts) {
|
|
|
557
579
|
Point.ZERO = new Point(Fp.ZERO, Fp.ZERO);
|
|
558
580
|
return {
|
|
559
581
|
Point: Point,
|
|
560
|
-
|
|
582
|
+
ProjectivePoint: ProjectivePoint,
|
|
561
583
|
normalizePrivateKey,
|
|
562
584
|
weierstrassEquation,
|
|
563
585
|
isWithinCurveOrder,
|
|
@@ -635,7 +657,7 @@ function weierstrass(curveDef) {
|
|
|
635
657
|
// 0 is disallowed by arbitrary reasons. Probably because infinity point?
|
|
636
658
|
return _0n < num && num < Fp.ORDER;
|
|
637
659
|
}
|
|
638
|
-
const { Point,
|
|
660
|
+
const { Point, ProjectivePoint, normalizePrivateKey, weierstrassEquation, isWithinCurveOrder } = weierstrassPoints({
|
|
639
661
|
...CURVE,
|
|
640
662
|
toBytes(c, point, isCompressed) {
|
|
641
663
|
if (isCompressed) {
|
|
@@ -958,18 +980,19 @@ function weierstrass(curveDef) {
|
|
|
958
980
|
* @returns Signature with its point on curve Q OR undefined if params were invalid
|
|
959
981
|
*/
|
|
960
982
|
function kmdToSig(kBytes, m, d, lowS = true) {
|
|
983
|
+
const { n } = CURVE;
|
|
961
984
|
const k = truncateHash(kBytes, true);
|
|
962
985
|
if (!isWithinCurveOrder(k))
|
|
963
986
|
return;
|
|
964
987
|
// Important: all mod() calls in the function must be done over `n`
|
|
965
|
-
const
|
|
988
|
+
const kinv = mod.invert(k, n);
|
|
966
989
|
const q = Point.BASE.multiply(k);
|
|
967
990
|
// r = x mod n
|
|
968
991
|
const r = mod.mod(q.x, n);
|
|
969
992
|
if (r === _0n)
|
|
970
993
|
return;
|
|
971
994
|
// s = (1/k * (m + dr) mod n
|
|
972
|
-
const s = mod.mod(
|
|
995
|
+
const s = mod.mod(kinv * mod.mod(m + mod.mod(d * r, n), n), n);
|
|
973
996
|
if (s === _0n)
|
|
974
997
|
return;
|
|
975
998
|
let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n);
|
|
@@ -1049,7 +1072,7 @@ function weierstrass(curveDef) {
|
|
|
1049
1072
|
// R = u1⋅G - u2⋅P
|
|
1050
1073
|
const u1 = mod.mod(h * sinv, n);
|
|
1051
1074
|
const u2 = mod.mod(r * sinv, n);
|
|
1052
|
-
// Some implementations compare R.x in
|
|
1075
|
+
// Some implementations compare R.x in projective, without inversion.
|
|
1053
1076
|
// The speed-up is <5%, so we don't complicate the code.
|
|
1054
1077
|
const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2);
|
|
1055
1078
|
if (!R)
|
|
@@ -1064,9 +1087,120 @@ function weierstrass(curveDef) {
|
|
|
1064
1087
|
sign,
|
|
1065
1088
|
verify,
|
|
1066
1089
|
Point,
|
|
1067
|
-
|
|
1090
|
+
ProjectivePoint,
|
|
1068
1091
|
Signature,
|
|
1069
1092
|
utils,
|
|
1070
1093
|
};
|
|
1071
1094
|
}
|
|
1072
1095
|
exports.weierstrass = weierstrass;
|
|
1096
|
+
// Implementation of the Shallue and van de Woestijne method for any Weierstrass curve
|
|
1097
|
+
// TODO: check if there is a way to merge this with uvRation in Edwards && move to modular?
|
|
1098
|
+
// b = True and y = sqrt(u / v) if (u / v) is square in F, and
|
|
1099
|
+
// b = False and y = sqrt(Z * (u / v)) otherwise.
|
|
1100
|
+
function SWUFpSqrtRatio(Fp, Z) {
|
|
1101
|
+
// Generic implementation
|
|
1102
|
+
const q = Fp.ORDER;
|
|
1103
|
+
let l = 0n;
|
|
1104
|
+
for (let o = q - 1n; o % 2n === 0n; o /= 2n)
|
|
1105
|
+
l += 1n;
|
|
1106
|
+
const c1 = l; // 1. c1, the largest integer such that 2^c1 divides q - 1.
|
|
1107
|
+
const c2 = (q - 1n) / 2n ** c1; // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic
|
|
1108
|
+
const c3 = (c2 - 1n) / 2n; // 3. c3 = (c2 - 1) / 2 # Integer arithmetic
|
|
1109
|
+
const c4 = 2n ** c1 - 1n; // 4. c4 = 2^c1 - 1 # Integer arithmetic
|
|
1110
|
+
const c5 = 2n ** (c1 - 1n); // 5. c5 = 2^(c1 - 1) # Integer arithmetic
|
|
1111
|
+
const c6 = Fp.pow(Z, c2); // 6. c6 = Z^c2
|
|
1112
|
+
const c7 = Fp.pow(Z, (c2 + 1n) / 2n); // 7. c7 = Z^((c2 + 1) / 2)
|
|
1113
|
+
let sqrtRatio = (u, v) => {
|
|
1114
|
+
let tv1 = c6; // 1. tv1 = c6
|
|
1115
|
+
let tv2 = Fp.pow(v, c4); // 2. tv2 = v^c4
|
|
1116
|
+
let tv3 = Fp.square(tv2); // 3. tv3 = tv2^2
|
|
1117
|
+
tv3 = Fp.mul(tv3, v); // 4. tv3 = tv3 * v
|
|
1118
|
+
let tv5 = Fp.mul(u, tv3); // 5. tv5 = u * tv3
|
|
1119
|
+
tv5 = Fp.pow(tv5, c3); // 6. tv5 = tv5^c3
|
|
1120
|
+
tv5 = Fp.mul(tv5, tv2); // 7. tv5 = tv5 * tv2
|
|
1121
|
+
tv2 = Fp.mul(tv5, v); // 8. tv2 = tv5 * v
|
|
1122
|
+
tv3 = Fp.mul(tv5, u); // 9. tv3 = tv5 * u
|
|
1123
|
+
let tv4 = Fp.mul(tv3, tv2); // 10. tv4 = tv3 * tv2
|
|
1124
|
+
tv5 = Fp.pow(tv4, c5); // 11. tv5 = tv4^c5
|
|
1125
|
+
let isQR = Fp.equals(tv5, Fp.ONE); // 12. isQR = tv5 == 1
|
|
1126
|
+
tv2 = Fp.mul(tv3, c7); // 13. tv2 = tv3 * c7
|
|
1127
|
+
tv5 = Fp.mul(tv4, tv1); // 14. tv5 = tv4 * tv1
|
|
1128
|
+
tv3 = Fp.cmov(tv2, tv3, isQR); // 15. tv3 = CMOV(tv2, tv3, isQR)
|
|
1129
|
+
tv4 = Fp.cmov(tv5, tv4, isQR); // 16. tv4 = CMOV(tv5, tv4, isQR)
|
|
1130
|
+
// 17. for i in (c1, c1 - 1, ..., 2):
|
|
1131
|
+
for (let i = c1; i > 1; i--) {
|
|
1132
|
+
let tv5 = 2n ** (i - 2n); // 18. tv5 = i - 2; 19. tv5 = 2^tv5
|
|
1133
|
+
let tvv5 = Fp.pow(tv4, tv5); // 20. tv5 = tv4^tv5
|
|
1134
|
+
const e1 = Fp.equals(tvv5, Fp.ONE); // 21. e1 = tv5 == 1
|
|
1135
|
+
tv2 = Fp.mul(tv3, tv1); // 22. tv2 = tv3 * tv1
|
|
1136
|
+
tv1 = Fp.mul(tv1, tv1); // 23. tv1 = tv1 * tv1
|
|
1137
|
+
tvv5 = Fp.mul(tv4, tv1); // 24. tv5 = tv4 * tv1
|
|
1138
|
+
tv3 = Fp.cmov(tv2, tv3, e1); // 25. tv3 = CMOV(tv2, tv3, e1)
|
|
1139
|
+
tv4 = Fp.cmov(tvv5, tv4, e1); // 26. tv4 = CMOV(tv5, tv4, e1)
|
|
1140
|
+
}
|
|
1141
|
+
return { isValid: isQR, value: tv3 };
|
|
1142
|
+
};
|
|
1143
|
+
if (Fp.ORDER % 4n === 3n) {
|
|
1144
|
+
// sqrt_ratio_3mod4(u, v)
|
|
1145
|
+
const c1 = (Fp.ORDER - 3n) / 4n; // 1. c1 = (q - 3) / 4 # Integer arithmetic
|
|
1146
|
+
const c2 = Fp.sqrt(Fp.negate(Z)); // 2. c2 = sqrt(-Z)
|
|
1147
|
+
sqrtRatio = (u, v) => {
|
|
1148
|
+
let tv1 = Fp.square(v); // 1. tv1 = v^2
|
|
1149
|
+
const tv2 = Fp.mul(u, v); // 2. tv2 = u * v
|
|
1150
|
+
tv1 = Fp.mul(tv1, tv2); // 3. tv1 = tv1 * tv2
|
|
1151
|
+
let y1 = Fp.pow(tv1, c1); // 4. y1 = tv1^c1
|
|
1152
|
+
y1 = Fp.mul(y1, tv2); // 5. y1 = y1 * tv2
|
|
1153
|
+
const y2 = Fp.mul(y1, c2); // 6. y2 = y1 * c2
|
|
1154
|
+
const tv3 = Fp.mul(Fp.square(y1), v); // 7. tv3 = y1^2; 8. tv3 = tv3 * v
|
|
1155
|
+
const isQR = Fp.equals(tv3, u); // 9. isQR = tv3 == u
|
|
1156
|
+
let y = Fp.cmov(y2, y1, isQR); // 10. y = CMOV(y2, y1, isQR)
|
|
1157
|
+
return { isValid: isQR, value: y }; // 11. return (isQR, y) isQR ? y : y*c2
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
1160
|
+
// No curves uses that
|
|
1161
|
+
// if (Fp.ORDER % 8n === 5n) // sqrt_ratio_5mod8
|
|
1162
|
+
return sqrtRatio;
|
|
1163
|
+
}
|
|
1164
|
+
exports.SWUFpSqrtRatio = SWUFpSqrtRatio;
|
|
1165
|
+
// From draft-irtf-cfrg-hash-to-curve-16
|
|
1166
|
+
function mapToCurveSimpleSWU(Fp, opts) {
|
|
1167
|
+
mod.validateField(Fp);
|
|
1168
|
+
if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z))
|
|
1169
|
+
throw new Error('mapToCurveSimpleSWU: invalid opts');
|
|
1170
|
+
const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z);
|
|
1171
|
+
if (!Fp.isOdd)
|
|
1172
|
+
throw new Error('Fp.isOdd is not implemented!');
|
|
1173
|
+
// Input: u, an element of F.
|
|
1174
|
+
// Output: (x, y), a point on E.
|
|
1175
|
+
return (u) => {
|
|
1176
|
+
// prettier-ignore
|
|
1177
|
+
let tv1, tv2, tv3, tv4, tv5, tv6, x, y;
|
|
1178
|
+
tv1 = Fp.square(u); // 1. tv1 = u^2
|
|
1179
|
+
tv1 = Fp.mul(tv1, opts.Z); // 2. tv1 = Z * tv1
|
|
1180
|
+
tv2 = Fp.square(tv1); // 3. tv2 = tv1^2
|
|
1181
|
+
tv2 = Fp.add(tv2, tv1); // 4. tv2 = tv2 + tv1
|
|
1182
|
+
tv3 = Fp.add(tv2, Fp.ONE); // 5. tv3 = tv2 + 1
|
|
1183
|
+
tv3 = Fp.mul(tv3, opts.B); // 6. tv3 = B * tv3
|
|
1184
|
+
tv4 = Fp.cmov(opts.Z, Fp.negate(tv2), !Fp.equals(tv2, Fp.ZERO)); // 7. tv4 = CMOV(Z, -tv2, tv2 != 0)
|
|
1185
|
+
tv4 = Fp.mul(tv4, opts.A); // 8. tv4 = A * tv4
|
|
1186
|
+
tv2 = Fp.square(tv3); // 9. tv2 = tv3^2
|
|
1187
|
+
tv6 = Fp.square(tv4); // 10. tv6 = tv4^2
|
|
1188
|
+
tv5 = Fp.mul(tv6, opts.A); // 11. tv5 = A * tv6
|
|
1189
|
+
tv2 = Fp.add(tv2, tv5); // 12. tv2 = tv2 + tv5
|
|
1190
|
+
tv2 = Fp.mul(tv2, tv3); // 13. tv2 = tv2 * tv3
|
|
1191
|
+
tv6 = Fp.mul(tv6, tv4); // 14. tv6 = tv6 * tv4
|
|
1192
|
+
tv5 = Fp.mul(tv6, opts.B); // 15. tv5 = B * tv6
|
|
1193
|
+
tv2 = Fp.add(tv2, tv5); // 16. tv2 = tv2 + tv5
|
|
1194
|
+
x = Fp.mul(tv1, tv3); // 17. x = tv1 * tv3
|
|
1195
|
+
const { isValid, value } = sqrtRatio(tv2, tv6); // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6)
|
|
1196
|
+
y = Fp.mul(tv1, u); // 19. y = tv1 * u -> Z * u^3 * y1
|
|
1197
|
+
y = Fp.mul(y, value); // 20. y = y * y1
|
|
1198
|
+
x = Fp.cmov(x, tv3, isValid); // 21. x = CMOV(x, tv3, is_gx1_square)
|
|
1199
|
+
y = Fp.cmov(y, value, isValid); // 22. y = CMOV(y, y1, is_gx1_square)
|
|
1200
|
+
const e1 = Fp.isOdd(u) === Fp.isOdd(y); // 23. e1 = sgn0(u) == sgn0(y)
|
|
1201
|
+
y = Fp.cmov(Fp.negate(y), y, e1); // 24. y = CMOV(-y, y, e1)
|
|
1202
|
+
x = Fp.div(x, tv4); // 25. x = x / tv4
|
|
1203
|
+
return { x, y };
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
exports.mapToCurveSimpleSWU = mapToCurveSimpleSWU;
|