@noble/curves 0.8.2 → 0.9.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 (108) hide show
  1. package/README.md +232 -176
  2. package/_shortw_utils.d.ts +3 -2
  3. package/_shortw_utils.d.ts.map +1 -1
  4. package/abstract/bls.d.ts +15 -15
  5. package/abstract/bls.d.ts.map +1 -1
  6. package/abstract/bls.js.map +1 -1
  7. package/abstract/curve.d.ts +9 -7
  8. package/abstract/curve.d.ts.map +1 -1
  9. package/abstract/curve.js +5 -1
  10. package/abstract/curve.js.map +1 -1
  11. package/abstract/edwards.d.ts +4 -3
  12. package/abstract/edwards.d.ts.map +1 -1
  13. package/abstract/hash-to-curve.d.ts +6 -6
  14. package/abstract/hash-to-curve.d.ts.map +1 -1
  15. package/abstract/hash-to-curve.js.map +1 -1
  16. package/abstract/modular.d.ts +24 -12
  17. package/abstract/modular.d.ts.map +1 -1
  18. package/abstract/modular.js +16 -3
  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/poseidon.d.ts +4 -4
  23. package/abstract/poseidon.d.ts.map +1 -1
  24. package/abstract/poseidon.js.map +1 -1
  25. package/abstract/utils.d.ts +7 -7
  26. package/abstract/utils.d.ts.map +1 -1
  27. package/abstract/weierstrass.d.ts +40 -18
  28. package/abstract/weierstrass.d.ts.map +1 -1
  29. package/abstract/weierstrass.js +20 -6
  30. package/abstract/weierstrass.js.map +1 -1
  31. package/bls12-381.d.ts +14 -14
  32. package/bls12-381.d.ts.map +1 -1
  33. package/bls12-381.js +2 -2
  34. package/bls12-381.js.map +1 -1
  35. package/bn.js +1 -1
  36. package/bn.js.map +1 -1
  37. package/ed25519.d.ts +1 -1
  38. package/ed25519.d.ts.map +1 -1
  39. package/ed25519.js +2 -2
  40. package/ed25519.js.map +1 -1
  41. package/ed448.js +1 -1
  42. package/ed448.js.map +1 -1
  43. package/esm/abstract/bls.js.map +1 -1
  44. package/esm/abstract/curve.js +5 -1
  45. package/esm/abstract/curve.js.map +1 -1
  46. package/esm/abstract/hash-to-curve.js.map +1 -1
  47. package/esm/abstract/modular.js +14 -1
  48. package/esm/abstract/modular.js.map +1 -1
  49. package/esm/abstract/poseidon.js.map +1 -1
  50. package/esm/abstract/weierstrass.js +20 -6
  51. package/esm/abstract/weierstrass.js.map +1 -1
  52. package/esm/bls12-381.js +2 -2
  53. package/esm/bls12-381.js.map +1 -1
  54. package/esm/bn.js +2 -2
  55. package/esm/bn.js.map +1 -1
  56. package/esm/ed25519.js +3 -2
  57. package/esm/ed25519.js.map +1 -1
  58. package/esm/ed448.js +1 -1
  59. package/esm/ed448.js.map +1 -1
  60. package/esm/jubjub.js +2 -2
  61. package/esm/jubjub.js.map +1 -1
  62. package/esm/p256.js +1 -1
  63. package/esm/p256.js.map +1 -1
  64. package/esm/p384.js +1 -1
  65. package/esm/p384.js.map +1 -1
  66. package/esm/p521.js +1 -1
  67. package/esm/p521.js.map +1 -1
  68. package/esm/pasta.js +2 -2
  69. package/esm/pasta.js.map +1 -1
  70. package/esm/secp256k1.js +1 -1
  71. package/esm/secp256k1.js.map +1 -1
  72. package/jubjub.js +1 -1
  73. package/jubjub.js.map +1 -1
  74. package/p256.d.ts +4 -2
  75. package/p256.d.ts.map +1 -1
  76. package/p256.js +1 -1
  77. package/p256.js.map +1 -1
  78. package/p384.d.ts +4 -2
  79. package/p384.d.ts.map +1 -1
  80. package/p384.js +1 -1
  81. package/p384.js.map +1 -1
  82. package/p521.d.ts +4 -2
  83. package/p521.d.ts.map +1 -1
  84. package/p521.js +1 -1
  85. package/p521.js.map +1 -1
  86. package/package.json +9 -9
  87. package/pasta.js +2 -2
  88. package/pasta.js.map +1 -1
  89. package/secp256k1.d.ts +2 -1
  90. package/secp256k1.d.ts.map +1 -1
  91. package/secp256k1.js +1 -1
  92. package/secp256k1.js.map +1 -1
  93. package/src/abstract/bls.ts +11 -11
  94. package/src/abstract/curve.ts +7 -3
  95. package/src/abstract/hash-to-curve.ts +2 -2
  96. package/src/abstract/modular.ts +28 -19
  97. package/src/abstract/poseidon.ts +2 -2
  98. package/src/abstract/weierstrass.ts +27 -11
  99. package/src/bls12-381.ts +5 -5
  100. package/src/bn.ts +2 -2
  101. package/src/ed25519.ts +1 -1
  102. package/src/ed448.ts +1 -1
  103. package/src/jubjub.ts +2 -2
  104. package/src/p256.ts +1 -1
  105. package/src/p384.ts +1 -1
  106. package/src/p521.ts +1 -1
  107. package/src/pasta.ts +2 -2
  108. package/src/secp256k1.ts +2 -3
package/README.md CHANGED
@@ -1,28 +1,21 @@
1
1
  # noble-curves
2
2
 
3
- [Audited](#security) & minimal JS implementation of elliptic curve cryptography.
3
+ Audited & minimal JS implementation of elliptic curve cryptography.
4
4
 
5
- - **noble** family, zero dependencies
6
5
  - Short Weierstrass, Edwards, Montgomery curves
7
6
  - ECDSA, EdDSA, Schnorr, BLS signature schemes, ECDH key agreement
7
+ - 🔒 [**Audited**](#security) by an independent security firm
8
8
  - #️⃣ [hash to curve](#abstracthash-to-curve-hashing-strings-to-curve-points)
9
9
  for encoding or hashing an arbitrary string to an elliptic curve point
10
10
  - 🧜‍♂️ [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash
11
11
  - 🏎 [Ultra-fast](#speed), hand-optimized for caveats of JS engines
12
- - 🔍 Unique tests ensure correctness with Wycheproof vectors and [cryptofuzz](https://github.com/guidovranken/cryptofuzz) differential fuzzing
13
- - 🔻 Tree-shaking-friendly: there is no entry point, which ensures small size of your app
12
+ - 🔍 Unique tests ensure correctness with Wycheproof vectors and
13
+ [cryptofuzz](https://github.com/guidovranken/cryptofuzz) differential fuzzing
14
+ - 🔻 Tree-shaking-friendly: use only what's necessary, other code won't be included
14
15
 
15
- Package consists of two parts:
16
-
17
- 1. [Abstract](#abstract-api), zero-dependency EC algorithms
18
- 2. [Implementations](#implementations), utilizing one dependency `@noble/hashes`, providing ready-to-use:
19
- - NIST curves secp256r1/P256, secp384r1/P384, secp521r1/P521
20
- - SECG curve secp256k1
21
- - ed25519/curve25519/x25519/ristretto255, edwards448/curve448/x448 [RFC7748](https://www.rfc-editor.org/rfc/rfc7748) / [RFC8032](https://www.rfc-editor.org/rfc/rfc8032) / [ZIP215](https://zips.z.cash/zip-0215) stuff
22
- - pairing-friendly curves bls12-381, bn254
23
-
24
- Check out [Upgrading](#upgrading) if you've previously used single-feature noble packages
25
- ([secp256k1](https://github.com/paulmillr/noble-secp256k1), [ed25519](https://github.com/paulmillr/noble-ed25519)).
16
+ Check out [Upgrading](#upgrading) if you've previously used single-feature noble
17
+ packages ([secp256k1](https://github.com/paulmillr/noble-secp256k1),
18
+ [ed25519](https://github.com/paulmillr/noble-ed25519)).
26
19
  See [Resources](#resources) for articles and real-world software that uses curves.
27
20
 
28
21
  ### This library belongs to _noble_ crypto
@@ -30,33 +23,50 @@ See [Resources](#resources) for articles and real-world software that uses curve
30
23
  > **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools.
31
24
 
32
25
  - No dependencies, protection against supply chain attacks
33
- - Easily auditable TypeScript/JS code
26
+ - Auditable TypeScript / JS code
34
27
  - Supported in all major browsers and stable node.js versions
35
28
  - All releases are signed with PGP keys
36
29
  - Check out [homepage](https://paulmillr.com/noble/) & all libraries:
37
30
  [curves](https://github.com/paulmillr/noble-curves)
38
- ([secp256k1](https://github.com/paulmillr/noble-secp256k1),
31
+ (4kb versions [secp256k1](https://github.com/paulmillr/noble-secp256k1),
39
32
  [ed25519](https://github.com/paulmillr/noble-ed25519)),
40
33
  [hashes](https://github.com/paulmillr/noble-hashes)
41
34
 
42
35
  ## Usage
43
36
 
44
- Use NPM for browser / node.js:
37
+ Browser, deno and node.js are supported:
45
38
 
46
39
  > npm install @noble/curves
47
40
 
48
- For [Deno](https://deno.land), use it with [npm specifier](https://deno.land/manual@v1.28.0/node/npm_specifiers). In browser, you could also include the single file from
41
+ For [Deno](https://deno.land), use it with
42
+ [npm specifier](https://deno.land/manual@v1.28.0/node/npm_specifiers).
43
+ In browser, you could also include the single file from
49
44
  [GitHub's releases page](https://github.com/paulmillr/noble-curves/releases).
50
45
 
51
- The library is tree-shaking-friendly and does not expose root entry point as `import * from '@noble/curves'`.
52
- Instead, you need to import specific primitives. This is done to ensure small size of your apps.
46
+ The library is tree-shaking-friendly and does not expose root entry point as
47
+ `import * from '@noble/curves'`. Instead, you need to import specific primitives.
48
+ This is done to ensure small size of your apps.
49
+
50
+ Package consists of two parts:
51
+
52
+ 1. [Implementations](#implementations), utilizing one dependency `@noble/hashes`,
53
+ providing ready-to-use:
54
+ - NIST curves secp256r1/P256, secp384r1/P384, secp521r1/P521
55
+ - SECG curve secp256k1
56
+ - ed25519/curve25519/x25519/ristretto255, edwards448/curve448/x448
57
+ implementing
58
+ [RFC7748](https://www.rfc-editor.org/rfc/rfc7748) /
59
+ [RFC8032](https://www.rfc-editor.org/rfc/rfc8032) /
60
+ [ZIP215](https://zips.z.cash/zip-0215) standards
61
+ - pairing-friendly curves bls12-381, bn254
62
+ 2. [Abstract](#abstract-api), zero-dependency EC algorithms
53
63
 
54
64
  ### Implementations
55
65
 
56
66
  Each curve can be used in the following way:
57
67
 
58
68
  ```ts
59
- import { secp256k1 } from '@noble/curves/secp256k1'; // ECMAScript Modules (ESM) and Common.js
69
+ import { secp256k1 } from '@noble/curves/secp256k1'; // ESM and Common.js
60
70
  // import { secp256k1 } from 'npm:@noble/curves@1.2.0/secp256k1'; // Deno
61
71
  const priv = secp256k1.utils.randomPrivateKey();
62
72
  const pub = secp256k1.getPublicKey(priv);
@@ -64,8 +74,9 @@ const msg = new Uint8Array(32).fill(1);
64
74
  const sig = secp256k1.sign(msg, priv);
65
75
  secp256k1.verify(sig, msg, pub) === true;
66
76
 
77
+ // hex strings are also supported besides Uint8Arrays:
67
78
  const privHex = '46c930bc7bb4db7f55da20798697421b98c4175a52c630294d75a84b9c126236';
68
- const pub2 = secp256k1.getPublicKey(privHex); // keys & other inputs can be Uint8Array-s or hex strings
79
+ const pub2 = secp256k1.getPublicKey(privHex);
69
80
  ```
70
81
 
71
82
  All curves:
@@ -90,7 +101,7 @@ Weierstrass curves feature recovering public keys from signatures and ECDH key a
90
101
  const sigImprovedSecurity = secp256k1.sign(msg, priv, { extraEntropy: true });
91
102
  sig.recoverPublicKey(msg) === pub; // public key recovery
92
103
  const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
93
- const shared = secp256k1.getSharedSecret(priv, someonesPub); // ECDH (elliptic curve diffie-hellman)
104
+ const shared = secp256k1.getSharedSecret(priv, someonesPub); // ECDH
94
105
  ```
95
106
 
96
107
  secp256k1 has schnorr signature implementation which follows
@@ -103,7 +114,6 @@ const pub = schnorr.getPublicKey(priv);
103
114
  const msg = new TextEncoder().encode('hello');
104
115
  const sig = schnorr.sign(msg, priv);
105
116
  const isValid = schnorr.verify(sig, msg, pub);
106
- console.log(isValid);
107
117
  ```
108
118
 
109
119
  ed25519 module has ed25519ctx / ed25519ph variants,
@@ -134,18 +144,27 @@ RistrettoPoint.hashToCurve('Ristretto is traditionally a short shot of espresso
134
144
  // also has add(), equals(), multiply(), toRawBytes() methods
135
145
  ```
136
146
 
137
- ed448 module is basically the same:
147
+ ed448 is similar:
138
148
 
139
149
  ```ts
140
150
  import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448';
141
151
  import { hashToCurve, encodeToCurve } from '@noble/curves/ed448';
152
+ ed448.getPublicKey(ed448.utils.randomPrivateKey());
153
+ ```
154
+
155
+ Every curve has params:
156
+
157
+ ```ts
158
+ import { secp256k1 } from '@noble/curves/secp256k1'; // ESM and Common.js
159
+ console.log(secp256k1.CURVE.p, secp256k1.CURVE.n, secp256k1.CURVE.a, secp256k1.CURVE.b);
142
160
  ```
143
161
 
144
162
  BLS12-381 pairing-friendly Barreto-Lynn-Scott elliptic curve construction allows to
145
163
  construct [zk-SNARKs](https://z.cash/technology/zksnarks/) at the 128-bit security
146
164
  and use aggregated, batch-verifiable
147
165
  [threshold signatures](https://medium.com/snigirev.stepan/bls-signatures-better-than-schnorr-5a7fe30ea716),
148
- using Boneh-Lynn-Shacham signature scheme.
166
+ using Boneh-Lynn-Shacham signature scheme. Compatible with ETH and others,
167
+ just make sure to provide correct DST (domain separation tag argument).
149
168
 
150
169
  ```ts
151
170
  import { bls12_381 as bls } from '@noble/curves/bls12-381';
@@ -182,10 +201,13 @@ console.log({ publicKeys, signatures3, aggSignature3, isValid3 });
182
201
 
183
202
  ## Abstract API
184
203
 
185
- Abstract API allows to define custom curves. All arithmetics is done with JS bigints over finite fields,
186
- which is defined from `modular` sub-module. For scalar multiplication, we use [precomputed tables with w-ary non-adjacent form (wNAF)](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/).
187
- Precomputes are enabled for weierstrass and edwards BASE points of a curve. You could precompute any
188
- other point (e.g. for ECDH) using `utils.precompute()` method: check out examples.
204
+ Abstract API allows to define custom curves. All arithmetics is done with JS
205
+ bigints over finite fields, which is defined from `modular` sub-module. For
206
+ scalar multiplication, we use
207
+ [precomputed tables with w-ary non-adjacent form (wNAF)](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/).
208
+ Precomputes are enabled for weierstrass and edwards BASE points of a curve. You
209
+ could precompute any other point (e.g. for ECDH) using `utils.precompute()`
210
+ method: check out examples.
189
211
 
190
212
  There are following zero-dependency algorithms:
191
213
 
@@ -201,14 +223,36 @@ There are following zero-dependency algorithms:
201
223
 
202
224
  ```ts
203
225
  import { weierstrass } from '@noble/curves/abstract/weierstrass';
226
+ import { Field } from '@noble/curves/abstract/modular'; // finite field for mod arithmetics
227
+ import { sha256 } from '@noble/hashes/sha256'; // 3rd-party sha256() of type utils.CHash
228
+ import { hmac } from '@noble/hashes/hmac'; // 3rd-party hmac() that will accept sha256()
229
+ import { concatBytes, randomBytes } from '@noble/hashes/utils'; // 3rd-party utilities
230
+ const secq256k1 = weierstrass({
231
+ // secq256k1: cycle of secp256k1 with Fp/N flipped.
232
+ // https://personaelabs.org/posts/spartan-ecdsa
233
+ // https://zcash.github.io/halo2/background/curves.html#cycles-of-curves
234
+ a: 0n,
235
+ b: 7n,
236
+ Fp: Field(2n ** 256n - 432420386565659656852420866394968145599n),
237
+ n: 2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n,
238
+ Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
239
+ Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
240
+ hash: sha256,
241
+ hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)),
242
+ randomBytes,
243
+ });
244
+
245
+ // weierstrassPoints can also be used if you don't need ECDSA, hash, hmac, randomBytes
204
246
  ```
205
247
 
206
- Short Weierstrass curve's formula is `y² = x³ + ax + b`. `weierstrass` expects arguments `a`, `b`, field `Fp`, curve order `n`, cofactor `h`
248
+ Short Weierstrass curve's formula is `y² = x³ + ax + b`. `weierstrass`
249
+ expects arguments `a`, `b`, field `Fp`, curve order `n`, cofactor `h`
207
250
  and coordinates `Gx`, `Gy` of generator point.
208
251
 
209
- **`k` generation** is done deterministically, following [RFC6979](https://www.rfc-editor.org/rfc/rfc6979).
210
- For this you will need `hmac` & `hash`, which in our implementations is provided by noble-hashes.
211
- If you're using different hashing library, make sure to wrap it in the following interface:
252
+ **`k` generation** is done deterministically, following
253
+ [RFC6979](https://www.rfc-editor.org/rfc/rfc6979). For this you will need
254
+ `hmac` & `hash`, which in our implementations is provided by noble-hashes. If
255
+ you're using different hashing library, make sure to wrap it in the following interface:
212
256
 
213
257
  ```ts
214
258
  type CHash = {
@@ -224,11 +268,36 @@ type CHash = {
224
268
  1. Exported as `ProjectivePoint`
225
269
  2. Represented in projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z)
226
270
  3. Use complete exception-free formulas for addition and doubling
227
- 4. Can be decoded/encoded from/to Uint8Array / hex strings using `ProjectivePoint.fromHex` and `ProjectivePoint#toRawBytes()`
271
+ 4. Can be decoded/encoded from/to Uint8Array / hex strings using
272
+ `ProjectivePoint.fromHex` and `ProjectivePoint#toRawBytes()`
228
273
  5. Have `assertValidity()` which checks for being on-curve
229
274
  6. Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates
230
275
 
231
276
  ```ts
277
+ // `weierstrassPoints()` returns `CURVE` and `ProjectivePoint`
278
+ // `weierstrass()` returns `CurveFn`
279
+ type SignOpts = { lowS?: boolean; prehash?: boolean; extraEntropy: boolean | Uint8Array };
280
+ type CurveFn = {
281
+ CURVE: ReturnType<typeof validateOpts>;
282
+ getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array;
283
+ getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array;
284
+ sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => SignatureType;
285
+ verify: (
286
+ signature: Hex | SignatureType,
287
+ msgHash: Hex,
288
+ publicKey: Hex,
289
+ opts?: { lowS?: boolean; prehash?: boolean }
290
+ ) => boolean;
291
+ ProjectivePoint: ProjectivePointConstructor;
292
+ Signature: SignatureConstructor;
293
+ utils: {
294
+ normPrivateKeyToScalar: (key: PrivKey) => bigint;
295
+ isValidPrivateKey(key: PrivKey): boolean;
296
+ randomPrivateKey: () => Uint8Array;
297
+ precompute: (windowSize?: number, point?: ProjPointType<bigint>) => ProjPointType<bigint>;
298
+ };
299
+ };
300
+
232
301
  // T is usually bigint, but can be something else like complex numbers in BLS curves
233
302
  interface ProjPointType<T> extends Group<ProjPointType<T>> {
234
303
  readonly px: T;
@@ -254,7 +323,8 @@ interface ProjConstructor<T> extends GroupConstructor<ProjPointType<T>> {
254
323
  }
255
324
  ```
256
325
 
257
- **ECDSA signatures** are represented by `Signature` instances and can be described by the interface:
326
+ **ECDSA signatures** are represented by `Signature` instances and can be
327
+ described by the interface:
258
328
 
259
329
  ```ts
260
330
  interface SignatureType {
@@ -279,28 +349,9 @@ type SignatureConstructor = {
279
349
  };
280
350
  ```
281
351
 
282
- Example implementing [secq256k1](https://personaelabs.org/posts/spartan-ecdsa) (NOT secp256k1)
283
- [cycle](https://zcash.github.io/halo2/background/curves.html#cycles-of-curves) of secp256k1 with Fp/N flipped.
352
+ More examples:
284
353
 
285
354
  ```typescript
286
- import { weierstrass } from '@noble/curves/abstract/weierstrass';
287
- import { Field } from '@noble/curves/abstract/modular'; // finite field, mod arithmetics done over it
288
- import { sha256 } from '@noble/hashes/sha256'; // 3rd-party sha256() of type utils.CHash, with blockLen/outputLen
289
- import { hmac } from '@noble/hashes/hmac'; // 3rd-party hmac() that will accept sha256()
290
- import { concatBytes, randomBytes } from '@noble/hashes/utils'; // 3rd-party utilities
291
- const secq256k1 = weierstrass({
292
- // secq256k1: cycle of secp256k1 with Fp/N flipped.
293
- a: 0n,
294
- b: 7n,
295
- Fp: Field(2n ** 256n - 432420386565659656852420866394968145599n),
296
- n: 2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n,
297
- Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
298
- Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
299
- hash: sha256,
300
- hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)),
301
- randomBytes,
302
- });
303
-
304
355
  // All curves expose same generic interface.
305
356
  const priv = secq256k1.utils.randomPrivateKey();
306
357
  secq256k1.getPublicKey(priv); // Convert private key to public.
@@ -318,6 +369,7 @@ point.assertValidity(); // Checks for being on-curve
318
369
  point.toAffine(); // Converts to 2d affine xy coordinates
319
370
 
320
371
  secq256k1.CURVE.n;
372
+ secq256k1.CURVE.p;
321
373
  secq256k1.CURVE.Fp.mod();
322
374
  secq256k1.CURVE.hash();
323
375
 
@@ -326,84 +378,19 @@ const fast = secq256k1.utils.precompute(8, Point.fromHex(someonesPubKey));
326
378
  fast.multiply(privKey); // much faster ECDH now
327
379
  ```
328
380
 
329
- `weierstrass()` returns `CurveFn`:
330
-
331
- ```ts
332
- type SignOpts = { lowS?: boolean; prehash?: boolean; extraEntropy: boolean | Uint8Array };
333
- type CurveFn = {
334
- CURVE: ReturnType<typeof validateOpts>;
335
- getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array;
336
- getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array;
337
- sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => SignatureType;
338
- verify: (
339
- signature: Hex | SignatureType,
340
- msgHash: Hex,
341
- publicKey: Hex,
342
- opts?: { lowS?: boolean; prehash?: boolean }
343
- ) => boolean;
344
- ProjectivePoint: ProjectivePointConstructor;
345
- Signature: SignatureConstructor;
346
- utils: {
347
- normPrivateKeyToScalar: (key: PrivKey) => bigint;
348
- isValidPrivateKey(key: PrivKey): boolean;
349
- randomPrivateKey: () => Uint8Array;
350
- precompute: (windowSize?: number, point?: ProjPointType<bigint>) => ProjPointType<bigint>;
351
- };
352
- };
353
- ```
354
-
355
381
  ### abstract/edwards: Twisted Edwards curve
356
382
 
357
- Twisted Edwards curve's formula is `ax² + y² = 1 + dx²y²`. You must specify `a`, `d`, field `Fp`, order `n`, cofactor `h`
358
- and coordinates `Gx`, `Gy` of generator point.
359
-
360
- For EdDSA signatures, `hash` param required. `adjustScalarBytes` which instructs how to change private scalars could be specified.
361
-
362
- **Edwards points:**
363
-
364
- 1. Exported as `ExtendedPoint`
365
- 2. Represented in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z)
366
- 3. Use complete exception-free formulas for addition and doubling
367
- 4. Can be decoded/encoded from/to Uint8Array / hex strings using `ExtendedPoint.fromHex` and `ExtendedPoint#toRawBytes()`
368
- 5. Have `assertValidity()` which checks for being on-curve
369
- 6. Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates
370
- 7. Have `isTorsionFree()`, `clearCofactor()` and `isSmallOrder()` utilities to handle torsions
371
-
372
- ```ts
373
- interface ExtPointType extends Group<ExtPointType> {
374
- readonly ex: bigint;
375
- readonly ey: bigint;
376
- readonly ez: bigint;
377
- readonly et: bigint;
378
- assertValidity(): void;
379
- multiply(scalar: bigint): ExtPointType;
380
- multiplyUnsafe(scalar: bigint): ExtPointType;
381
- isSmallOrder(): boolean;
382
- isTorsionFree(): boolean;
383
- clearCofactor(): ExtPointType;
384
- toAffine(iz?: bigint): AffinePoint<bigint>;
385
- }
386
- // Static methods of Extended Point with coordinates in X, Y, Z, T
387
- interface ExtPointConstructor extends GroupConstructor<ExtPointType> {
388
- new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType;
389
- fromAffine(p: AffinePoint<bigint>): ExtPointType;
390
- fromHex(hex: Hex): ExtPointType;
391
- fromPrivateKey(privateKey: Hex): ExtPointType;
392
- }
393
- ```
394
-
395
- Example implementing edwards25519:
396
-
397
383
  ```ts
398
384
  import { twistedEdwards } from '@noble/curves/abstract/edwards';
399
- import { Field, div } from '@noble/curves/abstract/modular';
385
+ import { Field } from '@noble/curves/abstract/modular';
400
386
  import { sha512 } from '@noble/hashes/sha512';
387
+ import { randomBytes } from '@noble/hashes/utils';
401
388
 
402
389
  const Fp = Field(2n ** 255n - 19n);
403
390
  const ed25519 = twistedEdwards({
404
391
  a: -1n,
405
392
  d: Fp.div(-121665n, 121666n), // -121665n/121666n mod p
406
- Fp,
393
+ Fp: Fp,
407
394
  n: 2n ** 252n + 27742317777372353535851937790883648493n,
408
395
  h: 8n,
409
396
  Gx: 15112221349535400772501151409588531511454012693041857206046113283949847762202n,
@@ -420,9 +407,23 @@ const ed25519 = twistedEdwards({
420
407
  } as const);
421
408
  ```
422
409
 
423
- `twistedEdwards()` returns `CurveFn` of following type:
410
+ Twisted Edwards curve's formula is `ax² + y² = 1 + dx²y²`. You must specify `a`, `d`, field `Fp`, order `n`, cofactor `h`
411
+ and coordinates `Gx`, `Gy` of generator point.
412
+
413
+ For EdDSA signatures, `hash` param required. `adjustScalarBytes` which instructs how to change private scalars could be specified.
414
+
415
+ **Edwards points:**
416
+
417
+ 1. Exported as `ExtendedPoint`
418
+ 2. Represented in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z)
419
+ 3. Use complete exception-free formulas for addition and doubling
420
+ 4. Can be decoded/encoded from/to Uint8Array / hex strings using `ExtendedPoint.fromHex` and `ExtendedPoint#toRawBytes()`
421
+ 5. Have `assertValidity()` which checks for being on-curve
422
+ 6. Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates
423
+ 7. Have `isTorsionFree()`, `clearCofactor()` and `isSmallOrder()` utilities to handle torsions
424
424
 
425
425
  ```ts
426
+ // `twistedEdwards()` returns `CurveFn` of following type:
426
427
  type CurveFn = {
427
428
  CURVE: ReturnType<typeof validateOpts>;
428
429
  getPublicKey: (privateKey: Hex) => Uint8Array;
@@ -440,21 +441,39 @@ type CurveFn = {
440
441
  };
441
442
  };
442
443
  };
444
+
445
+ interface ExtPointType extends Group<ExtPointType> {
446
+ readonly ex: bigint;
447
+ readonly ey: bigint;
448
+ readonly ez: bigint;
449
+ readonly et: bigint;
450
+ assertValidity(): void;
451
+ multiply(scalar: bigint): ExtPointType;
452
+ multiplyUnsafe(scalar: bigint): ExtPointType;
453
+ isSmallOrder(): boolean;
454
+ isTorsionFree(): boolean;
455
+ clearCofactor(): ExtPointType;
456
+ toAffine(iz?: bigint): AffinePoint<bigint>;
457
+ }
458
+ // Static methods of Extended Point with coordinates in X, Y, Z, T
459
+ interface ExtPointConstructor extends GroupConstructor<ExtPointType> {
460
+ new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType;
461
+ fromAffine(p: AffinePoint<bigint>): ExtPointType;
462
+ fromHex(hex: Hex): ExtPointType;
463
+ fromPrivateKey(privateKey: Hex): ExtPointType;
464
+ }
443
465
  ```
444
466
 
445
467
  ### abstract/montgomery: Montgomery curve
446
468
 
447
- The module contains methods for x-only ECDH on Curve25519 / Curve448 from RFC7748. Proper Elliptic Curve Points are not implemented yet.
448
-
449
- You must specify curve params `Fp`, `a`, `Gu` coordinate of u, `montgomeryBits` and `nByteLength`.
450
-
451
469
  ```typescript
452
470
  import { montgomery } from '@noble/curves/abstract/montgomery';
471
+ import { Field } from '@noble/curves/abstract/modular';
453
472
 
454
473
  const x25519 = montgomery({
455
- Fp: Field(2n ** 255n - 19n),
456
474
  a: 486662n,
457
475
  Gu: 9n,
476
+ Fp: Field(2n ** 255n - 19n),
458
477
  montgomeryBits: 255,
459
478
  nByteLength: 32,
460
479
  // Optional param
@@ -467,6 +486,11 @@ const x25519 = montgomery({
467
486
  });
468
487
  ```
469
488
 
489
+ The module contains methods for x-only ECDH on Curve25519 / Curve448 from RFC7748.
490
+ Proper Elliptic Curve Points are not implemented yet.
491
+
492
+ You must specify curve params `Fp`, `a`, `Gu` coordinate of u, `montgomeryBits` and `nByteLength`.
493
+
470
494
  ### abstract/hash-to-curve: Hashing strings to curve points
471
495
 
472
496
  The module allows to hash arbitrary strings to elliptic curve points. Implements [hash-to-curve v16](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16).
@@ -507,19 +531,37 @@ function expand_message_xof(
507
531
  ): Uint8Array;
508
532
  ```
509
533
 
510
- `hash_to_field(msg, count, options)` [(spec)](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3)
534
+ `hash_to_field(msg, count, options)`
535
+ [(spec)](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3)
511
536
  hashes arbitrary-length byte strings to a list of one or more elements of a finite field F.
512
537
 
513
- - `msg` a byte string containing the message to hash
514
- - `count` the number of elements of F to output
515
- - `options` `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`.
516
- - `p` is field prime, m=field extension (1 for prime fields)
517
- - `k` is security target in bits (e.g. 128).
518
- - `expand` should be `xmd` for SHA2, SHA3, BLAKE; `xof` for SHAKE, BLAKE-XOF
519
- - `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props
520
- - Returns `[u_0, ..., u_(count - 1)]`, a list of field elements.
521
-
522
538
  ```ts
539
+ /**
540
+ * * `DST` is a domain separation tag, defined in section 2.2.5
541
+ * * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m
542
+ * * `m` is extension degree (1 for prime fields)
543
+ * * `k` is the target security target in bits (e.g. 128), from section 5.1
544
+ * * `expand` is `xmd` (SHA2, SHA3, BLAKE) or `xof` (SHAKE, BLAKE-XOF)
545
+ * * `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props
546
+ */
547
+ type UnicodeOrBytes = string | Uint8Array;
548
+ type Opts = {
549
+ DST: UnicodeOrBytes;
550
+ p: bigint;
551
+ m: number;
552
+ k: number;
553
+ expand?: 'xmd' | 'xof';
554
+ hash: CHash;
555
+ };
556
+
557
+ /**
558
+ * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F
559
+ * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3
560
+ * @param msg a byte string containing the message to hash
561
+ * @param count the number of elements of F to output
562
+ * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above
563
+ * @returns [u_0, ..., u_(count - 1)], a list of field elements.
564
+ */
523
565
  function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][];
524
566
  ```
525
567
 
@@ -704,6 +746,13 @@ hashToCurve
704
746
  └─ed448 x 1,045 ops/sec @ 956μs/op
705
747
  ```
706
748
 
749
+ ## Contributing & testing
750
+
751
+ 1. Clone the repository
752
+ 2. `npm install` to install build dependencies like TypeScript
753
+ 3. `npm run build` to compile TypeScript code
754
+ 4. `npm run test` will execute all main tests
755
+
707
756
  ## Resources
708
757
 
709
758
  Article about some of library's features: [Learning fast elliptic-curve cryptography](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/)
@@ -719,45 +768,52 @@ Projects using the library:
719
768
  - Threshold sigs demo [genthresh.com](https://genthresh.com)
720
769
  - BBS signatures [github.com/Wind4Greg/BBS-Draft-Checks](https://github.com/Wind4Greg/BBS-Draft-Checks) following [draft-irtf-cfrg-bbs-signatures-latest](https://identity.foundation/bbs-signature/draft-irtf-cfrg-bbs-signatures.html)
721
770
  - Others
722
- - All curves demo: Elliptic curve calculator [paulmillr.com/ecc](https://paulmillr.com/ecc)
771
+ - All curves demo: Elliptic curve calculator [paulmillr.com/noble](https://paulmillr.com/noble)
723
772
  - [micro-starknet](https://github.com/paulmillr/micro-starknet) for stark-friendly elliptic curve.
773
+
724
774
  ## Upgrading
725
775
 
726
- If you're coming from single-feature noble packages, the following changes need to be kept in mind:
727
-
728
- - 2d affine (x, y) points have been removed to reduce complexity and improve speed
729
- - Removed `number` support as a type for private keys, `bigint` is still supported
730
- - `mod`, `invert` are no longer present in `utils`: use `@noble/curves/abstract/modular`
731
-
732
- Upgrading from @noble/secp256k1 1.7:
733
-
734
- - Compressed (33-byte) public keys are now returned by default, instead of uncompressed
735
- - Methods are now synchronous. Setting `secp.utils.hmacSha256` is no longer required
736
- - `sign()`
737
- - `der`, `recovered` options were removed
738
- - `canonical` was renamed to `lowS`
739
- - Return type is now `{ r: bigint, s: bigint, recovery: number }` instance of `Signature`
740
- - `verify()`
741
- - `strict` was renamed to `lowS`
742
- - `recoverPublicKey()`: moved to sig instance `Signature#recoverPublicKey(msgHash)`
743
- - `Point` was removed: use `ProjectivePoint` in xyz coordinates
744
- - `utils`: Many methods were removed, others were moved to `schnorr` namespace
745
-
746
- Upgrading from @noble/ed25519 1.7:
747
-
748
- - Methods are now synchronous. Setting `secp.utils.hmacSha256` is no longer required
749
- - ed25519ph, ed25519ctx
750
- - `Point` was removed: use `ExtendedPoint` in xyzt coordinates
751
- - `Signature` was removed
752
- - `getSharedSecret` was removed: use separate x25519 sub-module
776
+ Previously, the library was split into single-feature packages
777
+ noble-secp256k1 and noble-ed25519. curves can be thought as a continuation of their
778
+ original work. The libraries now changed their direction towards providing
779
+ minimal 4kb implementations of cryptography and are not as feature-complete.
780
+
781
+ Upgrading from [@noble/secp256k1](https://github.com/paulmillr/noble-secp256k1) 1.7:
782
+
783
+ - `getPublicKey`
784
+ - now produce 33-byte compressed signatures by default
785
+ - to use old behavior, which produced 65-byte uncompressed keys, set
786
+ argument `isCompressed` to `false`: `getPublicKey(priv, false)`
787
+ - `sign`
788
+ - is now sync; use `signAsync` for async version
789
+ - now returns `Signature` instance with `{ r, s, recovery }` properties
790
+ - `canonical` option was renamed to `lowS`
791
+ - `recovered` option has been removed because recovery bit is always returned now
792
+ - `der` option has been removed. There are 2 options:
793
+ 1. Use compact encoding: `fromCompact`, `toCompactRawBytes`, `toCompactHex`.
794
+ Compact encoding is simply a concatenation of 32-byte r and 32-byte s.
795
+ 2. If you must use DER encoding, switch to noble-curves (see above).
796
+ - `verify`
797
+ - `strict` option was renamed to `lowS`
798
+ - `getSharedSecret`
799
+ - now produce 33-byte compressed signatures by default
800
+ - to use old behavior, which produced 65-byte uncompressed keys, set
801
+ argument `isCompressed` to `false`: `getSharedSecret(a, b, false)`
802
+ - `recoverPublicKey(msg, sig, rec)` was changed to `sig.recoverPublicKey(msg)`
803
+ - `number` type for private keys have been removed: use `bigint` instead
804
+ - `Point` (2d xy) has been changed to `ProjectivePoint` (3d xyz)
805
+ - `utils` were split into `utils` (same api as in noble-curves) and
806
+ `etc` (`hmacSha256Sync` and others)
807
+
808
+ Upgrading from [@noble/ed25519](https://github.com/paulmillr/noble-ed25519) 1.7:
809
+
810
+ - Methods are now sync by default
753
811
  - `bigint` is no longer allowed in `getPublicKey`, `sign`, `verify`. Reason: ed25519 is LE, can lead to bugs
754
-
755
- ## Contributing & testing
756
-
757
- 1. Clone the repository
758
- 2. `npm install` to install build dependencies like TypeScript
759
- 3. `npm run build` to compile TypeScript code
760
- 4. `npm run test` will execute all main tests
812
+ - `Point` (2d xy) has been changed to `ExtendedPoint` (xyzt)
813
+ - `Signature` was removed: just use raw bytes or hex now
814
+ - `utils` were split into `utils` (same api as in noble-curves) and
815
+ `etc` (`sha512Sync` and others)
816
+ - `getSharedSecret` was moved to `x25519` module
761
817
 
762
818
  ## License
763
819
 
@@ -6,13 +6,13 @@ export declare function getHash(hash: CHash): {
6
6
  hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => Uint8Array;
7
7
  randomBytes: typeof randomBytes;
8
8
  };
9
- declare type CurveDef = Readonly<Omit<CurveType, 'hash' | 'hmac' | 'randomBytes'>>;
9
+ type CurveDef = Readonly<Omit<CurveType, 'hash' | 'hmac' | 'randomBytes'>>;
10
10
  export declare function createCurve(curveDef: CurveDef, defHash: CHash): Readonly<{
11
11
  create: (hash: CHash) => import("./abstract/weierstrass.js").CurveFn;
12
12
  CURVE: Readonly<{
13
13
  readonly nBitLength: number;
14
14
  readonly nByteLength: number;
15
- readonly Fp: import("./abstract/modular.js").Field<bigint>;
15
+ readonly Fp: import("./abstract/modular.js").IField<bigint>;
16
16
  readonly n: bigint;
17
17
  readonly h: bigint;
18
18
  readonly hEff?: bigint | undefined;
@@ -40,6 +40,7 @@ export declare function createCurve(curveDef: CurveDef, defHash: CHash): Readonl
40
40
  lowS: boolean;
41
41
  readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;
42
42
  readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;
43
+ readonly p: bigint;
43
44
  }>;
44
45
  getPublicKey: (privateKey: import("./abstract/utils.js").PrivKey, isCompressed?: boolean | undefined) => Uint8Array;
45
46
  getSharedSecret: (privateA: import("./abstract/utils.js").PrivKey, publicB: import("./abstract/utils.js").Hex, isCompressed?: boolean | undefined) => Uint8Array;
@@ -1 +1 @@
1
- {"version":3,"file":"_shortw_utils.d.ts","sourceRoot":"","sources":["src/_shortw_utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAe,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAe,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAG5C,wBAAgB,OAAO,CAAC,IAAI,EAAE,KAAK;;gBAGnB,UAAU,WAAW,UAAU,EAAE;;EAGhD;AAED,aAAK,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC;AAC3E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK;mBACtC,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAE5B"}
1
+ {"version":3,"file":"_shortw_utils.d.ts","sourceRoot":"","sources":["src/_shortw_utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAe,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAe,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAG5C,wBAAgB,OAAO,CAAC,IAAI,EAAE,KAAK;;gBAGnB,UAAU,WAAW,UAAU,EAAE;;EAGhD;AAED,KAAK,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC;AAC3E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK;mBACtC,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAE5B"}