@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
package/src/utils.ts CHANGED
@@ -5,88 +5,441 @@
5
5
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
6
6
  import {
7
7
  abytes as abytes_,
8
- anumber,
8
+ anumber as anumber_,
9
9
  bytesToHex as bytesToHex_,
10
10
  concatBytes as concatBytes_,
11
11
  hexToBytes as hexToBytes_,
12
+ isBytes as isBytes_,
13
+ randomBytes as randomBytes_,
12
14
  } from '@noble/hashes/utils.js';
13
- export {
14
- abytes,
15
- anumber,
16
- bytesToHex,
17
- concatBytes,
18
- hexToBytes,
19
- isBytes,
20
- randomBytes,
21
- } from '@noble/hashes/utils.js';
15
+ /**
16
+ * Bytes API type helpers for old + new TypeScript.
17
+ *
18
+ * TS 5.6 has `Uint8Array`, while TS 5.9+ made it generic `Uint8Array<ArrayBuffer>`.
19
+ * We can't use specific return type, because TS 5.6 will error.
20
+ * We can't use generic return type, because most TS 5.9 software will expect specific type.
21
+ *
22
+ * Maps typed-array input leaves to broad forms.
23
+ * These are compatibility adapters, not ownership guarantees.
24
+ *
25
+ * - `TArg` keeps byte inputs broad.
26
+ * - `TRet` marks byte outputs for TS 5.6 and TS 5.9+ compatibility.
27
+ */
28
+ export type TypedArg<T> = T extends BigInt64Array
29
+ ? BigInt64Array
30
+ : T extends BigUint64Array
31
+ ? BigUint64Array
32
+ : T extends Float32Array
33
+ ? Float32Array
34
+ : T extends Float64Array
35
+ ? Float64Array
36
+ : T extends Int16Array
37
+ ? Int16Array
38
+ : T extends Int32Array
39
+ ? Int32Array
40
+ : T extends Int8Array
41
+ ? Int8Array
42
+ : T extends Uint16Array
43
+ ? Uint16Array
44
+ : T extends Uint32Array
45
+ ? Uint32Array
46
+ : T extends Uint8ClampedArray
47
+ ? Uint8ClampedArray
48
+ : T extends Uint8Array
49
+ ? Uint8Array
50
+ : never;
51
+ /** Maps typed-array output leaves to narrow TS-compatible forms. */
52
+ export type TypedRet<T> = T extends BigInt64Array
53
+ ? ReturnType<typeof BigInt64Array.of>
54
+ : T extends BigUint64Array
55
+ ? ReturnType<typeof BigUint64Array.of>
56
+ : T extends Float32Array
57
+ ? ReturnType<typeof Float32Array.of>
58
+ : T extends Float64Array
59
+ ? ReturnType<typeof Float64Array.of>
60
+ : T extends Int16Array
61
+ ? ReturnType<typeof Int16Array.of>
62
+ : T extends Int32Array
63
+ ? ReturnType<typeof Int32Array.of>
64
+ : T extends Int8Array
65
+ ? ReturnType<typeof Int8Array.of>
66
+ : T extends Uint16Array
67
+ ? ReturnType<typeof Uint16Array.of>
68
+ : T extends Uint32Array
69
+ ? ReturnType<typeof Uint32Array.of>
70
+ : T extends Uint8ClampedArray
71
+ ? ReturnType<typeof Uint8ClampedArray.of>
72
+ : T extends Uint8Array
73
+ ? ReturnType<typeof Uint8Array.of>
74
+ : never;
75
+ /** Recursively adapts byte-carrying API input types. See {@link TypedArg}. */
76
+ export type TArg<T> =
77
+ | T
78
+ | ([TypedArg<T>] extends [never]
79
+ ? T extends (...args: infer A) => infer R
80
+ ? ((...args: { [K in keyof A]: TRet<A[K]> }) => TArg<R>) & {
81
+ [K in keyof T]: T[K] extends (...args: any) => any ? T[K] : TArg<T[K]>;
82
+ }
83
+ : T extends [infer A, ...infer R]
84
+ ? [TArg<A>, ...{ [K in keyof R]: TArg<R[K]> }]
85
+ : T extends readonly [infer A, ...infer R]
86
+ ? readonly [TArg<A>, ...{ [K in keyof R]: TArg<R[K]> }]
87
+ : T extends (infer A)[]
88
+ ? TArg<A>[]
89
+ : T extends readonly (infer A)[]
90
+ ? readonly TArg<A>[]
91
+ : T extends Promise<infer A>
92
+ ? Promise<TArg<A>>
93
+ : T extends object
94
+ ? { [K in keyof T]: TArg<T[K]> }
95
+ : T
96
+ : TypedArg<T>);
97
+ /** Recursively adapts byte-carrying API output types. See {@link TypedArg}. */
98
+ export type TRet<T> = T extends unknown
99
+ ? T &
100
+ ([TypedRet<T>] extends [never]
101
+ ? T extends (...args: infer A) => infer R
102
+ ? ((...args: { [K in keyof A]: TArg<A[K]> }) => TRet<R>) & {
103
+ [K in keyof T]: T[K] extends (...args: any) => any ? T[K] : TRet<T[K]>;
104
+ }
105
+ : T extends [infer A, ...infer R]
106
+ ? [TRet<A>, ...{ [K in keyof R]: TRet<R[K]> }]
107
+ : T extends readonly [infer A, ...infer R]
108
+ ? readonly [TRet<A>, ...{ [K in keyof R]: TRet<R[K]> }]
109
+ : T extends (infer A)[]
110
+ ? TRet<A>[]
111
+ : T extends readonly (infer A)[]
112
+ ? readonly TRet<A>[]
113
+ : T extends Promise<infer A>
114
+ ? Promise<TRet<A>>
115
+ : T extends object
116
+ ? { [K in keyof T]: TRet<T[K]> }
117
+ : T
118
+ : TypedRet<T>)
119
+ : never;
120
+ /**
121
+ * Validates that a value is a byte array.
122
+ * @param value - Value to validate.
123
+ * @param length - Optional exact byte length.
124
+ * @param title - Optional field name.
125
+ * @returns Original byte array.
126
+ * @example
127
+ * Reject non-byte input before passing data into curve code.
128
+ *
129
+ * ```ts
130
+ * abytes(new Uint8Array(1));
131
+ * ```
132
+ */
133
+ export const abytes = <T extends TArg<Uint8Array>>(value: T, length?: number, title?: string): T =>
134
+ abytes_(value, length, title) as T;
135
+ /**
136
+ * Validates that a value is a non-negative safe integer.
137
+ * @param n - Value to validate.
138
+ * @param title - Optional field name.
139
+ * @example
140
+ * Validate a numeric length before allocating buffers.
141
+ *
142
+ * ```ts
143
+ * anumber(1);
144
+ * ```
145
+ */
146
+ export const anumber: typeof anumber_ = anumber_;
147
+ /**
148
+ * Encodes bytes as lowercase hex.
149
+ * @param bytes - Bytes to encode.
150
+ * @returns Lowercase hex string.
151
+ * @example
152
+ * Serialize bytes as hex for logging or fixtures.
153
+ *
154
+ * ```ts
155
+ * bytesToHex(Uint8Array.of(1, 2, 3));
156
+ * ```
157
+ */
158
+ export const bytesToHex: typeof bytesToHex_ = bytesToHex_;
159
+ /**
160
+ * Concatenates byte arrays.
161
+ * @param arrays - Byte arrays to join.
162
+ * @returns Concatenated bytes.
163
+ * @example
164
+ * Join domain-separated chunks into one buffer.
165
+ *
166
+ * ```ts
167
+ * concatBytes(Uint8Array.of(1), Uint8Array.of(2));
168
+ * ```
169
+ */
170
+ export const concatBytes = (...arrays: TArg<Uint8Array[]>): TRet<Uint8Array> =>
171
+ concatBytes_(...arrays) as TRet<Uint8Array>;
172
+ /**
173
+ * Decodes lowercase or uppercase hex into bytes.
174
+ * @param hex - Hex string to decode.
175
+ * @returns Decoded bytes.
176
+ * @example
177
+ * Parse fixture hex into bytes before hashing.
178
+ *
179
+ * ```ts
180
+ * hexToBytes('0102');
181
+ * ```
182
+ */
183
+ export const hexToBytes = (hex: string): TRet<Uint8Array> => hexToBytes_(hex) as TRet<Uint8Array>;
184
+ /**
185
+ * Checks whether a value is a Uint8Array.
186
+ * @param a - Value to inspect.
187
+ * @returns `true` when `a` is a Uint8Array.
188
+ * @example
189
+ * Branch on byte input before decoding it.
190
+ *
191
+ * ```ts
192
+ * isBytes(new Uint8Array(1));
193
+ * ```
194
+ */
195
+ export const isBytes: typeof isBytes_ = isBytes_;
196
+ /**
197
+ * Reads random bytes from the platform CSPRNG.
198
+ * @param bytesLength - Number of random bytes to read.
199
+ * @returns Fresh random bytes.
200
+ * @example
201
+ * Generate a random seed for a keypair.
202
+ *
203
+ * ```ts
204
+ * randomBytes(2);
205
+ * ```
206
+ */
207
+ export const randomBytes = (bytesLength?: number): TRet<Uint8Array> =>
208
+ randomBytes_(bytesLength) as TRet<Uint8Array>;
22
209
  const _0n = /* @__PURE__ */ BigInt(0);
23
210
  const _1n = /* @__PURE__ */ BigInt(1);
24
211
 
212
+ /** Callable hash interface with metadata and optional extendable output support. */
25
213
  export type CHash = {
26
- (message: Uint8Array): Uint8Array;
214
+ /**
215
+ * Hash one message.
216
+ * @param message - Message bytes to hash.
217
+ * @returns Digest bytes.
218
+ */
219
+ (message: TArg<Uint8Array>): TRet<Uint8Array>;
220
+ /** Hash block length in bytes. */
27
221
  blockLen: number;
222
+ /** Default output length in bytes. */
28
223
  outputLen: number;
29
- create(opts?: { dkLen?: number }): any; // For shake
224
+ /** Whether `.create()` can be used as an XOF stream. */
225
+ canXOF: boolean;
226
+ /**
227
+ * Create one stateful hash or XOF instance, for example SHAKE with a custom output length.
228
+ * @param opts - Optional extendable-output configuration:
229
+ * - `dkLen` (optional): Optional output length for XOF-style hashes.
230
+ * @returns Hash instance.
231
+ */
232
+ create(opts?: { dkLen?: number }): any;
30
233
  };
31
- export type FHash = (message: Uint8Array) => Uint8Array;
234
+ /** Plain callable hash interface. */
235
+ export type FHash = (message: TArg<Uint8Array>) => TRet<Uint8Array>;
236
+ /** HMAC callback signature. */
237
+ export type HmacFn = (key: TArg<Uint8Array>, message: TArg<Uint8Array>) => TRet<Uint8Array>;
238
+ /**
239
+ * Validates that a flag is boolean.
240
+ * @param value - Value to validate.
241
+ * @param title - Optional field name.
242
+ * @returns Original value.
243
+ * @throws On wrong argument types. {@link TypeError}
244
+ * @example
245
+ * Reject non-boolean option flags early.
246
+ *
247
+ * ```ts
248
+ * abool(true);
249
+ * ```
250
+ */
32
251
  export function abool(value: boolean, title: string = ''): boolean {
33
252
  if (typeof value !== 'boolean') {
34
253
  const prefix = title && `"${title}" `;
35
- throw new Error(prefix + 'expected boolean, got type=' + typeof value);
254
+ throw new TypeError(prefix + 'expected boolean, got type=' + typeof value);
36
255
  }
37
256
  return value;
38
257
  }
39
258
 
40
- // Used in weierstrass, der
41
- function abignumber(n: number | bigint) {
259
+ /**
260
+ * Validates that a value is a non-negative bigint or safe integer.
261
+ * @param n - Value to validate.
262
+ * @returns The same validated value.
263
+ * @throws On wrong argument ranges or values. {@link RangeError}
264
+ * @example
265
+ * Validate one integer-like value before serializing it.
266
+ *
267
+ * ```ts
268
+ * abignumber(1n);
269
+ * ```
270
+ */
271
+ export function abignumber<T extends number | bigint>(n: T): T {
42
272
  if (typeof n === 'bigint') {
43
- if (!isPosBig(n)) throw new Error('positive bigint expected, got ' + n);
273
+ if (!isPosBig(n)) throw new RangeError('positive bigint expected, got ' + n);
44
274
  } else anumber(n);
45
275
  return n;
46
276
  }
47
277
 
278
+ /**
279
+ * Validates that a value is a safe integer.
280
+ * @param value - Integer to validate.
281
+ * @param title - Optional field name.
282
+ * @throws On wrong argument types. {@link TypeError}
283
+ * @throws On wrong argument ranges or values. {@link RangeError}
284
+ * @example
285
+ * Validate a window size before scalar arithmetic uses it.
286
+ *
287
+ * ```ts
288
+ * asafenumber(1);
289
+ * ```
290
+ */
48
291
  export function asafenumber(value: number, title: string = ''): void {
292
+ if (typeof value !== 'number') {
293
+ const prefix = title && `"${title}" `;
294
+ throw new TypeError(prefix + 'expected number, got type=' + typeof value);
295
+ }
49
296
  if (!Number.isSafeInteger(value)) {
50
297
  const prefix = title && `"${title}" `;
51
- throw new Error(prefix + 'expected safe integer, got type=' + typeof value);
298
+ throw new RangeError(prefix + 'expected safe integer, got ' + value);
52
299
  }
53
300
  }
54
301
 
302
+ /**
303
+ * Encodes a bigint into even-length big-endian hex.
304
+ * The historical "unpadded" name only means "no fixed-width field padding"; odd-length hex still
305
+ * gets one leading zero nibble so the result always represents whole bytes.
306
+ * @param num - Number to encode.
307
+ * @returns Big-endian hex string.
308
+ * @throws On wrong argument ranges or values. {@link RangeError}
309
+ * @example
310
+ * Encode a scalar into hex without a `0x` prefix.
311
+ *
312
+ * ```ts
313
+ * numberToHexUnpadded(255n);
314
+ * ```
315
+ */
55
316
  export function numberToHexUnpadded(num: number | bigint): string {
56
317
  const hex = abignumber(num).toString(16);
57
318
  return hex.length & 1 ? '0' + hex : hex;
58
319
  }
59
320
 
321
+ /**
322
+ * Parses a big-endian hex string into bigint.
323
+ * Accepts odd-length hex through the native `BigInt('0x' + hex)` parser and currently surfaces the
324
+ * same native `SyntaxError` for malformed hex instead of wrapping it in a library-specific error.
325
+ * @param hex - Hex string without `0x`.
326
+ * @returns Parsed bigint value.
327
+ * @throws On wrong argument types. {@link TypeError}
328
+ * @example
329
+ * Parse a scalar from fixture hex.
330
+ *
331
+ * ```ts
332
+ * hexToNumber('ff');
333
+ * ```
334
+ */
60
335
  export function hexToNumber(hex: string): bigint {
61
- if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);
336
+ if (typeof hex !== 'string') throw new TypeError('hex string expected, got ' + typeof hex);
62
337
  return hex === '' ? _0n : BigInt('0x' + hex); // Big Endian
63
338
  }
64
339
 
65
340
  // BE: Big Endian, LE: Little Endian
66
- export function bytesToNumberBE(bytes: Uint8Array): bigint {
341
+ /**
342
+ * Parses big-endian bytes into bigint.
343
+ * @param bytes - Bytes in big-endian order.
344
+ * @returns Parsed bigint value.
345
+ * @throws On wrong argument types. {@link TypeError}
346
+ * @example
347
+ * Read a scalar encoded in network byte order.
348
+ *
349
+ * ```ts
350
+ * bytesToNumberBE(Uint8Array.of(1, 0));
351
+ * ```
352
+ */
353
+ export function bytesToNumberBE(bytes: TArg<Uint8Array>): bigint {
67
354
  return hexToNumber(bytesToHex_(bytes));
68
355
  }
69
- export function bytesToNumberLE(bytes: Uint8Array): bigint {
356
+ /**
357
+ * Parses little-endian bytes into bigint.
358
+ * @param bytes - Bytes in little-endian order.
359
+ * @returns Parsed bigint value.
360
+ * @throws On wrong argument types. {@link TypeError}
361
+ * @example
362
+ * Read a scalar encoded in little-endian form.
363
+ *
364
+ * ```ts
365
+ * bytesToNumberLE(Uint8Array.of(1, 0));
366
+ * ```
367
+ */
368
+ export function bytesToNumberLE(bytes: TArg<Uint8Array>): bigint {
70
369
  return hexToNumber(bytesToHex_(copyBytes(abytes_(bytes)).reverse()));
71
370
  }
72
371
 
73
- export function numberToBytesBE(n: number | bigint, len: number): Uint8Array {
74
- anumber(len);
372
+ /**
373
+ * Encodes a bigint into fixed-length big-endian bytes.
374
+ * @param n - Number to encode.
375
+ * @param len - Output length in bytes. Must be greater than zero.
376
+ * @returns Big-endian byte array.
377
+ * @throws On wrong argument ranges or values. {@link RangeError}
378
+ * @example
379
+ * Serialize a scalar into a 32-byte field element.
380
+ *
381
+ * ```ts
382
+ * numberToBytesBE(255n, 2);
383
+ * ```
384
+ */
385
+ export function numberToBytesBE(n: number | bigint, len: number): TRet<Uint8Array> {
386
+ anumber_(len);
387
+ if (len === 0) throw new RangeError('zero length');
75
388
  n = abignumber(n);
76
- const res = hexToBytes_(n.toString(16).padStart(len * 2, '0'));
77
- if (res.length !== len) throw new Error('number too large');
78
- return res;
389
+ const hex = n.toString(16);
390
+ // Detect overflow before hex parsing so oversized values don't leak the shared odd-hex error.
391
+ if (hex.length > len * 2) throw new RangeError('number too large');
392
+ return hexToBytes_(hex.padStart(len * 2, '0')) as TRet<Uint8Array>;
79
393
  }
80
- export function numberToBytesLE(n: number | bigint, len: number): Uint8Array {
81
- return numberToBytesBE(n, len).reverse();
394
+ /**
395
+ * Encodes a bigint into fixed-length little-endian bytes.
396
+ * @param n - Number to encode.
397
+ * @param len - Output length in bytes.
398
+ * @returns Little-endian byte array.
399
+ * @throws On wrong argument ranges or values. {@link RangeError}
400
+ * @example
401
+ * Serialize a scalar for little-endian protocols.
402
+ *
403
+ * ```ts
404
+ * numberToBytesLE(255n, 2);
405
+ * ```
406
+ */
407
+ export function numberToBytesLE(n: number | bigint, len: number): TRet<Uint8Array> {
408
+ return numberToBytesBE(n, len).reverse() as TRet<Uint8Array>;
82
409
  }
83
410
  // Unpadded, rarely used
84
- export function numberToVarBytesBE(n: number | bigint): Uint8Array {
85
- return hexToBytes_(numberToHexUnpadded(abignumber(n)));
411
+ /**
412
+ * Encodes a bigint into variable-length big-endian bytes.
413
+ * @param n - Number to encode.
414
+ * @returns Variable-length big-endian bytes.
415
+ * @throws On wrong argument ranges or values. {@link RangeError}
416
+ * @example
417
+ * Serialize a bigint without fixed-width padding.
418
+ *
419
+ * ```ts
420
+ * numberToVarBytesBE(255n);
421
+ * ```
422
+ */
423
+ export function numberToVarBytesBE(n: number | bigint): TRet<Uint8Array> {
424
+ return hexToBytes_(numberToHexUnpadded(abignumber(n))) as TRet<Uint8Array>;
86
425
  }
87
426
 
88
427
  // Compares 2 u8a-s in kinda constant time
89
- export function equalBytes(a: Uint8Array, b: Uint8Array): boolean {
428
+ /**
429
+ * Compares two byte arrays in constant-ish time.
430
+ * @param a - Left byte array.
431
+ * @param b - Right byte array.
432
+ * @returns `true` when bytes match.
433
+ * @example
434
+ * Compare two encoded points without early exit.
435
+ *
436
+ * ```ts
437
+ * equalBytes(Uint8Array.of(1), Uint8Array.of(1));
438
+ * ```
439
+ */
440
+ export function equalBytes(a: TArg<Uint8Array>, b: TArg<Uint8Array>): boolean {
441
+ a = abytes(a);
442
+ b = abytes(b);
90
443
  if (a.length !== b.length) return false;
91
444
  let diff = 0;
92
445
  for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];
@@ -96,39 +449,83 @@ export function equalBytes(a: Uint8Array, b: Uint8Array): boolean {
96
449
  /**
97
450
  * Copies Uint8Array. We can't use u8a.slice(), because u8a can be Buffer,
98
451
  * and Buffer#slice creates mutable copy. Never use Buffers!
452
+ * @param bytes - Bytes to copy.
453
+ * @returns Detached copy.
454
+ * @example
455
+ * Make an isolated copy before mutating serialized bytes.
456
+ *
457
+ * ```ts
458
+ * copyBytes(Uint8Array.of(1, 2, 3));
459
+ * ```
99
460
  */
100
- export function copyBytes(bytes: Uint8Array): Uint8Array {
101
- return Uint8Array.from(bytes);
461
+ export function copyBytes(bytes: TArg<Uint8Array>): TRet<Uint8Array> {
462
+ // `Uint8Array.from(...)` would also accept arrays / other typed arrays. Keep this helper strict
463
+ // because callers use it at byte-validation boundaries before mutating the detached copy.
464
+ return Uint8Array.from(abytes(bytes)) as TRet<Uint8Array>;
102
465
  }
103
466
 
104
467
  /**
105
468
  * Decodes 7-bit ASCII string to Uint8Array, throws on non-ascii symbols
106
469
  * Should be safe to use for things expected to be ASCII.
107
470
  * Returns exact same result as `TextEncoder` for ASCII or throws.
471
+ * @param ascii - ASCII input text.
472
+ * @returns Encoded bytes.
473
+ * @throws On wrong argument types. {@link TypeError}
474
+ * @example
475
+ * Encode an ASCII domain-separation tag.
476
+ *
477
+ * ```ts
478
+ * asciiToBytes('ABC');
479
+ * ```
108
480
  */
109
- export function asciiToBytes(ascii: string): Uint8Array {
481
+ export function asciiToBytes(ascii: string): TRet<Uint8Array> {
482
+ if (typeof ascii !== 'string') throw new TypeError('ascii string expected, got ' + typeof ascii);
110
483
  return Uint8Array.from(ascii, (c, i) => {
111
484
  const charCode = c.charCodeAt(0);
112
485
  if (c.length !== 1 || charCode > 127) {
113
- throw new Error(
486
+ throw new RangeError(
114
487
  `string contains non-ASCII character "${ascii[i]}" with code ${charCode} at position ${i}`
115
488
  );
116
489
  }
117
490
  return charCode;
118
- });
491
+ }) as TRet<Uint8Array>;
119
492
  }
120
493
 
121
- // Is positive bigint
494
+ // Historical name: this accepts non-negative bigints, including zero.
122
495
  const isPosBig = (n: bigint) => typeof n === 'bigint' && _0n <= n;
123
496
 
497
+ /**
498
+ * Checks whether a bigint lies inside a half-open range.
499
+ * @param n - Candidate value.
500
+ * @param min - Inclusive lower bound.
501
+ * @param max - Exclusive upper bound.
502
+ * @returns `true` when the value is inside the range.
503
+ * @example
504
+ * Check whether a candidate scalar fits the field order.
505
+ *
506
+ * ```ts
507
+ * inRange(2n, 1n, 3n);
508
+ * ```
509
+ */
124
510
  export function inRange(n: bigint, min: bigint, max: bigint): boolean {
125
511
  return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;
126
512
  }
127
513
 
128
514
  /**
129
- * Asserts min <= n < max. NOTE: It's < max and not <= max.
515
+ * Asserts `min <= n < max`. NOTE: upper bound is exclusive.
516
+ * @param title - Value label for error messages.
517
+ * @param n - Candidate value.
518
+ * @param min - Inclusive lower bound.
519
+ * @param max - Exclusive upper bound.
520
+ * Wrong-type inputs are not separated from out-of-range values here: they still flow through the
521
+ * shared `RangeError` path because this is only a throwing wrapper around `inRange(...)`.
522
+ * @throws On wrong argument ranges or values. {@link RangeError}
130
523
  * @example
131
- * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n)
524
+ * Assert that a bigint stays within one half-open range.
525
+ *
526
+ * ```ts
527
+ * aInRange('x', 2n, 1n, 256n);
528
+ * ```
132
529
  */
133
530
  export function aInRange(title: string, n: bigint, min: bigint, max: bigint): void {
134
531
  // Why min <= n < max and not a (min < n < max) OR b (min <= n <= max)?
@@ -137,7 +534,7 @@ export function aInRange(title: string, n: bigint, min: bigint, max: bigint): vo
137
534
  // - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)`
138
535
  // - our way is the cleanest: `inRange('x', x, 0n, P)
139
536
  if (!inRange(n, min, max))
140
- throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n);
537
+ throw new RangeError('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n);
141
538
  }
142
539
 
143
540
  // Bit operations
@@ -146,8 +543,20 @@ export function aInRange(title: string, n: bigint, min: bigint, max: bigint): vo
146
543
  * Calculates amount of bits in a bigint.
147
544
  * Same as `n.toString(2).length`
148
545
  * TODO: merge with nLength in modular
546
+ * @param n - Value to inspect.
547
+ * @returns Bit length.
548
+ * @throws If the value is negative. {@link Error}
549
+ * @example
550
+ * Measure the bit length of a scalar before serialization.
551
+ *
552
+ * ```ts
553
+ * bitLen(8n);
554
+ * ```
149
555
  */
150
556
  export function bitLen(n: bigint): number {
557
+ // Size callers in this repo only use non-negative orders / scalars, so negative inputs are a
558
+ // contract bug and must not silently collapse to zero bits.
559
+ if (n < _0n) throw new Error('expected non-negative bigint, got ' + n);
151
560
  let len;
152
561
  for (len = 0; n > _0n; n >>= _1n, len += 1);
153
562
  return len;
@@ -157,6 +566,17 @@ export function bitLen(n: bigint): number {
157
566
  * Gets single bit at position.
158
567
  * NOTE: first bit position is 0 (same as arrays)
159
568
  * Same as `!!+Array.from(n.toString(2)).reverse()[pos]`
569
+ * @param n - Source value.
570
+ * @param pos - Bit position. Negative positions are passed through to raw
571
+ * bigint shift semantics; because the mask is built as `1n << pos`,
572
+ * they currently collapse to `0n` and make the helper a no-op.
573
+ * @returns Bit as bigint.
574
+ * @example
575
+ * Gets single bit at position.
576
+ *
577
+ * ```ts
578
+ * bitGet(5n, 0);
579
+ * ```
160
580
  */
161
581
  export function bitGet(n: bigint, pos: number): bigint {
162
582
  return (n >> BigInt(pos)) & _1n;
@@ -164,52 +584,92 @@ export function bitGet(n: bigint, pos: number): bigint {
164
584
 
165
585
  /**
166
586
  * Sets single bit at position.
587
+ * @param n - Source value.
588
+ * @param pos - Bit position. Negative positions are passed through to raw bigint shift semantics,
589
+ * so they currently behave like left shifts.
590
+ * @param value - Whether the bit should be set.
591
+ * @returns Updated bigint.
592
+ * @example
593
+ * Sets single bit at position.
594
+ *
595
+ * ```ts
596
+ * bitSet(0n, 1, true);
597
+ * ```
167
598
  */
168
599
  export function bitSet(n: bigint, pos: number, value: boolean): bigint {
169
- return n | ((value ? _1n : _0n) << BigInt(pos));
600
+ const mask = _1n << BigInt(pos);
601
+ // Clearing needs AND-not here; OR with zero leaves an already-set bit untouched.
602
+ return value ? n | mask : n & ~mask;
170
603
  }
171
604
 
172
605
  /**
173
606
  * Calculate mask for N bits. Not using ** operator with bigints because of old engines.
174
607
  * Same as BigInt(`0b${Array(i).fill('1').join('')}`)
608
+ * @param n - Number of bits. Negative widths are currently passed through to raw bigint shift
609
+ * semantics and therefore produce `-1n`.
610
+ * @returns Bitmask value.
611
+ * @example
612
+ * Calculate mask for N bits.
613
+ *
614
+ * ```ts
615
+ * bitMask(4);
616
+ * ```
175
617
  */
176
618
  export const bitMask = (n: number): bigint => (_1n << BigInt(n)) - _1n;
177
619
 
178
620
  // DRBG
179
621
 
180
- type Pred<T> = (v: Uint8Array) => T | undefined;
622
+ type Pred<T> = (v: TArg<Uint8Array>) => T | undefined;
181
623
  /**
182
624
  * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
183
- * @returns function that will call DRBG until 2nd arg returns something meaningful
625
+ * @param hashLen - Hash output size in bytes. Callers are expected to pass a positive length; `0`
626
+ * is not rejected here and would make the internal generate loop non-progressing.
627
+ * @param qByteLen - Requested output size in bytes. Callers are expected to pass a positive length.
628
+ * @param hmacFn - HMAC implementation.
629
+ * @returns Function that will call DRBG until the predicate returns anything
630
+ * other than `undefined`.
631
+ * @throws On wrong argument types. {@link TypeError}
184
632
  * @example
185
- * const drbg = createHmacDRBG<Key>(32, 32, hmac);
186
- * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined
633
+ * Build a deterministic nonce generator for RFC6979-style signing.
634
+ *
635
+ * ```ts
636
+ * import { createHmacDrbg } from '@noble/curves/utils.js';
637
+ * import { hmac } from '@noble/hashes/hmac.js';
638
+ * import { sha256 } from '@noble/hashes/sha2.js';
639
+ * const drbg = createHmacDrbg(32, 32, (key, msg) => hmac(sha256, key, msg));
640
+ * const seed = new Uint8Array(32);
641
+ * drbg(seed, (bytes) => bytes);
642
+ * ```
187
643
  */
188
644
  export function createHmacDrbg<T>(
189
645
  hashLen: number,
190
646
  qByteLen: number,
191
- hmacFn: (key: Uint8Array, message: Uint8Array) => Uint8Array
192
- ): (seed: Uint8Array, predicate: Pred<T>) => T {
193
- anumber(hashLen, 'hashLen');
194
- anumber(qByteLen, 'qByteLen');
195
- if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function');
196
- const u8n = (len: number): Uint8Array => new Uint8Array(len); // creates Uint8Array
647
+ hmacFn: TArg<HmacFn>
648
+ ): TRet<(seed: Uint8Array, predicate: Pred<T>) => T> {
649
+ anumber_(hashLen, 'hashLen');
650
+ anumber_(qByteLen, 'qByteLen');
651
+ if (typeof hmacFn !== 'function') throw new TypeError('hmacFn must be a function');
652
+ // creates Uint8Array
653
+ const u8n = (len: number): TRet<Uint8Array> => new Uint8Array(len) as TRet<Uint8Array>;
197
654
  const NULL = Uint8Array.of();
198
655
  const byte0 = Uint8Array.of(0x00);
199
656
  const byte1 = Uint8Array.of(0x01);
200
657
  const _maxDrbgIters = 1000;
201
658
 
202
- // Step B, Step C: set hashLen to 8*ceil(hlen/8)
203
- let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
204
- let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same
659
+ // Step B, Step C: set hashLen to 8*ceil(hlen/8).
660
+ // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 signatures.
661
+ let v: Uint8Array = u8n(hashLen);
662
+ // Steps B and C of RFC6979 3.2.
663
+ let k: Uint8Array = u8n(hashLen);
205
664
  let i = 0; // Iterations counter, will throw when over 1000
206
665
  const reset = () => {
207
666
  v.fill(1);
208
667
  k.fill(0);
209
668
  i = 0;
210
669
  };
211
- const h = (...msgs: Uint8Array[]) => hmacFn(k, concatBytes_(v, ...msgs)); // hmac(k)(v, ...values)
212
- const reseed = (seed: Uint8Array = NULL) => {
670
+ // hmac(k)(v, ...values)
671
+ const h = (...msgs: TArg<Uint8Array[]>) => (hmacFn as HmacFn)(k, concatBytes(v, ...msgs));
672
+ const reseed = (seed: TArg<Uint8Array> = NULL) => {
213
673
  // HMAC-DRBG reseed() function. Steps D-G
214
674
  k = h(byte0, seed); // k = hmac(k || v || 0x00 || seed)
215
675
  v = h(); // v = hmac(k || v)
@@ -228,32 +688,55 @@ export function createHmacDrbg<T>(
228
688
  out.push(sl);
229
689
  len += v.length;
230
690
  }
231
- return concatBytes_(...out);
691
+ return concatBytes(...out);
232
692
  };
233
- const genUntil = (seed: Uint8Array, pred: Pred<T>): T => {
693
+ const genUntil = (seed: TArg<Uint8Array>, pred: TArg<Pred<T>>): T => {
234
694
  reset();
235
695
  reseed(seed); // Steps D-G
236
- let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1]
237
- while (!(res = pred(gen()))) reseed();
696
+ let res: T | undefined = undefined; // Step H: grind until the predicate accepts a candidate.
697
+ // Falsy values like 0 are valid outputs.
698
+ while ((res = (pred as Pred<T>)(gen())) === undefined) reseed();
238
699
  reset();
239
700
  return res;
240
701
  };
241
- return genUntil;
702
+ return genUntil as TRet<(seed: Uint8Array, predicate: Pred<T>) => T>;
242
703
  }
243
704
 
705
+ /**
706
+ * Validates declared required and optional field types on a plain object.
707
+ * Extra keys are intentionally ignored because many callers validate only the subset they use from
708
+ * richer option bags or runtime objects.
709
+ * @param object - Object to validate.
710
+ * @param fields - Required field types.
711
+ * @param optFields - Optional field types.
712
+ * @throws On wrong argument types. {@link TypeError}
713
+ * @example
714
+ * Check user options before building a curve helper.
715
+ *
716
+ * ```ts
717
+ * validateObject({ flag: true }, { flag: 'boolean' });
718
+ * ```
719
+ */
244
720
  export function validateObject(
245
721
  object: Record<string, any>,
246
722
  fields: Record<string, string> = {},
247
723
  optFields: Record<string, string> = {}
248
724
  ): void {
249
- if (!object || typeof object !== 'object') throw new Error('expected valid options object');
725
+ if (Object.prototype.toString.call(object) !== '[object Object]')
726
+ throw new TypeError('expected valid options object');
250
727
  type Item = keyof typeof object;
251
728
  function checkField(fieldName: Item, expectedType: string, isOpt: boolean) {
729
+ // Config/data fields must be explicit own properties, but runtime objects such as Field
730
+ // instances intentionally satisfy required method slots via their shared prototype.
731
+ if (!isOpt && expectedType !== 'function' && !Object.hasOwn(object, fieldName))
732
+ throw new TypeError(`param "${fieldName}" is invalid: expected own property`);
252
733
  const val = object[fieldName];
253
734
  if (isOpt && val === undefined) return;
254
735
  const current = typeof val;
255
736
  if (current !== expectedType || val === null)
256
- throw new Error(`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`);
737
+ throw new TypeError(
738
+ `param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`
739
+ );
257
740
  }
258
741
  const iter = (f: typeof fields, isOpt: boolean) =>
259
742
  Object.entries(f).forEach(([k, v]) => checkField(k, v, isOpt));
@@ -262,38 +745,44 @@ export function validateObject(
262
745
  }
263
746
 
264
747
  /**
265
- * throws not implemented error
748
+ * Throws not implemented error.
749
+ * @returns Never returns.
750
+ * @throws If the unfinished code path is reached. {@link Error}
751
+ * @example
752
+ * Surface the placeholder error from an unfinished code path.
753
+ *
754
+ * ```ts
755
+ * try {
756
+ * notImplemented();
757
+ * } catch {}
758
+ * ```
266
759
  */
267
760
  export const notImplemented = (): never => {
268
761
  throw new Error('not implemented');
269
762
  };
270
763
 
271
- /**
272
- * Memoizes (caches) computation result.
273
- * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed.
274
- */
275
- export function memoized<T extends object, R, O extends any[]>(
276
- fn: (arg: T, ...args: O) => R
277
- ): (arg: T, ...args: O) => R {
278
- const map = new WeakMap<T, R>();
279
- return (arg: T, ...args: O): R => {
280
- const val = map.get(arg);
281
- if (val !== undefined) return val;
282
- const computed = fn(arg, ...args);
283
- map.set(arg, computed);
284
- return computed;
285
- };
286
- }
287
-
764
+ /** Generic keygen/getPublicKey interface shared by curve helpers. */
288
765
  export interface CryptoKeys {
766
+ /** Public byte lengths for keys and optional seeds. */
289
767
  lengths: { seed?: number; public?: number; secret?: number };
768
+ /**
769
+ * Generate one secret/public keypair.
770
+ * @param seed - Optional seed bytes for deterministic key generation.
771
+ * @returns Fresh secret/public keypair.
772
+ */
290
773
  keygen: (seed?: Uint8Array) => { secretKey: Uint8Array; publicKey: Uint8Array };
774
+ /**
775
+ * Derive one public key from a secret key.
776
+ * @param secretKey - Secret key bytes.
777
+ * @returns Public key bytes.
778
+ */
291
779
  getPublicKey: (secretKey: Uint8Array) => Uint8Array;
292
780
  }
293
781
 
294
782
  /** Generic interface for signatures. Has keygen, sign and verify. */
295
783
  export interface Signer extends CryptoKeys {
296
784
  // Interfaces are fun. We cannot just add new fields without copying old ones.
785
+ /** Public byte lengths for keys, signatures, and optional signing randomness. */
297
786
  lengths: {
298
787
  seed?: number;
299
788
  public?: number;
@@ -301,6 +790,19 @@ export interface Signer extends CryptoKeys {
301
790
  signRand?: number;
302
791
  signature?: number;
303
792
  };
793
+ /**
794
+ * Sign one message.
795
+ * @param msg - Message bytes to sign.
796
+ * @param secretKey - Secret key bytes.
797
+ * @returns Signature bytes.
798
+ */
304
799
  sign: (msg: Uint8Array, secretKey: Uint8Array) => Uint8Array;
800
+ /**
801
+ * Verify one signature.
802
+ * @param sig - Signature bytes.
803
+ * @param msg - Signed message bytes.
804
+ * @param publicKey - Public key bytes.
805
+ * @returns `true` when the signature is valid.
806
+ */
305
807
  verify: (sig: Uint8Array, msg: Uint8Array, publicKey: Uint8Array) => boolean;
306
808
  }