@noble/curves 1.1.0 → 1.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 (67) hide show
  1. package/README.md +267 -164
  2. package/abstract/bls.d.ts.map +1 -1
  3. package/abstract/bls.js +2 -2
  4. package/abstract/bls.js.map +1 -1
  5. package/abstract/hash-to-curve.d.ts +1 -1
  6. package/abstract/hash-to-curve.d.ts.map +1 -1
  7. package/abstract/hash-to-curve.js +14 -8
  8. package/abstract/hash-to-curve.js.map +1 -1
  9. package/abstract/modular.d.ts +51 -11
  10. package/abstract/modular.d.ts.map +1 -1
  11. package/abstract/modular.js +79 -21
  12. package/abstract/modular.js.map +1 -1
  13. package/abstract/poseidon.d.ts.map +1 -1
  14. package/abstract/poseidon.js +39 -41
  15. package/abstract/poseidon.js.map +1 -1
  16. package/abstract/utils.d.ts +1 -0
  17. package/abstract/utils.d.ts.map +1 -1
  18. package/abstract/utils.js +2 -1
  19. package/abstract/utils.js.map +1 -1
  20. package/abstract/weierstrass.d.ts +2 -1
  21. package/abstract/weierstrass.d.ts.map +1 -1
  22. package/abstract/weierstrass.js +13 -11
  23. package/abstract/weierstrass.js.map +1 -1
  24. package/bls12-381.d.ts.map +1 -1
  25. package/bls12-381.js +7 -8
  26. package/bls12-381.js.map +1 -1
  27. package/ed25519.d.ts +1 -0
  28. package/ed25519.d.ts.map +1 -1
  29. package/ed25519.js +9 -6
  30. package/ed25519.js.map +1 -1
  31. package/ed448.d.ts +51 -2
  32. package/ed448.d.ts.map +1 -1
  33. package/ed448.js +206 -28
  34. package/ed448.js.map +1 -1
  35. package/esm/abstract/bls.js +3 -3
  36. package/esm/abstract/bls.js.map +1 -1
  37. package/esm/abstract/hash-to-curve.js +14 -8
  38. package/esm/abstract/hash-to-curve.js.map +1 -1
  39. package/esm/abstract/modular.js +75 -20
  40. package/esm/abstract/modular.js.map +1 -1
  41. package/esm/abstract/poseidon.js +39 -41
  42. package/esm/abstract/poseidon.js.map +1 -1
  43. package/esm/abstract/utils.js +2 -1
  44. package/esm/abstract/utils.js.map +1 -1
  45. package/esm/abstract/weierstrass.js +13 -11
  46. package/esm/abstract/weierstrass.js.map +1 -1
  47. package/esm/bls12-381.js +7 -8
  48. package/esm/bls12-381.js.map +1 -1
  49. package/esm/ed25519.js +9 -6
  50. package/esm/ed25519.js.map +1 -1
  51. package/esm/ed448.js +208 -31
  52. package/esm/ed448.js.map +1 -1
  53. package/esm/jubjub.js +1 -1
  54. package/esm/jubjub.js.map +1 -1
  55. package/esm/package.json +1 -4
  56. package/jubjub.js.map +1 -1
  57. package/package.json +4 -3
  58. package/src/abstract/bls.ts +3 -3
  59. package/src/abstract/hash-to-curve.ts +14 -8
  60. package/src/abstract/modular.ts +81 -22
  61. package/src/abstract/poseidon.ts +39 -40
  62. package/src/abstract/utils.ts +4 -1
  63. package/src/abstract/weierstrass.ts +13 -11
  64. package/src/bls12-381.ts +7 -8
  65. package/src/ed25519.ts +9 -6
  66. package/src/ed448.ts +251 -33
  67. package/src/jubjub.ts +1 -1
package/README.md CHANGED
@@ -9,26 +9,23 @@ Audited & minimal JS implementation of elliptic curve cryptography.
9
9
  - ➰ Short Weierstrass, Edwards, Montgomery curves
10
10
  - ✍️ ECDSA, EdDSA, Schnorr, BLS signature schemes, ECDH key agreement
11
11
  - 🔖 SUF-CMA and SBS (non-repudiation) for ed25519, ed448 and others
12
- - #️⃣ Hash-to-curve
13
- for encoding or hashing an arbitrary string to an elliptic curve point
12
+ - #️⃣ hash-to-curve for encoding or hashing an arbitrary string to an elliptic curve point
14
13
  - 🧜‍♂️ Poseidon ZK-friendly hash
15
14
 
16
- Check out [Upgrading](#upgrading) if you've previously used single-feature noble
17
- packages. See [Resources](#resources) for articles and real-world software that uses curves.
18
-
19
15
  ### This library belongs to _noble_ crypto
20
16
 
21
17
  > **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools.
22
18
 
23
19
  - No dependencies, protection against supply chain attacks
24
20
  - Auditable TypeScript / JS code
25
- - Supported in all major browsers and stable node.js versions
26
- - All releases are signed with PGP keys
21
+ - Supported on all major platforms
22
+ - Releases are signed with PGP keys and built transparently with NPM provenance
27
23
  - Check out [homepage](https://paulmillr.com/noble/) & all libraries:
28
- [curves](https://github.com/paulmillr/noble-curves)
29
- (4kb versions [secp256k1](https://github.com/paulmillr/noble-secp256k1),
30
- [ed25519](https://github.com/paulmillr/noble-ed25519)),
31
- [hashes](https://github.com/paulmillr/noble-hashes)
24
+ [ciphers](https://github.com/paulmillr/noble-ciphers),
25
+ [curves](https://github.com/paulmillr/noble-curves),
26
+ [hashes](https://github.com/paulmillr/noble-hashes),
27
+ 4kb [secp256k1](https://github.com/paulmillr/noble-secp256k1) /
28
+ [ed25519](https://github.com/paulmillr/noble-ed25519)
32
29
 
33
30
  ## Usage
34
31
 
@@ -39,33 +36,52 @@ For [Deno](https://deno.land), ensure to use [npm specifier](https://deno.land/m
39
36
  For React Native, you may need a [polyfill for crypto.getRandomValues](https://github.com/LinusU/react-native-get-random-values).
40
37
  If you don't like NPM, a standalone [noble-curves.js](https://github.com/paulmillr/noble-curves/releases) is also available.
41
38
 
42
- The library is tree-shaking-friendly and does not expose root entry point as
43
- `@noble/curves`. Instead, you need to import specific primitives.
44
- This is done to ensure small size of your apps.
39
+ - [Implementations](#implementations)
40
+ - [ECDSA signature scheme](#ecdsa-signature-scheme)
41
+ - [ECDSA public key recovery & extra entropy](#ecdsa-public-key-recovery--extra-entropy)
42
+ - [ECDH (Elliptic Curve Diffie-Hellman)](#ecdh-elliptic-curve-diffie-hellman)
43
+ - [Schnorr signatures over secp256k1, BIP340](#schnorr-signatures-over-secp256k1-bip340)
44
+ - [ed25519, X25519, ristretto255](#ed25519-x25519-ristretto255)
45
+ - [ed448, X448, decaf448](#ed448-x448-decaf448)
46
+ - [bls12-381](#bls12-381)
47
+ - [All available imports](#all-available-imports)
48
+ - [Accessing a curve's variables](#accessing-a-curves-variables)
49
+ - [Abstract API](#abstract-api)
50
+ - [abstract/weierstrass: Short Weierstrass curve](#abstractweierstrass-short-weierstrass-curve)
51
+ - [abstract/edwards: Twisted Edwards curve](#abstractedwards-twisted-edwards-curve)
52
+ - [abstract/montgomery: Montgomery curve](#abstractmontgomery-montgomery-curve)
53
+ - [abstract/bls: Barreto-Lynn-Scott curves](#abstractbls-barreto-lynn-scott-curves)
54
+ - [abstract/hash-to-curve: Hashing strings to curve points](#abstracthash-to-curve-hashing-strings-to-curve-points)
55
+ - [abstract/poseidon: Poseidon hash](#abstractposeidon-poseidon-hash)
56
+ - [abstract/modular: Modular arithmetics utilities](#abstractmodular-modular-arithmetics-utilities)
57
+ - [Creating private keys from hashes](#creating-private-keys-from-hashes)
58
+ - [abstract/utils: Useful utilities](#abstractutils-useful-utilities)
59
+ - [Security](#security)
60
+ - [Speed](#speed)
61
+ - [Contributing & testing](#contributing--testing)
62
+ - [Upgrading](#upgrading)
63
+ - [Resources](#resources)
64
+ - [Demos](#demos)
65
+ - [Projects using curves](#projects-using-curves)
66
+ - [License](#license)
45
67
 
46
- The package consists of two parts:
68
+ ### Implementations
47
69
 
48
- * [Implementations](#implementations), utilizing one dependency [noble-hashes](https://github.com/paulmillr/noble-hashes),
49
- providing ready-to-use:
50
- - NIST curves secp256r1 / p256, secp384r1 / p384, secp521r1 / p521
51
- - SECG curve secp256k1
52
- - ed25519 / curve25519 / x25519 / ristretto255, edwards448 / curve448 / x448
53
- - pairing-friendly curves bls12-381, bn254
54
- - [pasta](https://electriccoin.co/blog/the-pasta-curves-for-halo-2-and-beyond/) curves
55
- 2. [Abstract](#abstract-api), zero-dependency elliptic curve algorithms
70
+ Implementations are utilizing [noble-hashes](https://github.com/paulmillr/noble-hashes).
71
+ [Abstract API](#abstract-api) doesn't depend on them: you can use a different hashing library.
56
72
 
57
- ### Implementations
73
+ #### ECDSA signature scheme
58
74
 
59
- #### Generic example for all curves, secp256k1
75
+ Generic example that works for all curves, shown for secp256k1:
60
76
 
61
77
  ```ts
62
- // Each curve has similar methods
78
+ // import * from '@noble/curves'; // Error: use sub-imports, to ensure small app size
63
79
  import { secp256k1 } from '@noble/curves/secp256k1'; // ESM and Common.js
64
80
  // import { secp256k1 } from 'npm:@noble/curves@1.2.0/secp256k1'; // Deno
65
81
  const priv = secp256k1.utils.randomPrivateKey();
66
82
  const pub = secp256k1.getPublicKey(priv);
67
- const msg = new Uint8Array(32).fill(1);
68
- const sig = secp256k1.sign(msg, priv);
83
+ const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa
84
+ const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available
69
85
  const isValid = secp256k1.verify(sig, msg, pub) === true;
70
86
 
71
87
  // hex strings are also supported besides Uint8Arrays:
@@ -73,29 +89,22 @@ const privHex = '46c930bc7bb4db7f55da20798697421b98c4175a52c630294d75a84b9c12623
73
89
  const pub2 = secp256k1.getPublicKey(privHex);
74
90
  ```
75
91
 
76
- #### All imports
92
+ #### ECDSA public key recovery & extra entropy
77
93
 
78
- ```typescript
79
- import { secp256k1, schnorr } from '@noble/curves/secp256k1';
80
- import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519';
81
- import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448';
82
- import { p256 } from '@noble/curves/p256';
83
- import { p384 } from '@noble/curves/p384';
84
- import { p521 } from '@noble/curves/p521';
85
- import { pallas, vesta } from '@noble/curves/pasta';
86
- import { bls12_381 } from '@noble/curves/bls12-381';
87
- import { bn254 } from '@noble/curves/bn254';
88
- import { jubjub } from '@noble/curves/jubjub';
94
+ ```ts
95
+ sig.recoverPublicKey(msg).toRawBytes(); // === pub; // public key recovery
96
+
97
+ // extraEntropy https://moderncrypto.org/mail-archive/curves/2017/000925.html
98
+ const sigImprovedSecurity = secp256k1.sign(msg, priv, { extraEntropy: true });
89
99
  ```
90
100
 
91
- #### ECDSA public key recovery & ECDH
101
+ #### ECDH (Elliptic Curve Diffie-Hellman)
92
102
 
93
103
  ```ts
94
- // extraEntropy https://moderncrypto.org/mail-archive/curves/2017/000925.html
95
- const sigImprovedSecurity = secp256k1.sign(msg, priv, { extraEntropy: true });
96
- sig.recoverPublicKey(msg) === pub; // public key recovery
104
+ // 1. The output includes parity byte. Strip it using shared.slice(1)
105
+ // 2. The output is not hashed. More secure way is sha256(shared) or hkdf(shared)
97
106
  const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
98
- const shared = secp256k1.getSharedSecret(priv, someonesPub); // ECDH
107
+ const shared = secp256k1.getSharedSecret(priv, someonesPub);
99
108
  ```
100
109
 
101
110
  #### Schnorr signatures over secp256k1 (BIP340)
@@ -129,7 +138,6 @@ It has SUF-CMA (strong unforgeability under chosen message attacks).
129
138
  and additionally provides non-repudiation with SBS [(Strongly Binding Signatures)](https://eprint.iacr.org/2020/1244).
130
139
 
131
140
  X25519 follows [RFC7748](https://www.rfc-editor.org/rfc/rfc7748).
132
- ristretto255 follows [irtf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448).
133
141
 
134
142
  ```ts
135
143
  // Variants from RFC8032: with context, prehashed
@@ -147,17 +155,36 @@ x25519.getPublicKey(x25519.utils.randomPrivateKey());
147
155
  import { edwardsToMontgomeryPub, edwardsToMontgomeryPriv } from '@noble/curves/ed25519';
148
156
  edwardsToMontgomeryPub(ed25519.getPublicKey(ed25519.utils.randomPrivateKey()));
149
157
  edwardsToMontgomeryPriv(ed25519.utils.randomPrivateKey());
158
+ ```
150
159
 
160
+ ristretto255 follows [irtf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448).
161
+
162
+ ```ts
151
163
  // hash-to-curve, ristretto255
152
- import { hashToCurve, encodeToCurve, RistrettoPoint } from '@noble/curves/ed25519';
164
+ import { utf8ToBytes } from '@noble/hashes/utils';
165
+ import { sha512 } from '@noble/hashes/sha512';
166
+ import {
167
+ hashToCurve,
168
+ encodeToCurve,
169
+ RistrettoPoint,
170
+ hashToRistretto255,
171
+ } from '@noble/curves/ed25519';
172
+
173
+ const msg = utf8ToBytes('Ristretto is traditionally a short shot of espresso coffee');
174
+ hashToCurve(msg);
175
+
153
176
  const rp = RistrettoPoint.fromHex(
154
177
  '6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919'
155
178
  );
156
- RistrettoPoint.hashToCurve('Ristretto is traditionally a short shot of espresso coffee');
157
- // also has add(), equals(), multiply(), toRawBytes() methods
179
+ RistrettoPoint.BASE.multiply(2n).add(rp).subtract(RistrettoPoint.BASE).toRawBytes();
180
+ RistrettoPoint.ZERO.equals(dp) === false;
181
+ // pre-hashed hash-to-curve
182
+ RistrettoPoint.hashToCurve(sha512(msg));
183
+ // full hash-to-curve including domain separation tag
184
+ hashToRistretto255(msg, { DST: 'ristretto255_XMD:SHA-512_R255MAP_RO_' });
158
185
  ```
159
186
 
160
- #### ed448, X448
187
+ #### ed448, X448, decaf448
161
188
 
162
189
  ```ts
163
190
  import { ed448 } from '@noble/curves/ed448';
@@ -167,17 +194,65 @@ const msg = new TextEncoder().encode('whatsup');
167
194
  const sig = ed448.sign(msg, priv);
168
195
  ed448.verify(sig, msg, pub);
169
196
 
170
- import { ed448ph, ed448ctx, x448, hashToCurve, encodeToCurve } from '@noble/curves/ed448';
197
+ // Variants from RFC8032: prehashed
198
+ import { ed448ph } from '@noble/curves/ed448';
199
+ ```
200
+
201
+ ECDH using Curve448 aka X448, follows [RFC7748](https://www.rfc-editor.org/rfc/rfc7748).
202
+
203
+ ```ts
204
+ import { x448 } from '@noble/curves/ed448';
171
205
  x448.getSharedSecret(priv, pub) === x448.scalarMult(priv, pub); // aliases
172
206
  x448.getPublicKey(priv) === x448.scalarMultBase(priv);
207
+
208
+ // ed448 => x448 conversion
209
+ import { edwardsToMontgomeryPub } from '@noble/curves/ed448';
210
+ edwardsToMontgomeryPub(ed448.getPublicKey(ed448.utils.randomPrivateKey()));
211
+ ```
212
+
213
+ decaf448 follows [irtf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448).
214
+
215
+ ```ts
216
+ import { utf8ToBytes } from '@noble/hashes/utils';
217
+ import { shake256 } from '@noble/hashes/sha3';
218
+ import { hashToCurve, encodeToCurve, DecafPoint, hashToDecaf448 } from '@noble/curves/ed448';
219
+
220
+ const msg = utf8ToBytes('Ristretto is traditionally a short shot of espresso coffee');
221
+ hashToCurve(msg);
222
+
223
+ const dp = DecafPoint.fromHex(
224
+ 'c898eb4f87f97c564c6fd61fc7e49689314a1f818ec85eeb3bd5514ac816d38778f69ef347a89fca817e66defdedce178c7cc709b2116e75'
225
+ );
226
+ DecafPoint.BASE.multiply(2n).add(dp).subtract(DecafPoint.BASE).toRawBytes();
227
+ DecafPoint.ZERO.equals(dp) === false;
228
+ // pre-hashed hash-to-curve
229
+ DecafPoint.hashToCurve(shake256(msg, { dkLen: 112 }));
230
+ // full hash-to-curve including domain separation tag
231
+ hashToDecaf448(msg, { DST: 'decaf448_XOF:SHAKE256_D448MAP_RO_' });
173
232
  ```
174
233
 
175
- Same RFC7748 / RFC8032 are followed.
234
+ Same RFC7748 / RFC8032 / IRTF draft are followed.
176
235
 
177
236
  #### bls12-381
178
237
 
179
238
  See [abstract/bls](#abstractbls-barreto-lynn-scott-curves).
180
239
 
240
+ #### All available imports
241
+
242
+ ```typescript
243
+ import { secp256k1, schnorr } from '@noble/curves/secp256k1';
244
+ import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519';
245
+ import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448';
246
+ import { p256 } from '@noble/curves/p256';
247
+ import { p384 } from '@noble/curves/p384';
248
+ import { p521 } from '@noble/curves/p521';
249
+ import { pallas, vesta } from '@noble/curves/pasta';
250
+ import { bls12_381 } from '@noble/curves/bls12-381';
251
+ import { bn254 } from '@noble/curves/bn254'; // also known as alt_bn128
252
+ import { jubjub } from '@noble/curves/jubjub';
253
+ import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils';
254
+ ```
255
+
181
256
  #### Accessing a curve's variables
182
257
 
183
258
  ```ts
@@ -199,17 +274,6 @@ Precomputes are enabled for weierstrass and edwards BASE points of a curve. You
199
274
  could precompute any other point (e.g. for ECDH) using `utils.precompute()`
200
275
  method: check out examples.
201
276
 
202
- There are following zero-dependency algorithms:
203
-
204
- - [abstract/weierstrass: Short Weierstrass curve](#abstractweierstrass-short-weierstrass-curve)
205
- - [abstract/edwards: Twisted Edwards curve](#abstractedwards-twisted-edwards-curve)
206
- - [abstract/montgomery: Montgomery curve](#abstractmontgomery-montgomery-curve)
207
- - [abstract/bls: Barreto-Lynn-Scott curves](#abstractbls-barreto-lynn-scott-curves)
208
- - [abstract/hash-to-curve: Hashing strings to curve points](#abstracthash-to-curve-hashing-strings-to-curve-points)
209
- - [abstract/poseidon: Poseidon hash](#abstractposeidon-poseidon-hash)
210
- - [abstract/modular: Modular arithmetics utilities](#abstractmodular-modular-arithmetics-utilities)
211
- - [abstract/utils: General utilities](#abstractutils-general-utilities)
212
-
213
277
  ### abstract/weierstrass: Short Weierstrass curve
214
278
 
215
279
  ```ts
@@ -233,7 +297,7 @@ const secq256k1 = weierstrass({
233
297
  randomBytes,
234
298
  });
235
299
 
236
- // Replace weierstrass with weierstrassPoints if you don't need ECDSA, hash, hmac, randomBytes
300
+ // Replace weierstrass() with weierstrassPoints() if you don't need ECDSA, hash, hmac, randomBytes
237
301
  ```
238
302
 
239
303
  Short Weierstrass curve's formula is `y² = x³ + ax + b`. `weierstrass`
@@ -254,6 +318,11 @@ type CHash = {
254
318
  };
255
319
  ```
256
320
 
321
+ **Message hash** is expected instead of message itself:
322
+
323
+ - `sign(msgHash, privKey)` is default behavior, assuming you pre-hash msg with sha2, or other hash
324
+ - `sign(msg, privKey, {prehash: true})` option can be used if you want to pass the message itself
325
+
257
326
  **Weierstrass points:**
258
327
 
259
328
  1. Exported as `ProjectivePoint`
@@ -349,6 +418,7 @@ More examples:
349
418
  const priv = secq256k1.utils.randomPrivateKey();
350
419
  secq256k1.getPublicKey(priv); // Convert private key to public.
351
420
  const sig = secq256k1.sign(msg, priv); // Sign msg with private key.
421
+ const sig2 = secq256k1.sign(msg, priv, { prehash: true }); // hash(msg)
352
422
  secq256k1.verify(sig, msg, priv); // Verify if sig is correct.
353
423
 
354
424
  const Point = secq256k1.ProjectivePoint;
@@ -496,6 +566,8 @@ use aggregated, batch-verifiable
496
566
  [threshold signatures](https://medium.com/snigirev.stepan/bls-signatures-better-than-schnorr-5a7fe30ea716),
497
567
  using Boneh-Lynn-Shacham signature scheme.
498
568
 
569
+ The module doesn't expose `CURVE` property: use `G1.CURVE`, `G2.CURVE` instead.
570
+
499
571
  Main methods and properties are:
500
572
 
501
573
  - `getPublicKey(privateKey)`
@@ -539,7 +611,12 @@ const aggSignature3 = bls.aggregateSignatures(signatures3);
539
611
  const isValid3 = bls.verifyBatch(aggSignature3, messages, publicKeys);
540
612
  console.log({ publicKeys, signatures3, aggSignature3, isValid3 });
541
613
 
542
- // bls.pairing(PointG1, PointG2) // pairings
614
+ // Pairings, with and without final exponentiation
615
+ // bls.pairing(PointG1, PointG2);
616
+ // bls.pairing(PointG1, PointG2, false);
617
+ // bls.fields.Fp12.finalExponentiate(bls.fields.Fp12.mul(eGS, ePHm));
618
+
619
+ // Others
543
620
  // bls.G1.ProjectivePoint.BASE, bls.G2.ProjectivePoint.BASE
544
621
  // bls.fields.Fp, bls.fields.Fp2, bls.fields.Fp12, bls.fields.Fr
545
622
 
@@ -598,7 +675,7 @@ utils: {
598
675
 
599
676
  ### abstract/hash-to-curve: Hashing strings to curve points
600
677
 
601
- 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).
678
+ The module allows to hash arbitrary strings to elliptic curve points. Implements [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380).
602
679
 
603
680
  Every curve has exported `hashToCurve` and `encodeToCurve` methods. You should always prefer `hashToCurve` for security:
604
681
 
@@ -614,19 +691,17 @@ bls12_381.G1.hashToCurve(randomBytes(), { DST: 'another' });
614
691
  bls12_381.G2.hashToCurve(randomBytes(), { DST: 'custom' });
615
692
  ```
616
693
 
617
- If you need low-level methods from spec:
618
-
619
- `expand_message_xmd` [(spec)](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.4.1) produces a uniformly random byte string using a cryptographic hash function H that outputs b bits.
620
-
621
- Hash must conform to `CHash` interface (see [weierstrass section](#abstractweierstrass-short-weierstrass-curve)).
694
+ Low-level methods from the spec:
622
695
 
623
696
  ```ts
697
+ // produces a uniformly random byte string using a cryptographic hash function H that outputs b bits.
624
698
  function expand_message_xmd(
625
699
  msg: Uint8Array,
626
700
  DST: Uint8Array,
627
701
  lenInBytes: number,
628
- H: CHash
702
+ H: CHash // For CHash see abstract/weierstrass docs section
629
703
  ): Uint8Array;
704
+ // produces a uniformly random byte string using an extendable-output function (XOF) H.
630
705
  function expand_message_xof(
631
706
  msg: Uint8Array,
632
707
  DST: Uint8Array,
@@ -634,13 +709,9 @@ function expand_message_xof(
634
709
  k: number,
635
710
  H: CHash
636
711
  ): Uint8Array;
637
- ```
638
-
639
- `hash_to_field(msg, count, options)`
640
- [(spec)](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3)
641
- hashes arbitrary-length byte strings to a list of one or more elements of a finite field F.
712
+ // Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F
713
+ function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][];
642
714
 
643
- ```ts
644
715
  /**
645
716
  * * `DST` is a domain separation tag, defined in section 2.2.5
646
717
  * * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m
@@ -651,23 +722,13 @@ hashes arbitrary-length byte strings to a list of one or more elements of a fini
651
722
  */
652
723
  type UnicodeOrBytes = string | Uint8Array;
653
724
  type Opts = {
654
- DST: UnicodeOrBytes;
655
- p: bigint;
656
- m: number;
657
- k: number;
658
- expand?: 'xmd' | 'xof';
659
- hash: CHash;
725
+ DST: UnicodeOrBytes;
726
+ p: bigint;
727
+ m: number;
728
+ k: number;
729
+ expand?: 'xmd' | 'xof';
730
+ hash: CHash;
660
731
  };
661
-
662
- /**
663
- * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F
664
- * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3
665
- * @param msg a byte string containing the message to hash
666
- * @param count the number of elements of F to output
667
- * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above
668
- * @returns [u_0, ..., u_(count - 1)], a list of field elements.
669
- */
670
- function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][];
671
732
  ```
672
733
 
673
734
  ### abstract/poseidon: Poseidon hash
@@ -710,30 +771,40 @@ mod.invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse
710
771
  mod.invertBatch([1n, 2n, 4n], 21n); // => [1n, 11n, 16n] in one inversion
711
772
  ```
712
773
 
713
- #### Creating private keys from hashes
774
+ Field operations are not constant-time: they are using JS bigints, see [security](#security).
775
+ The fact is mostly irrelevant, but the important method to keep in mind is `pow`,
776
+ which may leak exponent bits, when used naïvely.
714
777
 
715
- Suppose you have `sha256(something)` (e.g. from HMAC) and you want to make a private key from it.
716
- Even though p256 or secp256k1 may have 32-byte private keys,
717
- and sha256 output is also 32-byte, you can't just use it and reduce it modulo `CURVE.n`.
778
+ `mod.Field` is always **field over prime**. Non-prime fields aren't supported for now.
779
+ We don't test for prime-ness for speed and because algorithms are probabilistic anyway.
780
+ Initializing a non-prime field could make your app suspectible to
781
+ DoS (infilite loop) on Tonelli-Shanks square root calculation.
718
782
 
719
- Doing so will make the result key [biased](https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/).
783
+ Unlike `mod.invert`, `mod.invertBatch` won't throw on `0`: make sure to throw an error yourself.
784
+
785
+ #### Creating private keys from hashes
720
786
 
721
- To avoid the bias, we implement FIPS 186 B.4.1, which allows to take arbitrary
722
- byte array and produce valid scalars / private keys with bias being neglible.
787
+ You can't simply make a 32-byte private key from a 32-byte hash.
788
+ Doing so will make the key [biased](https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/).
723
789
 
724
- Use [hash-to-curve](#abstracthash-to-curve-hashing-strings-to-curve-points) if you need
725
- hashing to **public keys**; the function in the module instead operates on **private keys**.
790
+ To make the bias negligible, we follow [FIPS 186-5 A.2](https://csrc.nist.gov/publications/detail/fips/186/5/final)
791
+ and [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380#section-5.2).
792
+ This means, for 32-byte key, we would need 48-byte hash to get 2^-128 bias, which matches curve security level.
793
+
794
+ `hashToPrivateScalar()` that hashes to **private key** was created for this purpose.
795
+ Use [abstract/hash-to-curve](#abstracthash-to-curve-hashing-strings-to-curve-points)
796
+ if you need to hash to **public key**.
726
797
 
727
798
  ```ts
728
799
  import { p256 } from '@noble/curves/p256';
729
800
  import { sha256 } from '@noble/hashes/sha256';
730
801
  import { hkdf } from '@noble/hashes/hkdf';
731
802
  const someKey = new Uint8Array(32).fill(2); // Needs to actually be random, not .fill(2)
732
- const derived = hkdf(sha256, someKey, undefined, 'application', 40); // 40 bytes
803
+ const derived = hkdf(sha256, someKey, undefined, 'application', 48); // 48 bytes for 32-byte priv
733
804
  const validPrivateKey = mod.hashToPrivateScalar(derived, p256.CURVE.n);
734
805
  ```
735
806
 
736
- ### abstract/utils: General utilities
807
+ ### abstract/utils: Useful utilities
737
808
 
738
809
  ```ts
739
810
  import * as utils from '@noble/curves/abstract/utils';
@@ -755,18 +826,36 @@ utils.equalBytes(Uint8Array.from([0xde]), Uint8Array.from([0xde]));
755
826
 
756
827
  ## Security
757
828
 
758
- 1. The library has been audited in Feb 2023 by an independent security firm [Trail of Bits](https://www.trailofbits.com):
759
- [PDF](https://github.com/trailofbits/publications/blob/master/reviews/2023-01-ryanshea-noblecurveslibrary-securityreview.pdf).
760
- The audit has been funded by [Ryan Shea](https://www.shea.io). Audit scope was abstract modules `curve`, `hash-to-curve`, `modular`, `poseidon`, `utils`, `weierstrass`, and top-level modules `_shortw_utils` and `secp256k1`. See [changes since audit](https://github.com/paulmillr/noble-curves/compare/0.7.3..main).
761
- 2. The library has been fuzzed by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz). You can run the fuzzer by yourself to check it.
762
- 3. [Timing attack](https://en.wikipedia.org/wiki/Timing_attack) considerations: _JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard to achieve in a scripting language. Which means _any other JS library can't have constant-timeness_. Even statically typed Rust, a language without GC, [makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security) for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones. Use low-level libraries & languages. Nonetheless we're targetting algorithmic constant time.
763
-
764
- We consider infrastructure attacks like rogue NPM modules very important; that's why it's crucial to minimize the amount of 3rd-party dependencies & native bindings. If your app uses 500 dependencies, any dep could get hacked and you'll be downloading malware with every `npm install`. Our goal is to minimize this attack vector. As for devDependencies used by the library:
765
-
766
- - `@scure` base, bip32, bip39 (used in tests), micro-bmark (benchmark), micro-should (testing) are developed by us
767
- and follow the same practices such as: minimal library size, auditability, signed releases
768
- - prettier (linter), fast-check (property-based testing),
769
- typescript versions are locked and rarely updated. Every update is checked with `npm-diff`.
829
+ 1. The library has been independently audited:
830
+
831
+ - in Feb 2023 by [Trail of Bits](https://www.trailofbits.com):
832
+ [PDF](https://github.com/trailofbits/publications/blob/master/reviews/2023-01-ryanshea-noblecurveslibrary-securityreview.pdf).
833
+ The audit has been funded by [Ryan Shea](https://www.shea.io).
834
+ Audit scope was abstract modules `curve`, `hash-to-curve`, `modular`, `poseidon`, `utils`, `weierstrass`,
835
+ and top-level modules `_shortw_utils` and `secp256k1`.
836
+ See [changes since v0.7.3 audit](https://github.com/paulmillr/noble-curves/compare/0.7.3..main).
837
+
838
+ 2. The library has been fuzzed by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz).
839
+ You can run the fuzzer by yourself to check it.
840
+ 3. [Timing attack](https://en.wikipedia.org/wiki/Timing_attack) considerations:
841
+ _JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard to
842
+ achieve in a scripting language. Which means _any other JS library can't have
843
+ constant-timeness_. Even statically typed Rust, a language without GC,
844
+ [makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security)
845
+ for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones.
846
+ Use low-level libraries & languages. Nonetheless we're targetting algorithmic constant time.
847
+
848
+ We consider infrastructure attacks like rogue NPM modules very important;
849
+ that's why it's crucial to minimize the amount of 3rd-party dependencies & native bindings.
850
+ If your app uses 500 dependencies, any dep could get hacked and you'll be
851
+ downloading malware with every `npm install`. Our goal is to minimize this attack vector.
852
+ As for devDependencies used by the library:
853
+
854
+ - `@scure` base, bip32, bip39 (used in tests), micro-bmark (benchmark), micro-should (testing)
855
+ are developed by us and follow the same practices such as: minimal library size, auditability,
856
+ signed releases
857
+ - prettier (linter), fast-check (property-based testing), typescript versions
858
+ are locked and rarely updated. Every update is checked with `npm-diff`.
770
859
  The packages are big, which makes it hard to audit their source code thoroughly and fully.
771
860
  - They are only used if you clone the git repo and want to add some feature to it. End-users won't use them.
772
861
 
@@ -865,35 +954,37 @@ ed448 x 1,247 ops/sec @ 801μs/op
865
954
  ## Upgrading
866
955
 
867
956
  Previously, the library was split into single-feature packages
868
- noble-secp256k1, noble-ed25519 and noble-bls12-381.
957
+ [noble-secp256k1](https://github.com/paulmillr/noble-secp256k1),
958
+ [noble-ed25519](https://github.com/paulmillr/noble-ed25519) and
959
+ [noble-bls12-381](https://github.com/paulmillr/noble-bls12-381).
869
960
 
870
961
  Curves continue their original work. The single-feature packages changed their
871
962
  direction towards providing minimal 4kb implementations of cryptography,
872
963
  which means they have less features.
873
964
 
874
- Upgrading from @noble/secp256k1 2.0 or @noble/ed25519 2.0: no changes, libraries are compatible.
965
+ Upgrading from noble-secp256k1 2.0 or noble-ed25519 2.0: no changes, libraries are compatible.
875
966
 
876
- Upgrading from [@noble/secp256k1](https://github.com/paulmillr/noble-secp256k1) 1.7:
967
+ Upgrading from noble-secp256k1 1.7:
877
968
 
878
969
  - `getPublicKey`
879
- - now produce 33-byte compressed signatures by default
880
- - to use old behavior, which produced 65-byte uncompressed keys, set
881
- argument `isCompressed` to `false`: `getPublicKey(priv, false)`
970
+ - now produce 33-byte compressed signatures by default
971
+ - to use old behavior, which produced 65-byte uncompressed keys, set
972
+ argument `isCompressed` to `false`: `getPublicKey(priv, false)`
882
973
  - `sign`
883
- - is now sync; use `signAsync` for async version
884
- - now returns `Signature` instance with `{ r, s, recovery }` properties
885
- - `canonical` option was renamed to `lowS`
886
- - `recovered` option has been removed because recovery bit is always returned now
887
- - `der` option has been removed. There are 2 options:
888
- 1. Use compact encoding: `fromCompact`, `toCompactRawBytes`, `toCompactHex`.
889
- Compact encoding is simply a concatenation of 32-byte r and 32-byte s.
890
- 2. If you must use DER encoding, switch to noble-curves (see above).
974
+ - is now sync; use `signAsync` for async version
975
+ - now returns `Signature` instance with `{ r, s, recovery }` properties
976
+ - `canonical` option was renamed to `lowS`
977
+ - `recovered` option has been removed because recovery bit is always returned now
978
+ - `der` option has been removed. There are 2 options:
979
+ 1. Use compact encoding: `fromCompact`, `toCompactRawBytes`, `toCompactHex`.
980
+ Compact encoding is simply a concatenation of 32-byte r and 32-byte s.
981
+ 2. If you must use DER encoding, switch to noble-curves (see above).
891
982
  - `verify`
892
- - `strict` option was renamed to `lowS`
983
+ - `strict` option was renamed to `lowS`
893
984
  - `getSharedSecret`
894
- - now produce 33-byte compressed signatures by default
895
- - to use old behavior, which produced 65-byte uncompressed keys, set
896
- argument `isCompressed` to `false`: `getSharedSecret(a, b, false)`
985
+ - now produce 33-byte compressed signatures by default
986
+ - to use old behavior, which produced 65-byte uncompressed keys, set
987
+ argument `isCompressed` to `false`: `getSharedSecret(a, b, false)`
897
988
  - `recoverPublicKey(msg, sig, rec)` was changed to `sig.recoverPublicKey(msg)`
898
989
  - `number` type for private keys have been removed: use `bigint` instead
899
990
  - `Point` (2d xy) has been changed to `ProjectivePoint` (3d xyz)
@@ -914,53 +1005,65 @@ Upgrading from [@noble/ed25519](https://github.com/paulmillr/noble-ed25519) 1.7:
914
1005
  Upgrading from [@noble/bls12-381](https://github.com/paulmillr/noble-bls12-381):
915
1006
 
916
1007
  - Methods and classes were renamed:
917
- - PointG1 -> G1.Point, PointG2 -> G2.Point
918
- - PointG2.fromSignature -> Signature.decode, PointG2.toSignature -> Signature.encode
1008
+ - PointG1 -> G1.Point, PointG2 -> G2.Point
1009
+ - PointG2.fromSignature -> Signature.decode, PointG2.toSignature -> Signature.encode
919
1010
  - Fp2 ORDER was corrected
920
1011
 
921
1012
  ## Resources
922
1013
 
923
- Useful documentation and articles about the library or its primitives:
924
-
925
1014
  - [Learning fast elliptic-curve cryptography](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/)
926
- - [Taming the many EdDSAs](https://csrc.nist.gov/csrc/media/Presentations/2023/crclub-2023-03-08/images-media/20230308-crypto-club-slides--taming-the-many-EdDSAs.pdf)
927
- that describes concepts of Strong UnForgeability under Chosen Message Attacks and Strongly Binding Signatures
1015
+ - EdDSA
1016
+ - [A Deep dive into Ed25519 Signatures](https://cendyne.dev/posts/2022-03-06-ed25519-signatures.html)
1017
+ - [Ed25519 Deep Dive Addendum](https://cendyne.dev/posts/2022-09-11-ed25519-deep-dive-addendum.html)
1018
+ - [It’s 255:19AM. Do you know what your validation criteria are?](https://hdevalence.ca/blog/2020-10-04-its-25519am)
1019
+ - [Taming the many EdDSAs](https://csrc.nist.gov/csrc/media/Presentations/2023/crclub-2023-03-08/images-media/20230308-crypto-club-slides--taming-the-many-EdDSAs.pdf)
1020
+ that describes concepts of Strong UnForgeability under Chosen Message Attacks and Strongly Binding Signatures
1021
+ - [Cofactor Explained: Clearing Elliptic Curves’ dirty little secret](https://loup-vaillant.fr/tutorials/cofactor)
1022
+ - [Surrounded by Elligators](https://loup-vaillant.fr/articles/implementing-elligator)
928
1023
  - Pairings and BLS
929
- - [BLS signatures for busy people](https://gist.github.com/paulmillr/18b802ad219b1aee34d773d08ec26ca2)
930
- - [BLS12-381 for the rest of us](https://hackmd.io/@benjaminion/bls12-381)
931
- - [Key concepts of pairings](https://medium.com/@alonmuroch_65570/bls-signatures-part-2-key-concepts-of-pairings-27a8a9533d0c)
932
- - Pairing over bls12-381:
933
- [part 1](https://research.nccgroup.com/2020/07/06/pairing-over-bls12-381-part-1-fields/),
934
- [part 2](https://research.nccgroup.com/2020/07/13/pairing-over-bls12-381-part-2-curves/),
935
- [part 3](https://research.nccgroup.com/2020/08/13/pairing-over-bls12-381-part-3-pairing/)
936
- - [Estimating the bit security of pairing-friendly curves](https://research.nccgroup.com/2022/02/03/estimating-the-bit-security-of-pairing-friendly-curves/)
1024
+ - [BLS signatures for busy people](https://gist.github.com/paulmillr/18b802ad219b1aee34d773d08ec26ca2)
1025
+ - [BLS12-381 for the rest of us](https://hackmd.io/@benjaminion/bls12-381)
1026
+ - [Key concepts of pairings](https://medium.com/@alonmuroch_65570/bls-signatures-part-2-key-concepts-of-pairings-27a8a9533d0c)
1027
+ - Pairing over bls12-381:
1028
+ [fields](https://research.nccgroup.com/2020/07/06/pairing-over-bls12-381-part-1-fields/),
1029
+ [curves](https://research.nccgroup.com/2020/07/13/pairing-over-bls12-381-part-2-curves/),
1030
+ [pairings](https://research.nccgroup.com/2020/08/13/pairing-over-bls12-381-part-3-pairing/)
1031
+ - [Estimating the bit security of pairing-friendly curves](https://research.nccgroup.com/2022/02/03/estimating-the-bit-security-of-pairing-friendly-curves/)
937
1032
 
938
- Online demos:
1033
+ ### Demos
939
1034
 
940
1035
  - [Elliptic Curve Calculator](https://paulmillr.com/noble): add / multiply points, sign messages
941
1036
  - [BLS threshold signatures](https://genthresh.com)
942
1037
 
943
- Projects using noble-curves:
1038
+ ### Projects using curves
944
1039
 
945
- - [scure-bip32](https://github.com/paulmillr/scure-bip32) and separate [bip32](https://github.com/bitcoinjs/bip32) HDkey libraries
1040
+ - HDkey libraries: [scure-bip32](https://github.com/paulmillr/scure-bip32), [bip32](https://github.com/bitcoinjs/bip32)
1041
+ - Social networks: [nostr](https://github.com/nbd-wtf/nostr-tools), [bluesky](https://github.com/bluesky-social/atproto)
946
1042
  - Ethereum libraries:
947
- - [ethereum-cryptography](https://github.com/ethereum/js-ethereum-cryptography)
948
- - [@ethereumjs](https://github.com/ethereumjs/ethereumjs-monorepo)
949
- - [micro-eth-signer](https://github.com/paulmillr/micro-eth-signer)
950
- - [ethers](https://github.com/ethers-io/ethers.js) (old noble-secp256k1 for now)
951
- - [viem.sh](https://viem.sh)
952
- - [metamask's eth-sig-util](https://github.com/MetaMask/eth-sig-util)
953
- - [gridplus lattice sdk](https://github.com/GridPlus/lattice-eth2-utils)
954
- - Bitcoin libraries: [scure-btc-signer](https://github.com/paulmillr/scure-btc-signer)
1043
+ - [ethereum-cryptography](https://github.com/ethereum/js-ethereum-cryptography)
1044
+ - [micro-eth-signer](https://github.com/paulmillr/micro-eth-signer),
1045
+ [ethers](https://github.com/ethers-io/ethers.js) (old noble),
1046
+ [viem.sh](https://viem.sh),
1047
+ [@ethereumjs](https://github.com/ethereumjs/ethereumjs-monorepo)
1048
+ - [metamask's eth-sig-util](https://github.com/MetaMask/eth-sig-util)
1049
+ - [gridplus lattice sdk](https://github.com/GridPlus/lattice-eth2-utils)
1050
+ - Bitcoin libraries:
1051
+ - [scure-btc-signer](https://github.com/paulmillr/scure-btc-signer)
1052
+ - [tapscript](https://github.com/cmdruid/tapscript)
955
1053
  - Solana libraries: [micro-sol-signer](https://github.com/paulmillr/micro-sol-signer), [solana-web3.js](https://github.com/solana-labs/solana-web3.js)
956
- - [polkadot.js](https://github.com/polkadot-js/common), [micro-starknet](https://github.com/paulmillr/micro-starknet)
957
- - [protonmail](https://github.com/ProtonMail/WebClients) (old noble-ed25519 for now)
958
- - [did-jwt](https://github.com/decentralized-identity/did-jwt), [hpke-js](https://github.com/dajiaji/hpke-js), [nostr-tools](https://github.com/nbd-wtf/nostr-tools)
1054
+ - Other web3 stuff:
1055
+ - [scure-starknet](https://github.com/paulmillr/scure-starknet)
1056
+ - [aztec](https://github.com/AztecProtocol/aztec-packages)
1057
+ - [polkadot.js](https://github.com/polkadot-js/common), [drand-client](https://github.com/drand/drand-client), [moneroj](https://github.com/beritani/moneroj), [tronlib](https://github.com/CoinSpace/tronlib)
1058
+ - [protonmail](https://github.com/ProtonMail/WebClients) (old noble for now)
1059
+ - [did-jwt](https://github.com/decentralized-identity/did-jwt), [hpke-js](https://github.com/dajiaji/hpke-js),
1060
+ [js-libp2p-noise](https://github.com/ChainSafe/js-libp2p-noise)
959
1061
  - [ed25519-keygen](https://github.com/paulmillr/ed25519-keygen) SSH, PGP, TOR key generation
960
1062
  - [secp256k1 compatibility layer](https://github.com/ethereum/js-ethereum-cryptography/blob/2.0.0/src/secp256k1-compat.ts)
961
- for users who want to switch from secp256k1-node or tiny-secp256k1. Allows to see which methods map to corresponding noble code.
1063
+ for users who want to switch from secp256k1-node or tiny-secp256k1. Allows to see which methods map to corresponding noble code.
962
1064
  - [BLS BBS signatures](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)
963
1065
  - [KZG trusted setup ceremony](https://github.com/dsrvlabs/czg-keremony)
1066
+ - See [full list of projects on GitHub](https://github.com/paulmillr/noble-curves/network/dependents).
964
1067
 
965
1068
  ## License
966
1069