@noble/curves 1.9.4 → 1.9.5

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.
Files changed (103) hide show
  1. package/abstract/curve.d.ts +47 -46
  2. package/abstract/curve.d.ts.map +1 -1
  3. package/abstract/curve.js +9 -6
  4. package/abstract/curve.js.map +1 -1
  5. package/abstract/edwards.d.ts +33 -31
  6. package/abstract/edwards.d.ts.map +1 -1
  7. package/abstract/edwards.js +123 -122
  8. package/abstract/edwards.js.map +1 -1
  9. package/abstract/modular.d.ts +1 -1
  10. package/abstract/modular.d.ts.map +1 -1
  11. package/abstract/modular.js +4 -4
  12. package/abstract/modular.js.map +1 -1
  13. package/abstract/montgomery.d.ts +2 -6
  14. package/abstract/montgomery.d.ts.map +1 -1
  15. package/abstract/montgomery.js +13 -10
  16. package/abstract/montgomery.js.map +1 -1
  17. package/abstract/weierstrass.d.ts +161 -92
  18. package/abstract/weierstrass.d.ts.map +1 -1
  19. package/abstract/weierstrass.js +340 -267
  20. package/abstract/weierstrass.js.map +1 -1
  21. package/bls12-381.d.ts.map +1 -1
  22. package/bls12-381.js +4 -4
  23. package/bls12-381.js.map +1 -1
  24. package/ed25519.d.ts +15 -15
  25. package/ed25519.d.ts.map +1 -1
  26. package/ed25519.js +41 -38
  27. package/ed25519.js.map +1 -1
  28. package/ed448.d.ts +13 -13
  29. package/ed448.d.ts.map +1 -1
  30. package/ed448.js +43 -35
  31. package/ed448.js.map +1 -1
  32. package/esm/abstract/curve.d.ts +47 -46
  33. package/esm/abstract/curve.d.ts.map +1 -1
  34. package/esm/abstract/curve.js +9 -6
  35. package/esm/abstract/curve.js.map +1 -1
  36. package/esm/abstract/edwards.d.ts +33 -31
  37. package/esm/abstract/edwards.d.ts.map +1 -1
  38. package/esm/abstract/edwards.js +124 -123
  39. package/esm/abstract/edwards.js.map +1 -1
  40. package/esm/abstract/modular.d.ts +1 -1
  41. package/esm/abstract/modular.d.ts.map +1 -1
  42. package/esm/abstract/modular.js +4 -4
  43. package/esm/abstract/modular.js.map +1 -1
  44. package/esm/abstract/montgomery.d.ts +2 -6
  45. package/esm/abstract/montgomery.d.ts.map +1 -1
  46. package/esm/abstract/montgomery.js +14 -11
  47. package/esm/abstract/montgomery.js.map +1 -1
  48. package/esm/abstract/weierstrass.d.ts +161 -92
  49. package/esm/abstract/weierstrass.d.ts.map +1 -1
  50. package/esm/abstract/weierstrass.js +342 -270
  51. package/esm/abstract/weierstrass.js.map +1 -1
  52. package/esm/bls12-381.d.ts.map +1 -1
  53. package/esm/bls12-381.js +5 -5
  54. package/esm/bls12-381.js.map +1 -1
  55. package/esm/ed25519.d.ts +15 -15
  56. package/esm/ed25519.d.ts.map +1 -1
  57. package/esm/ed25519.js +40 -37
  58. package/esm/ed25519.js.map +1 -1
  59. package/esm/ed448.d.ts +13 -13
  60. package/esm/ed448.d.ts.map +1 -1
  61. package/esm/ed448.js +42 -34
  62. package/esm/ed448.js.map +1 -1
  63. package/esm/misc.js +2 -2
  64. package/esm/misc.js.map +1 -1
  65. package/esm/nist.d.ts +6 -0
  66. package/esm/nist.d.ts.map +1 -1
  67. package/esm/nist.js +6 -0
  68. package/esm/nist.js.map +1 -1
  69. package/esm/secp256k1.d.ts +2 -6
  70. package/esm/secp256k1.d.ts.map +1 -1
  71. package/esm/secp256k1.js +8 -11
  72. package/esm/secp256k1.js.map +1 -1
  73. package/esm/utils.d.ts +14 -0
  74. package/esm/utils.d.ts.map +1 -1
  75. package/esm/utils.js +43 -0
  76. package/esm/utils.js.map +1 -1
  77. package/misc.js +2 -2
  78. package/misc.js.map +1 -1
  79. package/nist.d.ts +6 -0
  80. package/nist.d.ts.map +1 -1
  81. package/nist.js +7 -1
  82. package/nist.js.map +1 -1
  83. package/package.json +1 -1
  84. package/secp256k1.d.ts +2 -6
  85. package/secp256k1.d.ts.map +1 -1
  86. package/secp256k1.js +7 -10
  87. package/secp256k1.js.map +1 -1
  88. package/src/abstract/curve.ts +131 -68
  89. package/src/abstract/edwards.ts +162 -166
  90. package/src/abstract/modular.ts +4 -4
  91. package/src/abstract/montgomery.ts +16 -16
  92. package/src/abstract/weierstrass.ts +510 -395
  93. package/src/bls12-381.ts +5 -4
  94. package/src/ed25519.ts +51 -46
  95. package/src/ed448.ts +46 -44
  96. package/src/misc.ts +2 -2
  97. package/src/nist.ts +7 -0
  98. package/src/secp256k1.ts +10 -12
  99. package/src/utils.ts +48 -0
  100. package/utils.d.ts +14 -0
  101. package/utils.d.ts.map +1 -1
  102. package/utils.js +47 -0
  103. package/utils.js.map +1 -1
@@ -7,14 +7,16 @@
7
7
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
8
8
  import {
9
9
  _validateObject,
10
- abool,
11
- abytes,
10
+ _abool2 as abool,
11
+ _abytes2 as abytes,
12
12
  aInRange,
13
13
  bytesToHex,
14
14
  bytesToNumberLE,
15
15
  concatBytes,
16
+ copyBytes,
16
17
  ensureBytes,
17
18
  memoized,
19
+ notImplemented,
18
20
  numberToBytesLE,
19
21
  randomBytes,
20
22
  type FHash,
@@ -27,7 +29,7 @@ import {
27
29
  wNAF,
28
30
  type AffinePoint,
29
31
  type BasicCurve,
30
- type CurveInfo,
32
+ type CurveLengths,
31
33
  type CurvePoint,
32
34
  type CurvePointCons,
33
35
  } from './curve.ts';
@@ -39,23 +41,6 @@ const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _8n = BigInt(8);
39
41
 
40
42
  export type UVRatio = (u: bigint, v: bigint) => { isValid: boolean; value: bigint };
41
43
 
42
- // TODO: remove
43
- export type CurveType = BasicCurve<bigint> & {
44
- a: bigint; // curve param a
45
- d: bigint; // curve param d
46
- /** @deprecated the property will be removed in next release */
47
- hash: FHash; // Hashing
48
- randomBytes?: (bytesLength?: number) => Uint8Array; // CSPRNG
49
- adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array; // clears bits to get valid field elemtn
50
- domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array; // Used for hashing
51
- uvRatio?: UVRatio; // Ratio √(u/v)
52
- prehash?: FHash; // RFC 8032 pre-hashing of messages to sign() / verify()
53
- mapToCurve?: (scalar: bigint[]) => AffinePoint<bigint>; // for hash-to-curve standard
54
- };
55
-
56
- // TODO: remove
57
- export type CurveTypeWithLength = Readonly<CurveType & Partial<NLength>>;
58
-
59
44
  /** Instance of Extended Point with coordinates in X, Y, Z, T. */
60
45
  export interface EdwardsPoint extends CurvePoint<bigint, EdwardsPoint> {
61
46
  /** extended X coordinate. Different from affine x. */
@@ -81,8 +66,9 @@ export interface EdwardsPoint extends CurvePoint<bigint, EdwardsPoint> {
81
66
  readonly et: bigint;
82
67
  }
83
68
  /** Static methods of Extended Point with coordinates in X, Y, Z, T. */
84
- export interface EdwardsPointCons extends CurvePointCons<bigint, EdwardsPoint> {
69
+ export interface EdwardsPointCons extends CurvePointCons<EdwardsPoint> {
85
70
  new (X: bigint, Y: bigint, Z: bigint, T: bigint): EdwardsPoint;
71
+ CURVE(): EdwardsOpts;
86
72
  fromBytes(bytes: Uint8Array, zip215?: boolean): EdwardsPoint;
87
73
  fromHex(hex: Hex, zip215?: boolean): EdwardsPoint;
88
74
  /** @deprecated use `import { pippenger } from '@noble/curves/abstract/curve.js';` */
@@ -124,6 +110,7 @@ export type EdwardsOpts = Readonly<{
124
110
  export type EdwardsExtraOpts = Partial<{
125
111
  Fp: IField<bigint>;
126
112
  Fn: IField<bigint>;
113
+ FpFnLE: boolean;
127
114
  uvRatio: (u: bigint, v: bigint) => { isValid: boolean; value: bigint };
128
115
  }>;
129
116
 
@@ -199,24 +186,9 @@ export interface EdDSA {
199
186
  /** @deprecated use `point.precompute()` */
200
187
  precompute: (windowSize?: number, point?: EdwardsPoint) => EdwardsPoint;
201
188
  };
202
- info: CurveInfo;
189
+ lengths: CurveLengths;
203
190
  }
204
191
 
205
- // Legacy params. TODO: remove
206
- export type CurveFn = {
207
- /** @deprecated the property will be removed in next release */
208
- CURVE: CurveType;
209
- keygen: EdDSA['keygen'];
210
- getPublicKey: EdDSA['getPublicKey'];
211
- sign: EdDSA['sign'];
212
- verify: EdDSA['verify'];
213
- Point: EdwardsPointCons;
214
- /** @deprecated use `Point` */
215
- ExtendedPoint: EdwardsPointCons;
216
- utils: EdDSA['utils'];
217
- info: CurveInfo;
218
- };
219
-
220
192
  function isEdValidXY(Fp: IField<bigint>, CURVE: EdwardsOpts, x: bigint, y: bigint): boolean {
221
193
  const x2 = Fp.sqr(x);
222
194
  const y2 = Fp.sqr(y);
@@ -225,10 +197,12 @@ function isEdValidXY(Fp: IField<bigint>, CURVE: EdwardsOpts, x: bigint, y: bigin
225
197
  return Fp.eql(left, right);
226
198
  }
227
199
 
228
- export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): EdwardsPointCons {
229
- const { Fp, Fn } = _createCurveFields('edwards', CURVE, curveOpts);
200
+ export function edwards(params: EdwardsOpts, extraOpts: EdwardsExtraOpts = {}): EdwardsPointCons {
201
+ const validated = _createCurveFields('edwards', params, extraOpts, extraOpts.FpFnLE);
202
+ const { Fp, Fn } = validated;
203
+ let CURVE = validated.CURVE as EdwardsOpts;
230
204
  const { h: cofactor, n: CURVE_ORDER } = CURVE;
231
- _validateObject(curveOpts, {}, { uvRatio: 'function' });
205
+ _validateObject(extraOpts, {}, { uvRatio: 'function' });
232
206
 
233
207
  // Important:
234
208
  // There are some places where Fp.BYTES is used instead of nByteLength.
@@ -239,7 +213,7 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
239
213
 
240
214
  // sqrt(u/v)
241
215
  const uvRatio =
242
- curveOpts.uvRatio ||
216
+ extraOpts.uvRatio ||
243
217
  ((u: bigint, v: bigint) => {
244
218
  try {
245
219
  return { isValid: true, value: Fp.sqrt(Fp.div(u, v)) };
@@ -307,8 +281,9 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
307
281
  static readonly BASE = new Point(CURVE.Gx, CURVE.Gy, _1n, modP(CURVE.Gx * CURVE.Gy));
308
282
  // zero / infinity / identity point
309
283
  static readonly ZERO = new Point(_0n, _1n, _1n, _0n); // 0, 1, 1, 0
310
- // fields
284
+ // math field
311
285
  static readonly Fp = Fp;
286
+ // scalar field
312
287
  static readonly Fn = Fn;
313
288
 
314
289
  readonly X: bigint;
@@ -324,34 +299,8 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
324
299
  Object.freeze(this);
325
300
  }
326
301
 
327
- get x(): bigint {
328
- return this.toAffine().x;
329
- }
330
- get y(): bigint {
331
- return this.toAffine().y;
332
- }
333
-
334
- // TODO: remove
335
- get ex(): bigint {
336
- return this.X;
337
- }
338
- get ey(): bigint {
339
- return this.Y;
340
- }
341
- get ez(): bigint {
342
- return this.Z;
343
- }
344
- get et(): bigint {
345
- return this.T;
346
- }
347
- static normalizeZ(points: Point[]): Point[] {
348
- return normalizeZ(Point, points);
349
- }
350
- static msm(points: Point[], scalars: bigint[]): Point {
351
- return pippenger(Point, Fn, points, scalars);
352
- }
353
- _setWindowSize(windowSize: number) {
354
- this.precompute(windowSize);
302
+ static CURVE(): EdwardsOpts {
303
+ return CURVE as EdwardsOpts;
355
304
  }
356
305
 
357
306
  static fromAffine(p: AffinePoint<bigint>): Point {
@@ -362,6 +311,50 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
362
311
  return new Point(x, y, _1n, modP(x * y));
363
312
  }
364
313
 
314
+ // Uses algo from RFC8032 5.1.3.
315
+ static fromBytes(bytes: Uint8Array, zip215 = false): Point {
316
+ const len = Fp.BYTES;
317
+ const { a, d } = CURVE;
318
+ bytes = copyBytes(abytes(bytes, len, 'point'));
319
+ abool(zip215, 'zip215');
320
+ const normed = copyBytes(bytes); // copy again, we'll manipulate it
321
+ const lastByte = bytes[len - 1]; // select last byte
322
+ normed[len - 1] = lastByte & ~0x80; // clear last bit
323
+ const y = bytesToNumberLE(normed);
324
+
325
+ // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5.
326
+ // RFC8032 prohibits >= p, but ZIP215 doesn't
327
+ // zip215=true: 0 <= y < MASK (2^256 for ed25519)
328
+ // zip215=false: 0 <= y < P (2^255-19 for ed25519)
329
+ const max = zip215 ? MASK : Fp.ORDER;
330
+ aInRange('pointHex.y', y, _0n, max);
331
+
332
+ // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case:
333
+ // ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a)
334
+ const y2 = modP(y * y); // denominator is always non-0 mod p.
335
+ const u = modP(y2 - _1n); // u = y² - 1
336
+ const v = modP(d * y2 - a); // v = d y² + 1.
337
+ let { isValid, value: x } = uvRatio(u, v); // √(u/v)
338
+ if (!isValid) throw new Error('Point.fromHex: invalid y coordinate');
339
+ const isXOdd = (x & _1n) === _1n; // There are 2 square roots. Use x_0 bit to select proper
340
+ const isLastByteOdd = (lastByte & 0x80) !== 0; // x_0, last bit
341
+ if (!zip215 && x === _0n && isLastByteOdd)
342
+ // if x=0 and x_0 = 1, fail
343
+ throw new Error('Point.fromHex: x=0 and x_0=1');
344
+ if (isLastByteOdd !== isXOdd) x = modP(-x); // if x_0 != x mod 2, set x = p-x
345
+ return Point.fromAffine({ x, y });
346
+ }
347
+ static fromHex(bytes: Uint8Array, zip215 = false): Point {
348
+ return Point.fromBytes(ensureBytes('point', bytes), zip215);
349
+ }
350
+
351
+ get x(): bigint {
352
+ return this.toAffine().x;
353
+ }
354
+ get y(): bigint {
355
+ return this.toAffine().y;
356
+ }
357
+
365
358
  precompute(windowSize: number = 8, isLazy = true) {
366
359
  wnaf.createCache(this, windowSize);
367
360
  if (!isLazy) this.multiply(_2n); // random number
@@ -489,45 +482,6 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
489
482
  return this.multiplyUnsafe(cofactor);
490
483
  }
491
484
 
492
- static fromBytes(bytes: Uint8Array, zip215 = false): Point {
493
- abytes(bytes);
494
- return Point.fromHex(bytes, zip215);
495
- }
496
-
497
- // Converts hash string or Uint8Array to Point.
498
- // Uses algo from RFC8032 5.1.3.
499
- static fromHex(hex: Hex, zip215 = false): Point {
500
- const { d, a } = CURVE;
501
- const len = Fp.BYTES;
502
- hex = ensureBytes('pointHex', hex, len); // copy hex to a new array
503
- abool('zip215', zip215);
504
- const normed = hex.slice(); // copy again, we'll manipulate it
505
- const lastByte = hex[len - 1]; // select last byte
506
- normed[len - 1] = lastByte & ~0x80; // clear last bit
507
- const y = bytesToNumberLE(normed);
508
-
509
- // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5.
510
- // RFC8032 prohibits >= p, but ZIP215 doesn't
511
- // zip215=true: 0 <= y < MASK (2^256 for ed25519)
512
- // zip215=false: 0 <= y < P (2^255-19 for ed25519)
513
- const max = zip215 ? MASK : Fp.ORDER;
514
- aInRange('pointHex.y', y, _0n, max);
515
-
516
- // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case:
517
- // ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a)
518
- const y2 = modP(y * y); // denominator is always non-0 mod p.
519
- const u = modP(y2 - _1n); // u = y² - 1
520
- const v = modP(d * y2 - a); // v = d y² + 1.
521
- let { isValid, value: x } = uvRatio(u, v); // √(u/v)
522
- if (!isValid) throw new Error('Point.fromHex: invalid y coordinate');
523
- const isXOdd = (x & _1n) === _1n; // There are 2 square roots. Use x_0 bit to select proper
524
- const isLastByteOdd = (lastByte & 0x80) !== 0; // x_0, last bit
525
- if (!zip215 && x === _0n && isLastByteOdd)
526
- // if x=0 and x_0 = 1, fail
527
- throw new Error('Point.fromHex: x=0 and x_0=1');
528
- if (isLastByteOdd !== isXOdd) x = modP(-x); // if x_0 != x mod 2, set x = p-x
529
- return Point.fromAffine({ x, y });
530
- }
531
485
  toBytes(): Uint8Array {
532
486
  const { x, y } = this.toAffine();
533
487
  const bytes = numberToBytesLE(y, Fp.BYTES); // each y has 2 x values (x, -y)
@@ -545,6 +499,29 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
545
499
  toString() {
546
500
  return `<Point ${this.is0() ? 'ZERO' : this.toHex()}>`;
547
501
  }
502
+
503
+ // TODO: remove
504
+ get ex(): bigint {
505
+ return this.X;
506
+ }
507
+ get ey(): bigint {
508
+ return this.Y;
509
+ }
510
+ get ez(): bigint {
511
+ return this.Z;
512
+ }
513
+ get et(): bigint {
514
+ return this.T;
515
+ }
516
+ static normalizeZ(points: Point[]): Point[] {
517
+ return normalizeZ(Point, points);
518
+ }
519
+ static msm(points: Point[], scalars: bigint[]): Point {
520
+ return pippenger(Point, Fn, points, scalars);
521
+ }
522
+ _setWindowSize(windowSize: number) {
523
+ this.precompute(windowSize);
524
+ }
548
525
  }
549
526
  const wnaf = new wNAF(Point, Fn.BYTES * 8); // Fn.BITS?
550
527
  return Point;
@@ -575,11 +552,11 @@ export abstract class PrimeEdwardsPoint<T extends PrimeEdwardsPoint<T>>
575
552
 
576
553
  // Static methods that must be implemented by subclasses
577
554
  static fromBytes(_bytes: Uint8Array): any {
578
- throw new Error('fromBytes must be implemented by subclass');
555
+ notImplemented();
579
556
  }
580
557
 
581
558
  static fromHex(_hex: Hex): any {
582
- throw new Error('fromHex must be implemented by subclass');
559
+ notImplemented();
583
560
  }
584
561
 
585
562
  get x(): bigint {
@@ -663,7 +640,7 @@ export abstract class PrimeEdwardsPoint<T extends PrimeEdwardsPoint<T>>
663
640
  /**
664
641
  * Initializes EdDSA signatures over given Edwards curve.
665
642
  */
666
- export function eddsa(Point: EdwardsPointCons, cHash: FHash, eddsaOpts: EdDSAOpts): EdDSA {
643
+ export function eddsa(Point: EdwardsPointCons, cHash: FHash, eddsaOpts: EdDSAOpts = {}): EdDSA {
667
644
  if (typeof cHash !== 'function') throw new Error('"hash" function param is required');
668
645
  _validateObject(
669
646
  eddsaOpts,
@@ -686,7 +663,7 @@ export function eddsa(Point: EdwardsPointCons, cHash: FHash, eddsaOpts: EdDSAOpt
686
663
  const domain =
687
664
  eddsaOpts.domain ||
688
665
  ((data: Uint8Array, ctx: Uint8Array, phflag: boolean) => {
689
- abool('phflag', phflag);
666
+ abool(phflag, 'phflag');
690
667
  if (ctx.length || phflag) throw new Error('Contexts/pre-hash are not supported');
691
668
  return data;
692
669
  }); // NOOP
@@ -703,7 +680,7 @@ export function eddsa(Point: EdwardsPointCons, cHash: FHash, eddsaOpts: EdDSAOpt
703
680
 
704
681
  // Get the hashed private scalar per RFC8032 5.1.5
705
682
  function getPrivateScalar(key: Hex) {
706
- const len = Fp.BYTES;
683
+ const len = lengths.secret;
707
684
  key = ensureBytes('private key', key, len);
708
685
  // Hash private key with curve's hash function to produce uniformingly random input
709
686
  // Check byte lengths: ensure(64, h(ensure(32, key)))
@@ -757,21 +734,23 @@ export function eddsa(Point: EdwardsPointCons, cHash: FHash, eddsaOpts: EdDSAOpt
757
734
  */
758
735
  function verify(sig: Hex, msg: Hex, publicKey: Hex, options = verifyOpts): boolean {
759
736
  const { context, zip215 } = options;
760
- const len = Fp.BYTES; // Verifies EdDSA signature against message and public key. RFC8032 5.1.7.
761
- sig = ensureBytes('signature', sig, 2 * len); // An extended group equation is checked.
737
+ const len = lengths.signature; // Verifies EdDSA signature against message and public key. RFC8032 5.1.7.
738
+ sig = ensureBytes('signature', sig, len); // An extended group equation is checked.
762
739
  msg = ensureBytes('message', msg);
763
- publicKey = ensureBytes('publicKey', publicKey, len);
764
- if (zip215 !== undefined) abool('zip215', zip215);
740
+ publicKey = ensureBytes('publicKey', publicKey, lengths.public);
741
+ if (zip215 !== undefined) abool(zip215, 'zip215');
765
742
  if (prehash) msg = prehash(msg); // for ed25519ph, etc
766
743
 
767
- const s = bytesToNumberLE(sig.slice(len, 2 * len));
744
+ const mid = len / 2;
745
+ const r = sig.subarray(0, mid);
746
+ const s = bytesToNumberLE(sig.subarray(mid, len));
768
747
  let A, R, SB;
769
748
  try {
770
749
  // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5.
771
750
  // zip215=true: 0 <= y < MASK (2^256 for ed25519)
772
751
  // zip215=false: 0 <= y < P (2^255-19 for ed25519)
773
- A = Point.fromHex(publicKey, zip215);
774
- R = Point.fromHex(sig.slice(0, len), zip215);
752
+ A = Point.fromBytes(publicKey, zip215);
753
+ R = Point.fromBytes(r, zip215);
775
754
  SB = G.multiplyUnsafe(s); // 0 <= s < l is done inside
776
755
  } catch (error) {
777
756
  return false;
@@ -787,27 +766,42 @@ export function eddsa(Point: EdwardsPointCons, cHash: FHash, eddsaOpts: EdDSAOpt
787
766
 
788
767
  G.precompute(8); // Enable precomputes. Slows down first publicKey computation by 20ms.
789
768
 
790
- const size = Fp.BYTES;
769
+ const _size = Fp.BYTES;
791
770
  const lengths = {
792
- secret: size,
793
- public: size,
794
- signature: 2 * size,
795
- seed: size,
771
+ secret: _size,
772
+ public: _size,
773
+ signature: 2 * _size,
774
+ seed: _size,
796
775
  };
797
776
  function randomSecretKey(seed = randomBytes_!(lengths.seed)): Uint8Array {
798
- return seed;
777
+ return abytes(seed, lengths.seed, 'seed');
778
+ }
779
+ function keygen(seed?: Uint8Array) {
780
+ const secretKey = utils.randomSecretKey(seed);
781
+ return { secretKey, publicKey: getPublicKey(secretKey) };
782
+ }
783
+
784
+ function isValidSecretKey(key: Uint8Array): boolean {
785
+ try {
786
+ return !!Fn.fromBytes(key, false);
787
+ } catch (error) {
788
+ return false;
789
+ }
790
+ }
791
+
792
+ function isValidPublicKey(key: Uint8Array, zip215?: boolean): boolean {
793
+ try {
794
+ return !!Point.fromBytes(key, zip215);
795
+ } catch (error) {
796
+ return false;
797
+ }
799
798
  }
800
799
 
801
800
  const utils = {
802
801
  getExtendedPublicKey,
803
- /** ed25519 priv keys are uniform 32b. No need to check for modulo bias, like in secp256k1. */
804
802
  randomSecretKey,
805
-
806
803
  isValidSecretKey,
807
804
  isValidPublicKey,
808
-
809
- randomPrivateKey: randomSecretKey,
810
-
811
805
  /**
812
806
  * Converts ed public key to x public key. Uses formula:
813
807
  * - ed25519:
@@ -824,50 +818,28 @@ export function eddsa(Point: EdwardsPointCons, cHash: FHash, eddsaOpts: EdDSAOpt
824
818
  */
825
819
  toMontgomery(publicKey: Uint8Array): Uint8Array {
826
820
  const { y } = Point.fromBytes(publicKey);
821
+ const size = lengths.public;
827
822
  const is25519 = size === 32;
828
823
  if (!is25519 && size !== 57) throw new Error('only defined for 25519 and 448');
829
824
  const u = is25519 ? Fp.div(_1n + y, _1n - y) : Fp.div(y - _1n, y + _1n);
830
825
  return Fp.toBytes(u);
831
826
  },
832
827
 
833
- toMontgomeryPriv(privateKey: Uint8Array): Uint8Array {
834
- abytes(privateKey, size);
835
- const hashed = cHash(privateKey.subarray(0, size));
828
+ toMontgomeryPriv(secretKey: Uint8Array): Uint8Array {
829
+ const size = lengths.secret;
830
+ abytes(secretKey, size);
831
+ const hashed = cHash(secretKey.subarray(0, size));
836
832
  return adjustScalarBytes(hashed).subarray(0, size);
837
833
  },
838
834
 
839
- /**
840
- * We're doing scalar multiplication (used in getPublicKey etc) with precomputed BASE_POINT
841
- * values. This slows down first getPublicKey() by milliseconds (see Speed section),
842
- * but allows to speed-up subsequent getPublicKey() calls up to 20x.
843
- * @param windowSize 2, 4, 8, 16
844
- */
835
+ /** @deprecated */
836
+ randomPrivateKey: randomSecretKey,
837
+ /** @deprecated */
845
838
  precompute(windowSize = 8, point: EdwardsPoint = Point.BASE): EdwardsPoint {
846
839
  return point.precompute(windowSize, false);
847
840
  },
848
841
  };
849
842
 
850
- function keygen(seed?: Uint8Array) {
851
- const secretKey = utils.randomSecretKey(seed);
852
- return { secretKey, publicKey: getPublicKey(secretKey) };
853
- }
854
-
855
- function isValidSecretKey(key: Uint8Array): boolean {
856
- try {
857
- return !!Fn.fromBytes(key, false);
858
- } catch (error) {
859
- return false;
860
- }
861
- }
862
-
863
- function isValidPublicKey(key: Uint8Array, zip215?: boolean): boolean {
864
- try {
865
- return !!Point.fromBytes(key, zip215);
866
- } catch (error) {
867
- return false;
868
- }
869
- }
870
-
871
843
  return Object.freeze({
872
844
  keygen,
873
845
  getPublicKey,
@@ -875,18 +847,43 @@ export function eddsa(Point: EdwardsPointCons, cHash: FHash, eddsaOpts: EdDSAOpt
875
847
  verify,
876
848
  utils,
877
849
  Point,
878
- info: { type: 'edwards' as const, lengths },
850
+ lengths,
879
851
  });
880
852
  }
881
853
 
882
- // TODO: remove
854
+ // TODO: remove everything below
855
+ export type CurveType = BasicCurve<bigint> & {
856
+ a: bigint; // curve param a
857
+ d: bigint; // curve param d
858
+ /** @deprecated the property will be removed in next release */
859
+ hash: FHash; // Hashing
860
+ randomBytes?: (bytesLength?: number) => Uint8Array; // CSPRNG
861
+ adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array; // clears bits to get valid field elemtn
862
+ domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array; // Used for hashing
863
+ uvRatio?: UVRatio; // Ratio √(u/v)
864
+ prehash?: FHash; // RFC 8032 pre-hashing of messages to sign() / verify()
865
+ mapToCurve?: (scalar: bigint[]) => AffinePoint<bigint>; // for hash-to-curve standard
866
+ };
867
+ export type CurveTypeWithLength = Readonly<CurveType & Partial<NLength>>;
868
+ export type CurveFn = {
869
+ /** @deprecated the property will be removed in next release */
870
+ CURVE: CurveType;
871
+ keygen: EdDSA['keygen'];
872
+ getPublicKey: EdDSA['getPublicKey'];
873
+ sign: EdDSA['sign'];
874
+ verify: EdDSA['verify'];
875
+ Point: EdwardsPointCons;
876
+ /** @deprecated use `Point` */
877
+ ExtendedPoint: EdwardsPointCons;
878
+ utils: EdDSA['utils'];
879
+ lengths: CurveLengths;
880
+ };
883
881
  export type EdComposed = {
884
882
  CURVE: EdwardsOpts;
885
883
  curveOpts: EdwardsExtraOpts;
886
884
  hash: FHash;
887
885
  eddsaOpts: EdDSAOpts;
888
886
  };
889
- // TODO: remove
890
887
  function _eddsa_legacy_opts_to_new(c: CurveTypeWithLength): EdComposed {
891
888
  const CURVE: EdwardsOpts = {
892
889
  a: c.a,
@@ -909,7 +906,6 @@ function _eddsa_legacy_opts_to_new(c: CurveTypeWithLength): EdComposed {
909
906
  };
910
907
  return { CURVE, curveOpts, hash: c.hash, eddsaOpts };
911
908
  }
912
- // TODO: remove
913
909
  function _eddsa_new_output_to_legacy(c: CurveTypeWithLength, eddsa: EdDSA): CurveFn {
914
910
  const legacy = Object.assign({}, eddsa, { ExtendedPoint: eddsa.Point, CURVE: c });
915
911
  return legacy;
@@ -384,7 +384,7 @@ type FieldOpts = Partial<{
384
384
  sqrt: SqrtFn;
385
385
  isLE: boolean;
386
386
  BITS: number;
387
- modOnDecode: boolean; // bls12-381 requires mod(n) instead of rejecting keys >= n
387
+ modFromBytes: boolean; // bls12-381 requires mod(n) instead of rejecting keys >= n
388
388
  allowedLengths?: readonly number[]; // for P521 (adds padding for smaller sizes)
389
389
  }>;
390
390
  /**
@@ -415,7 +415,7 @@ export function Field(
415
415
  if (ORDER <= _0n) throw new Error('invalid field: expected ORDER > 0, got ' + ORDER);
416
416
  let _nbitLength: number | undefined = undefined;
417
417
  let _sqrt: SqrtFn | undefined = undefined;
418
- let modOnDecode: boolean = false;
418
+ let modFromBytes: boolean = false;
419
419
  let allowedLengths: undefined | readonly number[] = undefined;
420
420
  if (typeof bitLenOrOpts === 'object' && bitLenOrOpts != null) {
421
421
  if (opts.sqrt || isLE) throw new Error('cannot specify opts in two arguments');
@@ -423,7 +423,7 @@ export function Field(
423
423
  if (_opts.BITS) _nbitLength = _opts.BITS;
424
424
  if (_opts.sqrt) _sqrt = _opts.sqrt;
425
425
  if (typeof _opts.isLE === 'boolean') isLE = _opts.isLE;
426
- if (typeof _opts.modOnDecode === 'boolean') modOnDecode = _opts.modOnDecode;
426
+ if (typeof _opts.modFromBytes === 'boolean') modFromBytes = _opts.modFromBytes;
427
427
  allowedLengths = _opts.allowedLengths;
428
428
  } else {
429
429
  if (typeof bitLenOrOpts === 'number') _nbitLength = bitLenOrOpts;
@@ -490,7 +490,7 @@ export function Field(
490
490
  if (bytes.length !== BYTES)
491
491
  throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length);
492
492
  let scalar = isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
493
- if (modOnDecode) scalar = mod(scalar, ORDER);
493
+ if (modFromBytes) scalar = mod(scalar, ORDER);
494
494
  if (!skipValidation)
495
495
  if (!f.isValid(scalar)) throw new Error('invalid field element: outside of range 0..ORDER');
496
496
  // NOTE: we don't validate scalar here, please use isValid. This done such way because some
@@ -7,13 +7,14 @@
7
7
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
8
8
  import {
9
9
  _validateObject,
10
+ abytes,
10
11
  aInRange,
11
12
  bytesToNumberLE,
12
13
  ensureBytes,
13
14
  numberToBytesLE,
14
15
  randomBytes,
15
16
  } from '../utils.ts';
16
- import type { CurveInfo } from './curve.ts';
17
+ import type { CurveLengths } from './curve.ts';
17
18
  import { mod } from './modular.ts';
18
19
 
19
20
  const _0n = BigInt(0);
@@ -40,11 +41,7 @@ export type MontgomeryECDH = {
40
41
  randomPrivateKey: () => Uint8Array;
41
42
  };
42
43
  GuBytes: Uint8Array;
43
- info: {
44
- type: 'montgomery';
45
- lengths: Omit<CurveInfo['lengths'], 'signature'>;
46
- publicKeyHasPrefix?: boolean;
47
- };
44
+ lengths: CurveLengths;
48
45
  keygen: (seed?: Uint8Array) => { secretKey: Uint8Array; publicKey: Uint8Array };
49
46
  };
50
47
  export type CurveFn = MontgomeryECDH;
@@ -167,20 +164,23 @@ export function montgomery(curveDef: CurveType): MontgomeryECDH {
167
164
  const z2 = powPminus2(z_2); // `Fp.pow(x, P - _2n)` is much slower equivalent
168
165
  return modP(x_2 * z2); // Return x_2 * (z_2^(p - 2))
169
166
  }
170
- const randomSecretKey = (seed = randomBytes_(fieldLen)) => seed;
171
- const utils = {
172
- randomSecretKey,
173
- randomPrivateKey: randomSecretKey,
174
- };
175
- function keygen(seed?: Uint8Array) {
176
- const secretKey = utils.randomSecretKey(seed);
177
- return { secretKey, publicKey: scalarMultBase(secretKey) };
178
- }
179
167
  const lengths = {
180
168
  secret: fieldLen,
181
169
  public: fieldLen,
182
170
  seed: fieldLen,
183
171
  };
172
+ const randomSecretKey = (seed = randomBytes_(fieldLen)) => {
173
+ abytes(seed, lengths.seed);
174
+ return seed;
175
+ };
176
+ function keygen(seed?: Uint8Array) {
177
+ const secretKey = randomSecretKey(seed);
178
+ return { secretKey, publicKey: scalarMultBase(secretKey) };
179
+ }
180
+ const utils = {
181
+ randomSecretKey,
182
+ randomPrivateKey: randomSecretKey,
183
+ };
184
184
  return {
185
185
  keygen,
186
186
  getSharedSecret: (secretKey: Hex, publicKey: Hex) => scalarMult(secretKey, publicKey),
@@ -189,6 +189,6 @@ export function montgomery(curveDef: CurveType): MontgomeryECDH {
189
189
  scalarMultBase,
190
190
  utils,
191
191
  GuBytes: GuBytes.slice(),
192
- info: { type: 'montgomery' as const, lengths },
192
+ lengths,
193
193
  };
194
194
  }