@noble/curves 2.0.0-beta.1 → 2.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +442 -273
  2. package/abstract/bls.d.ts +17 -17
  3. package/abstract/bls.d.ts.map +1 -1
  4. package/abstract/bls.js.map +1 -1
  5. package/abstract/curve.d.ts +14 -9
  6. package/abstract/curve.d.ts.map +1 -1
  7. package/abstract/curve.js +9 -3
  8. package/abstract/curve.js.map +1 -1
  9. package/abstract/edwards.d.ts +7 -9
  10. package/abstract/edwards.d.ts.map +1 -1
  11. package/abstract/edwards.js +12 -16
  12. package/abstract/edwards.js.map +1 -1
  13. package/abstract/hash-to-curve.d.ts +32 -31
  14. package/abstract/hash-to-curve.d.ts.map +1 -1
  15. package/abstract/hash-to-curve.js +15 -14
  16. package/abstract/hash-to-curve.js.map +1 -1
  17. package/abstract/modular.d.ts.map +1 -1
  18. package/abstract/modular.js +7 -5
  19. package/abstract/modular.js.map +1 -1
  20. package/abstract/montgomery.d.ts +3 -3
  21. package/abstract/montgomery.d.ts.map +1 -1
  22. package/abstract/montgomery.js +9 -13
  23. package/abstract/montgomery.js.map +1 -1
  24. package/abstract/oprf.d.ts +4 -4
  25. package/abstract/oprf.d.ts.map +1 -1
  26. package/abstract/oprf.js +2 -2
  27. package/abstract/oprf.js.map +1 -1
  28. package/abstract/poseidon.d.ts.map +1 -1
  29. package/abstract/poseidon.js +8 -9
  30. package/abstract/poseidon.js.map +1 -1
  31. package/abstract/weierstrass.d.ts +66 -20
  32. package/abstract/weierstrass.d.ts.map +1 -1
  33. package/abstract/weierstrass.js +72 -68
  34. package/abstract/weierstrass.js.map +1 -1
  35. package/bls12-381.d.ts +3 -9
  36. package/bls12-381.d.ts.map +1 -1
  37. package/bls12-381.js +3 -14
  38. package/bls12-381.js.map +1 -1
  39. package/bn254.d.ts +3 -3
  40. package/bn254.d.ts.map +1 -1
  41. package/bn254.js.map +1 -1
  42. package/ed25519.d.ts +22 -18
  43. package/ed25519.d.ts.map +1 -1
  44. package/ed25519.js +59 -31
  45. package/ed25519.js.map +1 -1
  46. package/ed448.d.ts +17 -8
  47. package/ed448.d.ts.map +1 -1
  48. package/ed448.js +69 -52
  49. package/ed448.js.map +1 -1
  50. package/index.d.ts +1 -0
  51. package/index.js +20 -4
  52. package/index.js.map +1 -1
  53. package/misc.js +2 -2
  54. package/misc.js.map +1 -1
  55. package/nist.d.ts +20 -2
  56. package/nist.d.ts.map +1 -1
  57. package/nist.js +30 -10
  58. package/nist.js.map +1 -1
  59. package/package.json +14 -13
  60. package/secp256k1.d.ts +10 -7
  61. package/secp256k1.d.ts.map +1 -1
  62. package/secp256k1.js +15 -16
  63. package/secp256k1.js.map +1 -1
  64. package/src/abstract/bls.ts +22 -22
  65. package/src/abstract/curve.ts +19 -5
  66. package/src/abstract/edwards.ts +20 -23
  67. package/src/abstract/hash-to-curve.ts +50 -51
  68. package/src/abstract/modular.ts +7 -5
  69. package/src/abstract/montgomery.ts +12 -18
  70. package/src/abstract/oprf.ts +5 -5
  71. package/src/abstract/poseidon.ts +6 -8
  72. package/src/abstract/weierstrass.ts +139 -89
  73. package/src/bls12-381.ts +4 -15
  74. package/src/bn254.ts +6 -6
  75. package/src/ed25519.ts +65 -40
  76. package/src/ed448.ts +87 -69
  77. package/src/index.ts +19 -3
  78. package/src/misc.ts +2 -2
  79. package/src/nist.ts +31 -15
  80. package/src/secp256k1.ts +16 -18
  81. package/src/utils.ts +33 -83
  82. package/src/webcrypto.ts +148 -107
  83. package/utils.d.ts +4 -20
  84. package/utils.d.ts.map +1 -1
  85. package/utils.js +30 -73
  86. package/utils.js.map +1 -1
  87. package/webcrypto.d.ts +73 -21
  88. package/webcrypto.d.ts.map +1 -1
  89. package/webcrypto.js +101 -76
  90. package/webcrypto.js.map +1 -1
  91. package/_shortw_utils.d.ts +0 -19
  92. package/_shortw_utils.d.ts.map +0 -1
  93. package/_shortw_utils.js +0 -20
  94. package/_shortw_utils.js.map +0 -1
  95. package/abstract/utils.d.ts +0 -5
  96. package/abstract/utils.d.ts.map +0 -1
  97. package/abstract/utils.js +0 -23
  98. package/abstract/utils.js.map +0 -1
  99. package/jubjub.d.ts +0 -12
  100. package/jubjub.d.ts.map +0 -1
  101. package/jubjub.js +0 -15
  102. package/jubjub.js.map +0 -1
  103. package/p256.d.ts +0 -16
  104. package/p256.d.ts.map +0 -1
  105. package/p256.js +0 -13
  106. package/p256.js.map +0 -1
  107. package/p384.d.ts +0 -16
  108. package/p384.d.ts.map +0 -1
  109. package/p384.js +0 -13
  110. package/p384.js.map +0 -1
  111. package/p521.d.ts +0 -16
  112. package/p521.d.ts.map +0 -1
  113. package/p521.js +0 -13
  114. package/p521.js.map +0 -1
  115. package/pasta.d.ts +0 -10
  116. package/pasta.d.ts.map +0 -1
  117. package/pasta.js +0 -13
  118. package/pasta.js.map +0 -1
package/src/nist.ts CHANGED
@@ -19,7 +19,7 @@ import {
19
19
 
20
20
  // p = 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n - 1n
21
21
  // a = Fp256.create(BigInt('-3'));
22
- const p256_CURVE: WeierstrassOpts<bigint> = {
22
+ const p256_CURVE: WeierstrassOpts<bigint> = /* @__PURE__ */ (() => ({
23
23
  p: BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'),
24
24
  n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),
25
25
  h: BigInt(1),
@@ -27,10 +27,10 @@ const p256_CURVE: WeierstrassOpts<bigint> = {
27
27
  b: BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b'),
28
28
  Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'),
29
29
  Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'),
30
- };
30
+ }))();
31
31
 
32
32
  // p = 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
33
- const p384_CURVE: WeierstrassOpts<bigint> = {
33
+ const p384_CURVE: WeierstrassOpts<bigint> = /* @__PURE__ */ (() => ({
34
34
  p: BigInt(
35
35
  '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff'
36
36
  ),
@@ -50,10 +50,10 @@ const p384_CURVE: WeierstrassOpts<bigint> = {
50
50
  Gy: BigInt(
51
51
  '0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f'
52
52
  ),
53
- };
53
+ }))();
54
54
 
55
55
  // p = 2n**521n - 1n
56
- const p521_CURVE: WeierstrassOpts<bigint> = {
56
+ const p521_CURVE: WeierstrassOpts<bigint> = /* @__PURE__ */ (() => ({
57
57
  p: BigInt(
58
58
  '0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
59
59
  ),
@@ -73,21 +73,36 @@ const p521_CURVE: WeierstrassOpts<bigint> = {
73
73
  Gy: BigInt(
74
74
  '0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'
75
75
  ),
76
- };
76
+ }))();
77
77
 
78
78
  type SwuOpts = {
79
79
  A: bigint;
80
80
  B: bigint;
81
81
  Z: bigint;
82
82
  };
83
+
83
84
  function createSWU(Point: WeierstrassPointCons<bigint>, opts: SwuOpts) {
84
85
  const map = mapToCurveSimpleSWU(Point.Fp, opts);
85
86
  return (scalars: bigint[]) => map(scalars[0]);
86
87
  }
87
88
 
88
- /** NIST P256 (aka secp256r1, prime256v1) curve, ECDSA and ECDH methods. */
89
-
89
+ // NIST P256
90
90
  const p256_Point = /* @__PURE__ */ weierstrass(p256_CURVE);
91
+ /**
92
+ * NIST P256 (aka secp256r1, prime256v1) curve, ECDSA and ECDH methods.
93
+ * Hashes inputs with sha256 by default.
94
+ *
95
+ * @example
96
+ * ```js
97
+ * import { p256 } from '@noble/curves/nist.js';
98
+ * const { secretKey, publicKey } = p256.keygen();
99
+ * // const publicKey = p256.getPublicKey(secretKey);
100
+ * const msg = new TextEncoder().encode('hello noble');
101
+ * const sig = p256.sign(msg, secretKey);
102
+ * const isValid = p256.verify(sig, msg, publicKey);
103
+ * // const sigKeccak = p256.sign(keccak256(msg), secretKey, { prehash: false });
104
+ * ```
105
+ */
91
106
  export const p256: ECDSA = /* @__PURE__ */ ecdsa(p256_Point, sha256);
92
107
  /** Hashing / encoding to p256 points / field. RFC 9380 methods. */
93
108
  export const p256_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__ */ (() => {
@@ -109,7 +124,7 @@ export const p256_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__
109
124
  }
110
125
  );
111
126
  })();
112
-
127
+ /** p256 OPRF, defined in RFC 9497. */
113
128
  export const p256_oprf: OPRF = /* @__PURE__ */ (() =>
114
129
  createORPF({
115
130
  name: 'P256-SHA256',
@@ -119,8 +134,9 @@ export const p256_oprf: OPRF = /* @__PURE__ */ (() =>
119
134
  hashToScalar: p256_hasher.hashToScalar,
120
135
  }))();
121
136
 
137
+ // NIST P384
122
138
  const p384_Point = /* @__PURE__ */ weierstrass(p384_CURVE);
123
- /** NIST P384 (aka secp384r1) curve, ECDSA and ECDH methods. */
139
+ /** NIST P384 (aka secp384r1) curve, ECDSA and ECDH methods. Hashes inputs with sha384 by default. */
124
140
  export const p384: ECDSA = /* @__PURE__ */ ecdsa(p384_Point, sha384);
125
141
  /** Hashing / encoding to p384 points / field. RFC 9380 methods. */
126
142
  export const p384_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__ */ (() => {
@@ -142,7 +158,7 @@ export const p384_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__
142
158
  }
143
159
  );
144
160
  })();
145
-
161
+ /** p384 OPRF, defined in RFC 9497. */
146
162
  export const p384_oprf: OPRF = /* @__PURE__ */ (() =>
147
163
  createORPF({
148
164
  name: 'P384-SHA384',
@@ -152,11 +168,11 @@ export const p384_oprf: OPRF = /* @__PURE__ */ (() =>
152
168
  hashToScalar: p384_hasher.hashToScalar,
153
169
  }))();
154
170
 
155
- const Fn521 = /* @__PURE__ */ Field(p521_CURVE.n, { allowedLengths: [65, 66] });
171
+ // NIST P521
172
+ const Fn521 = /* @__PURE__ */ (() => Field(p521_CURVE.n, { allowedLengths: [65, 66] }))();
156
173
  const p521_Point = /* @__PURE__ */ weierstrass(p521_CURVE, { Fn: Fn521 });
157
- /** NIST P521 (aka secp521r1) curve, ECDSA and ECDH methods. */
174
+ /** NIST P521 (aka secp521r1) curve, ECDSA and ECDH methods. Hashes inputs with sha512 by default. */
158
175
  export const p521: ECDSA = /* @__PURE__ */ ecdsa(p521_Point, sha512);
159
-
160
176
  /** Hashing / encoding to p521 points / field. RFC 9380 methods. */
161
177
  export const p521_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__ */ (() => {
162
178
  return createHasher(
@@ -177,7 +193,7 @@ export const p521_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__
177
193
  }
178
194
  );
179
195
  })();
180
-
196
+ /** p521 OPRF, defined in RFC 9497. */
181
197
  export const p521_oprf: OPRF = /* @__PURE__ */ (() =>
182
198
  createORPF({
183
199
  name: 'P521-SHA512',
package/src/secp256k1.ts CHANGED
@@ -8,7 +8,7 @@
8
8
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
9
9
  import { sha256 } from '@noble/hashes/sha2.js';
10
10
  import { randomBytes } from '@noble/hashes/utils.js';
11
- import type { CurveLengths } from './abstract/curve.ts';
11
+ import { createKeygen, type CurveLengths } from './abstract/curve.ts';
12
12
  import { createHasher, type H2CHasher, isogenyMap } from './abstract/hash-to-curve.ts';
13
13
  import { Field, mapHashToField, pow2 } from './abstract/modular.ts';
14
14
  import {
@@ -21,7 +21,7 @@ import {
21
21
  type WeierstrassOpts,
22
22
  type WeierstrassPointCons,
23
23
  } from './abstract/weierstrass.ts';
24
- import { abytes, asciiToBytes, bytesToNumberBE, concatBytes, inRange } from './utils.ts';
24
+ import { abytes, asciiToBytes, bytesToNumberBE, concatBytes } from './utils.ts';
25
25
 
26
26
  // Seems like generator was produced from some seed:
27
27
  // `Pointk1.BASE.multiply(Pointk1.Fn.inv(2n, N)).toAffine().x`
@@ -45,7 +45,6 @@ const secp256k1_ENDO: EndomorphismOpts = {
45
45
  };
46
46
 
47
47
  const _0n = /* @__PURE__ */ BigInt(0);
48
- const _1n = /* @__PURE__ */ BigInt(1);
49
48
  const _2n = /* @__PURE__ */ BigInt(2);
50
49
 
51
50
  /**
@@ -83,20 +82,22 @@ const Pointk1 = /* @__PURE__ */ weierstrass(secp256k1_CURVE, {
83
82
  });
84
83
 
85
84
  /**
86
- * secp256k1 curve, ECDSA and ECDH methods.
85
+ * secp256k1 curve: ECDSA and ECDH methods.
87
86
  *
88
- * Field: `2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n`
87
+ * Uses sha256 to hash messages. To use a different hash,
88
+ * pass `{ prehash: false }` to sign / verify.
89
89
  *
90
90
  * @example
91
91
  * ```js
92
- * import { secp256k1 } from '@noble/curves/secp256k1';
92
+ * import { secp256k1 } from '@noble/curves/secp256k1.js';
93
93
  * const { secretKey, publicKey } = secp256k1.keygen();
94
- * const msg = new TextEncoder().encode('hello');
94
+ * // const publicKey = secp256k1.getPublicKey(secretKey);
95
+ * const msg = new TextEncoder().encode('hello noble');
95
96
  * const sig = secp256k1.sign(msg, secretKey);
96
- * const isValid = secp256k1.verify(sig, msg, publicKey) === true;
97
+ * const isValid = secp256k1.verify(sig, msg, publicKey);
98
+ * // const sigKeccak = secp256k1.sign(keccak256(msg), secretKey, { prehash: false });
97
99
  * ```
98
100
  */
99
-
100
101
  export const secp256k1: ECDSA = /* @__PURE__ */ ecdsa(Pointk1, sha256);
101
102
 
102
103
  // Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code.
@@ -188,16 +189,17 @@ function schnorrSign(
188
189
  * Will swallow errors & return false except for initial type validation of arguments.
189
190
  */
190
191
  function schnorrVerify(signature: Uint8Array, message: Uint8Array, publicKey: Uint8Array): boolean {
191
- const { Fn, BASE } = Pointk1;
192
+ const { Fp, Fn, BASE } = Pointk1;
192
193
  const sig = abytes(signature, 64, 'signature');
193
194
  const m = abytes(message, undefined, 'message');
194
195
  const pub = abytes(publicKey, 32, 'publicKey');
195
196
  try {
196
197
  const P = lift_x(num(pub)); // P = lift_x(int(pk)); fail if that fails
197
198
  const r = num(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.
198
- if (!inRange(r, _1n, secp256k1_CURVE.p)) return false;
199
+ if (!Fp.isValidNot0(r)) return false;
199
200
  const s = num(sig.subarray(32, 64)); // Let s = int(sig[32:64]); fail if s ≥ n.
200
- if (!inRange(s, _1n, secp256k1_CURVE.n)) return false;
201
+ if (!Fn.isValidNot0(s)) return false;
202
+
201
203
  const e = challenge(Fn.toBytes(r), pointToBytes(P), m); // int(challenge(bytes(r)||bytes(P)||m))%n
202
204
  // R = s⋅G - e⋅P, where -eP == (n-e)P
203
205
  const R = BASE.multiplyUnsafe(s).add(P.multiplyUnsafe(Fn.neg(e)));
@@ -229,7 +231,7 @@ export type SecpSchnorr = {
229
231
  * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
230
232
  * @example
231
233
  * ```js
232
- * import { schnorr } from '@noble/curves/secp256k1';
234
+ * import { schnorr } from '@noble/curves/secp256k1.js';
233
235
  * const { secretKey, publicKey } = schnorr.keygen();
234
236
  * // const publicKey = schnorr.getPublicKey(secretKey);
235
237
  * const msg = new TextEncoder().encode('hello');
@@ -243,12 +245,8 @@ export const schnorr: SecpSchnorr = /* @__PURE__ */ (() => {
243
245
  const randomSecretKey = (seed = randomBytes(seedLength)): Uint8Array => {
244
246
  return mapHashToField(seed, secp256k1_CURVE.n);
245
247
  };
246
- function keygen(seed?: Uint8Array) {
247
- const secretKey = randomSecretKey(seed);
248
- return { secretKey, publicKey: schnorrGetPublicKey(secretKey) };
249
- }
250
248
  return {
251
- keygen,
249
+ keygen: createKeygen(randomSecretKey, schnorrGetPublicKey),
252
250
  getPublicKey: schnorrGetPublicKey,
253
251
  sign: schnorrSign,
254
252
  verify: schnorrVerify,
package/src/utils.ts CHANGED
@@ -9,18 +9,15 @@ import {
9
9
  bytesToHex as bytesToHex_,
10
10
  concatBytes as concatBytes_,
11
11
  hexToBytes as hexToBytes_,
12
- isBytes as isBytes_,
13
12
  } from '@noble/hashes/utils.js';
14
13
  export {
15
14
  abytes,
16
15
  anumber,
17
16
  bytesToHex,
18
- bytesToUtf8,
19
17
  concatBytes,
20
18
  hexToBytes,
21
19
  isBytes,
22
20
  randomBytes,
23
- utf8ToBytes
24
21
  } from '@noble/hashes/utils.js';
25
22
  const _0n = /* @__PURE__ */ BigInt(0);
26
23
  const _1n = /* @__PURE__ */ BigInt(1);
@@ -34,22 +31,29 @@ export type CHash = {
34
31
  export type FHash = (message: Uint8Array) => Uint8Array;
35
32
  export function abool(value: boolean, title: string = ''): boolean {
36
33
  if (typeof value !== 'boolean') {
37
- const prefix = title && `"${title}"`;
34
+ const prefix = title && `"${title}" `;
38
35
  throw new Error(prefix + 'expected boolean, got type=' + typeof value);
39
36
  }
40
37
  return value;
41
38
  }
42
39
 
43
40
  // Used in weierstrass, der
44
- function abignumer(n: number | bigint) {
41
+ function abignumber(n: number | bigint) {
45
42
  if (typeof n === 'bigint') {
46
43
  if (!isPosBig(n)) throw new Error('positive bigint expected, got ' + n);
47
44
  } else anumber(n);
48
45
  return n;
49
46
  }
50
47
 
48
+ export function asafenumber(value: number, title: string = ''): void {
49
+ if (!Number.isSafeInteger(value)) {
50
+ const prefix = title && `"${title}" `;
51
+ throw new Error(prefix + 'expected safe integer, got type=' + typeof value);
52
+ }
53
+ }
54
+
51
55
  export function numberToHexUnpadded(num: number | bigint): string {
52
- const hex = abignumer(num).toString(16);
56
+ const hex = abignumber(num).toString(16);
53
57
  return hex.length & 1 ? '0' + hex : hex;
54
58
  }
55
59
 
@@ -68,7 +72,7 @@ export function bytesToNumberLE(bytes: Uint8Array): bigint {
68
72
 
69
73
  export function numberToBytesBE(n: number | bigint, len: number): Uint8Array {
70
74
  anumber(len);
71
- n = abignumer(n);
75
+ n = abignumber(n);
72
76
  const res = hexToBytes_(n.toString(16).padStart(len * 2, '0'));
73
77
  if (res.length !== len) throw new Error('number too large');
74
78
  return res;
@@ -78,7 +82,7 @@ export function numberToBytesLE(n: number | bigint, len: number): Uint8Array {
78
82
  }
79
83
  // Unpadded, rarely used
80
84
  export function numberToVarBytesBE(n: number | bigint): Uint8Array {
81
- return hexToBytes_(numberToHexUnpadded(abignumer(n)));
85
+ return hexToBytes_(numberToHexUnpadded(abignumber(n)));
82
86
  }
83
87
 
84
88
  // Compares 2 u8a-s in kinda constant time
@@ -114,16 +118,6 @@ export function asciiToBytes(ascii: string): Uint8Array {
114
118
  });
115
119
  }
116
120
 
117
- /**
118
- * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
119
- */
120
- // export const utf8ToBytes: typeof utf8ToBytes_ = utf8ToBytes_;
121
- /**
122
- * Converts bytes to string using UTF8 encoding.
123
- * @example bytesToUtf8(Uint8Array.from([97, 98, 99])) // 'abc'
124
- */
125
- // export const bytesToUtf8: typeof bytesToUtf8_ = bytesToUtf8_;
126
-
127
121
  // Is positive bigint
128
122
  const isPosBig = (n: bigint) => typeof n === 'bigint' && _0n <= n;
129
123
 
@@ -194,14 +188,18 @@ type Pred<T> = (v: Uint8Array) => T | undefined;
194
188
  export function createHmacDrbg<T>(
195
189
  hashLen: number,
196
190
  qByteLen: number,
197
- hmacFn: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array
191
+ hmacFn: (key: Uint8Array, message: Uint8Array) => Uint8Array
198
192
  ): (seed: Uint8Array, predicate: Pred<T>) => T {
199
- if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number');
200
- if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number');
193
+ anumber(hashLen, 'hashLen');
194
+ anumber(qByteLen, 'qByteLen');
201
195
  if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function');
196
+ const u8n = (len: number): Uint8Array => new Uint8Array(len); // creates Uint8Array
197
+ const NULL = u8n(0);
198
+ const byte0 = Uint8Array.of(0x00);
199
+ const byte1 = Uint8Array.of(0x01);
200
+ const _maxDrbgIters = 1000;
201
+
202
202
  // Step B, Step C: set hashLen to 8*ceil(hlen/8)
203
- const u8n = (len: number) => new Uint8Array(len); // creates Uint8Array
204
- const u8of = (byte: number) => Uint8Array.of(byte); // another shortcut
205
203
  let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
206
204
  let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same
207
205
  let i = 0; // Iterations counter, will throw when over 1000
@@ -210,18 +208,18 @@ export function createHmacDrbg<T>(
210
208
  k.fill(0);
211
209
  i = 0;
212
210
  };
213
- const h = (...b: Uint8Array[]) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)
214
- const reseed = (seed = u8n(0)) => {
211
+ const h = (...msgs: Uint8Array[]) => hmacFn(k, concatBytes_(v, ...msgs)); // hmac(k)(v, ...values)
212
+ const reseed = (seed = NULL) => {
215
213
  // HMAC-DRBG reseed() function. Steps D-G
216
- k = h(u8of(0x00), seed); // k = hmac(k || v || 0x00 || seed)
214
+ k = h(byte0, seed); // k = hmac(k || v || 0x00 || seed)
217
215
  v = h(); // v = hmac(k || v)
218
216
  if (seed.length === 0) return;
219
- k = h(u8of(0x01), seed); // k = hmac(k || v || 0x01 || seed)
217
+ k = h(byte1, seed); // k = hmac(k || v || 0x01 || seed)
220
218
  v = h(); // v = hmac(k || v)
221
219
  };
222
220
  const gen = () => {
223
221
  // HMAC-DRBG generate() function
224
- if (i++ >= 1000) throw new Error('drbg: tried 1000 values');
222
+ if (i++ >= _maxDrbgIters) throw new Error('drbg: tried max amount of iterations');
225
223
  let len = 0;
226
224
  const out: Uint8Array[] = [];
227
225
  while (len < qByteLen) {
@@ -232,7 +230,7 @@ export function createHmacDrbg<T>(
232
230
  }
233
231
  return concatBytes_(...out);
234
232
  };
235
- const genUntil = (seed: Uint8Array, pred: Pred<T>): T => {
233
+ const genUntil = (seed: Uint8Array<any>, pred: Pred<T>): T => {
236
234
  reset();
237
235
  reseed(seed); // Steps D-G
238
236
  let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1]
@@ -243,59 +241,9 @@ export function createHmacDrbg<T>(
243
241
  return genUntil;
244
242
  }
245
243
 
246
- // Validating curves and fields
247
-
248
- const validatorFns = {
249
- bigint: (val: any): boolean => typeof val === 'bigint',
250
- function: (val: any): boolean => typeof val === 'function',
251
- boolean: (val: any): boolean => typeof val === 'boolean',
252
- string: (val: any): boolean => typeof val === 'string',
253
- stringOrUint8Array: (val: any): boolean => typeof val === 'string' || isBytes_(val),
254
- isSafeInteger: (val: any): boolean => Number.isSafeInteger(val),
255
- array: (val: any): boolean => Array.isArray(val),
256
- field: (val: any, object: any): any => (object as any).Fp.isValid(val),
257
- hash: (val: any): boolean => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
258
- } as const;
259
- type Validator = keyof typeof validatorFns;
260
- type ValMap<T extends Record<string, any>> = { [K in keyof T]?: Validator };
261
- // type Record<K extends string | number | symbol, T> = { [P in K]: T; }
262
-
263
- export function validateObject<T extends Record<string, any>>(
264
- object: T,
265
- validators: ValMap<T>,
266
- optValidators: ValMap<T> = {}
267
- ): T {
268
- const checkField = (fieldName: keyof T, type: Validator, isOptional: boolean) => {
269
- const checkVal = validatorFns[type];
270
- if (typeof checkVal !== 'function') throw new Error('invalid validator function');
271
-
272
- const val = object[fieldName as keyof typeof object];
273
- if (isOptional && val === undefined) return;
274
- if (!checkVal(val, object)) {
275
- throw new Error(
276
- 'param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val
277
- );
278
- }
279
- };
280
- for (const [fieldName, type] of Object.entries(validators)) checkField(fieldName, type!, false);
281
- for (const [fieldName, type] of Object.entries(optValidators)) checkField(fieldName, type!, true);
282
- return object;
283
- }
284
- // validate type tests
285
- // const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 };
286
- // const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok!
287
- // // Should fail type-check
288
- // const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' });
289
- // const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' });
290
- // const z3 = validateObject(o, { test: 'boolean', z: 'bug' });
291
- // const z4 = validateObject(o, { a: 'boolean', z: 'bug' });
292
-
293
- export function isHash(val: CHash): boolean {
294
- return typeof val === 'function' && Number.isSafeInteger(val.outputLen);
295
- }
296
- export function _validateObject(
244
+ export function validateObject(
297
245
  object: Record<string, any>,
298
- fields: Record<string, string>,
246
+ fields: Record<string, string> = {},
299
247
  optFields: Record<string, string> = {}
300
248
  ): void {
301
249
  if (!object || typeof object !== 'object') throw new Error('expected valid options object');
@@ -307,8 +255,10 @@ export function _validateObject(
307
255
  if (current !== expectedType || val === null)
308
256
  throw new Error(`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`);
309
257
  }
310
- Object.entries(fields).forEach(([k, v]) => checkField(k, v, false));
311
- Object.entries(optFields).forEach(([k, v]) => checkField(k, v, true));
258
+ const iter = (f: typeof fields, isOpt: boolean) =>
259
+ Object.entries(f).forEach(([k, v]) => checkField(k, v, isOpt));
260
+ iter(fields, false);
261
+ iter(optFields, true);
312
262
  }
313
263
 
314
264
  /**