@noble/curves 1.9.1 → 1.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/README.md +56 -25
  2. package/_shortw_utils.d.ts +7 -5
  3. package/_shortw_utils.d.ts.map +1 -1
  4. package/_shortw_utils.js +2 -8
  5. package/_shortw_utils.js.map +1 -1
  6. package/abstract/bls.d.ts +60 -24
  7. package/abstract/bls.d.ts.map +1 -1
  8. package/abstract/bls.js +158 -109
  9. package/abstract/bls.js.map +1 -1
  10. package/abstract/curve.d.ts +44 -9
  11. package/abstract/curve.d.ts.map +1 -1
  12. package/abstract/curve.js +86 -7
  13. package/abstract/curve.js.map +1 -1
  14. package/abstract/edwards.d.ts +112 -25
  15. package/abstract/edwards.d.ts.map +1 -1
  16. package/abstract/edwards.js +138 -102
  17. package/abstract/edwards.js.map +1 -1
  18. package/abstract/fft.d.ts +12 -10
  19. package/abstract/fft.d.ts.map +1 -1
  20. package/abstract/fft.js +12 -13
  21. package/abstract/fft.js.map +1 -1
  22. package/abstract/hash-to-curve.d.ts +25 -11
  23. package/abstract/hash-to-curve.d.ts.map +1 -1
  24. package/abstract/hash-to-curve.js +17 -14
  25. package/abstract/hash-to-curve.js.map +1 -1
  26. package/abstract/modular.d.ts +24 -11
  27. package/abstract/modular.d.ts.map +1 -1
  28. package/abstract/modular.js +49 -20
  29. package/abstract/modular.js.map +1 -1
  30. package/abstract/montgomery.d.ts +1 -1
  31. package/abstract/montgomery.d.ts.map +1 -1
  32. package/abstract/montgomery.js +5 -4
  33. package/abstract/montgomery.js.map +1 -1
  34. package/abstract/poseidon.d.ts +5 -13
  35. package/abstract/poseidon.d.ts.map +1 -1
  36. package/abstract/poseidon.js +12 -7
  37. package/abstract/poseidon.js.map +1 -1
  38. package/abstract/tower.d.ts +20 -46
  39. package/abstract/tower.d.ts.map +1 -1
  40. package/abstract/tower.js +9 -3
  41. package/abstract/tower.js.map +1 -1
  42. package/abstract/utils.d.ts +1 -115
  43. package/abstract/utils.d.ts.map +1 -1
  44. package/abstract/utils.js +17 -371
  45. package/abstract/utils.js.map +1 -1
  46. package/abstract/weierstrass.d.ts +132 -76
  47. package/abstract/weierstrass.d.ts.map +1 -1
  48. package/abstract/weierstrass.js +462 -398
  49. package/abstract/weierstrass.js.map +1 -1
  50. package/bls12-381.d.ts +2 -0
  51. package/bls12-381.d.ts.map +1 -1
  52. package/bls12-381.js +504 -466
  53. package/bls12-381.js.map +1 -1
  54. package/bn254.d.ts +2 -0
  55. package/bn254.d.ts.map +1 -1
  56. package/bn254.js +44 -32
  57. package/bn254.js.map +1 -1
  58. package/ed25519.d.ts +8 -5
  59. package/ed25519.d.ts.map +1 -1
  60. package/ed25519.js +67 -54
  61. package/ed25519.js.map +1 -1
  62. package/ed448.d.ts +10 -6
  63. package/ed448.d.ts.map +1 -1
  64. package/ed448.js +80 -57
  65. package/ed448.js.map +1 -1
  66. package/esm/_shortw_utils.d.ts +7 -5
  67. package/esm/_shortw_utils.d.ts.map +1 -1
  68. package/esm/_shortw_utils.js +2 -8
  69. package/esm/_shortw_utils.js.map +1 -1
  70. package/esm/abstract/bls.d.ts +60 -24
  71. package/esm/abstract/bls.d.ts.map +1 -1
  72. package/esm/abstract/bls.js +158 -109
  73. package/esm/abstract/bls.js.map +1 -1
  74. package/esm/abstract/curve.d.ts +44 -9
  75. package/esm/abstract/curve.d.ts.map +1 -1
  76. package/esm/abstract/curve.js +83 -8
  77. package/esm/abstract/curve.js.map +1 -1
  78. package/esm/abstract/edwards.d.ts +112 -25
  79. package/esm/abstract/edwards.d.ts.map +1 -1
  80. package/esm/abstract/edwards.js +138 -104
  81. package/esm/abstract/edwards.js.map +1 -1
  82. package/esm/abstract/fft.d.ts +12 -10
  83. package/esm/abstract/fft.d.ts.map +1 -1
  84. package/esm/abstract/fft.js +10 -11
  85. package/esm/abstract/fft.js.map +1 -1
  86. package/esm/abstract/hash-to-curve.d.ts +25 -11
  87. package/esm/abstract/hash-to-curve.d.ts.map +1 -1
  88. package/esm/abstract/hash-to-curve.js +17 -14
  89. package/esm/abstract/hash-to-curve.js.map +1 -1
  90. package/esm/abstract/modular.d.ts +24 -11
  91. package/esm/abstract/modular.d.ts.map +1 -1
  92. package/esm/abstract/modular.js +48 -19
  93. package/esm/abstract/modular.js.map +1 -1
  94. package/esm/abstract/montgomery.d.ts +1 -1
  95. package/esm/abstract/montgomery.d.ts.map +1 -1
  96. package/esm/abstract/montgomery.js +5 -4
  97. package/esm/abstract/montgomery.js.map +1 -1
  98. package/esm/abstract/poseidon.d.ts +5 -13
  99. package/esm/abstract/poseidon.d.ts.map +1 -1
  100. package/esm/abstract/poseidon.js +12 -7
  101. package/esm/abstract/poseidon.js.map +1 -1
  102. package/esm/abstract/tower.d.ts +20 -46
  103. package/esm/abstract/tower.d.ts.map +1 -1
  104. package/esm/abstract/tower.js +9 -3
  105. package/esm/abstract/tower.js.map +1 -1
  106. package/esm/abstract/utils.d.ts +1 -115
  107. package/esm/abstract/utils.d.ts.map +1 -1
  108. package/esm/abstract/utils.js +3 -344
  109. package/esm/abstract/utils.js.map +1 -1
  110. package/esm/abstract/weierstrass.d.ts +132 -76
  111. package/esm/abstract/weierstrass.d.ts.map +1 -1
  112. package/esm/abstract/weierstrass.js +460 -400
  113. package/esm/abstract/weierstrass.js.map +1 -1
  114. package/esm/bls12-381.d.ts +2 -0
  115. package/esm/bls12-381.d.ts.map +1 -1
  116. package/esm/bls12-381.js +503 -465
  117. package/esm/bls12-381.js.map +1 -1
  118. package/esm/bn254.d.ts +2 -0
  119. package/esm/bn254.d.ts.map +1 -1
  120. package/esm/bn254.js +41 -29
  121. package/esm/bn254.js.map +1 -1
  122. package/esm/ed25519.d.ts +8 -5
  123. package/esm/ed25519.d.ts.map +1 -1
  124. package/esm/ed25519.js +62 -49
  125. package/esm/ed25519.js.map +1 -1
  126. package/esm/ed448.d.ts +10 -6
  127. package/esm/ed448.d.ts.map +1 -1
  128. package/esm/ed448.js +74 -51
  129. package/esm/ed448.js.map +1 -1
  130. package/esm/misc.d.ts.map +1 -1
  131. package/esm/misc.js +31 -26
  132. package/esm/misc.js.map +1 -1
  133. package/esm/nist.d.ts +7 -16
  134. package/esm/nist.d.ts.map +1 -1
  135. package/esm/nist.js +86 -97
  136. package/esm/nist.js.map +1 -1
  137. package/esm/p256.d.ts +3 -3
  138. package/esm/p384.d.ts +3 -3
  139. package/esm/p521.d.ts +3 -3
  140. package/esm/secp256k1.d.ts +6 -6
  141. package/esm/secp256k1.d.ts.map +1 -1
  142. package/esm/secp256k1.js +43 -40
  143. package/esm/secp256k1.js.map +1 -1
  144. package/esm/utils.d.ts +96 -0
  145. package/esm/utils.d.ts.map +1 -0
  146. package/esm/utils.js +279 -0
  147. package/esm/utils.js.map +1 -0
  148. package/misc.d.ts.map +1 -1
  149. package/misc.js +35 -30
  150. package/misc.js.map +1 -1
  151. package/nist.d.ts +7 -16
  152. package/nist.d.ts.map +1 -1
  153. package/nist.js +86 -97
  154. package/nist.js.map +1 -1
  155. package/p256.d.ts +3 -3
  156. package/p384.d.ts +3 -3
  157. package/p521.d.ts +3 -3
  158. package/package.json +14 -5
  159. package/secp256k1.d.ts +6 -6
  160. package/secp256k1.d.ts.map +1 -1
  161. package/secp256k1.js +46 -43
  162. package/secp256k1.js.map +1 -1
  163. package/src/_shortw_utils.ts +5 -15
  164. package/src/abstract/bls.ts +260 -145
  165. package/src/abstract/curve.ts +115 -13
  166. package/src/abstract/edwards.ts +279 -138
  167. package/src/abstract/fft.ts +30 -19
  168. package/src/abstract/hash-to-curve.ts +51 -27
  169. package/src/abstract/modular.ts +49 -28
  170. package/src/abstract/montgomery.ts +9 -7
  171. package/src/abstract/poseidon.ts +22 -18
  172. package/src/abstract/tower.ts +36 -67
  173. package/src/abstract/utils.ts +3 -378
  174. package/src/abstract/weierstrass.ts +700 -453
  175. package/src/bls12-381.ts +540 -489
  176. package/src/bn254.ts +47 -35
  177. package/src/ed25519.ts +80 -64
  178. package/src/ed448.ts +129 -92
  179. package/src/misc.ts +39 -34
  180. package/src/nist.ts +138 -127
  181. package/src/p256.ts +3 -3
  182. package/src/p384.ts +3 -3
  183. package/src/p521.ts +3 -3
  184. package/src/secp256k1.ts +58 -46
  185. package/src/utils.ts +328 -0
  186. package/utils.d.ts +96 -0
  187. package/utils.d.ts.map +1 -0
  188. package/utils.js +313 -0
  189. package/utils.js.map +1 -0
@@ -4,8 +4,8 @@
4
4
  * @module
5
5
  */
6
6
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
7
- import { type IField, nLength, validateField } from './modular.ts';
8
- import { bitLen, bitMask, validateObject } from './utils.ts';
7
+ import { bitLen, bitMask, validateObject } from '../utils.ts';
8
+ import { Field, FpInvertBatch, type IField, nLength, validateField } from './modular.ts';
9
9
 
10
10
  const _0n = BigInt(0);
11
11
  const _1n = BigInt(1);
@@ -22,19 +22,43 @@ export interface Group<T extends Group<T>> {
22
22
  subtract(other: T): T;
23
23
  equals(other: T): boolean;
24
24
  multiply(scalar: bigint): T;
25
+ toAffine?(invertedZ?: any): AffinePoint<any>;
25
26
  }
26
27
 
27
28
  export type GroupConstructor<T> = {
28
29
  BASE: T;
29
30
  ZERO: T;
30
31
  };
32
+ export type ExtendedGroupConstructor<T> = GroupConstructor<T> & {
33
+ Fp: IField<any>;
34
+ Fn: IField<bigint>;
35
+ fromAffine(ap: AffinePoint<any>): T;
36
+ };
31
37
  export type Mapper<T> = (i: T[]) => T[];
32
38
 
33
- function constTimeNegate<T extends Group<T>>(condition: boolean, item: T): T {
39
+ export function negateCt<T extends Group<T>>(condition: boolean, item: T): T {
34
40
  const neg = item.negate();
35
41
  return condition ? neg : item;
36
42
  }
37
43
 
44
+ /**
45
+ * Takes a bunch of Projective Points but executes only one
46
+ * inversion on all of them. Inversion is very slow operation,
47
+ * so this improves performance massively.
48
+ * Optimization: converts a list of projective points to a list of identical points with Z=1.
49
+ */
50
+ export function normalizeZ<T>(
51
+ c: ExtendedGroupConstructor<T>,
52
+ property: 'pz' | 'ez',
53
+ points: T[]
54
+ ): T[] {
55
+ const getz = property === 'pz' ? (p: any) => p.pz : (p: any) => p.ez;
56
+ const toInv = FpInvertBatch(c.Fp, points.map(getz));
57
+ // @ts-ignore
58
+ const affined = points.map((p, i) => p.toAffine(toInv[i]));
59
+ return affined.map(c.fromAffine);
60
+ }
61
+
38
62
  function validateW(W: number, bits: number) {
39
63
  if (!Number.isSafeInteger(W) || W <= 0 || W > bits)
40
64
  throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W);
@@ -107,16 +131,20 @@ function getW(P: any): number {
107
131
  return pointWindowSizes.get(P) || 1;
108
132
  }
109
133
 
134
+ function assert0(n: bigint): void {
135
+ if (n !== _0n) throw new Error('invalid wNAF');
136
+ }
137
+
110
138
  export type IWNAF<T extends Group<T>> = {
111
139
  constTimeNegate: <T extends Group<T>>(condition: boolean, item: T) => T;
112
140
  hasPrecomputes(elm: T): boolean;
113
141
  unsafeLadder(elm: T, n: bigint, p?: T): T;
114
142
  precomputeWindow(elm: T, W: number): Group<T>[];
115
- getPrecomputes(W: number, P: T, transform: Mapper<T>): T[];
143
+ getPrecomputes(W: number, P: T, transform?: Mapper<T>): T[];
116
144
  wNAF(W: number, precomputes: T[], n: bigint): { p: T; f: T };
117
145
  wNAFUnsafe(W: number, precomputes: T[], n: bigint, acc?: T): T;
118
- wNAFCached(P: T, n: bigint, transform: Mapper<T>): { p: T; f: T };
119
- wNAFCachedUnsafe(P: T, n: bigint, transform: Mapper<T>, prev?: T): T;
146
+ wNAFCached(P: T, n: bigint, transform?: Mapper<T>): { p: T; f: T };
147
+ wNAFCachedUnsafe(P: T, n: bigint, transform?: Mapper<T>, prev?: T): T;
120
148
  setWindowSize(P: T, W: number): void;
121
149
  };
122
150
 
@@ -136,7 +164,7 @@ export type IWNAF<T extends Group<T>> = {
136
164
  */
137
165
  export function wNAF<T extends Group<T>>(c: GroupConstructor<T>, bits: number): IWNAF<T> {
138
166
  return {
139
- constTimeNegate,
167
+ constTimeNegate: negateCt,
140
168
 
141
169
  hasPrecomputes(elm: T) {
142
170
  return getW(elm) !== 1;
@@ -212,12 +240,13 @@ export function wNAF<T extends Group<T>>(c: GroupConstructor<T>, bits: number):
212
240
  if (isZero) {
213
241
  // bits are 0: add garbage to fake point
214
242
  // Important part for const-time getPublicKey: add random "noise" point to f.
215
- f = f.add(constTimeNegate(isNegF, precomputes[offsetF]));
243
+ f = f.add(negateCt(isNegF, precomputes[offsetF]));
216
244
  } else {
217
245
  // bits are 1: add to result point
218
- p = p.add(constTimeNegate(isNeg, precomputes[offset]));
246
+ p = p.add(negateCt(isNeg, precomputes[offset]));
219
247
  }
220
248
  }
249
+ assert0(n);
221
250
  // Return both real and fake points: JIT won't eliminate f.
222
251
  // At this point there is a way to F be infinity-point even if p is not,
223
252
  // which makes it less const-time: around 1 bigint multiply.
@@ -247,25 +276,30 @@ export function wNAF<T extends Group<T>>(c: GroupConstructor<T>, bits: number):
247
276
  acc = acc.add(isNeg ? item.negate() : item); // Re-using acc allows to save adds in MSM
248
277
  }
249
278
  }
279
+ assert0(n);
250
280
  return acc;
251
281
  },
252
282
 
253
- getPrecomputes(W: number, P: T, transform: Mapper<T>): T[] {
283
+ getPrecomputes(W: number, P: T, transform?: Mapper<T>): T[] {
254
284
  // Calculate precomputes on a first run, reuse them after
255
285
  let comp = pointPrecomputes.get(P);
256
286
  if (!comp) {
257
287
  comp = this.precomputeWindow(P, W) as T[];
258
- if (W !== 1) pointPrecomputes.set(P, transform(comp));
288
+ if (W !== 1) {
289
+ // Doing transform outside of if brings 15% perf hit
290
+ if (typeof transform === 'function') comp = transform(comp);
291
+ pointPrecomputes.set(P, comp);
292
+ }
259
293
  }
260
294
  return comp;
261
295
  },
262
296
 
263
- wNAFCached(P: T, n: bigint, transform: Mapper<T>): { p: T; f: T } {
297
+ wNAFCached(P: T, n: bigint, transform?: Mapper<T>): { p: T; f: T } {
264
298
  const W = getW(P);
265
299
  return this.wNAF(W, this.getPrecomputes(W, P, transform), n);
266
300
  },
267
301
 
268
- wNAFCachedUnsafe(P: T, n: bigint, transform: Mapper<T>, prev?: T): T {
302
+ wNAFCachedUnsafe(P: T, n: bigint, transform?: Mapper<T>, prev?: T): T {
269
303
  const W = getW(P);
270
304
  if (W === 1) return this.unsafeLadder(P, n, prev); // For W=1 ladder is ~x2 faster
271
305
  return this.wNAFUnsafe(W, this.getPrecomputes(W, P, transform), n, prev);
@@ -283,6 +317,29 @@ export function wNAF<T extends Group<T>>(c: GroupConstructor<T>, bits: number):
283
317
  };
284
318
  }
285
319
 
320
+ /**
321
+ * Endomorphism-specific multiplication for Koblitz curves.
322
+ * Cost: 128 dbl, 0-256 adds.
323
+ */
324
+ export function mulEndoUnsafe<T extends Group<T>>(
325
+ c: GroupConstructor<T>,
326
+ point: T,
327
+ k1: bigint,
328
+ k2: bigint
329
+ ): { p1: T; p2: T } {
330
+ let acc = point;
331
+ let p1 = c.ZERO;
332
+ let p2 = c.ZERO;
333
+ while (k1 > _0n || k2 > _0n) {
334
+ if (k1 & _1n) p1 = p1.add(acc);
335
+ if (k2 & _1n) p2 = p2.add(acc);
336
+ acc = acc.double();
337
+ k1 >>= _1n;
338
+ k2 >>= _1n;
339
+ }
340
+ return { p1, p2 };
341
+ }
342
+
286
343
  /**
287
344
  * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
288
345
  * 30x faster vs naive addition on L=4096, 10x faster than precomputes.
@@ -437,6 +494,8 @@ export type BasicCurve<T> = {
437
494
  allowInfinityPoint?: boolean; // bls12-381 requires it. ZERO point is valid, but invalid pubkey
438
495
  };
439
496
 
497
+ // TODO: remove
498
+ /** @deprecated */
440
499
  export function validateBasic<FP, T>(
441
500
  curve: BasicCurve<FP> & T
442
501
  ): Readonly<
@@ -469,3 +528,46 @@ export function validateBasic<FP, T>(
469
528
  ...{ p: curve.Fp.ORDER },
470
529
  } as const);
471
530
  }
531
+
532
+ export type ValidCurveParams<T> = {
533
+ a: T;
534
+ p: bigint;
535
+ n: bigint;
536
+ h: bigint;
537
+ Gx: T;
538
+ Gy: T;
539
+ } & ({ b: T } | { d: T });
540
+
541
+ function createField<T>(order: bigint, field?: IField<T>): IField<T> {
542
+ if (field) {
543
+ if (field.ORDER !== order) throw new Error('Field.ORDER must match order: Fp == p, Fn == n');
544
+ validateField(field);
545
+ return field;
546
+ } else {
547
+ return Field(order) as unknown as IField<T>;
548
+ }
549
+ }
550
+ export type FpFn<T> = { Fp: IField<T>; Fn: IField<bigint> };
551
+ /** Validates CURVE opts and creates fields */
552
+ export function _createCurveFields<T>(
553
+ type: 'weierstrass' | 'edwards',
554
+ CURVE: ValidCurveParams<T>,
555
+ curveOpts: Partial<FpFn<T>> = {}
556
+ ): FpFn<T> {
557
+ if (!CURVE || typeof CURVE !== 'object') throw new Error(`expected valid ${type} CURVE object`);
558
+ for (const p of ['p', 'n', 'h'] as const) {
559
+ const val = CURVE[p];
560
+ if (!(typeof val === 'bigint' && val > _0n))
561
+ throw new Error(`CURVE.${p} must be positive bigint`);
562
+ }
563
+ const Fp = createField(CURVE.p, curveOpts.Fp);
564
+ const Fn = createField(CURVE.n, curveOpts.Fn);
565
+ const _b: 'b' | 'd' = type === 'weierstrass' ? 'b' : 'd';
566
+ const params = ['Gx', 'Gy', 'a', _b] as const;
567
+ for (const p of params) {
568
+ // @ts-ignore
569
+ if (!Fp.isValid(CURVE[p]))
570
+ throw new Error(`CURVE.${p} must be valid field element of CURVE.Fp`);
571
+ }
572
+ return { Fp, Fn };
573
+ }