@noble/curves 2.0.1 → 2.2.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.
Files changed (110) hide show
  1. package/README.md +214 -122
  2. package/abstract/bls.d.ts +299 -16
  3. package/abstract/bls.d.ts.map +1 -1
  4. package/abstract/bls.js +82 -22
  5. package/abstract/bls.js.map +1 -1
  6. package/abstract/curve.d.ts +274 -27
  7. package/abstract/curve.d.ts.map +1 -1
  8. package/abstract/curve.js +177 -23
  9. package/abstract/curve.js.map +1 -1
  10. package/abstract/edwards.d.ts +166 -30
  11. package/abstract/edwards.d.ts.map +1 -1
  12. package/abstract/edwards.js +221 -86
  13. package/abstract/edwards.js.map +1 -1
  14. package/abstract/fft.d.ts +322 -10
  15. package/abstract/fft.d.ts.map +1 -1
  16. package/abstract/fft.js +154 -12
  17. package/abstract/fft.js.map +1 -1
  18. package/abstract/frost.d.ts +293 -0
  19. package/abstract/frost.d.ts.map +1 -0
  20. package/abstract/frost.js +704 -0
  21. package/abstract/frost.js.map +1 -0
  22. package/abstract/hash-to-curve.d.ts +173 -24
  23. package/abstract/hash-to-curve.d.ts.map +1 -1
  24. package/abstract/hash-to-curve.js +170 -31
  25. package/abstract/hash-to-curve.js.map +1 -1
  26. package/abstract/modular.d.ts +429 -37
  27. package/abstract/modular.d.ts.map +1 -1
  28. package/abstract/modular.js +414 -119
  29. package/abstract/modular.js.map +1 -1
  30. package/abstract/montgomery.d.ts +83 -12
  31. package/abstract/montgomery.d.ts.map +1 -1
  32. package/abstract/montgomery.js +32 -7
  33. package/abstract/montgomery.js.map +1 -1
  34. package/abstract/oprf.d.ts +164 -91
  35. package/abstract/oprf.d.ts.map +1 -1
  36. package/abstract/oprf.js +88 -29
  37. package/abstract/oprf.js.map +1 -1
  38. package/abstract/poseidon.d.ts +138 -7
  39. package/abstract/poseidon.d.ts.map +1 -1
  40. package/abstract/poseidon.js +178 -15
  41. package/abstract/poseidon.js.map +1 -1
  42. package/abstract/tower.d.ts +122 -3
  43. package/abstract/tower.d.ts.map +1 -1
  44. package/abstract/tower.js +323 -139
  45. package/abstract/tower.js.map +1 -1
  46. package/abstract/weierstrass.d.ts +339 -76
  47. package/abstract/weierstrass.d.ts.map +1 -1
  48. package/abstract/weierstrass.js +395 -205
  49. package/abstract/weierstrass.js.map +1 -1
  50. package/bls12-381.d.ts +16 -2
  51. package/bls12-381.d.ts.map +1 -1
  52. package/bls12-381.js +199 -209
  53. package/bls12-381.js.map +1 -1
  54. package/bn254.d.ts +11 -2
  55. package/bn254.d.ts.map +1 -1
  56. package/bn254.js +93 -38
  57. package/bn254.js.map +1 -1
  58. package/ed25519.d.ts +125 -14
  59. package/ed25519.d.ts.map +1 -1
  60. package/ed25519.js +202 -40
  61. package/ed25519.js.map +1 -1
  62. package/ed448.d.ts +108 -14
  63. package/ed448.d.ts.map +1 -1
  64. package/ed448.js +194 -42
  65. package/ed448.js.map +1 -1
  66. package/index.js +7 -1
  67. package/index.js.map +1 -1
  68. package/misc.d.ts +106 -7
  69. package/misc.d.ts.map +1 -1
  70. package/misc.js +141 -32
  71. package/misc.js.map +1 -1
  72. package/nist.d.ts +112 -11
  73. package/nist.d.ts.map +1 -1
  74. package/nist.js +139 -17
  75. package/nist.js.map +1 -1
  76. package/package.json +11 -6
  77. package/secp256k1.d.ts +92 -15
  78. package/secp256k1.d.ts.map +1 -1
  79. package/secp256k1.js +211 -28
  80. package/secp256k1.js.map +1 -1
  81. package/src/abstract/bls.ts +350 -67
  82. package/src/abstract/curve.ts +327 -44
  83. package/src/abstract/edwards.ts +367 -143
  84. package/src/abstract/fft.ts +369 -36
  85. package/src/abstract/frost.ts +1092 -0
  86. package/src/abstract/hash-to-curve.ts +255 -56
  87. package/src/abstract/modular.ts +591 -144
  88. package/src/abstract/montgomery.ts +114 -30
  89. package/src/abstract/oprf.ts +383 -194
  90. package/src/abstract/poseidon.ts +235 -35
  91. package/src/abstract/tower.ts +428 -159
  92. package/src/abstract/weierstrass.ts +710 -312
  93. package/src/bls12-381.ts +239 -236
  94. package/src/bn254.ts +107 -46
  95. package/src/ed25519.ts +227 -55
  96. package/src/ed448.ts +227 -57
  97. package/src/index.ts +7 -1
  98. package/src/misc.ts +154 -35
  99. package/src/nist.ts +143 -20
  100. package/src/secp256k1.ts +284 -41
  101. package/src/utils.ts +583 -81
  102. package/src/webcrypto.ts +302 -73
  103. package/utils.d.ts +457 -24
  104. package/utils.d.ts.map +1 -1
  105. package/utils.js +410 -53
  106. package/utils.js.map +1 -1
  107. package/webcrypto.d.ts +167 -25
  108. package/webcrypto.d.ts.map +1 -1
  109. package/webcrypto.js +165 -58
  110. package/webcrypto.js.map +1 -1
@@ -4,14 +4,17 @@
4
4
  * @module
5
5
  */
6
6
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
7
- import { bitLen, bitMask, type Signer } from '../utils.ts';
7
+ import { bitLen, bitMask, validateObject, type Signer, type TArg, type TRet } from '../utils.ts';
8
8
  import { Field, FpInvertBatch, validateField, type IField } from './modular.ts';
9
9
 
10
10
  const _0n = /* @__PURE__ */ BigInt(0);
11
11
  const _1n = /* @__PURE__ */ BigInt(1);
12
12
 
13
+ /** Affine point coordinates without projective fields. */
13
14
  export type AffinePoint<T> = {
15
+ /** Affine x coordinate. */
14
16
  x: T;
17
+ /** Affine y coordinate. */
15
18
  y: T;
16
19
  } & { Z?: never };
17
20
 
@@ -23,48 +26,144 @@ export type AffinePoint<T> = {
23
26
  // with `any`, because of recursion, `any implements CurvePoint`,
24
27
  // but we lose all constrains on methods.
25
28
 
26
- /** Base interface for all elliptic curve Points. */
29
+ /** Base interface for all elliptic-curve point instances. */
27
30
  export interface CurvePoint<F, P extends CurvePoint<F, P>> {
28
31
  /** Affine x coordinate. Different from projective / extended X coordinate. */
29
32
  x: F;
30
33
  /** Affine y coordinate. Different from projective / extended Y coordinate. */
31
34
  y: F;
35
+ /** Projective Z coordinate when the point keeps projective state. */
32
36
  Z?: F;
37
+ /**
38
+ * Double the point.
39
+ * @returns Doubled point.
40
+ */
33
41
  double(): P;
42
+ /**
43
+ * Negate the point.
44
+ * @returns Negated point.
45
+ */
34
46
  negate(): P;
47
+ /**
48
+ * Add another point from the same curve.
49
+ * @param other - Point to add.
50
+ * @returns Sum point.
51
+ */
35
52
  add(other: P): P;
53
+ /**
54
+ * Subtract another point from the same curve.
55
+ * @param other - Point to subtract.
56
+ * @returns Difference point.
57
+ */
36
58
  subtract(other: P): P;
59
+ /**
60
+ * Compare two points for equality.
61
+ * @param other - Point to compare.
62
+ * @returns Whether the points are equal.
63
+ */
37
64
  equals(other: P): boolean;
65
+ /**
66
+ * Multiply the point by a scalar in constant time.
67
+ * Implementations keep the subgroup-scalar contract strict and may reject
68
+ * `0` instead of returning the identity point.
69
+ * @param scalar - Scalar multiplier.
70
+ * @returns Product point.
71
+ */
38
72
  multiply(scalar: bigint): P;
73
+ /** Assert that the point satisfies the curve equation and subgroup checks. */
39
74
  assertValidity(): void;
75
+ /**
76
+ * Map the point into the prime-order subgroup when the curve requires it.
77
+ * @returns Prime-order point.
78
+ */
40
79
  clearCofactor(): P;
80
+ /**
81
+ * Check whether the point is the point at infinity.
82
+ * @returns Whether the point is zero.
83
+ */
41
84
  is0(): boolean;
85
+ /**
86
+ * Check whether the point belongs to the prime-order subgroup.
87
+ * @returns Whether the point is torsion-free.
88
+ */
42
89
  isTorsionFree(): boolean;
90
+ /**
91
+ * Check whether the point lies in a small torsion subgroup.
92
+ * @returns Whether the point has small order.
93
+ */
43
94
  isSmallOrder(): boolean;
95
+ /**
96
+ * Multiply the point by a scalar without constant-time guarantees.
97
+ * Public-scalar callers that need `0` should use this method instead of
98
+ * relying on `multiply(...)` to return the identity point.
99
+ * @param scalar - Scalar multiplier.
100
+ * @returns Product point.
101
+ */
44
102
  multiplyUnsafe(scalar: bigint): P;
45
103
  /**
46
104
  * Massively speeds up `p.multiply(n)` by using precompute tables (caching). See {@link wNAF}.
47
- * @param isLazy calculate cache now. Default (true) ensures it's deferred to first `multiply()`
105
+ * Cache state lives in internal WeakMaps keyed by point identity, not on the point object.
106
+ * Repeating `precompute(...)` for the same point identity replaces the remembered window size
107
+ * and forces table regeneration for that point.
108
+ * @param windowSize - Precompute window size.
109
+ * @param isLazy - calculate cache now. Default (true) ensures it's deferred to first `multiply()`
110
+ * @returns Same point instance with precompute tables attached.
48
111
  */
49
112
  precompute(windowSize?: number, isLazy?: boolean): P;
50
- /** Converts point to 2D xy affine coordinates */
113
+ /**
114
+ * Converts point to 2D xy affine coordinates.
115
+ * @param invertedZ - Optional inverted Z coordinate for batch normalization.
116
+ * @returns Affine x/y coordinates.
117
+ */
51
118
  toAffine(invertedZ?: F): AffinePoint<F>;
119
+ /**
120
+ * Encode the point into the curve's canonical byte form.
121
+ * @returns Encoded point bytes.
122
+ */
52
123
  toBytes(): Uint8Array;
124
+ /**
125
+ * Encode the point into the curve's canonical hex form.
126
+ * @returns Encoded point hex.
127
+ */
53
128
  toHex(): string;
54
129
  }
55
130
 
56
- /** Base interface for all elliptic curve Point constructors. */
131
+ /** Base interface for elliptic-curve point constructors. */
57
132
  export interface CurvePointCons<P extends CurvePoint<any, P>> {
133
+ /**
134
+ * Runtime brand check for points created by this constructor.
135
+ * @param item - Value to test.
136
+ * @returns Whether the value is a point from this constructor.
137
+ */
58
138
  [Symbol.hasInstance]: (item: unknown) => boolean;
139
+ /** Canonical subgroup generator. */
59
140
  BASE: P;
141
+ /** Point at infinity. */
60
142
  ZERO: P;
61
143
  /** Field for basic curve math */
62
144
  Fp: IField<P_F<P>>;
63
145
  /** Scalar field, for scalars in multiply and others */
64
146
  Fn: IField<bigint>;
65
- /** Creates point from x, y. Does NOT validate if the point is valid. Use `.assertValidity()`. */
147
+ /**
148
+ * Create one point from affine coordinates.
149
+ * Does NOT validate curve, subgroup, or wrapper invariants.
150
+ * Use `.assertValidity()` on adversarial inputs.
151
+ * @param p - Affine point coordinates.
152
+ * @returns Point instance.
153
+ */
66
154
  fromAffine(p: AffinePoint<P_F<P>>): P;
155
+ /**
156
+ * Decode a point from the canonical byte encoding.
157
+ * @param bytes - Encoded point bytes.
158
+ * Implementations MUST treat `bytes` as read-only.
159
+ * @returns Point instance.
160
+ */
67
161
  fromBytes(bytes: Uint8Array): P;
162
+ /**
163
+ * Decode a point from the canonical hex encoding.
164
+ * @param hex - Encoded point hex.
165
+ * @returns Point instance.
166
+ */
68
167
  fromHex(hex: string): P;
69
168
  }
70
169
 
@@ -79,11 +178,11 @@ export interface CurvePointCons<P extends CurvePoint<any, P>> {
79
178
  // `function test<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(`
80
179
  // if we want type safety around P, otherwise PC_P<PC> will be any
81
180
 
82
- /** Returns Fp type from Point (P_F<P> == P.F) */
181
+ /** Returns the affine field type for a point instance (`P_F<P> == P.F`). */
83
182
  export type P_F<P extends CurvePoint<any, P>> = P extends CurvePoint<infer F, P> ? F : never;
84
- /** Returns Fp type from PointCons (PC_F<PC> == PC.P.F) */
183
+ /** Returns the affine field type for a point constructor (`PC_F<PC> == PC.P.F`). */
85
184
  export type PC_F<PC extends CurvePointCons<CurvePoint<any, any>>> = PC['Fp']['ZERO'];
86
- /** Returns Point type from PointCons (PC_P<PC> == PC.P) */
185
+ /** Returns the point instance type for a point constructor (`PC_P<PC> == PC.P`). */
87
186
  export type PC_P<PC extends CurvePointCons<CurvePoint<any, any>>> = PC['ZERO'];
88
187
 
89
188
  // Ugly hack to get proper type inference, because in typescript fails to infer resursively.
@@ -100,6 +199,7 @@ export type PC_P<PC extends CurvePointCons<CurvePoint<any, any>>> = PC['ZERO'];
100
199
  // * But generally, we don't want to parametrize `CurvePointCons` over `F`: it will complicate
101
200
  // types, making them un-inferable
102
201
  // prettier-ignore
202
+ /** Wide point-constructor type used when the concrete curve is not important. */
103
203
  export type PC_ANY = CurvePointCons<
104
204
  CurvePoint<any,
105
205
  CurvePoint<any,
@@ -114,17 +214,79 @@ export type PC_ANY = CurvePointCons<
114
214
  >>>>>>>>>
115
215
  >;
116
216
 
217
+ /**
218
+ * Validates the static surface of a point constructor.
219
+ * This is only a cheap sanity check for the constructor hooks and fields consumed by generic
220
+ * factories; it does not certify `BASE`/`ZERO` semantics or prove the curve implementation itself.
221
+ * @param Point - Runtime point constructor.
222
+ * @throws On missing constructor hooks or malformed field metadata. {@link TypeError}
223
+ * @example
224
+ * Check that one point constructor exposes the static hooks generic helpers need.
225
+ *
226
+ * ```ts
227
+ * import { ed25519 } from '@noble/curves/ed25519.js';
228
+ * import { validatePointCons } from '@noble/curves/abstract/curve.js';
229
+ * validatePointCons(ed25519.Point);
230
+ * ```
231
+ */
232
+ export function validatePointCons<P extends CurvePoint<any, P>>(Point: CurvePointCons<P>): void {
233
+ const pc = Point as unknown as CurvePointCons<any>;
234
+ if (typeof (pc as unknown) !== 'function') throw new TypeError('Point must be a constructor');
235
+ // validateObject only accepts plain objects, so copy the constructor statics into one bag first.
236
+ validateObject(
237
+ {
238
+ Fp: pc.Fp,
239
+ Fn: pc.Fn,
240
+ fromAffine: pc.fromAffine,
241
+ fromBytes: pc.fromBytes,
242
+ fromHex: pc.fromHex,
243
+ },
244
+ {
245
+ Fp: 'object',
246
+ Fn: 'object',
247
+ fromAffine: 'function',
248
+ fromBytes: 'function',
249
+ fromHex: 'function',
250
+ }
251
+ );
252
+ validateField(pc.Fp);
253
+ validateField(pc.Fn);
254
+ }
255
+
256
+ /** Byte lengths used by one curve implementation. */
117
257
  export interface CurveLengths {
258
+ /** Secret-key length in bytes. */
118
259
  secretKey?: number;
260
+ /** Compressed public-key length in bytes. */
119
261
  publicKey?: number;
262
+ /** Uncompressed public-key length in bytes. */
120
263
  publicKeyUncompressed?: number;
264
+ /** Whether public-key encodings include a format prefix byte. */
121
265
  publicKeyHasPrefix?: boolean;
266
+ /** Signature length in bytes. */
122
267
  signature?: number;
268
+ /** Seed length in bytes when the curve exposes deterministic keygen from seed. */
123
269
  seed?: number;
124
270
  }
125
271
 
272
+ /** Reorders or otherwise remaps a batch while preserving its element type. */
126
273
  export type Mapper<T> = (i: T[]) => T[];
127
274
 
275
+ /**
276
+ * Computes both candidates first, but the final selection still branches on `condition`, so this
277
+ * is not a strict constant-time CMOV primitive.
278
+ * @param condition - Whether to negate the point.
279
+ * @param item - Point-like value.
280
+ * @returns Original or negated value.
281
+ * @example
282
+ * Keep the point or return its negation based on one boolean branch.
283
+ *
284
+ * ```ts
285
+ * import { negateCt } from '@noble/curves/abstract/curve.js';
286
+ * import { p256 } from '@noble/curves/nist.js';
287
+ * const maybeNegated = negateCt(true, p256.Point.BASE);
288
+ * ```
289
+ */
128
290
  export function negateCt<T extends { negate: () => T }>(condition: boolean, item: T): T {
129
291
  const neg = item.negate();
130
292
  return condition ? neg : item;
@@ -135,6 +297,18 @@ export function negateCt<T extends { negate: () => T }>(condition: boolean, item
135
297
  * inversion on all of them. Inversion is very slow operation,
136
298
  * so this improves performance massively.
137
299
  * Optimization: converts a list of projective points to a list of identical points with Z=1.
300
+ * Input points are left unchanged; the normalized points are returned as fresh instances.
301
+ * @param c - Point constructor.
302
+ * @param points - Projective points.
303
+ * @returns Fresh projective points reconstructed from normalized affine coordinates.
304
+ * @example
305
+ * Batch-normalize projective points with a single shared inversion.
306
+ *
307
+ * ```ts
308
+ * import { normalizeZ } from '@noble/curves/abstract/curve.js';
309
+ * import { p256 } from '@noble/curves/nist.js';
310
+ * const points = normalizeZ(p256.Point, [p256.Point.BASE, p256.Point.BASE.double()]);
311
+ * ```
138
312
  */
139
313
  export function normalizeZ<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(
140
314
  c: PC,
@@ -152,7 +326,10 @@ function validateW(W: number, bits: number) {
152
326
  throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W);
153
327
  }
154
328
 
155
- /** Internal wNAF opts for specific W and scalarBits */
329
+ /** Internal wNAF opts for specific W and scalarBits.
330
+ * Zero digits are skipped, so tables store only the positive half-window and callers reserve one
331
+ * extra carry window.
332
+ */
156
333
  type WOpts = {
157
334
  windows: number;
158
335
  windowSize: number;
@@ -188,11 +365,11 @@ function calcOffsets(n: bigint, window: number, wOpts: WOpts) {
188
365
  nextN += _1n; // +256 (carry)
189
366
  }
190
367
  const offsetStart = window * windowSize;
191
- const offset = offsetStart + Math.abs(wbits) - 1; // -1 because we skip zero
368
+ const offset = offsetStart + Math.abs(wbits) - 1; // -1 because we skip zero; ignore when isZero
192
369
  const isZero = wbits === 0; // is current window slice a 0?
193
370
  const isNeg = wbits < 0; // is current window slice negative?
194
- const isNegF = window % 2 !== 0; // fake random statement for noise
195
- const offsetF = offsetStart; // fake offset for noise
371
+ const isNegF = window % 2 !== 0; // fake branch noise only
372
+ const offsetF = offsetStart; // fake branch noise only
196
373
  return { nextN, offset, isZero, isNeg, isNegF, offsetF };
197
374
  }
198
375
 
@@ -218,10 +395,13 @@ const pointWindowSizes = new WeakMap<any, number>();
218
395
  function getW(P: any): number {
219
396
  // To disable precomputes:
220
397
  // return 1;
398
+ // `1` is also the uncached sentinel: use the ladder / non-precomputed path.
221
399
  return pointWindowSizes.get(P) || 1;
222
400
  }
223
401
 
224
402
  function assert0(n: bigint): void {
403
+ // Internal invariant: a non-zero remainder here means the wNAF window decomposition or loop
404
+ // count is inconsistent, not that the original caller provided a bad scalar.
225
405
  if (n !== _0n) throw new Error('invalid wNAF');
226
406
  }
227
407
 
@@ -240,8 +420,18 @@ function assert0(n: bigint): void {
240
420
  * - +1 window is neccessary for wNAF
241
421
  * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication
242
422
  *
243
- * @todo Research returning 2d JS array of windows, instead of a single window.
244
- * This would allow windows to be in different memory locations
423
+ * TODO: research returning a 2d JS array of windows instead of a single window.
424
+ * This would allow windows to be in different memory locations.
425
+ * @param Point - Point constructor.
426
+ * @param bits - Scalar bit length.
427
+ * @example
428
+ * Elliptic curve multiplication of Point by scalar.
429
+ *
430
+ * ```ts
431
+ * import { wNAF } from '@noble/curves/abstract/curve.js';
432
+ * import { p256 } from '@noble/curves/nist.js';
433
+ * const ladder = new wNAF(p256.Point, p256.Point.Fn.BITS);
434
+ * ```
245
435
  */
246
436
  export class wNAF<PC extends PC_ANY> {
247
437
  private readonly BASE: PC_P<PC>;
@@ -276,8 +466,8 @@ export class wNAF<PC extends PC_ANY> {
276
466
  * - 𝑊 is the window size
277
467
  * - 𝑛 is the bitlength of the curve order.
278
468
  * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
279
- * @param point Point instance
280
- * @param W window size
469
+ * @param point - Point instance
470
+ * @param W - window size
281
471
  * @returns precomputed point tables flattened to a single array
282
472
  */
283
473
  private precomputeWindow(point: PC_P<PC>, W: number): PC_P<PC>[] {
@@ -330,15 +520,16 @@ export class wNAF<PC extends PC_ANY> {
330
520
  }
331
521
  }
332
522
  assert0(n);
333
- // Return both real and fake points: JIT won't eliminate f.
334
- // At this point there is a way to F be infinity-point even if p is not,
335
- // which makes it less const-time: around 1 bigint multiply.
523
+ // Return both real and fake points so JIT keeps the noise path alive.
524
+ // Known caveat: negate/carry interactions can still drive `f` to infinity even when `p` is not,
525
+ // which weakens the noise path and leaves this only "less const-time" by about one bigint mul.
336
526
  return { p, f };
337
527
  }
338
528
 
339
529
  /**
340
- * Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form.
341
- * @param acc accumulator point to add result of multiplication
530
+ * Implements unsafe EC multiplication using precomputed tables
531
+ * and w-ary non-adjacent form.
532
+ * @param acc - accumulator point to add result of multiplication
342
533
  * @returns point
343
534
  */
344
535
  private wNAFUnsafe(
@@ -366,7 +557,8 @@ export class wNAF<PC extends PC_ANY> {
366
557
  }
367
558
 
368
559
  private getPrecomputes(W: number, point: PC_P<PC>, transform?: Mapper<PC_P<PC>>): PC_P<PC>[] {
369
- // Calculate precomputes on a first run, reuse them after
560
+ // Cache key is only point identity plus the remembered window size; callers must not reuse the
561
+ // same point with incompatible `transform(...)` layouts and expect a separate cache entry.
370
562
  let comp = pointPrecomputes.get(point);
371
563
  if (!comp) {
372
564
  comp = this.precomputeWindow(point, W) as PC_P<PC>[];
@@ -411,6 +603,19 @@ export class wNAF<PC extends PC_ANY> {
411
603
  /**
412
604
  * Endomorphism-specific multiplication for Koblitz curves.
413
605
  * Cost: 128 dbl, 0-256 adds.
606
+ * @param Point - Point constructor.
607
+ * @param point - Input point.
608
+ * @param k1 - First non-negative absolute scalar chunk.
609
+ * @param k2 - Second non-negative absolute scalar chunk.
610
+ * @returns Partial multiplication results.
611
+ * @example
612
+ * Endomorphism-specific multiplication for Koblitz curves.
613
+ *
614
+ * ```ts
615
+ * import { mulEndoUnsafe } from '@noble/curves/abstract/curve.js';
616
+ * import { secp256k1 } from '@noble/curves/secp256k1.js';
617
+ * const parts = mulEndoUnsafe(secp256k1.Point, secp256k1.Point.BASE, 3n, 5n);
618
+ * ```
414
619
  */
415
620
  export function mulEndoUnsafe<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(
416
621
  Point: PC,
@@ -436,10 +641,19 @@ export function mulEndoUnsafe<P extends CurvePoint<any, P>, PC extends CurvePoin
436
641
  * 30x faster vs naive addition on L=4096, 10x faster than precomputes.
437
642
  * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL.
438
643
  * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0.
439
- * @param c Curve Point constructor
440
- * @param fieldN field over CURVE.N - important that it's not over CURVE.P
441
- * @param points array of L curve points
442
- * @param scalars array of L scalars (aka secret keys / bigints)
644
+ * @param c - Curve Point constructor
645
+ * @param points - array of L curve points
646
+ * @param scalars - array of L scalars (aka secret keys / bigints)
647
+ * @returns MSM result point. Empty input is accepted and returns the identity.
648
+ * @throws If the point set, scalar set, or MSM sizing is invalid. {@link Error}
649
+ * @example
650
+ * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
651
+ *
652
+ * ```ts
653
+ * import { pippenger } from '@noble/curves/abstract/curve.js';
654
+ * import { p256 } from '@noble/curves/nist.js';
655
+ * const point = pippenger(p256.Point, [p256.Point.BASE, p256.Point.BASE.double()], [2n, 3n]);
656
+ * ```
443
657
  */
444
658
  export function pippenger<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(
445
659
  c: PC,
@@ -489,10 +703,21 @@ export function pippenger<P extends CurvePoint<any, P>, PC extends CurvePointCon
489
703
  }
490
704
  /**
491
705
  * Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
492
- * @param c Curve Point constructor
493
- * @param fieldN field over CURVE.N - important that it's not over CURVE.P
494
- * @param points array of L curve points
495
- * @returns function which multiplies points with scaars
706
+ * @param c - Curve Point constructor
707
+ * @param points - array of L curve points
708
+ * @param windowSize - Precompute window size.
709
+ * @returns Function which multiplies points with scalars. The closure accepts
710
+ * `scalars.length <= points.length`, and omitted trailing scalars are treated as zero.
711
+ * @throws If the point set or precompute window is invalid. {@link Error}
712
+ * @example
713
+ * Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
714
+ *
715
+ * ```ts
716
+ * import { precomputeMSMUnsafe } from '@noble/curves/abstract/curve.js';
717
+ * import { p256 } from '@noble/curves/nist.js';
718
+ * const msm = precomputeMSMUnsafe(p256.Point, [p256.Point.BASE], 4);
719
+ * const point = msm([3n]);
720
+ * ```
496
721
  */
497
722
  export function precomputeMSMUnsafe<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(
498
723
  c: PC,
@@ -569,35 +794,79 @@ export function precomputeMSMUnsafe<P extends CurvePoint<any, P>, PC extends Cur
569
794
  };
570
795
  }
571
796
 
797
+ /** Minimal curve parameters needed to construct a Weierstrass or Edwards curve. */
572
798
  export type ValidCurveParams<T> = {
799
+ /** Base-field modulus. */
573
800
  p: bigint;
801
+ /** Prime subgroup order. */
574
802
  n: bigint;
803
+ /** Cofactor. */
575
804
  h: bigint;
805
+ /** Curve parameter `a`. */
576
806
  a: T;
807
+ /** Weierstrass curve parameter `b`. */
577
808
  b?: T;
809
+ /** Edwards curve parameter `d`. */
578
810
  d?: T;
811
+ /** Generator x coordinate. */
579
812
  Gx: T;
813
+ /** Generator y coordinate. */
580
814
  Gy: T;
581
815
  };
582
816
 
583
- function createField<T>(order: bigint, field?: IField<T>, isLE?: boolean): IField<T> {
817
+ function createField<T>(order: bigint, field?: TArg<IField<T>>, isLE?: boolean): TRet<IField<T>> {
584
818
  if (field) {
819
+ // Reuse supplied field overrides as-is; `isLE` only affects freshly constructed fallback
820
+ // fields, and validateField() below only checks the arithmetic subset, not full byte/cmov
821
+ // behavior.
585
822
  if (field.ORDER !== order) throw new Error('Field.ORDER must match order: Fp == p, Fn == n');
586
823
  validateField(field);
587
- return field;
824
+ return field as TRet<IField<T>>;
588
825
  } else {
589
- return Field(order, { isLE }) as unknown as IField<T>;
826
+ return Field(order, { isLE }) as unknown as TRet<IField<T>>;
590
827
  }
591
828
  }
592
- export type FpFn<T> = { Fp: IField<T>; Fn: IField<bigint> };
829
+ /** Pair of fields used by curve constructors. */
830
+ export type FpFn<T> = {
831
+ /** Base field used for curve coordinates. */
832
+ Fp: IField<T>;
833
+ /** Scalar field used for secret scalars and subgroup arithmetic. */
834
+ Fn: IField<bigint>;
835
+ };
593
836
 
594
- /** Validates CURVE opts and creates fields */
837
+ /**
838
+ * Validates basic CURVE shape and field membership, then creates fields.
839
+ * This does not prove that the generator is on-curve, that subgroup/order data are consistent, or
840
+ * that the curve equation itself is otherwise sane.
841
+ * @param type - Curve family.
842
+ * @param CURVE - Curve parameters.
843
+ * @param curveOpts - Optional field overrides:
844
+ * - `Fp` (optional): Optional base-field override.
845
+ * - `Fn` (optional): Optional scalar-field override.
846
+ * @param FpFnLE - Whether field encoding is little-endian.
847
+ * @returns Frozen curve parameters and fields.
848
+ * @throws If the curve parameters or field overrides are invalid. {@link Error}
849
+ * @example
850
+ * Build curve fields from raw constants before constructing a curve instance.
851
+ *
852
+ * ```ts
853
+ * const curve = createCurveFields('weierstrass', {
854
+ * p: 17n,
855
+ * n: 19n,
856
+ * h: 1n,
857
+ * a: 2n,
858
+ * b: 2n,
859
+ * Gx: 5n,
860
+ * Gy: 1n,
861
+ * });
862
+ * ```
863
+ */
595
864
  export function createCurveFields<T>(
596
865
  type: 'weierstrass' | 'edwards',
597
866
  CURVE: ValidCurveParams<T>,
598
- curveOpts: Partial<FpFn<T>> = {},
867
+ curveOpts: TArg<Partial<FpFn<T>>> = {},
599
868
  FpFnLE?: boolean
600
- ): FpFn<T> & { CURVE: ValidCurveParams<T> } {
869
+ ): TRet<FpFn<T> & { CURVE: ValidCurveParams<T> }> {
601
870
  if (FpFnLE === undefined) FpFnLE = type === 'edwards';
602
871
  if (!CURVE || typeof CURVE !== 'object') throw new Error(`expected valid ${type} CURVE object`);
603
872
  for (const p of ['p', 'n', 'h'] as const) {
@@ -615,19 +884,33 @@ export function createCurveFields<T>(
615
884
  throw new Error(`CURVE.${p} must be valid field element of CURVE.Fp`);
616
885
  }
617
886
  CURVE = Object.freeze(Object.assign({}, CURVE));
618
- return { CURVE, Fp, Fn };
887
+ return { CURVE, Fp, Fn } as TRet<FpFn<T> & { CURVE: ValidCurveParams<T> }>;
619
888
  }
620
889
 
621
890
  type KeygenFn = (
622
891
  seed?: Uint8Array,
623
892
  isCompressed?: boolean
624
893
  ) => { secretKey: Uint8Array; publicKey: Uint8Array };
894
+ /**
895
+ * @param randomSecretKey - Secret-key generator.
896
+ * @param getPublicKey - Public-key derivation helper.
897
+ * @returns Keypair generator.
898
+ * @example
899
+ * Build a `keygen()` helper from existing secret-key and public-key primitives.
900
+ *
901
+ * ```ts
902
+ * import { createKeygen } from '@noble/curves/abstract/curve.js';
903
+ * import { p256 } from '@noble/curves/nist.js';
904
+ * const keygen = createKeygen(p256.utils.randomSecretKey, p256.getPublicKey);
905
+ * const pair = keygen();
906
+ * ```
907
+ */
625
908
  export function createKeygen(
626
909
  randomSecretKey: Function,
627
- getPublicKey: Signer['getPublicKey']
628
- ): KeygenFn {
629
- return function keygen(seed?: Uint8Array) {
630
- const secretKey = randomSecretKey(seed);
631
- return { secretKey, publicKey: getPublicKey(secretKey) };
910
+ getPublicKey: TArg<Signer['getPublicKey']>
911
+ ): TRet<KeygenFn> {
912
+ return function keygen(seed?: TArg<Uint8Array>) {
913
+ const secretKey = randomSecretKey(seed) as TRet<Uint8Array>;
914
+ return { secretKey, publicKey: getPublicKey(secretKey) as TRet<Uint8Array> };
632
915
  };
633
916
  }