@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
@@ -14,6 +14,8 @@ import {
14
14
  randomBytes,
15
15
  validateObject,
16
16
  type CryptoKeys,
17
+ type TArg,
18
+ type TRet,
17
19
  } from '../utils.ts';
18
20
  import { createKeygen, type CurveLengths } from './curve.ts';
19
21
  import { mod } from './modular.ts';
@@ -22,41 +24,118 @@ const _0n = BigInt(0);
22
24
  const _1n = BigInt(1);
23
25
  const _2n = BigInt(2);
24
26
 
27
+ /** Curve-specific hooks required to build one X25519/X448 helper. */
25
28
  export type MontgomeryOpts = {
26
- P: bigint; // finite field prime
29
+ /** Prime field modulus. */
30
+ P: bigint;
31
+ /** RFC 7748 variant name. */
27
32
  type: 'x25519' | 'x448';
28
- adjustScalarBytes: (bytes: Uint8Array) => Uint8Array;
33
+ /**
34
+ * Clamp or otherwise normalize one scalar byte string before use.
35
+ * @param bytes - Raw secret scalar bytes.
36
+ * @returns Adjusted scalar bytes ready for Montgomery multiplication.
37
+ */
38
+ adjustScalarBytes: (bytes: TArg<Uint8Array>) => TRet<Uint8Array>;
39
+ /**
40
+ * Invert one field element with exponentiation by `p - 2`.
41
+ * @param x - Field element to invert.
42
+ * @returns Multiplicative inverse of `x`.
43
+ */
29
44
  powPminus2: (x: bigint) => bigint;
30
- randomBytes?: (bytesLength?: number) => Uint8Array;
45
+ /**
46
+ * Optional randomness source for `keygen()` and `utils.randomSecretKey()`.
47
+ * Receives the requested byte length and returns fresh random bytes.
48
+ */
49
+ randomBytes?: (bytesLength?: number) => TRet<Uint8Array>;
31
50
  };
32
51
 
52
+ /** Public X25519/X448 ECDH API built on a Montgomery ladder. */
33
53
  export type MontgomeryECDH = {
34
- scalarMult: (scalar: Uint8Array, u: Uint8Array) => Uint8Array;
35
- scalarMultBase: (scalar: Uint8Array) => Uint8Array;
36
- getSharedSecret: (secretKeyA: Uint8Array, publicKeyB: Uint8Array) => Uint8Array;
37
- getPublicKey: (secretKey: Uint8Array) => Uint8Array;
54
+ /**
55
+ * Multiply one scalar by one Montgomery `u` coordinate.
56
+ * @param scalar - Secret scalar bytes.
57
+ * @param u - Public Montgomery `u` coordinate.
58
+ * @returns Shared point encoded as bytes.
59
+ */
60
+ scalarMult: (scalar: TArg<Uint8Array>, u: TArg<Uint8Array>) => TRet<Uint8Array>;
61
+ /**
62
+ * Multiply one scalar by the curve base point.
63
+ * @param scalar - Secret scalar bytes.
64
+ * @returns Public key bytes.
65
+ */
66
+ scalarMultBase: (scalar: TArg<Uint8Array>) => TRet<Uint8Array>;
67
+ /**
68
+ * Derive a shared secret from a local secret key and peer public key.
69
+ * @param secretKeyA - Local secret key bytes.
70
+ * @param publicKeyB - Peer public key bytes.
71
+ * Rejects low-order public inputs instead of returning the all-zero shared secret.
72
+ * @returns Shared secret bytes.
73
+ */
74
+ getSharedSecret: (secretKeyA: TArg<Uint8Array>, publicKeyB: TArg<Uint8Array>) => TRet<Uint8Array>;
75
+ /**
76
+ * Derive one public key from a secret key.
77
+ * @param secretKey - Secret key bytes.
78
+ * @returns Public key bytes.
79
+ */
80
+ getPublicKey: (secretKey: TArg<Uint8Array>) => TRet<Uint8Array>;
81
+ /** Utility helpers for secret-key generation. */
38
82
  utils: {
39
- randomSecretKey: () => Uint8Array;
83
+ /** Generate one random secret key with the curve's expected byte length. */
84
+ randomSecretKey: () => TRet<Uint8Array>;
40
85
  };
41
- GuBytes: Uint8Array;
86
+ /** Encoded Montgomery base point `u`. */
87
+ GuBytes: TRet<Uint8Array>;
88
+ /** Public lengths for keys and seeds. */
42
89
  lengths: CurveLengths;
43
- keygen: (seed?: Uint8Array) => { secretKey: Uint8Array; publicKey: Uint8Array };
90
+ /**
91
+ * Generate one random secret/public keypair.
92
+ * @param seed - Optional seed bytes to use instead of random generation.
93
+ * @returns Fresh secret/public keypair.
94
+ */
95
+ keygen: (seed?: TArg<Uint8Array>) => {
96
+ secretKey: TRet<Uint8Array>;
97
+ publicKey: TRet<Uint8Array>;
98
+ };
44
99
  };
45
100
 
46
- function validateOpts(curve: MontgomeryOpts) {
47
- validateObject(curve, {
48
- adjustScalarBytes: 'function',
49
- powPminus2: 'function',
50
- });
101
+ function validateOpts(curve: TArg<MontgomeryOpts>) {
102
+ // Validate constructor config eagerly, but do not call user-provided hooks here:
103
+ // `randomBytes` may be transcript-backed or otherwise contextual. Runtime type checks are
104
+ // enough to fail fast on malformed configs without consuming user state.
105
+ validateObject(
106
+ curve,
107
+ {
108
+ P: 'bigint',
109
+ type: 'string',
110
+ adjustScalarBytes: 'function',
111
+ powPminus2: 'function',
112
+ },
113
+ {
114
+ randomBytes: 'function',
115
+ }
116
+ );
51
117
  return Object.freeze({ ...curve } as const);
52
118
  }
53
119
 
54
- export function montgomery(curveDef: MontgomeryOpts): MontgomeryECDH {
120
+ /**
121
+ * @param curveDef - Montgomery curve definition.
122
+ * @returns ECDH helper namespace.
123
+ * @throws If the curve definition or derived shared point is invalid. {@link Error}
124
+ * @example
125
+ * Perform one X25519 key exchange through the generic Montgomery helper.
126
+ *
127
+ * ```ts
128
+ * import { x25519 } from '@noble/curves/ed25519.js';
129
+ * const alice = x25519.keygen();
130
+ * const shared = x25519.getSharedSecret(alice.secretKey, alice.publicKey);
131
+ * ```
132
+ */
133
+ export function montgomery(curveDef: TArg<MontgomeryOpts>): TRet<MontgomeryECDH> {
55
134
  const CURVE = validateOpts(curveDef);
56
135
  const { P, type, adjustScalarBytes, powPminus2, randomBytes: rand } = CURVE;
57
136
  const is25519 = type === 'x25519';
58
137
  if (!is25519 && type !== 'x448') throw new Error('invalid type');
59
- const randomBytes_ = rand || randomBytes;
138
+ const randomBytes_ = rand === undefined ? randomBytes : rand;
60
139
 
61
140
  const montgomeryBits = is25519 ? 255 : 448;
62
141
  const fieldLen = is25519 ? 32 : 56;
@@ -64,7 +143,7 @@ export function montgomery(curveDef: MontgomeryOpts): MontgomeryECDH {
64
143
  // RFC 7748 #5:
65
144
  // The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519 and
66
145
  // (156326 - 2) / 4 = 39081 for curve448/X448
67
- // const a = is25519 ? 156326n : 486662n;
146
+ // const a = is25519 ? 486662n : 156326n;
68
147
  const a24 = is25519 ? BigInt(121665) : BigInt(39081);
69
148
  // RFC: x25519 "the resulting integer is of the form 2^254 plus
70
149
  // eight times a value between 0 and 2^251 - 1 (inclusive)"
@@ -76,10 +155,10 @@ export function montgomery(curveDef: MontgomeryOpts): MontgomeryECDH {
76
155
  const maxScalar = minScalar + maxAdded + _1n; // (inclusive)
77
156
  const modP = (n: bigint) => mod(n, P);
78
157
  const GuBytes = encodeU(Gu);
79
- function encodeU(u: bigint): Uint8Array {
158
+ function encodeU(u: bigint): TRet<Uint8Array> {
80
159
  return numberToBytesLE(modP(u), fieldLen);
81
160
  }
82
- function decodeU(u: Uint8Array): bigint {
161
+ function decodeU(u: TArg<Uint8Array>): bigint {
83
162
  const _u = copyBytes(abytes(u, fieldLen, 'uCoordinate'));
84
163
  // RFC: When receiving such an array, implementations of X25519
85
164
  // (but not X448) MUST mask the most significant bit in the final byte.
@@ -90,10 +169,10 @@ export function montgomery(curveDef: MontgomeryOpts): MontgomeryECDH {
90
169
  // - 1 through 2^448 - 1 for X448.
91
170
  return modP(bytesToNumberLE(_u));
92
171
  }
93
- function decodeScalar(scalar: Uint8Array): bigint {
172
+ function decodeScalar(scalar: TArg<Uint8Array>): bigint {
94
173
  return bytesToNumberLE(adjustScalarBytes(copyBytes(abytes(scalar, fieldLen, 'scalar'))));
95
174
  }
96
- function scalarMult(scalar: Uint8Array, u: Uint8Array): Uint8Array {
175
+ function scalarMult(scalar: TArg<Uint8Array>, u: TArg<Uint8Array>): TRet<Uint8Array> {
97
176
  const pu = montgomeryLadder(decodeU(u), decodeScalar(scalar));
98
177
  // Some public keys are useless, of low-order. Curve author doesn't think
99
178
  // it needs to be validated, but we do it nonetheless.
@@ -102,7 +181,7 @@ export function montgomery(curveDef: MontgomeryOpts): MontgomeryECDH {
102
181
  return encodeU(pu);
103
182
  }
104
183
  // Computes public key from private. By doing scalar multiplication of base point.
105
- function scalarMultBase(scalar: Uint8Array): Uint8Array {
184
+ function scalarMultBase(scalar: TArg<Uint8Array>): TRet<Uint8Array> {
106
185
  return scalarMult(scalar, GuBytes);
107
186
  }
108
187
  const getPublicKey = scalarMultBase;
@@ -120,10 +199,10 @@ export function montgomery(curveDef: MontgomeryOpts): MontgomeryECDH {
120
199
  }
121
200
 
122
201
  /**
123
- * Montgomery x-only multiplication ladder.
124
- * @param pointU u coordinate (x) on Montgomery Curve 25519
125
- * @param scalar by which the point would be multiplied
126
- * @returns new Point on Montgomery curve
202
+ * Montgomery x-only multiplication ladder for the selected X25519/X448 curve.
203
+ * @param pointU - decoded Montgomery u coordinate for the selected curve
204
+ * @param scalar - decoded clamped scalar by which the point is multiplied
205
+ * @returns resulting Montgomery u coordinate for the selected curve
127
206
  */
128
207
  function montgomeryLadder(u: bigint, scalar: bigint): bigint {
129
208
  aInRange('u', u, _0n, P);
@@ -168,11 +247,16 @@ export function montgomery(curveDef: MontgomeryOpts): MontgomeryECDH {
168
247
  publicKey: fieldLen,
169
248
  seed: fieldLen,
170
249
  };
171
- const randomSecretKey = (seed = randomBytes_(fieldLen)) => {
250
+ const randomSecretKey = (seed?: TArg<Uint8Array>): TRet<Uint8Array> => {
251
+ seed = seed === undefined ? randomBytes_(fieldLen) : seed;
172
252
  abytes(seed, lengths.seed, 'seed');
173
- return seed;
253
+ // Reuse caller-supplied seed bytes verbatim; clamping is deferred until
254
+ // decodeScalar(...) when the secret key is actually used.
255
+ return seed as TRet<Uint8Array>;
174
256
  };
175
257
  const utils = { randomSecretKey };
258
+ Object.freeze(lengths);
259
+ Object.freeze(utils);
176
260
 
177
261
  return Object.freeze({
178
262
  keygen: createKeygen(randomSecretKey, getPublicKey),
@@ -181,7 +265,7 @@ export function montgomery(curveDef: MontgomeryOpts): MontgomeryECDH {
181
265
  scalarMult,
182
266
  scalarMultBase,
183
267
  utils,
184
- GuBytes: GuBytes.slice(),
268
+ GuBytes: GuBytes.slice() as TRet<Uint8Array>,
185
269
  lengths,
186
270
  }) satisfies CryptoKeys;
187
271
  }