@noble/curves 1.9.5 → 2.0.0-beta.1

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 (211) hide show
  1. package/README.md +267 -421
  2. package/abstract/bls.d.ts +49 -111
  3. package/abstract/bls.d.ts.map +1 -1
  4. package/abstract/bls.js +108 -152
  5. package/abstract/bls.js.map +1 -1
  6. package/abstract/curve.d.ts +7 -48
  7. package/abstract/curve.d.ts.map +1 -1
  8. package/abstract/curve.js +22 -47
  9. package/abstract/curve.js.map +1 -1
  10. package/abstract/edwards.d.ts +17 -68
  11. package/abstract/edwards.d.ts.map +1 -1
  12. package/abstract/edwards.js +98 -175
  13. package/abstract/edwards.js.map +1 -1
  14. package/abstract/fft.js +14 -27
  15. package/abstract/fft.js.map +1 -1
  16. package/abstract/hash-to-curve.d.ts +11 -24
  17. package/abstract/hash-to-curve.d.ts.map +1 -1
  18. package/abstract/hash-to-curve.js +30 -35
  19. package/abstract/hash-to-curve.js.map +1 -1
  20. package/abstract/modular.d.ts +5 -17
  21. package/abstract/modular.d.ts.map +1 -1
  22. package/abstract/modular.js +166 -167
  23. package/abstract/modular.js.map +1 -1
  24. package/abstract/montgomery.d.ts +4 -9
  25. package/abstract/montgomery.d.ts.map +1 -1
  26. package/abstract/montgomery.js +17 -20
  27. package/abstract/montgomery.js.map +1 -1
  28. package/abstract/oprf.d.ts +282 -0
  29. package/abstract/oprf.d.ts.map +1 -0
  30. package/abstract/oprf.js +297 -0
  31. package/abstract/oprf.js.map +1 -0
  32. package/abstract/poseidon.js +20 -24
  33. package/abstract/poseidon.js.map +1 -1
  34. package/abstract/tower.d.ts +9 -7
  35. package/abstract/tower.d.ts.map +1 -1
  36. package/abstract/tower.js +600 -364
  37. package/abstract/tower.js.map +1 -1
  38. package/abstract/weierstrass.d.ts +12 -145
  39. package/abstract/weierstrass.d.ts.map +1 -1
  40. package/abstract/weierstrass.js +153 -377
  41. package/abstract/weierstrass.js.map +1 -1
  42. package/bls12-381.d.ts +2 -2
  43. package/bls12-381.d.ts.map +1 -1
  44. package/bls12-381.js +174 -216
  45. package/bls12-381.js.map +1 -1
  46. package/bn254.d.ts +58 -10
  47. package/bn254.d.ts.map +1 -1
  48. package/bn254.js +70 -130
  49. package/bn254.js.map +1 -1
  50. package/ed25519.d.ts +12 -31
  51. package/ed25519.d.ts.map +1 -1
  52. package/ed25519.js +104 -146
  53. package/ed25519.js.map +1 -1
  54. package/ed448.d.ts +14 -33
  55. package/ed448.d.ts.map +1 -1
  56. package/ed448.js +105 -132
  57. package/ed448.js.map +1 -1
  58. package/index.js +1 -1
  59. package/misc.d.ts +10 -14
  60. package/misc.d.ts.map +1 -1
  61. package/misc.js +51 -60
  62. package/misc.js.map +1 -1
  63. package/nist.d.ts +11 -14
  64. package/nist.d.ts.map +1 -1
  65. package/nist.js +46 -55
  66. package/nist.js.map +1 -1
  67. package/package.json +9 -224
  68. package/secp256k1.d.ts +7 -23
  69. package/secp256k1.d.ts.map +1 -1
  70. package/secp256k1.js +72 -83
  71. package/secp256k1.js.map +1 -1
  72. package/src/abstract/bls.ts +197 -344
  73. package/src/abstract/curve.ts +10 -83
  74. package/src/abstract/edwards.ts +96 -223
  75. package/src/abstract/hash-to-curve.ts +32 -45
  76. package/src/abstract/modular.ts +144 -130
  77. package/src/abstract/montgomery.ts +21 -22
  78. package/src/abstract/oprf.ts +600 -0
  79. package/src/abstract/tower.ts +627 -382
  80. package/src/abstract/weierstrass.ts +101 -482
  81. package/src/bls12-381.ts +148 -176
  82. package/src/bn254.ts +67 -122
  83. package/src/ed25519.ts +65 -118
  84. package/src/ed448.ts +63 -113
  85. package/src/index.ts +1 -1
  86. package/src/misc.ts +66 -49
  87. package/src/nist.ts +48 -57
  88. package/src/secp256k1.ts +56 -88
  89. package/src/utils.ts +41 -61
  90. package/src/webcrypto.ts +362 -0
  91. package/utils.d.ts +28 -19
  92. package/utils.d.ts.map +1 -1
  93. package/utils.js +45 -121
  94. package/utils.js.map +1 -1
  95. package/webcrypto.d.ts +47 -0
  96. package/webcrypto.d.ts.map +1 -0
  97. package/webcrypto.js +231 -0
  98. package/webcrypto.js.map +1 -0
  99. package/esm/_shortw_utils.d.ts +0 -19
  100. package/esm/_shortw_utils.d.ts.map +0 -1
  101. package/esm/_shortw_utils.js +0 -16
  102. package/esm/_shortw_utils.js.map +0 -1
  103. package/esm/abstract/bls.d.ts +0 -190
  104. package/esm/abstract/bls.d.ts.map +0 -1
  105. package/esm/abstract/bls.js +0 -408
  106. package/esm/abstract/bls.js.map +0 -1
  107. package/esm/abstract/curve.d.ts +0 -231
  108. package/esm/abstract/curve.d.ts.map +0 -1
  109. package/esm/abstract/curve.js +0 -465
  110. package/esm/abstract/curve.js.map +0 -1
  111. package/esm/abstract/edwards.d.ts +0 -237
  112. package/esm/abstract/edwards.d.ts.map +0 -1
  113. package/esm/abstract/edwards.js +0 -632
  114. package/esm/abstract/edwards.js.map +0 -1
  115. package/esm/abstract/fft.d.ts +0 -122
  116. package/esm/abstract/fft.d.ts.map +0 -1
  117. package/esm/abstract/fft.js +0 -425
  118. package/esm/abstract/fft.js.map +0 -1
  119. package/esm/abstract/hash-to-curve.d.ts +0 -102
  120. package/esm/abstract/hash-to-curve.d.ts.map +0 -1
  121. package/esm/abstract/hash-to-curve.js +0 -203
  122. package/esm/abstract/hash-to-curve.js.map +0 -1
  123. package/esm/abstract/modular.d.ts +0 -171
  124. package/esm/abstract/modular.d.ts.map +0 -1
  125. package/esm/abstract/modular.js +0 -530
  126. package/esm/abstract/modular.js.map +0 -1
  127. package/esm/abstract/montgomery.d.ts +0 -30
  128. package/esm/abstract/montgomery.d.ts.map +0 -1
  129. package/esm/abstract/montgomery.js +0 -157
  130. package/esm/abstract/montgomery.js.map +0 -1
  131. package/esm/abstract/poseidon.d.ts +0 -68
  132. package/esm/abstract/poseidon.d.ts.map +0 -1
  133. package/esm/abstract/poseidon.js +0 -296
  134. package/esm/abstract/poseidon.js.map +0 -1
  135. package/esm/abstract/tower.d.ts +0 -93
  136. package/esm/abstract/tower.d.ts.map +0 -1
  137. package/esm/abstract/tower.js +0 -502
  138. package/esm/abstract/tower.js.map +0 -1
  139. package/esm/abstract/utils.d.ts +0 -5
  140. package/esm/abstract/utils.d.ts.map +0 -1
  141. package/esm/abstract/utils.js +0 -7
  142. package/esm/abstract/utils.js.map +0 -1
  143. package/esm/abstract/weierstrass.d.ts +0 -412
  144. package/esm/abstract/weierstrass.d.ts.map +0 -1
  145. package/esm/abstract/weierstrass.js +0 -1428
  146. package/esm/abstract/weierstrass.js.map +0 -1
  147. package/esm/bls12-381.d.ts +0 -16
  148. package/esm/bls12-381.d.ts.map +0 -1
  149. package/esm/bls12-381.js +0 -738
  150. package/esm/bls12-381.js.map +0 -1
  151. package/esm/bn254.d.ts +0 -18
  152. package/esm/bn254.d.ts.map +0 -1
  153. package/esm/bn254.js +0 -246
  154. package/esm/bn254.js.map +0 -1
  155. package/esm/ed25519.d.ts +0 -106
  156. package/esm/ed25519.d.ts.map +0 -1
  157. package/esm/ed25519.js +0 -467
  158. package/esm/ed25519.js.map +0 -1
  159. package/esm/ed448.d.ts +0 -101
  160. package/esm/ed448.d.ts.map +0 -1
  161. package/esm/ed448.js +0 -448
  162. package/esm/ed448.js.map +0 -1
  163. package/esm/index.d.ts +0 -2
  164. package/esm/index.d.ts.map +0 -1
  165. package/esm/index.js +0 -17
  166. package/esm/index.js.map +0 -1
  167. package/esm/jubjub.d.ts +0 -12
  168. package/esm/jubjub.d.ts.map +0 -1
  169. package/esm/jubjub.js +0 -12
  170. package/esm/jubjub.js.map +0 -1
  171. package/esm/misc.d.ts +0 -19
  172. package/esm/misc.d.ts.map +0 -1
  173. package/esm/misc.js +0 -109
  174. package/esm/misc.js.map +0 -1
  175. package/esm/nist.d.ts +0 -21
  176. package/esm/nist.d.ts.map +0 -1
  177. package/esm/nist.js +0 -132
  178. package/esm/nist.js.map +0 -1
  179. package/esm/p256.d.ts +0 -16
  180. package/esm/p256.d.ts.map +0 -1
  181. package/esm/p256.js +0 -16
  182. package/esm/p256.js.map +0 -1
  183. package/esm/p384.d.ts +0 -16
  184. package/esm/p384.d.ts.map +0 -1
  185. package/esm/p384.js +0 -16
  186. package/esm/p384.js.map +0 -1
  187. package/esm/p521.d.ts +0 -16
  188. package/esm/p521.d.ts.map +0 -1
  189. package/esm/p521.js +0 -16
  190. package/esm/p521.js.map +0 -1
  191. package/esm/package.json +0 -4
  192. package/esm/pasta.d.ts +0 -10
  193. package/esm/pasta.d.ts.map +0 -1
  194. package/esm/pasta.js +0 -10
  195. package/esm/pasta.js.map +0 -1
  196. package/esm/secp256k1.d.ts +0 -89
  197. package/esm/secp256k1.d.ts.map +0 -1
  198. package/esm/secp256k1.js +0 -292
  199. package/esm/secp256k1.js.map +0 -1
  200. package/esm/utils.d.ts +0 -110
  201. package/esm/utils.d.ts.map +0 -1
  202. package/esm/utils.js +0 -322
  203. package/esm/utils.js.map +0 -1
  204. package/src/_shortw_utils.ts +0 -21
  205. package/src/abstract/utils.ts +0 -7
  206. package/src/jubjub.ts +0 -12
  207. package/src/p256.ts +0 -15
  208. package/src/p384.ts +0 -15
  209. package/src/p521.ts +0 -15
  210. package/src/package.json +0 -3
  211. package/src/pasta.ts +0 -9
@@ -26,11 +26,11 @@
26
26
  */
27
27
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
28
28
  import { hmac as nobleHmac } from '@noble/hashes/hmac.js';
29
- import { ahash } from '@noble/hashes/utils';
29
+ import { ahash } from '@noble/hashes/utils.js';
30
30
  import {
31
31
  _validateObject,
32
- _abool2 as abool,
33
- _abytes2 as abytes,
32
+ abool,
33
+ abytes,
34
34
  aInRange,
35
35
  bitLen,
36
36
  bitMask,
@@ -38,39 +38,31 @@ import {
38
38
  bytesToNumberBE,
39
39
  concatBytes,
40
40
  createHmacDrbg,
41
- ensureBytes,
42
41
  hexToBytes,
43
- inRange,
44
42
  isBytes,
45
43
  memoized,
46
44
  numberToHexUnpadded,
47
45
  randomBytes as wcRandomBytes,
48
46
  type CHash,
49
- type Hex,
50
- type PrivKey,
47
+ type Signer,
51
48
  } from '../utils.ts';
52
49
  import {
53
50
  _createCurveFields,
54
51
  mulEndoUnsafe,
55
52
  negateCt,
56
53
  normalizeZ,
57
- pippenger,
58
54
  wNAF,
59
55
  type AffinePoint,
60
- type BasicCurve,
61
56
  type CurveLengths,
62
57
  type CurvePoint,
63
58
  type CurvePointCons,
64
59
  } from './curve.ts';
65
60
  import {
66
- Field,
67
61
  FpInvertBatch,
68
62
  getMinHashLength,
69
63
  mapHashToField,
70
- nLength,
71
64
  validateField,
72
65
  type IField,
73
- type NLength,
74
66
  } from './modular.ts';
75
67
 
76
68
  export type { AffinePoint };
@@ -105,7 +97,6 @@ export type EndomorphismOpts = {
105
97
  basises?: EndoBasis;
106
98
  splitScalar?: (k: bigint) => { k1neg: boolean; k1: bigint; k2neg: boolean; k2: bigint };
107
99
  };
108
-
109
100
  // We construct basis in such way that den is always positive and equals n, but num sign depends on basis (not on secret value)
110
101
  const divNearest = (num: bigint, den: bigint) => (num + (num >= 0 ? den : -den) / _2n) / den;
111
102
 
@@ -190,25 +181,6 @@ export interface WeierstrassPoint<T> extends CurvePoint<T, WeierstrassPoint<T>>
190
181
  /** Encodes point using IEEE P1363 (DER) encoding. First byte is 2/3/4. Default = isCompressed. */
191
182
  toBytes(isCompressed?: boolean): Uint8Array;
192
183
  toHex(isCompressed?: boolean): string;
193
-
194
- /** @deprecated use `.X` */
195
- readonly px: T;
196
- /** @deprecated use `.Y` */
197
- readonly py: T;
198
- /** @deprecated use `.Z` */
199
- readonly pz: T;
200
- /** @deprecated use `toBytes` */
201
- toRawBytes(isCompressed?: boolean): Uint8Array;
202
- /** @deprecated use `multiplyUnsafe` */
203
- multiplyAndAddUnsafe(
204
- Q: WeierstrassPoint<T>,
205
- a: bigint,
206
- b: bigint
207
- ): WeierstrassPoint<T> | undefined;
208
- /** @deprecated use `p.y % 2n === 0n` */
209
- hasEvenY(): boolean;
210
- /** @deprecated use `p.precompute(windowSize)` */
211
- _setWindowSize(windowSize: number): void;
212
184
  }
213
185
 
214
186
  /** Static methods for 3D XYZ projective points. */
@@ -216,12 +188,6 @@ export interface WeierstrassPointCons<T> extends CurvePointCons<WeierstrassPoint
216
188
  /** Does NOT validate if the point is valid. Use `.assertValidity()`. */
217
189
  new (X: T, Y: T, Z: T): WeierstrassPoint<T>;
218
190
  CURVE(): WeierstrassOpts<T>;
219
- /** @deprecated use `Point.BASE.multiply(Point.Fn.fromBytes(privateKey))` */
220
- fromPrivateKey(privateKey: PrivKey): WeierstrassPoint<T>;
221
- /** @deprecated use `import { normalizeZ } from '@noble/curves/abstract/curve.js';` */
222
- normalizeZ(points: WeierstrassPoint<T>[]): WeierstrassPoint<T>[];
223
- /** @deprecated use `import { pippenger } from '@noble/curves/abstract/curve.js';` */
224
- msm(points: WeierstrassPoint<T>[], scalars: bigint[]): WeierstrassPoint<T>;
225
191
  }
226
192
 
227
193
  /**
@@ -286,21 +252,17 @@ export type ECDSAOpts = Partial<{
286
252
  */
287
253
  export interface ECDH {
288
254
  keygen: (seed?: Uint8Array) => { secretKey: Uint8Array; publicKey: Uint8Array };
289
- getPublicKey: (secretKey: PrivKey, isCompressed?: boolean) => Uint8Array;
290
- getSharedSecret: (secretKeyA: PrivKey, publicKeyB: Hex, isCompressed?: boolean) => Uint8Array;
255
+ getPublicKey: (secretKey: Uint8Array, isCompressed?: boolean) => Uint8Array;
256
+ getSharedSecret: (
257
+ secretKeyA: Uint8Array,
258
+ publicKeyB: Uint8Array,
259
+ isCompressed?: boolean
260
+ ) => Uint8Array;
291
261
  Point: WeierstrassPointCons<bigint>;
292
262
  utils: {
293
- isValidSecretKey: (secretKey: PrivKey) => boolean;
263
+ isValidSecretKey: (secretKey: Uint8Array) => boolean;
294
264
  isValidPublicKey: (publicKey: Uint8Array, isCompressed?: boolean) => boolean;
295
265
  randomSecretKey: (seed?: Uint8Array) => Uint8Array;
296
- /** @deprecated use `randomSecretKey` */
297
- randomPrivateKey: (seed?: Uint8Array) => Uint8Array;
298
- /** @deprecated use `isValidSecretKey` */
299
- isValidPrivateKey: (secretKey: PrivKey) => boolean;
300
- /** @deprecated use `Point.Fn.fromBytes()` */
301
- normPrivateKeyToScalar: (key: PrivKey) => bigint;
302
- /** @deprecated use `point.precompute()` */
303
- precompute: (windowSize?: number, point?: WeierstrassPoint<bigint>) => WeierstrassPoint<bigint>;
304
266
  };
305
267
  lengths: CurveLengths;
306
268
  }
@@ -310,7 +272,7 @@ export interface ECDH {
310
272
  * Only supported for prime fields, not Fp2 (extension fields).
311
273
  */
312
274
  export interface ECDSA extends ECDH {
313
- sign: (message: Hex, secretKey: PrivKey, opts?: ECDSASignOpts) => ECDSASigRecovered;
275
+ sign: (message: Uint8Array, secretKey: Uint8Array, opts?: ECDSASignOpts) => Uint8Array;
314
276
  verify: (
315
277
  signature: Uint8Array,
316
278
  message: Uint8Array,
@@ -418,10 +380,10 @@ export const DER: IDER = {
418
380
  return bytesToNumberBE(data);
419
381
  },
420
382
  },
421
- toSig(hex: string | Uint8Array): { r: bigint; s: bigint } {
383
+ toSig(bytes: Uint8Array): { r: bigint; s: bigint } {
422
384
  // parse DER signature
423
385
  const { Err: E, _int: int, _tlv: tlv } = DER;
424
- const data = ensureBytes('signature', hex);
386
+ const data = abytes(bytes, undefined, 'signature');
425
387
  const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data);
426
388
  if (seqLeftBytes.length) throw new E('invalid signature: left bytes after parsing');
427
389
  const { v: rBytes, l: rLeftBytes } = tlv.decode(0x02, seqBytes);
@@ -442,23 +404,6 @@ export const DER: IDER = {
442
404
  // prettier-ignore
443
405
  const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
444
406
 
445
- export function _normFnElement(Fn: IField<bigint>, key: PrivKey): bigint {
446
- const { BYTES: expected } = Fn;
447
- let num: bigint;
448
- if (typeof key === 'bigint') {
449
- num = key;
450
- } else {
451
- let bytes = ensureBytes('private key', key);
452
- try {
453
- num = Fn.fromBytes(bytes);
454
- } catch (error) {
455
- throw new Error(`invalid private key: expected ui8a of size ${expected}, got ${typeof key}`);
456
- }
457
- }
458
- if (!Fn.isValidNot0(num)) throw new Error('invalid private key: out of range [1..N-1]');
459
- return num;
460
- }
461
-
462
407
  /**
463
408
  * Creates weierstrass Point constructor, based on specified curve options.
464
409
  *
@@ -476,7 +421,7 @@ const opts = {
476
421
  const p256_Point = weierstrass(opts);
477
422
  ```
478
423
  */
479
- export function weierstrassN<T>(
424
+ export function weierstrass<T>(
480
425
  params: WeierstrassOpts<T>,
481
426
  extraOpts: WeierstrassExtraOpts<T> = {}
482
427
  ): WeierstrassPointCons<T> {
@@ -531,7 +476,7 @@ export function weierstrassN<T>(
531
476
  }
532
477
  function pointFromBytes(bytes: Uint8Array) {
533
478
  abytes(bytes, undefined, 'Point');
534
- const { public: comp, publicUncompressed: uncomp } = lengths; // e.g. for 32-byte: 33, 65
479
+ const { publicKey: comp, publicKeyUncompressed: uncomp } = lengths; // e.g. for 32-byte: 33, 65
535
480
  const length = bytes.length;
536
481
  const head = bytes[0];
537
482
  const tail = bytes.subarray(1);
@@ -704,8 +649,9 @@ export function weierstrassN<T>(
704
649
  P.assertValidity();
705
650
  return P;
706
651
  }
707
- static fromHex(hex: Hex): Point {
708
- return Point.fromBytes(ensureBytes('pointHex', hex));
652
+
653
+ static fromHex(hex: string): Point {
654
+ return Point.fromBytes(hexToBytes(hex));
709
655
  }
710
656
 
711
657
  get x(): T {
@@ -959,35 +905,10 @@ export function weierstrassN<T>(
959
905
  toString() {
960
906
  return `<Point ${this.is0() ? 'ZERO' : this.toHex()}>`;
961
907
  }
962
-
963
- // TODO: remove
964
- get px(): T {
965
- return this.X;
966
- }
967
- get py(): T {
968
- return this.X;
969
- }
970
- get pz(): T {
971
- return this.Z;
972
- }
973
- toRawBytes(isCompressed = true): Uint8Array {
974
- return this.toBytes(isCompressed);
975
- }
976
- _setWindowSize(windowSize: number) {
977
- this.precompute(windowSize);
978
- }
979
- static normalizeZ(points: Point[]): Point[] {
980
- return normalizeZ(Point, points);
981
- }
982
- static msm(points: Point[], scalars: bigint[]): Point {
983
- return pippenger(Point, Fn, points, scalars);
984
- }
985
- static fromPrivateKey(privateKey: PrivKey) {
986
- return Point.BASE.multiply(_normFnElement(Fn, privateKey));
987
- }
988
908
  }
989
909
  const bits = Fn.BITS;
990
910
  const wnaf = new wNAF(Point, extraOpts.endo ? Math.ceil(bits / 2) : bits);
911
+ Point.BASE.precompute(8); // Enable precomputes. Slows down first publicKey computation by 20ms.
991
912
  return Point;
992
913
  }
993
914
 
@@ -996,39 +917,16 @@ export interface ECDSASignature {
996
917
  readonly r: bigint;
997
918
  readonly s: bigint;
998
919
  readonly recovery?: number;
999
- addRecoveryBit(recovery: number): ECDSASigRecovered;
920
+ addRecoveryBit(recovery: number): ECDSASignature & { readonly recovery: number };
1000
921
  hasHighS(): boolean;
1001
922
  toBytes(format?: string): Uint8Array;
1002
923
  toHex(format?: string): string;
1003
-
1004
- /** @deprecated */
1005
- assertValidity(): void;
1006
- /** @deprecated */
1007
- normalizeS(): ECDSASignature;
1008
- /** @deprecated use standalone method `curve.recoverPublicKey(sig.toBytes('recovered'), msg)` */
1009
- recoverPublicKey(msgHash: Hex): WeierstrassPoint<bigint>;
1010
- /** @deprecated use `.toBytes('compact')` */
1011
- toCompactRawBytes(): Uint8Array;
1012
- /** @deprecated use `.toBytes('compact')` */
1013
- toCompactHex(): string;
1014
- /** @deprecated use `.toBytes('der')` */
1015
- toDERRawBytes(): Uint8Array;
1016
- /** @deprecated use `.toBytes('der')` */
1017
- toDERHex(): string;
1018
924
  }
1019
- export type ECDSASigRecovered = ECDSASignature & {
1020
- readonly recovery: number;
1021
- };
1022
925
  /** Methods of ECDSA signature constructor. */
1023
926
  export type ECDSASignatureCons = {
1024
927
  new (r: bigint, s: bigint, recovery?: number): ECDSASignature;
1025
928
  fromBytes(bytes: Uint8Array, format?: ECDSASigFormat): ECDSASignature;
1026
929
  fromHex(hex: string, format?: ECDSASigFormat): ECDSASignature;
1027
-
1028
- /** @deprecated use `.fromBytes(bytes, 'compact')` */
1029
- fromCompact(hex: Hex): ECDSASignature;
1030
- /** @deprecated use `.fromBytes(bytes, 'der')` */
1031
- fromDER(hex: Hex): ECDSASignature;
1032
930
  };
1033
931
 
1034
932
  // Points start with byte 0x02 when y is even; otherwise 0x03
@@ -1171,9 +1069,9 @@ export function mapToCurveSimpleSWU<T>(
1171
1069
 
1172
1070
  function getWLengths<T>(Fp: IField<T>, Fn: IField<bigint>) {
1173
1071
  return {
1174
- secret: Fn.BYTES,
1175
- public: 1 + Fp.BYTES,
1176
- publicUncompressed: 1 + 2 * Fp.BYTES,
1072
+ secretKey: Fn.BYTES,
1073
+ publicKey: 1 + Fp.BYTES,
1074
+ publicKeyUncompressed: 1 + 2 * Fp.BYTES,
1177
1075
  publicKeyHasPrefix: true,
1178
1076
  signature: 2 * Fn.BYTES,
1179
1077
  };
@@ -1191,20 +1089,21 @@ export function ecdh(
1191
1089
  const randomBytes_ = ecdhOpts.randomBytes || wcRandomBytes;
1192
1090
  const lengths = Object.assign(getWLengths(Point.Fp, Fn), { seed: getMinHashLength(Fn.ORDER) });
1193
1091
 
1194
- function isValidSecretKey(secretKey: PrivKey) {
1092
+ function isValidSecretKey(secretKey: Uint8Array) {
1195
1093
  try {
1196
- return !!_normFnElement(Fn, secretKey);
1094
+ const num = Fn.fromBytes(secretKey);
1095
+ return Fn.isValidNot0(num);
1197
1096
  } catch (error) {
1198
1097
  return false;
1199
1098
  }
1200
1099
  }
1201
1100
 
1202
1101
  function isValidPublicKey(publicKey: Uint8Array, isCompressed?: boolean): boolean {
1203
- const { public: comp, publicUncompressed } = lengths;
1102
+ const { publicKey: comp, publicKeyUncompressed } = lengths;
1204
1103
  try {
1205
1104
  const l = publicKey.length;
1206
1105
  if (isCompressed === true && l !== comp) return false;
1207
- if (isCompressed === false && l !== publicUncompressed) return false;
1106
+ if (isCompressed === false && l !== publicKeyUncompressed) return false;
1208
1107
  return !!Point.fromBytes(publicKey);
1209
1108
  } catch (error) {
1210
1109
  return false;
@@ -1224,8 +1123,8 @@ export function ecdh(
1224
1123
  * @param isCompressed whether to return compact (default), or full key
1225
1124
  * @returns Public key, full when isCompressed=false; short when isCompressed=true
1226
1125
  */
1227
- function getPublicKey(secretKey: PrivKey, isCompressed = true): Uint8Array {
1228
- return Point.BASE.multiply(_normFnElement(Fn, secretKey)).toBytes(isCompressed);
1126
+ function getPublicKey(secretKey: Uint8Array, isCompressed = true): Uint8Array {
1127
+ return Point.BASE.multiply(Fn.fromBytes(secretKey)).toBytes(isCompressed);
1229
1128
  }
1230
1129
 
1231
1130
  function keygen(seed?: Uint8Array) {
@@ -1236,12 +1135,12 @@ export function ecdh(
1236
1135
  /**
1237
1136
  * Quick and dirty check for item being public key. Does not validate hex, or being on-curve.
1238
1137
  */
1239
- function isProbPub(item: PrivKey | PubKey): boolean | undefined {
1240
- if (typeof item === 'bigint') return false;
1241
- if (item instanceof Point) return true;
1242
- if (Fn.allowedLengths || lengths.secret === lengths.public) return undefined;
1243
- const l = ensureBytes('key', item).length;
1244
- return l === lengths.public || l === lengths.publicUncompressed;
1138
+ function isProbPub(item: Uint8Array): boolean | undefined {
1139
+ const { secretKey, publicKey, publicKeyUncompressed } = lengths;
1140
+ if (!isBytes(item)) return undefined;
1141
+ if (('_lengths' in Fn && Fn._lengths) || secretKey === publicKey) return undefined;
1142
+ const l = abytes(item, undefined, 'key').length;
1143
+ return l === publicKey || l === publicKeyUncompressed;
1245
1144
  }
1246
1145
 
1247
1146
  /**
@@ -1252,11 +1151,15 @@ export function ecdh(
1252
1151
  * @param isCompressed whether to return compact (default), or full key
1253
1152
  * @returns shared public key
1254
1153
  */
1255
- function getSharedSecret(secretKeyA: PrivKey, publicKeyB: Hex, isCompressed = true): Uint8Array {
1154
+ function getSharedSecret(
1155
+ secretKeyA: Uint8Array,
1156
+ publicKeyB: Uint8Array,
1157
+ isCompressed = true
1158
+ ): Uint8Array {
1256
1159
  if (isProbPub(secretKeyA) === true) throw new Error('first arg must be private key');
1257
1160
  if (isProbPub(publicKeyB) === false) throw new Error('second arg must be public key');
1258
- const s = _normFnElement(Fn, secretKeyA);
1259
- const b = Point.fromHex(publicKeyB); // checks for being on-curve
1161
+ const s = Fn.fromBytes(secretKeyA);
1162
+ const b = Point.fromBytes(publicKeyB); // checks for being on-curve
1260
1163
  return b.multiply(s).toBytes(isCompressed);
1261
1164
  }
1262
1165
 
@@ -1264,14 +1167,6 @@ export function ecdh(
1264
1167
  isValidSecretKey,
1265
1168
  isValidPublicKey,
1266
1169
  randomSecretKey,
1267
-
1268
- // TODO: remove
1269
- isValidPrivateKey: isValidSecretKey,
1270
- randomPrivateKey: randomSecretKey,
1271
- normPrivateKeyToScalar: (key: PrivKey) => _normFnElement(Fn, key),
1272
- precompute(windowSize = 8, point = Point.BASE): WeierstrassPoint<bigint> {
1273
- return point.precompute(windowSize, false);
1274
- },
1275
1170
  };
1276
1171
 
1277
1172
  return Object.freeze({ getPublicKey, getSharedSecret, keygen, Point, utils, lengths });
@@ -1290,6 +1185,7 @@ export function ecdh(
1290
1185
  * const p256_Point = weierstrass(...);
1291
1186
  * const p256_sha256 = ecdsa(p256_Point, sha256);
1292
1187
  * const p256_sha224 = ecdsa(p256_Point, sha224);
1188
+ * const p256_sha224_r = ecdsa(p256_Point, sha224, { randomBytes: (length) => { ... } });
1293
1189
  * ```
1294
1190
  */
1295
1191
  export function ecdsa(
@@ -1309,9 +1205,9 @@ export function ecdsa(
1309
1205
  bits2int_modN: 'function',
1310
1206
  }
1311
1207
  );
1312
-
1313
- const randomBytes_ = ecdsaOpts.randomBytes || wcRandomBytes;
1314
- const hmac_: HmacFnSync =
1208
+ ecdsaOpts = Object.assign({}, ecdsaOpts);
1209
+ const randomBytes = ecdsaOpts.randomBytes || wcRandomBytes;
1210
+ const hmac: HmacFnSync =
1315
1211
  ecdsaOpts.hmac ||
1316
1212
  (((key, ...msgs) => nobleHmac(hash, key, concatBytes(...msgs))) satisfies HmacFnSync);
1317
1213
 
@@ -1319,25 +1215,27 @@ export function ecdsa(
1319
1215
  const { ORDER: CURVE_ORDER, BITS: fnBits } = Fn;
1320
1216
  const { keygen, getPublicKey, getSharedSecret, utils, lengths } = ecdh(Point, ecdsaOpts);
1321
1217
  const defaultSigOpts: Required<ECDSASignOpts> = {
1322
- prehash: false,
1323
- lowS: typeof ecdsaOpts.lowS === 'boolean' ? ecdsaOpts.lowS : false,
1324
- format: undefined as any, //'compact' as ECDSASigFormat,
1218
+ prehash: true,
1219
+ lowS: typeof ecdsaOpts.lowS === 'boolean' ? ecdsaOpts.lowS : true,
1220
+ format: 'compact' as ECDSASigFormat,
1325
1221
  extraEntropy: false,
1326
1222
  };
1327
- const defaultSigOpts_format = 'compact';
1328
1223
 
1329
1224
  function isBiggerThanHalfOrder(number: bigint) {
1330
1225
  const HALF = CURVE_ORDER >> _1n;
1331
1226
  return number > HALF;
1332
1227
  }
1333
- function normalizeS(s: bigint) {
1334
- return isBiggerThanHalfOrder(s) ? Fn.neg(s) : s;
1335
- }
1336
1228
  function validateRS(title: string, num: bigint): bigint {
1337
1229
  if (!Fn.isValidNot0(num))
1338
1230
  throw new Error(`invalid signature ${title}: out of range 1..Point.Fn.ORDER`);
1339
1231
  return num;
1340
1232
  }
1233
+ function validateSigLength(bytes: Uint8Array, format: ECDSASigFormat) {
1234
+ validateSigFormat(format);
1235
+ const size = lengths.signature!;
1236
+ const sizer = format === 'compact' ? size : format === 'recovered' ? size + 1 : undefined;
1237
+ return abytes(bytes, sizer);
1238
+ }
1341
1239
 
1342
1240
  /**
1343
1241
  * ECDSA signature with its (r, s) properties. Supports compact, recovered & DER representations.
@@ -1346,6 +1244,7 @@ export function ecdsa(
1346
1244
  readonly r: bigint;
1347
1245
  readonly s: bigint;
1348
1246
  readonly recovery?: number;
1247
+
1349
1248
  constructor(r: bigint, s: bigint, recovery?: number) {
1350
1249
  this.r = validateRS('r', r); // r in [1..N-1];
1351
1250
  this.s = validateRS('s', s); // s in [1..N-1];
@@ -1353,22 +1252,19 @@ export function ecdsa(
1353
1252
  Object.freeze(this);
1354
1253
  }
1355
1254
 
1356
- static fromBytes(bytes: Uint8Array, format: ECDSASigFormat = defaultSigOpts_format): Signature {
1357
- validateSigFormat(format);
1358
- const size = lengths.signature!;
1255
+ static fromBytes(bytes: Uint8Array, format: ECDSASigFormat = defaultSigOpts.format): Signature {
1256
+ validateSigLength(bytes, format);
1359
1257
  let recid: number | undefined;
1360
1258
  if (format === 'der') {
1361
1259
  const { r, s } = DER.toSig(abytes(bytes));
1362
1260
  return new Signature(r, s);
1363
1261
  }
1364
1262
  if (format === 'recovered') {
1365
- abytes(bytes, size + 1);
1366
1263
  recid = bytes[0];
1367
1264
  format = 'compact';
1368
1265
  bytes = bytes.subarray(1);
1369
1266
  }
1370
- abytes(bytes, size);
1371
- const L = size / 2;
1267
+ const L = lengths.signature! / 2;
1372
1268
  const r = bytes.subarray(0, L);
1373
1269
  const s = bytes.subarray(L, L * 2);
1374
1270
  return new Signature(Fn.fromBytes(r), Fn.fromBytes(s), recid);
@@ -1382,7 +1278,7 @@ export function ecdsa(
1382
1278
  return new Signature(this.r, this.s, recovery) as RecoveredSignature;
1383
1279
  }
1384
1280
 
1385
- recoverPublicKey(msgHash: Hex): typeof Point.BASE {
1281
+ recoverPublicKey(messageHash: Uint8Array): WeierstrassPoint<bigint> {
1386
1282
  const FIELD_ORDER = Fp.ORDER;
1387
1283
  const { r, s, recovery: rec } = this;
1388
1284
  if (rec == null || ![0, 1, 2, 3].includes(rec)) throw new Error('recovery id invalid');
@@ -1403,7 +1299,7 @@ export function ecdsa(
1403
1299
  const x = Fp.toBytes(radj);
1404
1300
  const R = Point.fromBytes(concatBytes(pprefix((rec & 1) === 0), x));
1405
1301
  const ir = Fn.inv(radj); // r^-1
1406
- const h = bits2int_modN(ensureBytes('msgHash', msgHash)); // Truncate hash
1302
+ const h = bits2int_modN(abytes(messageHash, undefined, 'msgHash')); // Truncate hash
1407
1303
  const u1 = Fn.create(-h * ir); // -hr^-1
1408
1304
  const u2 = Fn.create(s * ir); // sr^-1
1409
1305
  // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1). unsafe is fine: there is no private data.
@@ -1418,7 +1314,7 @@ export function ecdsa(
1418
1314
  return isBiggerThanHalfOrder(this.s);
1419
1315
  }
1420
1316
 
1421
- toBytes(format: ECDSASigFormat = defaultSigOpts_format) {
1317
+ toBytes(format: ECDSASigFormat = defaultSigOpts.format) {
1422
1318
  validateSigFormat(format);
1423
1319
  if (format === 'der') return hexToBytes(DER.hexFromSig(this));
1424
1320
  const r = Fn.toBytes(this.r);
@@ -1433,30 +1329,6 @@ export function ecdsa(
1433
1329
  toHex(format?: ECDSASigFormat) {
1434
1330
  return bytesToHex(this.toBytes(format));
1435
1331
  }
1436
-
1437
- // TODO: remove
1438
- assertValidity(): void {}
1439
- static fromCompact(hex: Hex) {
1440
- return Signature.fromBytes(ensureBytes('sig', hex), 'compact');
1441
- }
1442
- static fromDER(hex: Hex) {
1443
- return Signature.fromBytes(ensureBytes('sig', hex), 'der');
1444
- }
1445
- normalizeS() {
1446
- return this.hasHighS() ? new Signature(this.r, Fn.neg(this.s), this.recovery) : this;
1447
- }
1448
- toDERRawBytes() {
1449
- return this.toBytes('der');
1450
- }
1451
- toDERHex() {
1452
- return bytesToHex(this.toBytes('der'));
1453
- }
1454
- toCompactRawBytes() {
1455
- return this.toBytes('compact');
1456
- }
1457
- toCompactHex() {
1458
- return bytesToHex(this.toBytes('compact'));
1459
- }
1460
1332
  }
1461
1333
  type RecoveredSignature = Signature & { recovery: number };
1462
1334
 
@@ -1466,7 +1338,7 @@ export function ecdsa(
1466
1338
  // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors
1467
1339
  const bits2int =
1468
1340
  ecdsaOpts.bits2int ||
1469
- function (bytes: Uint8Array): bigint {
1341
+ function bits2int_def(bytes: Uint8Array): bigint {
1470
1342
  // Our custom check "just in case", for protection against DoS
1471
1343
  if (bytes.length > 8192) throw new Error('input is too large');
1472
1344
  // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)
@@ -1477,20 +1349,23 @@ export function ecdsa(
1477
1349
  };
1478
1350
  const bits2int_modN =
1479
1351
  ecdsaOpts.bits2int_modN ||
1480
- function (bytes: Uint8Array): bigint {
1352
+ function bits2int_modN_def(bytes: Uint8Array): bigint {
1481
1353
  return Fn.create(bits2int(bytes)); // can't use bytesToNumberBE here
1482
1354
  };
1483
- // NOTE: pads output with zero as per spec
1355
+ // Pads output with zero as per spec
1484
1356
  const ORDER_MASK = bitMask(fnBits);
1485
- /**
1486
- * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.
1487
- */
1357
+ /** Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`. */
1488
1358
  function int2octets(num: bigint): Uint8Array {
1489
1359
  // IMPORTANT: the check ensures working for case `Fn.BYTES != Fn.BITS * 8`
1490
1360
  aInRange('num < 2^' + fnBits, num, _0n, ORDER_MASK);
1491
1361
  return Fn.toBytes(num);
1492
1362
  }
1493
1363
 
1364
+ function validateMsgAndHash(message: Uint8Array, prehash: boolean) {
1365
+ abytes(message, undefined, 'message');
1366
+ return prehash ? abytes(hash(message), undefined, 'prehashed message') : message;
1367
+ }
1368
+
1494
1369
  /**
1495
1370
  * Steps A, D of RFC6979 3.2.
1496
1371
  * Creates RFC6979 seed; converts msg/privKey to numbers.
@@ -1499,29 +1374,25 @@ export function ecdsa(
1499
1374
  * Warning: we cannot assume here that message has same amount of bytes as curve order,
1500
1375
  * this will be invalid at least for P521. Also it can be bigger for P224 + SHA256.
1501
1376
  */
1502
- function prepSig(message: Uint8Array, privateKey: PrivKey, opts: ECDSASignOpts) {
1503
- if (['recovered', 'canonical'].some((k) => k in opts))
1504
- throw new Error('sign() legacy options not supported');
1377
+ function prepSig(message: Uint8Array, privateKey: Uint8Array, opts: ECDSASignOpts) {
1505
1378
  const { lowS, prehash, extraEntropy } = validateSigOpts(opts, defaultSigOpts);
1506
- // RFC6979 3.2: we skip step A, because we already provide hash
1507
- message = abytes(message, undefined, 'message');
1508
- if (prehash) message = abytes(hash(message), undefined, 'prehashed message');
1509
-
1379
+ message = validateMsgAndHash(message, prehash); // RFC6979 3.2 A: h1 = H(m)
1510
1380
  // We can't later call bits2octets, since nested bits2int is broken for curves
1511
1381
  // with fnBits % 8 !== 0. Because of that, we unwrap it here as int2octets call.
1512
1382
  // const bits2octets = (bits) => int2octets(bits2int_modN(bits))
1513
1383
  const h1int = bits2int_modN(message);
1514
- const d = _normFnElement(Fn, privateKey); // validate secret key, convert to bigint
1384
+ const d = Fn.fromBytes(privateKey); // validate secret key, convert to bigint
1385
+ if (!Fn.isValidNot0(d)) throw new Error('invalid private key');
1515
1386
  const seedArgs = [int2octets(d), int2octets(h1int)];
1516
1387
  // extraEntropy. RFC6979 3.6: additional k' (optional).
1517
1388
  if (extraEntropy != null && extraEntropy !== false) {
1518
1389
  // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
1519
1390
  // gen random bytes OR pass as-is
1520
- const e = extraEntropy === true ? randomBytes_(lengths.secret) : extraEntropy;
1521
- seedArgs.push(ensureBytes('extraEntropy', e)); // check for being bytes
1391
+ const e = extraEntropy === true ? randomBytes(lengths.secretKey) : extraEntropy;
1392
+ seedArgs.push(abytes(e, undefined, 'extraEntropy')); // check for being bytes
1522
1393
  }
1523
1394
  const seed = concatBytes(...seedArgs); // Step D of RFC6979 3.2
1524
- const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!
1395
+ const m = h1int; // no need to call bits2int second time here, it is inside truncateHash!
1525
1396
  // Converts signature params into point w r/s, checks result for validity.
1526
1397
  // To transform k => Signature:
1527
1398
  // q = k⋅G
@@ -1533,7 +1404,7 @@ export function ecdsa(
1533
1404
  function k2sig(kBytes: Uint8Array): RecoveredSignature | undefined {
1534
1405
  // RFC 6979 Section 3.2, step 3: k = bits2int(T)
1535
1406
  // Important: all mod() calls here must be done over N
1536
- const k = bits2int(kBytes); // mod n, not mod p
1407
+ const k = bits2int(kBytes); // Cannot use fields methods, since it is group element
1537
1408
  if (!Fn.isValidNot0(k)) return; // Valid scalars (including k) must be in 1..N-1
1538
1409
  const ik = Fn.inv(k); // k^-1 mod n
1539
1410
  const q = Point.BASE.multiply(k).toAffine(); // q = k⋅G
@@ -1544,7 +1415,7 @@ export function ecdsa(
1544
1415
  let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n); // recovery bit (2 or 3, when q.x > n)
1545
1416
  let normS = s;
1546
1417
  if (lowS && isBiggerThanHalfOrder(s)) {
1547
- normS = normalizeS(s); // if lowS was passed, ensure s is always
1418
+ normS = Fn.neg(s); // if lowS was passed, ensure s is always
1548
1419
  recovery ^= 1; // // in the bottom half of N
1549
1420
  }
1550
1421
  return new Signature(r, normS, recovery) as RecoveredSignature; // use normS, not s
@@ -1563,17 +1434,13 @@ export function ecdsa(
1563
1434
  * s = (m + dr) / k mod n
1564
1435
  * ```
1565
1436
  */
1566
- function sign(message: Hex, secretKey: PrivKey, opts: ECDSASignOpts = {}): RecoveredSignature {
1567
- message = ensureBytes('message', message);
1437
+ function sign(message: Uint8Array, secretKey: Uint8Array, opts: ECDSASignOpts = {}): Uint8Array {
1568
1438
  const { seed, k2sig } = prepSig(message, secretKey, opts); // Steps A, D of RFC6979 3.2.
1569
- const drbg = createHmacDrbg<RecoveredSignature>(hash.outputLen, Fn.BYTES, hmac_);
1439
+ const drbg = createHmacDrbg<RecoveredSignature>(hash.outputLen, Fn.BYTES, hmac);
1570
1440
  const sig = drbg(seed, k2sig); // Steps B, C, D, E, F, G
1571
- return sig;
1441
+ return sig.toBytes(opts.format);
1572
1442
  }
1573
1443
 
1574
- // Enable precomputes. Slows down first publicKey computation by 20ms.
1575
- Point.BASE.precompute(8);
1576
-
1577
1444
  /**
1578
1445
  * Verifies a signature against message and public key.
1579
1446
  * Rejects lowS signatures by default: see {@link ECDSAVerifyOpts}.
@@ -1588,66 +1455,24 @@ export function ecdsa(
1588
1455
  * ```
1589
1456
  */
1590
1457
  function verify(
1591
- signature: Hex | SignatureLike,
1592
- message: Hex,
1593
- publicKey: Hex,
1458
+ signature: Uint8Array,
1459
+ message: Uint8Array,
1460
+ publicKey: Uint8Array,
1594
1461
  opts: ECDSAVerifyOpts = {}
1595
1462
  ): boolean {
1596
- const sg = signature;
1597
- message = ensureBytes('msgHash', message);
1598
- publicKey = ensureBytes('publicKey', publicKey);
1599
1463
  const { lowS, prehash, format } = validateSigOpts(opts, defaultSigOpts);
1600
- let _sig: Signature | undefined = undefined;
1601
- let P: WeierstrassPoint<bigint>;
1602
-
1603
- if ('strict' in opts) throw new Error('options.strict was renamed to lowS');
1604
- if (format === undefined) {
1605
- // Try to deduce format
1606
- const isHex = typeof sg === 'string' || isBytes(sg);
1607
- const isObj =
1608
- !isHex &&
1609
- sg !== null &&
1610
- typeof sg === 'object' &&
1611
- typeof sg.r === 'bigint' &&
1612
- typeof sg.s === 'bigint';
1613
- if (!isHex && !isObj)
1614
- throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance');
1615
- if (isObj) {
1616
- _sig = new Signature(sg.r, sg.s);
1617
- } else if (isHex) {
1618
- // TODO: remove this malleable check
1619
- // Signature can be represented in 2 ways: compact (2*Fn.BYTES) & DER (variable-length).
1620
- // Since DER can also be 2*Fn.BYTES bytes, we check for it first.
1621
- try {
1622
- _sig = Signature.fromDER(sg);
1623
- } catch (derError) {
1624
- if (!(derError instanceof DER.Err)) throw derError;
1625
- }
1626
- if (!_sig) {
1627
- try {
1628
- _sig = Signature.fromCompact(sg);
1629
- } catch (error) {
1630
- return false;
1631
- }
1632
- }
1633
- }
1634
- } else {
1635
- if (format === 'compact' || format === 'der') {
1636
- if (typeof sg !== 'string' && !isBytes(sg))
1637
- throw new Error('"der" / "compact" format expects Uint8Array signature');
1638
- _sig = Signature.fromBytes(ensureBytes('sig', sg), format);
1639
- } else {
1640
- throw new Error('format must be "compact", "der" or "js"');
1641
- }
1464
+ publicKey = abytes(publicKey, undefined, 'publicKey');
1465
+ message = validateMsgAndHash(message, prehash);
1466
+ if (!isBytes(signature as any)) {
1467
+ const end = signature instanceof Signature ? ', use sig.toBytes()' : '';
1468
+ throw new Error('verify expects Uint8Array signature' + end);
1642
1469
  }
1643
-
1644
- if (!_sig) return false;
1470
+ validateSigLength(signature, format); // execute this twice because we want loud error
1645
1471
  try {
1646
- P = Point.fromHex(publicKey);
1647
- if (lowS && _sig.hasHighS()) return false;
1648
- // todo: optional.hash => hash
1649
- if (prehash) message = hash(message);
1650
- const { r, s } = _sig;
1472
+ const sig = Signature.fromBytes(signature, format);
1473
+ const P = Point.fromBytes(publicKey);
1474
+ if (lowS && sig.hasHighS()) return false;
1475
+ const { r, s } = sig;
1651
1476
  const h = bits2int_modN(message); // mod n, not mod p
1652
1477
  const is = Fn.inv(s); // s^-1 mod n
1653
1478
  const u1 = Fn.create(h * is); // u1 = hs^-1 mod n
@@ -1666,10 +1491,8 @@ export function ecdsa(
1666
1491
  message: Uint8Array,
1667
1492
  opts: ECDSARecoverOpts = {}
1668
1493
  ): Uint8Array {
1669
- const prehash = opts.prehash !== undefined ? opts.prehash : defaultSigOpts.prehash;
1670
- abool(prehash, 'prehash');
1671
- message = abytes(message, undefined, 'message');
1672
- if (prehash) message = abytes(hash(message), undefined, 'prehashed message');
1494
+ const { prehash } = validateSigOpts(opts, defaultSigOpts);
1495
+ message = validateMsgAndHash(message, prehash);
1673
1496
  return Signature.fromBytes(signature, 'recovered').recoverPublicKey(message).toBytes();
1674
1497
  }
1675
1498
 
@@ -1685,209 +1508,5 @@ export function ecdsa(
1685
1508
  recoverPublicKey,
1686
1509
  Signature,
1687
1510
  hash,
1688
- });
1689
- }
1690
-
1691
- // TODO: remove everything below
1692
- /** @deprecated */
1693
- export type SignatureType = ECDSASignature;
1694
- /** @deprecated */
1695
- export type RecoveredSignatureType = ECDSASigRecovered;
1696
- /** @deprecated */
1697
- export type SignatureLike = { r: bigint; s: bigint };
1698
- /** @deprecated use `Uint8Array | boolean` */
1699
- export type Entropy = Hex | boolean;
1700
- export type BasicWCurve<T> = BasicCurve<T> & {
1701
- // Params: a, b
1702
- a: T;
1703
- b: T;
1704
-
1705
- // Optional params
1706
- allowedPrivateKeyLengths?: readonly number[]; // for P521
1707
- wrapPrivateKey?: boolean; // bls12-381 requires mod(n) instead of rejecting keys >= n
1708
- endo?: EndomorphismOpts;
1709
- // When a cofactor != 1, there can be an effective methods to:
1710
- // 1. Determine whether a point is torsion-free
1711
- isTorsionFree?: (c: WeierstrassPointCons<T>, point: WeierstrassPoint<T>) => boolean;
1712
- // 2. Clear torsion component
1713
- clearCofactor?: (c: WeierstrassPointCons<T>, point: WeierstrassPoint<T>) => WeierstrassPoint<T>;
1714
- };
1715
- /** @deprecated use ECDSASignOpts */
1716
- export type SignOpts = ECDSASignOpts;
1717
- /** @deprecated use ECDSASignOpts */
1718
- export type VerOpts = ECDSAVerifyOpts;
1719
-
1720
- /** @deprecated use WeierstrassPoint */
1721
- export type ProjPointType<T> = WeierstrassPoint<T>;
1722
- /** @deprecated use WeierstrassPointCons */
1723
- export type ProjConstructor<T> = WeierstrassPointCons<T>;
1724
-
1725
- // TODO: remove
1726
- export type CurvePointsType<T> = BasicWCurve<T> & {
1727
- fromBytes?: (bytes: Uint8Array) => AffinePoint<T>;
1728
- toBytes?: (
1729
- c: WeierstrassPointCons<T>,
1730
- point: WeierstrassPoint<T>,
1731
- isCompressed: boolean
1732
- ) => Uint8Array;
1733
- };
1734
-
1735
- // LegacyWeierstrassOpts
1736
- export type CurvePointsTypeWithLength<T> = Readonly<CurvePointsType<T> & Partial<NLength>>;
1737
-
1738
- // LegacyWeierstrass
1739
- export type CurvePointsRes<T> = {
1740
- Point: WeierstrassPointCons<T>;
1741
-
1742
- /** @deprecated use `Point.CURVE()` */
1743
- CURVE: CurvePointsType<T>;
1744
- /** @deprecated use `Point` */
1745
- ProjectivePoint: WeierstrassPointCons<T>;
1746
- /** @deprecated use `Point.Fn.fromBytes(privateKey)` */
1747
- normPrivateKeyToScalar: (key: PrivKey) => bigint;
1748
- /** @deprecated */
1749
- weierstrassEquation: (x: T) => T;
1750
- /** @deprecated use `Point.Fn.isValidNot0(num)` */
1751
- isWithinCurveOrder: (num: bigint) => boolean;
1752
- };
1753
-
1754
- // Aliases to legacy types
1755
- // export type CurveType = LegacyECDSAOpts;
1756
- // export type CurveFn = LegacyECDSA;
1757
- // export type CurvePointsRes<T> = LegacyWeierstrass<T>;
1758
- // export type CurvePointsType<T> = LegacyWeierstrassOpts<T>;
1759
- // export type CurvePointsTypeWithLength<T> = LegacyWeierstrassOpts<T>;
1760
- // export type BasicWCurve<T> = LegacyWeierstrassOpts<T>;
1761
-
1762
- /** @deprecated use `Uint8Array` */
1763
- export type PubKey = Hex | WeierstrassPoint<bigint>;
1764
- export type CurveType = BasicWCurve<bigint> & {
1765
- hash: CHash; // CHash not FHash because we need outputLen for DRBG
1766
- hmac?: HmacFnSync;
1767
- randomBytes?: (bytesLength?: number) => Uint8Array;
1768
- lowS?: boolean;
1769
- bits2int?: (bytes: Uint8Array) => bigint;
1770
- bits2int_modN?: (bytes: Uint8Array) => bigint;
1771
- };
1772
- export type CurveFn = {
1773
- /** @deprecated use `Point.CURVE()` */
1774
- CURVE: CurvePointsType<bigint>;
1775
- keygen: ECDSA['keygen'];
1776
- getPublicKey: ECDSA['getPublicKey'];
1777
- getSharedSecret: ECDSA['getSharedSecret'];
1778
- sign: ECDSA['sign'];
1779
- verify: ECDSA['verify'];
1780
- Point: WeierstrassPointCons<bigint>;
1781
- /** @deprecated use `Point` */
1782
- ProjectivePoint: WeierstrassPointCons<bigint>;
1783
- Signature: ECDSASignatureCons;
1784
- utils: ECDSA['utils'];
1785
- lengths: ECDSA['lengths'];
1786
- };
1787
- /** @deprecated use `weierstrass` in newer releases */
1788
- export function weierstrassPoints<T>(c: CurvePointsTypeWithLength<T>): CurvePointsRes<T> {
1789
- const { CURVE, curveOpts } = _weierstrass_legacy_opts_to_new(c);
1790
- const Point = weierstrassN(CURVE, curveOpts);
1791
- return _weierstrass_new_output_to_legacy(c, Point);
1792
- }
1793
- export type WsPointComposed<T> = {
1794
- CURVE: WeierstrassOpts<T>;
1795
- curveOpts: WeierstrassExtraOpts<T>;
1796
- };
1797
- export type WsComposed = {
1798
- /** @deprecated use `Point.CURVE()` */
1799
- CURVE: WeierstrassOpts<bigint>;
1800
- hash: CHash;
1801
- curveOpts: WeierstrassExtraOpts<bigint>;
1802
- ecdsaOpts: ECDSAOpts;
1803
- };
1804
- function _weierstrass_legacy_opts_to_new<T>(c: CurvePointsType<T>): WsPointComposed<T> {
1805
- const CURVE: WeierstrassOpts<T> = {
1806
- a: c.a,
1807
- b: c.b,
1808
- p: c.Fp.ORDER,
1809
- n: c.n,
1810
- h: c.h,
1811
- Gx: c.Gx,
1812
- Gy: c.Gy,
1813
- };
1814
- const Fp = c.Fp;
1815
- let allowedLengths = c.allowedPrivateKeyLengths
1816
- ? Array.from(new Set(c.allowedPrivateKeyLengths.map((l) => Math.ceil(l / 2))))
1817
- : undefined;
1818
- const Fn = Field(CURVE.n, {
1819
- BITS: c.nBitLength,
1820
- allowedLengths: allowedLengths,
1821
- modFromBytes: c.wrapPrivateKey,
1822
- });
1823
- const curveOpts: WeierstrassExtraOpts<T> = {
1824
- Fp,
1825
- Fn,
1826
- allowInfinityPoint: c.allowInfinityPoint,
1827
- endo: c.endo,
1828
- isTorsionFree: c.isTorsionFree,
1829
- clearCofactor: c.clearCofactor,
1830
- fromBytes: c.fromBytes,
1831
- toBytes: c.toBytes,
1832
- };
1833
- return { CURVE, curveOpts };
1834
- }
1835
- function _ecdsa_legacy_opts_to_new(c: CurveType): WsComposed {
1836
- const { CURVE, curveOpts } = _weierstrass_legacy_opts_to_new(c);
1837
- const ecdsaOpts: ECDSAOpts = {
1838
- hmac: c.hmac,
1839
- randomBytes: c.randomBytes,
1840
- lowS: c.lowS,
1841
- bits2int: c.bits2int,
1842
- bits2int_modN: c.bits2int_modN,
1843
- };
1844
- return { CURVE, curveOpts, hash: c.hash, ecdsaOpts };
1845
- }
1846
- export function _legacyHelperEquat<T>(Fp: IField<T>, a: T, b: T): (x: T) => T {
1847
- /**
1848
- * y² = x³ + ax + b: Short weierstrass curve formula. Takes x, returns y².
1849
- * @returns y²
1850
- */
1851
- function weierstrassEquation(x: T): T {
1852
- const x2 = Fp.sqr(x); // x * x
1853
- const x3 = Fp.mul(x2, x); // x² * x
1854
- return Fp.add(Fp.add(x3, Fp.mul(x, a)), b); // x³ + a * x + b
1855
- }
1856
- return weierstrassEquation;
1857
- }
1858
- function _weierstrass_new_output_to_legacy<T>(
1859
- c: CurvePointsType<T>,
1860
- Point: WeierstrassPointCons<T>
1861
- ): CurvePointsRes<T> {
1862
- const { Fp, Fn } = Point;
1863
- function isWithinCurveOrder(num: bigint): boolean {
1864
- return inRange(num, _1n, Fn.ORDER);
1865
- }
1866
- const weierstrassEquation = _legacyHelperEquat(Fp, c.a, c.b);
1867
- return Object.assign(
1868
- {},
1869
- {
1870
- CURVE: c,
1871
- Point: Point,
1872
- ProjectivePoint: Point,
1873
- normPrivateKeyToScalar: (key: PrivKey) => _normFnElement(Fn, key),
1874
- weierstrassEquation,
1875
- isWithinCurveOrder,
1876
- }
1877
- );
1878
- }
1879
- function _ecdsa_new_output_to_legacy(c: CurveType, _ecdsa: ECDSA): CurveFn {
1880
- const Point = _ecdsa.Point;
1881
- return Object.assign({}, _ecdsa, {
1882
- ProjectivePoint: Point,
1883
- CURVE: Object.assign({}, c, nLength(Point.Fn.ORDER, Point.Fn.BITS)),
1884
- });
1885
- }
1886
-
1887
- // _ecdsa_legacy
1888
- export function weierstrass(c: CurveType): CurveFn {
1889
- const { CURVE, curveOpts, hash, ecdsaOpts } = _ecdsa_legacy_opts_to_new(c);
1890
- const Point = weierstrassN(CURVE, curveOpts);
1891
- const signs = ecdsa(Point, hash, ecdsaOpts);
1892
- return _ecdsa_new_output_to_legacy(c, signs);
1511
+ }) satisfies Signer;
1893
1512
  }