@noble/curves 1.4.2 → 1.5.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 +135 -123
- package/_shortw_utils.d.ts.map +1 -1
- package/abstract/bls.d.ts +37 -34
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +167 -115
- package/abstract/bls.js.map +1 -1
- package/abstract/curve.d.ts +2 -1
- package/abstract/curve.d.ts.map +1 -1
- package/abstract/curve.js +22 -7
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.d.ts +11 -0
- package/abstract/edwards.d.ts.map +1 -1
- package/abstract/edwards.js +79 -75
- package/abstract/edwards.js.map +1 -1
- package/abstract/modular.d.ts +4 -0
- package/abstract/modular.d.ts.map +1 -1
- package/abstract/modular.js +13 -2
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +4 -9
- package/abstract/montgomery.js.map +1 -1
- package/abstract/tower.d.ts +106 -0
- package/abstract/tower.d.ts.map +1 -0
- package/abstract/tower.js +497 -0
- package/abstract/tower.js.map +1 -0
- package/abstract/utils.d.ts +17 -0
- package/abstract/utils.d.ts.map +1 -1
- package/abstract/utils.js +50 -1
- package/abstract/utils.js.map +1 -1
- package/abstract/weierstrass.d.ts +7 -0
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +88 -72
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts +1 -65
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +48 -575
- package/bls12-381.js.map +1 -1
- package/bn254.d.ts +10 -6
- package/bn254.d.ts.map +1 -1
- package/bn254.js +207 -10
- package/bn254.js.map +1 -1
- package/ed25519.d.ts +7 -4
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +3 -0
- package/ed25519.js.map +1 -1
- package/esm/_shortw_utils.d.ts.map +1 -1
- package/esm/abstract/bls.d.ts +37 -34
- package/esm/abstract/bls.d.ts.map +1 -1
- package/esm/abstract/bls.js +168 -116
- package/esm/abstract/bls.js.map +1 -1
- package/esm/abstract/curve.d.ts +2 -1
- package/esm/abstract/curve.d.ts.map +1 -1
- package/esm/abstract/curve.js +22 -7
- package/esm/abstract/curve.js.map +1 -1
- package/esm/abstract/edwards.d.ts +11 -0
- package/esm/abstract/edwards.d.ts.map +1 -1
- package/esm/abstract/edwards.js +80 -76
- package/esm/abstract/edwards.js.map +1 -1
- package/esm/abstract/modular.d.ts +4 -0
- package/esm/abstract/modular.d.ts.map +1 -1
- package/esm/abstract/modular.js +12 -2
- package/esm/abstract/modular.js.map +1 -1
- package/esm/abstract/montgomery.d.ts.map +1 -1
- package/esm/abstract/montgomery.js +5 -10
- package/esm/abstract/montgomery.js.map +1 -1
- package/esm/abstract/tower.d.ts +106 -0
- package/esm/abstract/tower.d.ts.map +1 -0
- package/esm/abstract/tower.js +493 -0
- package/esm/abstract/tower.js.map +1 -0
- package/esm/abstract/utils.d.ts +17 -0
- package/esm/abstract/utils.d.ts.map +1 -1
- package/esm/abstract/utils.js +44 -0
- package/esm/abstract/utils.js.map +1 -1
- package/esm/abstract/weierstrass.d.ts +7 -0
- package/esm/abstract/weierstrass.d.ts.map +1 -1
- package/esm/abstract/weierstrass.js +89 -73
- package/esm/abstract/weierstrass.js.map +1 -1
- package/esm/bls12-381.d.ts +1 -65
- package/esm/bls12-381.d.ts.map +1 -1
- package/esm/bls12-381.js +50 -577
- package/esm/bls12-381.js.map +1 -1
- package/esm/bn254.d.ts +10 -6
- package/esm/bn254.d.ts.map +1 -1
- package/esm/bn254.js +206 -9
- package/esm/bn254.js.map +1 -1
- package/esm/ed25519.d.ts +7 -4
- package/esm/ed25519.d.ts.map +1 -1
- package/esm/ed25519.js +3 -0
- package/esm/ed25519.js.map +1 -1
- package/esm/p256.d.ts.map +1 -1
- package/esm/p384.d.ts.map +1 -1
- package/esm/p521.d.ts.map +1 -1
- package/esm/secp256k1.d.ts +6 -0
- package/esm/secp256k1.d.ts.map +1 -1
- package/esm/secp256k1.js +17 -13
- package/esm/secp256k1.js.map +1 -1
- package/p256.d.ts.map +1 -1
- package/p384.d.ts.map +1 -1
- package/p521.d.ts.map +1 -1
- package/package.json +2 -1
- package/secp256k1.d.ts +6 -0
- package/secp256k1.d.ts.map +1 -1
- package/secp256k1.js +16 -12
- package/secp256k1.js.map +1 -1
- package/src/abstract/bls.ts +222 -168
- package/src/abstract/curve.ts +23 -7
- package/src/abstract/edwards.ts +81 -68
- package/src/abstract/modular.ts +13 -3
- package/src/abstract/montgomery.ts +11 -10
- package/src/abstract/tower.ts +604 -0
- package/src/abstract/utils.ts +49 -0
- package/src/abstract/weierstrass.ts +85 -68
- package/src/bls12-381.ts +53 -707
- package/src/bn254.ts +224 -9
- package/src/ed25519.ts +5 -2
- package/src/secp256k1.ts +24 -12
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { AffinePoint, BasicCurve, Group, GroupConstructor, validateBasic, wNAF } from './curve.js';
|
|
4
4
|
import * as mod from './modular.js';
|
|
5
5
|
import * as ut from './utils.js';
|
|
6
|
-
import { CHash, Hex, PrivKey, ensureBytes } from './utils.js';
|
|
6
|
+
import { CHash, Hex, PrivKey, ensureBytes, memoized, abool } from './utils.js';
|
|
7
7
|
|
|
8
8
|
export type { AffinePoint };
|
|
9
9
|
type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
|
@@ -31,6 +31,11 @@ type Entropy = Hex | boolean;
|
|
|
31
31
|
export type SignOpts = { lowS?: boolean; extraEntropy?: Entropy; prehash?: boolean };
|
|
32
32
|
export type VerOpts = { lowS?: boolean; prehash?: boolean };
|
|
33
33
|
|
|
34
|
+
function validateSigVerOpts(opts: SignOpts | VerOpts) {
|
|
35
|
+
if (opts.lowS !== undefined) abool('lowS', opts.lowS);
|
|
36
|
+
if (opts.prehash !== undefined) abool('prehash', opts.prehash);
|
|
37
|
+
}
|
|
38
|
+
|
|
34
39
|
/**
|
|
35
40
|
* ### Design rationale for types
|
|
36
41
|
*
|
|
@@ -228,15 +233,12 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
228
233
|
|
|
229
234
|
// Valid group elements reside in range 1..n-1
|
|
230
235
|
function isWithinCurveOrder(num: bigint): boolean {
|
|
231
|
-
return
|
|
232
|
-
}
|
|
233
|
-
function assertGE(num: bigint) {
|
|
234
|
-
if (!isWithinCurveOrder(num)) throw new Error('Expected valid bigint: 0 < bigint < curve.n');
|
|
236
|
+
return ut.inRange(num, _1n, CURVE.n);
|
|
235
237
|
}
|
|
236
238
|
// Validates if priv key is valid and converts it to bigint.
|
|
237
239
|
// Supports options allowedPrivateKeyLengths and wrapPrivateKey.
|
|
238
240
|
function normPrivateKeyToScalar(key: PrivKey): bigint {
|
|
239
|
-
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
|
|
241
|
+
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n: N } = CURVE;
|
|
240
242
|
if (lengths && typeof key !== 'bigint') {
|
|
241
243
|
if (ut.isBytes(key)) key = ut.bytesToHex(key);
|
|
242
244
|
// Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes
|
|
@@ -252,15 +254,56 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
252
254
|
} catch (error) {
|
|
253
255
|
throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);
|
|
254
256
|
}
|
|
255
|
-
if (wrapPrivateKey) num = mod.mod(num,
|
|
256
|
-
|
|
257
|
+
if (wrapPrivateKey) num = mod.mod(num, N); // disabled by default, enabled for BLS
|
|
258
|
+
ut.aInRange('private key', num, _1n, N); // num in range [1..N-1]
|
|
257
259
|
return num;
|
|
258
260
|
}
|
|
259
261
|
|
|
260
|
-
const pointPrecomputes = new Map<Point, Point[]>();
|
|
261
262
|
function assertPrjPoint(other: unknown) {
|
|
262
263
|
if (!(other instanceof Point)) throw new Error('ProjectivePoint expected');
|
|
263
264
|
}
|
|
265
|
+
|
|
266
|
+
// Memoized toAffine / validity check. They are heavy. Points are immutable.
|
|
267
|
+
|
|
268
|
+
// Converts Projective point to affine (x, y) coordinates.
|
|
269
|
+
// Can accept precomputed Z^-1 - for example, from invertBatch.
|
|
270
|
+
// (x, y, z) ∋ (x=x/z, y=y/z)
|
|
271
|
+
const toAffineMemo = memoized((p: Point, iz?: T): AffinePoint<T> => {
|
|
272
|
+
const { px: x, py: y, pz: z } = p;
|
|
273
|
+
// Fast-path for normalized points
|
|
274
|
+
if (Fp.eql(z, Fp.ONE)) return { x, y };
|
|
275
|
+
const is0 = p.is0();
|
|
276
|
+
// If invZ was 0, we return zero point. However we still want to execute
|
|
277
|
+
// all operations, so we replace invZ with a random number, 1.
|
|
278
|
+
if (iz == null) iz = is0 ? Fp.ONE : Fp.inv(z);
|
|
279
|
+
const ax = Fp.mul(x, iz);
|
|
280
|
+
const ay = Fp.mul(y, iz);
|
|
281
|
+
const zz = Fp.mul(z, iz);
|
|
282
|
+
if (is0) return { x: Fp.ZERO, y: Fp.ZERO };
|
|
283
|
+
if (!Fp.eql(zz, Fp.ONE)) throw new Error('invZ was invalid');
|
|
284
|
+
return { x: ax, y: ay };
|
|
285
|
+
});
|
|
286
|
+
// NOTE: on exception this will crash 'cached' and no value will be set.
|
|
287
|
+
// Otherwise true will be return
|
|
288
|
+
const assertValidMemo = memoized((p: Point) => {
|
|
289
|
+
if (p.is0()) {
|
|
290
|
+
// (0, 1, 0) aka ZERO is invalid in most contexts.
|
|
291
|
+
// In BLS, ZERO can be serialized, so we allow it.
|
|
292
|
+
// (0, 0, 0) is wrong representation of ZERO and is always invalid.
|
|
293
|
+
if (CURVE.allowInfinityPoint && !Fp.is0(p.py)) return;
|
|
294
|
+
throw new Error('bad point: ZERO');
|
|
295
|
+
}
|
|
296
|
+
// Some 3rd-party test vectors require different wording between here & `fromCompressedHex`
|
|
297
|
+
const { x, y } = p.toAffine();
|
|
298
|
+
// Check if x, y are valid field elements
|
|
299
|
+
if (!Fp.isValid(x) || !Fp.isValid(y)) throw new Error('bad point: x or y not FE');
|
|
300
|
+
const left = Fp.sqr(y); // y²
|
|
301
|
+
const right = weierstrassEquation(x); // x³ + ax + b
|
|
302
|
+
if (!Fp.eql(left, right)) throw new Error('bad point: equation left != right');
|
|
303
|
+
if (!p.isTorsionFree()) throw new Error('bad point: not in prime-order subgroup');
|
|
304
|
+
return true;
|
|
305
|
+
});
|
|
306
|
+
|
|
264
307
|
/**
|
|
265
308
|
* Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z)
|
|
266
309
|
* Default Point works in 2d / affine coordinates: (x, y)
|
|
@@ -278,6 +321,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
278
321
|
if (px == null || !Fp.isValid(px)) throw new Error('x required');
|
|
279
322
|
if (py == null || !Fp.isValid(py)) throw new Error('y required');
|
|
280
323
|
if (pz == null || !Fp.isValid(pz)) throw new Error('z required');
|
|
324
|
+
Object.freeze(this);
|
|
281
325
|
}
|
|
282
326
|
|
|
283
327
|
// Does not validate if the point is on-curve.
|
|
@@ -325,35 +369,16 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
325
369
|
return Point.BASE.multiply(normPrivateKeyToScalar(privateKey));
|
|
326
370
|
}
|
|
327
371
|
|
|
328
|
-
// We calculate precomputes for elliptic curve point multiplication
|
|
329
|
-
// using windowed method. This specifies window size and
|
|
330
|
-
// stores precomputed values. Usually only base point would be precomputed.
|
|
331
|
-
_WINDOW_SIZE?: number;
|
|
332
|
-
|
|
333
372
|
// "Private method", don't use it directly
|
|
334
373
|
_setWindowSize(windowSize: number) {
|
|
335
|
-
this
|
|
336
|
-
pointPrecomputes.delete(this);
|
|
374
|
+
wnaf.setWindowSize(this, windowSize);
|
|
337
375
|
}
|
|
338
376
|
|
|
339
377
|
// A point on curve is valid if it conforms to equation.
|
|
340
378
|
assertValidity(): void {
|
|
341
|
-
|
|
342
|
-
// (0, 1, 0) aka ZERO is invalid in most contexts.
|
|
343
|
-
// In BLS, ZERO can be serialized, so we allow it.
|
|
344
|
-
// (0, 0, 0) is wrong representation of ZERO and is always invalid.
|
|
345
|
-
if (CURVE.allowInfinityPoint && !Fp.is0(this.py)) return;
|
|
346
|
-
throw new Error('bad point: ZERO');
|
|
347
|
-
}
|
|
348
|
-
// Some 3rd-party test vectors require different wording between here & `fromCompressedHex`
|
|
349
|
-
const { x, y } = this.toAffine();
|
|
350
|
-
// Check if x, y are valid field elements
|
|
351
|
-
if (!Fp.isValid(x) || !Fp.isValid(y)) throw new Error('bad point: x or y not FE');
|
|
352
|
-
const left = Fp.sqr(y); // y²
|
|
353
|
-
const right = weierstrassEquation(x); // x³ + ax + b
|
|
354
|
-
if (!Fp.eql(left, right)) throw new Error('bad point: equation left != right');
|
|
355
|
-
if (!this.isTorsionFree()) throw new Error('bad point: not in prime-order subgroup');
|
|
379
|
+
assertValidMemo(this);
|
|
356
380
|
}
|
|
381
|
+
|
|
357
382
|
hasEvenY(): boolean {
|
|
358
383
|
const { y } = this.toAffine();
|
|
359
384
|
if (Fp.isOdd) return !Fp.isOdd(y);
|
|
@@ -480,14 +505,11 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
480
505
|
return this.add(other.negate());
|
|
481
506
|
}
|
|
482
507
|
|
|
483
|
-
|
|
508
|
+
is0() {
|
|
484
509
|
return this.equals(Point.ZERO);
|
|
485
510
|
}
|
|
486
511
|
private wNAF(n: bigint): { p: Point; f: Point } {
|
|
487
|
-
return wnaf.wNAFCached(this,
|
|
488
|
-
const toInv = Fp.invertBatch(comp.map((p) => p.pz));
|
|
489
|
-
return comp.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);
|
|
490
|
-
});
|
|
512
|
+
return wnaf.wNAFCached(this, n, Point.normalizeZ);
|
|
491
513
|
}
|
|
492
514
|
|
|
493
515
|
/**
|
|
@@ -495,16 +517,16 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
495
517
|
* It's faster, but should only be used when you don't care about
|
|
496
518
|
* an exposed private key e.g. sig verification, which works over *public* keys.
|
|
497
519
|
*/
|
|
498
|
-
multiplyUnsafe(
|
|
520
|
+
multiplyUnsafe(sc: bigint): Point {
|
|
521
|
+
ut.aInRange('scalar', sc, _0n, CURVE.n);
|
|
499
522
|
const I = Point.ZERO;
|
|
500
|
-
if (
|
|
501
|
-
|
|
502
|
-
if (n === _1n) return this;
|
|
523
|
+
if (sc === _0n) return I;
|
|
524
|
+
if (sc === _1n) return this;
|
|
503
525
|
const { endo } = CURVE;
|
|
504
|
-
if (!endo) return wnaf.unsafeLadder(this,
|
|
526
|
+
if (!endo) return wnaf.unsafeLadder(this, sc);
|
|
505
527
|
|
|
506
528
|
// Apply endomorphism
|
|
507
|
-
let { k1neg, k1, k2neg, k2 } = endo.splitScalar(
|
|
529
|
+
let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc);
|
|
508
530
|
let k1p = I;
|
|
509
531
|
let k2p = I;
|
|
510
532
|
let d: Point = this;
|
|
@@ -531,12 +553,11 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
531
553
|
* @returns New point
|
|
532
554
|
*/
|
|
533
555
|
multiply(scalar: bigint): Point {
|
|
534
|
-
|
|
535
|
-
|
|
556
|
+
const { endo, n: N } = CURVE;
|
|
557
|
+
ut.aInRange('scalar', scalar, _1n, N);
|
|
536
558
|
let point: Point, fake: Point; // Fake point is used to const-time mult
|
|
537
|
-
const { endo } = CURVE;
|
|
538
559
|
if (endo) {
|
|
539
|
-
const { k1neg, k1, k2neg, k2 } = endo.splitScalar(
|
|
560
|
+
const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar);
|
|
540
561
|
let { p: k1p, f: f1p } = this.wNAF(k1);
|
|
541
562
|
let { p: k2p, f: f2p } = this.wNAF(k2);
|
|
542
563
|
k1p = wnaf.constTimeNegate(k1neg, k1p);
|
|
@@ -545,7 +566,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
545
566
|
point = k1p.add(k2p);
|
|
546
567
|
fake = f1p.add(f2p);
|
|
547
568
|
} else {
|
|
548
|
-
const { p, f } = this.wNAF(
|
|
569
|
+
const { p, f } = this.wNAF(scalar);
|
|
549
570
|
point = p;
|
|
550
571
|
fake = f;
|
|
551
572
|
}
|
|
@@ -573,17 +594,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
573
594
|
// Can accept precomputed Z^-1 - for example, from invertBatch.
|
|
574
595
|
// (x, y, z) ∋ (x=x/z, y=y/z)
|
|
575
596
|
toAffine(iz?: T): AffinePoint<T> {
|
|
576
|
-
|
|
577
|
-
const is0 = this.is0();
|
|
578
|
-
// If invZ was 0, we return zero point. However we still want to execute
|
|
579
|
-
// all operations, so we replace invZ with a random number, 1.
|
|
580
|
-
if (iz == null) iz = is0 ? Fp.ONE : Fp.inv(z);
|
|
581
|
-
const ax = Fp.mul(x, iz);
|
|
582
|
-
const ay = Fp.mul(y, iz);
|
|
583
|
-
const zz = Fp.mul(z, iz);
|
|
584
|
-
if (is0) return { x: Fp.ZERO, y: Fp.ZERO };
|
|
585
|
-
if (!Fp.eql(zz, Fp.ONE)) throw new Error('invZ was invalid');
|
|
586
|
-
return { x: ax, y: ay };
|
|
597
|
+
return toAffineMemo(this, iz);
|
|
587
598
|
}
|
|
588
599
|
isTorsionFree(): boolean {
|
|
589
600
|
const { h: cofactor, isTorsionFree } = CURVE;
|
|
@@ -599,11 +610,13 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
599
610
|
}
|
|
600
611
|
|
|
601
612
|
toRawBytes(isCompressed = true): Uint8Array {
|
|
613
|
+
abool('isCompressed', isCompressed);
|
|
602
614
|
this.assertValidity();
|
|
603
615
|
return toBytes(Point, this, isCompressed);
|
|
604
616
|
}
|
|
605
617
|
|
|
606
618
|
toHex(isCompressed = true): string {
|
|
619
|
+
abool('isCompressed', isCompressed);
|
|
607
620
|
return ut.bytesToHex(this.toRawBytes(isCompressed));
|
|
608
621
|
}
|
|
609
622
|
}
|
|
@@ -691,15 +704,19 @@ export type CurveFn = {
|
|
|
691
704
|
};
|
|
692
705
|
};
|
|
693
706
|
|
|
707
|
+
/**
|
|
708
|
+
* Creates short weierstrass curve and ECDSA signature methods for it.
|
|
709
|
+
* @example
|
|
710
|
+
* import { Field } from '@noble/curves/abstract/modular';
|
|
711
|
+
* // Before that, define BigInt-s: a, b, p, n, Gx, Gy
|
|
712
|
+
* const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n })
|
|
713
|
+
*/
|
|
694
714
|
export function weierstrass(curveDef: CurveType): CurveFn {
|
|
695
715
|
const CURVE = validateOpts(curveDef) as ReturnType<typeof validateOpts>;
|
|
696
716
|
const { Fp, n: CURVE_ORDER } = CURVE;
|
|
697
717
|
const compressedLen = Fp.BYTES + 1; // e.g. 33 for 32
|
|
698
718
|
const uncompressedLen = 2 * Fp.BYTES + 1; // e.g. 65 for 32
|
|
699
719
|
|
|
700
|
-
function isValidFieldElement(num: bigint): boolean {
|
|
701
|
-
return _0n < num && num < Fp.ORDER; // 0 is banned since it's not invertible FE
|
|
702
|
-
}
|
|
703
720
|
function modN(a: bigint) {
|
|
704
721
|
return mod.mod(a, CURVE_ORDER);
|
|
705
722
|
}
|
|
@@ -718,6 +735,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
718
735
|
const a = point.toAffine();
|
|
719
736
|
const x = Fp.toBytes(a.x);
|
|
720
737
|
const cat = ut.concatBytes;
|
|
738
|
+
abool('isCompressed', isCompressed);
|
|
721
739
|
if (isCompressed) {
|
|
722
740
|
return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x);
|
|
723
741
|
} else {
|
|
@@ -731,7 +749,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
731
749
|
// this.assertValidity() is done inside of fromHex
|
|
732
750
|
if (len === compressedLen && (head === 0x02 || head === 0x03)) {
|
|
733
751
|
const x = ut.bytesToNumberBE(tail);
|
|
734
|
-
if (!
|
|
752
|
+
if (!ut.inRange(x, _1n, Fp.ORDER)) throw new Error('Point is not on curve');
|
|
735
753
|
const y2 = weierstrassEquation(x); // y² = x³ + ax + b
|
|
736
754
|
let y: bigint;
|
|
737
755
|
try {
|
|
@@ -797,9 +815,8 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
797
815
|
}
|
|
798
816
|
|
|
799
817
|
assertValidity(): void {
|
|
800
|
-
//
|
|
801
|
-
|
|
802
|
-
if (!isWithinCurveOrder(this.s)) throw new Error('s must be 0 < s < CURVE.n');
|
|
818
|
+
ut.aInRange('r', this.r, _1n, CURVE_ORDER); // r in [1..N]
|
|
819
|
+
ut.aInRange('s', this.s, _1n, CURVE_ORDER); // s in [1..N]
|
|
803
820
|
}
|
|
804
821
|
|
|
805
822
|
addRecoveryBit(recovery: number): RecoveredSignature {
|
|
@@ -949,9 +966,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
949
966
|
* Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.
|
|
950
967
|
*/
|
|
951
968
|
function int2octets(num: bigint): Uint8Array {
|
|
952
|
-
|
|
953
|
-
if (!(_0n <= num && num < ORDER_MASK))
|
|
954
|
-
throw new Error(`bigint expected < 2^${CURVE.nBitLength}`);
|
|
969
|
+
ut.aInRange(`num < 2^${CURVE.nBitLength}`, num, _0n, ORDER_MASK);
|
|
955
970
|
// works with order, can have different size than numToField!
|
|
956
971
|
return ut.numberToBytesBE(num, CURVE.nByteLength);
|
|
957
972
|
}
|
|
@@ -968,6 +983,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
968
983
|
let { lowS, prehash, extraEntropy: ent } = opts; // generates low-s sigs by default
|
|
969
984
|
if (lowS == null) lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash
|
|
970
985
|
msgHash = ensureBytes('msgHash', msgHash);
|
|
986
|
+
validateSigVerOpts(opts);
|
|
971
987
|
if (prehash) msgHash = ensureBytes('prehashed msgHash', hash(msgHash));
|
|
972
988
|
|
|
973
989
|
// We can't later call bits2octets, since nested bits2int is broken for curves
|
|
@@ -1058,6 +1074,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
1058
1074
|
msgHash = ensureBytes('msgHash', msgHash);
|
|
1059
1075
|
publicKey = ensureBytes('publicKey', publicKey);
|
|
1060
1076
|
if ('strict' in opts) throw new Error('options.strict was renamed to lowS');
|
|
1077
|
+
validateSigVerOpts(opts);
|
|
1061
1078
|
const { lowS, prehash } = opts;
|
|
1062
1079
|
|
|
1063
1080
|
let _sig: Signature | undefined = undefined;
|