@noble/curves 1.0.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 (103) hide show
  1. package/README.md +399 -247
  2. package/_shortw_utils.d.ts +1 -1
  3. package/abstract/bls.d.ts.map +1 -1
  4. package/abstract/bls.js +2 -2
  5. package/abstract/bls.js.map +1 -1
  6. package/abstract/edwards.d.ts +7 -2
  7. package/abstract/edwards.d.ts.map +1 -1
  8. package/abstract/edwards.js +7 -2
  9. package/abstract/edwards.js.map +1 -1
  10. package/abstract/hash-to-curve.d.ts +1 -1
  11. package/abstract/hash-to-curve.d.ts.map +1 -1
  12. package/abstract/hash-to-curve.js +14 -8
  13. package/abstract/hash-to-curve.js.map +1 -1
  14. package/abstract/modular.d.ts +55 -13
  15. package/abstract/modular.d.ts.map +1 -1
  16. package/abstract/modular.js +82 -22
  17. package/abstract/modular.js.map +1 -1
  18. package/abstract/poseidon.d.ts.map +1 -1
  19. package/abstract/poseidon.js +39 -41
  20. package/abstract/poseidon.js.map +1 -1
  21. package/abstract/utils.d.ts +43 -5
  22. package/abstract/utils.d.ts.map +1 -1
  23. package/abstract/utils.js +70 -26
  24. package/abstract/utils.js.map +1 -1
  25. package/abstract/weierstrass.d.ts +18 -2
  26. package/abstract/weierstrass.d.ts.map +1 -1
  27. package/abstract/weierstrass.js +40 -22
  28. package/abstract/weierstrass.js.map +1 -1
  29. package/bls12-381.d.ts.map +1 -1
  30. package/bls12-381.js +11 -11
  31. package/bls12-381.js.map +1 -1
  32. package/ed25519.d.ts +33 -20
  33. package/ed25519.d.ts.map +1 -1
  34. package/ed25519.js +60 -38
  35. package/ed25519.js.map +1 -1
  36. package/ed448.d.ts +53 -4
  37. package/ed448.d.ts.map +1 -1
  38. package/ed448.js +217 -38
  39. package/ed448.js.map +1 -1
  40. package/esm/abstract/bls.js +3 -3
  41. package/esm/abstract/bls.js.map +1 -1
  42. package/esm/abstract/edwards.js +7 -2
  43. package/esm/abstract/edwards.js.map +1 -1
  44. package/esm/abstract/hash-to-curve.js +14 -8
  45. package/esm/abstract/hash-to-curve.js.map +1 -1
  46. package/esm/abstract/modular.js +78 -21
  47. package/esm/abstract/modular.js.map +1 -1
  48. package/esm/abstract/poseidon.js +39 -41
  49. package/esm/abstract/poseidon.js.map +1 -1
  50. package/esm/abstract/utils.js +70 -26
  51. package/esm/abstract/utils.js.map +1 -1
  52. package/esm/abstract/weierstrass.js +40 -22
  53. package/esm/abstract/weierstrass.js.map +1 -1
  54. package/esm/bls12-381.js +11 -11
  55. package/esm/bls12-381.js.map +1 -1
  56. package/esm/ed25519.js +60 -38
  57. package/esm/ed25519.js.map +1 -1
  58. package/esm/ed448.js +217 -38
  59. package/esm/ed448.js.map +1 -1
  60. package/esm/jubjub.js +1 -1
  61. package/esm/jubjub.js.map +1 -1
  62. package/esm/p256.js +10 -9
  63. package/esm/p256.js.map +1 -1
  64. package/esm/p384.js +7 -6
  65. package/esm/p384.js.map +1 -1
  66. package/esm/p521.js +7 -6
  67. package/esm/p521.js.map +1 -1
  68. package/esm/package.json +1 -4
  69. package/esm/secp256k1.js +11 -9
  70. package/esm/secp256k1.js.map +1 -1
  71. package/jubjub.js.map +1 -1
  72. package/p256.d.ts +4 -5
  73. package/p256.d.ts.map +1 -1
  74. package/p256.js +10 -10
  75. package/p256.js.map +1 -1
  76. package/p384.d.ts +4 -5
  77. package/p384.d.ts.map +1 -1
  78. package/p384.js +7 -7
  79. package/p384.js.map +1 -1
  80. package/p521.d.ts +4 -5
  81. package/p521.d.ts.map +1 -1
  82. package/p521.js +7 -7
  83. package/p521.js.map +1 -1
  84. package/package.json +7 -9
  85. package/secp256k1.d.ts +5 -5
  86. package/secp256k1.d.ts.map +1 -1
  87. package/secp256k1.js +11 -10
  88. package/secp256k1.js.map +1 -1
  89. package/src/abstract/bls.ts +3 -3
  90. package/src/abstract/edwards.ts +13 -4
  91. package/src/abstract/hash-to-curve.ts +14 -8
  92. package/src/abstract/modular.ts +84 -27
  93. package/src/abstract/poseidon.ts +39 -40
  94. package/src/abstract/utils.ts +77 -33
  95. package/src/abstract/weierstrass.ts +51 -29
  96. package/src/bls12-381.ts +12 -17
  97. package/src/ed25519.ts +105 -75
  98. package/src/ed448.ts +286 -64
  99. package/src/jubjub.ts +1 -1
  100. package/src/p256.ts +13 -14
  101. package/src/p384.ts +12 -13
  102. package/src/p521.ts +12 -13
  103. package/src/secp256k1.ts +60 -55
package/README.md CHANGED
@@ -5,73 +5,83 @@ Audited & minimal JS implementation of elliptic curve cryptography.
5
5
  - 🔒 [**Audited**](#security) by an independent security firm
6
6
  - 🔻 Tree-shaking-friendly: use only what's necessary, other code won't be included
7
7
  - 🏎 Ultra-fast, hand-optimized for caveats of JS engines
8
- - 🔍 Unique tests ensure correctness: property-based, cross-library and Wycheproof vectors, fuzzing
8
+ - 🔍 Unique tests ensure correctness: property-based, cross-library and Wycheproof vectors, fuzzing
9
9
  - ➰ Short Weierstrass, Edwards, Montgomery curves
10
10
  - ✍️ ECDSA, EdDSA, Schnorr, BLS signature schemes, ECDH key agreement
11
- - #️⃣ Hash-to-curve
12
- for encoding or hashing an arbitrary string to an elliptic curve point
11
+ - 🔖 SUF-CMA and SBS (non-repudiation) for ed25519, ed448 and others
12
+ - #️⃣ hash-to-curve for encoding or hashing an arbitrary string to an elliptic curve point
13
13
  - 🧜‍♂️ Poseidon ZK-friendly hash
14
14
 
15
- Check out [Upgrading](#upgrading) if you've previously used single-feature noble
16
- packages. See [Resources](#resources) for articles and real-world software that uses curves.
17
-
18
15
  ### This library belongs to _noble_ crypto
19
16
 
20
17
  > **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools.
21
18
 
22
19
  - No dependencies, protection against supply chain attacks
23
20
  - Auditable TypeScript / JS code
24
- - Supported in all major browsers and stable node.js versions
25
- - 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
26
23
  - Check out [homepage](https://paulmillr.com/noble/) & all libraries:
27
- [curves](https://github.com/paulmillr/noble-curves)
28
- (4kb versions [secp256k1](https://github.com/paulmillr/noble-secp256k1),
29
- [ed25519](https://github.com/paulmillr/noble-ed25519)),
30
- [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)
31
29
 
32
30
  ## Usage
33
31
 
34
- Browser, deno and node.js are supported:
35
-
36
32
  > npm install @noble/curves
37
33
 
38
- For [Deno](https://deno.land), use it with
39
- [npm specifier](https://deno.land/manual@v1.28.0/node/npm_specifiers).
40
- In browser, you could also include the single file from
41
- [GitHub's releases page](https://github.com/paulmillr/noble-curves/releases).
42
-
43
- The library is tree-shaking-friendly and does NOT expose root entry point as
44
- `import c from '@noble/curves'`. Instead, you need to import specific primitives.
45
- This is done to ensure small size of your apps.
46
-
47
- Package consists of two parts:
48
-
49
- 1. [Implementations](#implementations), utilizing one dependency [noble-hashes](https://github.com/paulmillr/noble-hashes),
50
- providing ready-to-use:
51
- - NIST curves secp256r1 / p256, secp384r1 / p384, secp521r1 / p521
52
- - SECG curve secp256k1
53
- - ed25519 / curve25519 / x25519 / ristretto255,
54
- edwards448 / curve448 / x448
55
- implementing
56
- [RFC7748](https://www.rfc-editor.org/rfc/rfc7748) /
57
- [RFC8032](https://www.rfc-editor.org/rfc/rfc8032) /
58
- [FIPS 186-5](https://csrc.nist.gov/publications/detail/fips/186/5/final) /
59
- [ZIP215](https://zips.z.cash/zip-0215) standards
60
- - pairing-friendly curves bls12-381, bn254
61
- - [pasta](https://electriccoin.co/blog/the-pasta-curves-for-halo-2-and-beyond/) curves
62
- 2. [Abstract](#abstract-api), zero-dependency EC algorithms
34
+ We support all major platforms and runtimes.
35
+ For [Deno](https://deno.land), ensure to use [npm specifier](https://deno.land/manual@v1.28.0/node/npm_specifiers).
36
+ For React Native, you may need a [polyfill for crypto.getRandomValues](https://github.com/LinusU/react-native-get-random-values).
37
+ If you don't like NPM, a standalone [noble-curves.js](https://github.com/paulmillr/noble-curves/releases) is also available.
38
+
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)
63
67
 
64
68
  ### Implementations
65
69
 
66
- Each curve can be used in the following way:
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.
72
+
73
+ #### ECDSA signature scheme
74
+
75
+ Generic example that works for all curves, shown for secp256k1:
67
76
 
68
77
  ```ts
78
+ // import * from '@noble/curves'; // Error: use sub-imports, to ensure small app size
69
79
  import { secp256k1 } from '@noble/curves/secp256k1'; // ESM and Common.js
70
80
  // import { secp256k1 } from 'npm:@noble/curves@1.2.0/secp256k1'; // Deno
71
81
  const priv = secp256k1.utils.randomPrivateKey();
72
82
  const pub = secp256k1.getPublicKey(priv);
73
- const msg = new Uint8Array(32).fill(1);
74
- 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
75
85
  const isValid = secp256k1.verify(sig, msg, pub) === true;
76
86
 
77
87
  // hex strings are also supported besides Uint8Arrays:
@@ -79,33 +89,25 @@ const privHex = '46c930bc7bb4db7f55da20798697421b98c4175a52c630294d75a84b9c12623
79
89
  const pub2 = secp256k1.getPublicKey(privHex);
80
90
  ```
81
91
 
82
- All curves:
92
+ #### ECDSA public key recovery & extra entropy
83
93
 
84
- ```typescript
85
- import { secp256k1, schnorr } from '@noble/curves/secp256k1';
86
- import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519';
87
- import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448';
88
- import { p256 } from '@noble/curves/p256';
89
- import { p384 } from '@noble/curves/p384';
90
- import { p521 } from '@noble/curves/p521';
91
- import { pallas, vesta } from '@noble/curves/pasta';
92
- import { bls12_381 } from '@noble/curves/bls12-381';
93
- import { bn254 } from '@noble/curves/bn254';
94
- 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 });
95
99
  ```
96
100
 
97
- Recovering public keys from weierstrass ECDSA signatures; using ECDH:
101
+ #### ECDH (Elliptic Curve Diffie-Hellman)
98
102
 
99
103
  ```ts
100
- // extraEntropy https://moderncrypto.org/mail-archive/curves/2017/000925.html
101
- const sigImprovedSecurity = secp256k1.sign(msg, priv, { extraEntropy: true });
102
- 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)
103
106
  const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
104
- const shared = secp256k1.getSharedSecret(priv, someonesPub); // ECDH
107
+ const shared = secp256k1.getSharedSecret(priv, someonesPub);
105
108
  ```
106
109
 
107
- Schnorr signatures over secp256k1 following
108
- [BIP340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki):
110
+ #### Schnorr signatures over secp256k1 (BIP340)
109
111
 
110
112
  ```ts
111
113
  import { schnorr } from '@noble/curves/secp256k1';
@@ -116,12 +118,7 @@ const sig = schnorr.sign(msg, priv);
116
118
  const isValid = schnorr.verify(sig, msg, pub);
117
119
  ```
118
120
 
119
- ed25519 module has ed25519ctx / ed25519ph variants,
120
- x25519 ECDH and [ristretto255](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448).
121
-
122
- Default `verify` behavior follows [ZIP215](https://zips.z.cash/zip-0215) and
123
- [can be used in consensus-critical applications](https://hdevalence.ca/blog/2020-10-04-its-25519am).
124
- `zip215: false` option switches verification criteria to RFC8032 / FIPS 186-5.
121
+ #### ed25519, X25519, ristretto255
125
122
 
126
123
  ```ts
127
124
  import { ed25519 } from '@noble/curves/ed25519';
@@ -131,7 +128,18 @@ const msg = new TextEncoder().encode('hello');
131
128
  const sig = ed25519.sign(msg, priv);
132
129
  ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215
133
130
  ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5
131
+ ```
132
+
133
+ Default `verify` behavior follows [ZIP215](https://zips.z.cash/zip-0215) and
134
+ [can be used in consensus-critical applications](https://hdevalence.ca/blog/2020-10-04-its-25519am).
135
+ It has SUF-CMA (strong unforgeability under chosen message attacks).
136
+ `zip215: false` option switches verification criteria to strict
137
+ [RFC8032](https://www.rfc-editor.org/rfc/rfc8032) / [FIPS 186-5](https://csrc.nist.gov/publications/detail/fips/186/5/final)
138
+ and additionally provides non-repudiation with SBS [(Strongly Binding Signatures)](https://eprint.iacr.org/2020/1244).
139
+
140
+ X25519 follows [RFC7748](https://www.rfc-editor.org/rfc/rfc7748).
134
141
 
142
+ ```ts
135
143
  // Variants from RFC8032: with context, prehashed
136
144
  import { ed25519ctx, ed25519ph } from '@noble/curves/ed25519';
137
145
 
@@ -141,31 +149,119 @@ const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4';
141
149
  const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c';
142
150
  x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases
143
151
  x25519.getPublicKey(priv) === x25519.scalarMultBase(priv);
152
+ x25519.getPublicKey(x25519.utils.randomPrivateKey());
153
+
154
+ // ed25519 => x25519 conversion
155
+ import { edwardsToMontgomeryPub, edwardsToMontgomeryPriv } from '@noble/curves/ed25519';
156
+ edwardsToMontgomeryPub(ed25519.getPublicKey(ed25519.utils.randomPrivateKey()));
157
+ edwardsToMontgomeryPriv(ed25519.utils.randomPrivateKey());
158
+ ```
159
+
160
+ ristretto255 follows [irtf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448).
161
+
162
+ ```ts
163
+ // hash-to-curve, ristretto255
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';
144
172
 
145
- // hash-to-curve
146
- import { hashToCurve, encodeToCurve } from '@noble/curves/ed25519';
173
+ const msg = utf8ToBytes('Ristretto is traditionally a short shot of espresso coffee');
174
+ hashToCurve(msg);
147
175
 
148
- import { RistrettoPoint } from '@noble/curves/ed25519';
149
176
  const rp = RistrettoPoint.fromHex(
150
177
  '6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919'
151
178
  );
152
- RistrettoPoint.hashToCurve('Ristretto is traditionally a short shot of espresso coffee');
153
- // 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_' });
185
+ ```
186
+
187
+ #### ed448, X448, decaf448
188
+
189
+ ```ts
190
+ import { ed448 } from '@noble/curves/ed448';
191
+ const priv = ed448.utils.randomPrivateKey();
192
+ const pub = ed448.getPublicKey(priv);
193
+ const msg = new TextEncoder().encode('whatsup');
194
+ const sig = ed448.sign(msg, priv);
195
+ ed448.verify(sig, msg, pub);
196
+
197
+ // Variants from RFC8032: prehashed
198
+ import { ed448ph } from '@noble/curves/ed448';
154
199
  ```
155
200
 
156
- ed448 is similar:
201
+ ECDH using Curve448 aka X448, follows [RFC7748](https://www.rfc-editor.org/rfc/rfc7748).
157
202
 
158
203
  ```ts
204
+ import { x448 } from '@noble/curves/ed448';
205
+ x448.getSharedSecret(priv, pub) === x448.scalarMult(priv, pub); // aliases
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_' });
232
+ ```
233
+
234
+ Same RFC7748 / RFC8032 / IRTF draft are followed.
235
+
236
+ #### bls12-381
237
+
238
+ See [abstract/bls](#abstractbls-barreto-lynn-scott-curves).
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';
159
245
  import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448';
160
- import { hashToCurve, encodeToCurve } from '@noble/curves/ed448';
161
- ed448.getPublicKey(ed448.utils.randomPrivateKey());
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';
162
254
  ```
163
255
 
164
- Every curve has `CURVE` object that contains its parameters, field, and others:
256
+ #### Accessing a curve's variables
165
257
 
166
258
  ```ts
167
- import { secp256k1 } from '@noble/curves/secp256k1'; // ESM and Common.js
168
- console.log(secp256k1.CURVE.p, secp256k1.CURVE.n, secp256k1.CURVE.a, secp256k1.CURVE.b);
259
+ import { secp256k1 } from '@noble/curves/secp256k1';
260
+ // Every curve has `CURVE` object that contains its parameters, field, and others
261
+ console.log(secp256k1.CURVE.p); // field modulus
262
+ console.log(secp256k1.CURVE.n); // curve order
263
+ console.log(secp256k1.CURVE.a, secp256k1.CURVE.b); // equation params
264
+ console.log(secp256k1.CURVE.Gx, secp256k1.CURVE.Gy); // base point coordinates
169
265
  ```
170
266
 
171
267
  ## Abstract API
@@ -178,17 +274,6 @@ Precomputes are enabled for weierstrass and edwards BASE points of a curve. You
178
274
  could precompute any other point (e.g. for ECDH) using `utils.precompute()`
179
275
  method: check out examples.
180
276
 
181
- There are following zero-dependency algorithms:
182
-
183
- - [abstract/weierstrass: Short Weierstrass curve](#abstractweierstrass-short-weierstrass-curve)
184
- - [abstract/edwards: Twisted Edwards curve](#abstractedwards-twisted-edwards-curve)
185
- - [abstract/montgomery: Montgomery curve](#abstractmontgomery-montgomery-curve)
186
- - [abstract/bls: Barreto-Lynn-Scott curves](#abstractbls-barreto-lynn-scott-curves)
187
- - [abstract/hash-to-curve: Hashing strings to curve points](#abstracthash-to-curve-hashing-strings-to-curve-points)
188
- - [abstract/poseidon: Poseidon hash](#abstractposeidon-poseidon-hash)
189
- - [abstract/modular: Modular arithmetics utilities](#abstractmodular-modular-arithmetics-utilities)
190
- - [abstract/utils: General utilities](#abstractutils-general-utilities)
191
-
192
277
  ### abstract/weierstrass: Short Weierstrass curve
193
278
 
194
279
  ```ts
@@ -212,7 +297,7 @@ const secq256k1 = weierstrass({
212
297
  randomBytes,
213
298
  });
214
299
 
215
- // 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
216
301
  ```
217
302
 
218
303
  Short Weierstrass curve's formula is `y² = x³ + ax + b`. `weierstrass`
@@ -233,6 +318,11 @@ type CHash = {
233
318
  };
234
319
  ```
235
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
+
236
326
  **Weierstrass points:**
237
327
 
238
328
  1. Exported as `ProjectivePoint`
@@ -328,6 +418,7 @@ More examples:
328
418
  const priv = secq256k1.utils.randomPrivateKey();
329
419
  secq256k1.getPublicKey(priv); // Convert private key to public.
330
420
  const sig = secq256k1.sign(msg, priv); // Sign msg with private key.
421
+ const sig2 = secq256k1.sign(msg, priv, { prehash: true }); // hash(msg)
331
422
  secq256k1.verify(sig, msg, priv); // Verify if sig is correct.
332
423
 
333
424
  const Point = secq256k1.ProjectivePoint;
@@ -475,6 +566,8 @@ use aggregated, batch-verifiable
475
566
  [threshold signatures](https://medium.com/snigirev.stepan/bls-signatures-better-than-schnorr-5a7fe30ea716),
476
567
  using Boneh-Lynn-Shacham signature scheme.
477
568
 
569
+ The module doesn't expose `CURVE` property: use `G1.CURVE`, `G2.CURVE` instead.
570
+
478
571
  Main methods and properties are:
479
572
 
480
573
  - `getPublicKey(privateKey)`
@@ -518,7 +611,12 @@ const aggSignature3 = bls.aggregateSignatures(signatures3);
518
611
  const isValid3 = bls.verifyBatch(aggSignature3, messages, publicKeys);
519
612
  console.log({ publicKeys, signatures3, aggSignature3, isValid3 });
520
613
 
521
- // 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
522
620
  // bls.G1.ProjectivePoint.BASE, bls.G2.ProjectivePoint.BASE
523
621
  // bls.fields.Fp, bls.fields.Fp2, bls.fields.Fp12, bls.fields.Fr
524
622
 
@@ -554,7 +652,7 @@ aggregateSignatures: {
554
652
  millerLoop: (ell: [Fp2, Fp2, Fp2][], g1: [Fp, Fp]) => Fp12;
555
653
  pairing: (P: ProjPointType<Fp>, Q: ProjPointType<Fp2>, withFinalExponent?: boolean) => Fp12;
556
654
  G1: CurvePointsRes<Fp> & ReturnType<typeof htf.createHasher<Fp>>;
557
- G2: CurvePointsRes<Fp2> & ReturnType<typeof htf.createHasher<Fp2>>;
655
+ G2: CurvePointsRes<Fp2> & ReturnType<typeof htf.createHasher<Fp2>>;
558
656
  Signature: SignatureCoder<Fp2>;
559
657
  params: {
560
658
  x: bigint;
@@ -567,7 +665,7 @@ fields: {
567
665
  Fp2: IField<Fp2>;
568
666
  Fp6: IField<Fp6>;
569
667
  Fp12: IField<Fp12>;
570
- Fr: IField<bigint>;
668
+ Fr: IField<bigint>;
571
669
  };
572
670
  utils: {
573
671
  randomPrivateKey: () => Uint8Array;
@@ -577,7 +675,7 @@ utils: {
577
675
 
578
676
  ### abstract/hash-to-curve: Hashing strings to curve points
579
677
 
580
- 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).
581
679
 
582
680
  Every curve has exported `hashToCurve` and `encodeToCurve` methods. You should always prefer `hashToCurve` for security:
583
681
 
@@ -593,19 +691,17 @@ bls12_381.G1.hashToCurve(randomBytes(), { DST: 'another' });
593
691
  bls12_381.G2.hashToCurve(randomBytes(), { DST: 'custom' });
594
692
  ```
595
693
 
596
- If you need low-level methods from spec:
597
-
598
- `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.
599
-
600
- Hash must conform to `CHash` interface (see [weierstrass section](#abstractweierstrass-short-weierstrass-curve)).
694
+ Low-level methods from the spec:
601
695
 
602
696
  ```ts
697
+ // produces a uniformly random byte string using a cryptographic hash function H that outputs b bits.
603
698
  function expand_message_xmd(
604
699
  msg: Uint8Array,
605
700
  DST: Uint8Array,
606
701
  lenInBytes: number,
607
- H: CHash
702
+ H: CHash // For CHash see abstract/weierstrass docs section
608
703
  ): Uint8Array;
704
+ // produces a uniformly random byte string using an extendable-output function (XOF) H.
609
705
  function expand_message_xof(
610
706
  msg: Uint8Array,
611
707
  DST: Uint8Array,
@@ -613,13 +709,9 @@ function expand_message_xof(
613
709
  k: number,
614
710
  H: CHash
615
711
  ): Uint8Array;
616
- ```
617
-
618
- `hash_to_field(msg, count, options)`
619
- [(spec)](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3)
620
- 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[][];
621
714
 
622
- ```ts
623
715
  /**
624
716
  * * `DST` is a domain separation tag, defined in section 2.2.5
625
717
  * * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m
@@ -630,23 +722,13 @@ hashes arbitrary-length byte strings to a list of one or more elements of a fini
630
722
  */
631
723
  type UnicodeOrBytes = string | Uint8Array;
632
724
  type Opts = {
633
- DST: UnicodeOrBytes;
634
- p: bigint;
635
- m: number;
636
- k: number;
637
- expand?: 'xmd' | 'xof';
638
- hash: CHash;
725
+ DST: UnicodeOrBytes;
726
+ p: bigint;
727
+ m: number;
728
+ k: number;
729
+ expand?: 'xmd' | 'xof';
730
+ hash: CHash;
639
731
  };
640
-
641
- /**
642
- * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F
643
- * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3
644
- * @param msg a byte string containing the message to hash
645
- * @param count the number of elements of F to output
646
- * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above
647
- * @returns [u_0, ..., u_(count - 1)], a list of field elements.
648
- */
649
- function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][];
650
732
  ```
651
733
 
652
734
  ### abstract/poseidon: Poseidon hash
@@ -689,30 +771,40 @@ mod.invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse
689
771
  mod.invertBatch([1n, 2n, 4n], 21n); // => [1n, 11n, 16n] in one inversion
690
772
  ```
691
773
 
692
- #### 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.
693
777
 
694
- Suppose you have `sha256(something)` (e.g. from HMAC) and you want to make a private key from it.
695
- Even though p256 or secp256k1 may have 32-byte private keys,
696
- 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.
782
+
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
697
786
 
698
- 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/).
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/).
699
789
 
700
- To avoid the bias, we implement FIPS 186 B.4.1, which allows to take arbitrary
701
- byte array and produce valid scalars / private keys with bias being neglible.
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.
702
793
 
703
- Use [hash-to-curve](#abstracthash-to-curve-hashing-strings-to-curve-points) if you need
704
- hashing to **public keys**; the function in the module instead operates on **private keys**.
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**.
705
797
 
706
798
  ```ts
707
799
  import { p256 } from '@noble/curves/p256';
708
800
  import { sha256 } from '@noble/hashes/sha256';
709
801
  import { hkdf } from '@noble/hashes/hkdf';
710
802
  const someKey = new Uint8Array(32).fill(2); // Needs to actually be random, not .fill(2)
711
- 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
712
804
  const validPrivateKey = mod.hashToPrivateScalar(derived, p256.CURVE.n);
713
805
  ```
714
806
 
715
- ### abstract/utils: General utilities
807
+ ### abstract/utils: Useful utilities
716
808
 
717
809
  ```ts
718
810
  import * as utils from '@noble/curves/abstract/utils';
@@ -734,96 +826,122 @@ utils.equalBytes(Uint8Array.from([0xde]), Uint8Array.from([0xde]));
734
826
 
735
827
  ## Security
736
828
 
737
- 1. The library has been audited during Jan-Feb 2023 by an independent security firm [Trail of Bits](https://www.trailofbits.com):
738
- [PDF](https://github.com/trailofbits/publications/blob/master/reviews/2023-01-ryanshea-noblecurveslibrary-securityreview.pdf).
739
- The audit has been funded by Ryan Shea. 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).
740
- 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.
741
- 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.
742
-
743
- 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:
744
-
745
- - `@scure` base, bip32, bip39 (used in tests), micro-bmark (benchmark), micro-should (testing) are developed by us
746
- and follow the same practices such as: minimal library size, auditability, signed releases
747
- - prettier (linter), fast-check (property-based testing),
748
- 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`.
749
859
  The packages are big, which makes it hard to audit their source code thoroughly and fully.
750
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.
751
861
 
862
+ As for key generation, we're deferring to built-in
863
+ [crypto.getRandomValues](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues)
864
+ which is considered cryptographically secure (CSPRNG).
865
+
752
866
  ## Speed
753
867
 
754
- Benchmark results on Apple M2 with node v19:
868
+ Benchmark results on Apple M2 with node v20:
755
869
 
756
870
  ```
757
871
  secp256k1
758
- init x 58 ops/sec @ 17ms/op
759
- getPublicKey x 5,640 ops/sec @ 177μs/op
760
- sign x 4,471 ops/sec @ 223μs/op
761
- verify x 780 ops/sec @ 1ms/op
762
- getSharedSecret x 465 ops/sec @ 2ms/op
763
- recoverPublicKey x 740 ops/sec @ 1ms/op
764
- schnorr.sign x 597 ops/sec @ 1ms/op
765
- schnorr.verify x 775 ops/sec @ 1ms/op
766
-
767
- P256
768
- init x 31 ops/sec @ 31ms/op
769
- getPublicKey x 5,607 ops/sec @ 178μs/op
770
- sign x 4,583 ops/sec @ 218μs/op
771
- verify x 540 ops/sec @ 1ms/op
772
-
773
- P384
774
- init x 15 ops/sec @ 63ms/op
775
- getPublicKey x 2,622 ops/sec @ 381μs/op
776
- sign x 2,106 ops/sec @ 474μs/op
777
- verify x 222 ops/sec @ 4ms/op
778
-
779
- P521
780
- init x 8 ops/sec @ 119ms/op
781
- getPublicKey x 1,371 ops/sec @ 729μs/op
782
- sign x 1,164 ops/sec @ 858μs/op
783
- verify x 118 ops/sec @ 8ms/op
872
+ init x 68 ops/sec @ 14ms/op
873
+ getPublicKey x 6,750 ops/sec @ 148μs/op
874
+ sign x 5,206 ops/sec @ 192μs/op
875
+ verify x 880 ops/sec @ 1ms/op
876
+ getSharedSecret x 536 ops/sec @ 1ms/op
877
+ recoverPublicKey x 852 ops/sec @ 1ms/op
878
+ schnorr.sign x 685 ops/sec @ 1ms/op
879
+ schnorr.verify x 908 ops/sec @ 1ms/op
880
+
881
+ p256
882
+ init x 38 ops/sec @ 26ms/op
883
+ getPublicKey x 6,530 ops/sec @ 153μs/op
884
+ sign x 5,074 ops/sec @ 197μs/op
885
+ verify x 626 ops/sec @ 1ms/op
886
+
887
+ p384
888
+ init x 17 ops/sec @ 57ms/op
889
+ getPublicKey x 2,883 ops/sec @ 346μs/op
890
+ sign x 2,358 ops/sec @ 424μs/op
891
+ verify x 245 ops/sec @ 4ms/op
892
+
893
+ p521
894
+ init x 9 ops/sec @ 109ms/op
895
+ getPublicKey x 1,516 ops/sec @ 659μs/op
896
+ sign x 1,271 ops/sec @ 786μs/op
897
+ verify x 123 ops/sec @ 8ms/op
784
898
 
785
899
  ed25519
786
- init x 47 ops/sec @ 20ms/op
787
- getPublicKey x 9,414 ops/sec @ 106μs/op
788
- sign x 4,516 ops/sec @ 221μs/op
789
- verify x 912 ops/sec @ 1ms/op
900
+ init x 54 ops/sec @ 18ms/op
901
+ getPublicKey x 10,269 ops/sec @ 97μs/op
902
+ sign x 5,110 ops/sec @ 195μs/op
903
+ verify x 1,049 ops/sec @ 952μs/op
790
904
 
791
905
  ed448
792
- init x 17 ops/sec @ 56ms/op
793
- getPublicKey x 3,363 ops/sec @ 297μs/op
794
- sign x 1,615 ops/sec @ 619μs/op
795
- verify x 319 ops/sec @ 3ms/op
906
+ init x 19 ops/sec @ 51ms/op
907
+ getPublicKey x 3,775 ops/sec @ 264μs/op
908
+ sign x 1,771 ops/sec @ 564μs/op
909
+ verify x 351 ops/sec @ 2ms/op
796
910
 
797
911
  ecdh
798
- ├─x25519 x 1,337 ops/sec @ 747μs/op
799
- ├─secp256k1 x 461 ops/sec @ 2ms/op
800
- ├─P256 x 441 ops/sec @ 2ms/op
801
- ├─P384 x 179 ops/sec @ 5ms/op
802
- ├─P521 x 93 ops/sec @ 10ms/op
803
- └─x448 x 496 ops/sec @ 2ms/op
912
+ ├─x25519 x 1,466 ops/sec @ 682μs/op
913
+ ├─secp256k1 x 539 ops/sec @ 1ms/op
914
+ ├─p256 x 511 ops/sec @ 1ms/op
915
+ ├─p384 x 199 ops/sec @ 5ms/op
916
+ ├─p521 x 103 ops/sec @ 9ms/op
917
+ └─x448 x 548 ops/sec @ 1ms/op
804
918
 
805
919
  bls12-381
806
- init x 32 ops/sec @ 30ms/op
807
- getPublicKey 1-bit x 858 ops/sec @ 1ms/op
808
- getPublicKey x 858 ops/sec @ 1ms/op
809
- sign x 49 ops/sec @ 20ms/op
810
- verify x 34 ops/sec @ 28ms/op
811
- pairing x 94 ops/sec @ 10ms/op
812
- aggregatePublicKeys/8 x 116 ops/sec @ 8ms/op
813
- aggregatePublicKeys/32 x 31 ops/sec @ 31ms/op
814
- aggregatePublicKeys/128 x 7 ops/sec @ 125ms/op
815
- aggregateSignatures/8 x 45 ops/sec @ 22ms/op
816
- aggregateSignatures/32 x 11 ops/sec @ 84ms/op
817
- aggregateSignatures/128 x 3 ops/sec @ 332ms/opp
920
+ init x 36 ops/sec @ 27ms/op
921
+ getPublicKey 1-bit x 973 ops/sec @ 1ms/op
922
+ getPublicKey x 970 ops/sec @ 1ms/op
923
+ sign x 55 ops/sec @ 17ms/op
924
+ verify x 39 ops/sec @ 25ms/op
925
+ pairing x 106 ops/sec @ 9ms/op
926
+ aggregatePublicKeys/8 x 129 ops/sec @ 7ms/op
927
+ aggregatePublicKeys/32 x 34 ops/sec @ 28ms/op
928
+ aggregatePublicKeys/128 x 8 ops/sec @ 112ms/op
929
+ aggregatePublicKeys/512 x 2 ops/sec @ 446ms/op
930
+ aggregatePublicKeys/2048 x 0 ops/sec @ 1778ms/op
931
+ aggregateSignatures/8 x 50 ops/sec @ 19ms/op
932
+ aggregateSignatures/32 x 13 ops/sec @ 74ms/op
933
+ aggregateSignatures/128 x 3 ops/sec @ 296ms/op
934
+ aggregateSignatures/512 x 0 ops/sec @ 1180ms/op
935
+ aggregateSignatures/2048 x 0 ops/sec @ 4715ms/op
818
936
 
819
937
  hash-to-curve
820
- hash_to_field x 850,340 ops/sec @ 1μs/op
821
- secp256k1 x 2,143 ops/sec @ 466μs/op
822
- P256 x 3,861 ops/sec @ 258μs/op
823
- P384 x 1,526 ops/sec @ 655μs/op
824
- P521 x 748 ops/sec @ 1ms/op
825
- ed25519 x 2,772 ops/sec @ 360μs/op
826
- ed448 x 1,146 ops/sec @ 871μs/op
938
+ hash_to_field x 91,600 ops/sec @ 10μs/op
939
+ secp256k1 x 2,373 ops/sec @ 421μs/op
940
+ p256 x 4,310 ops/sec @ 231μs/op
941
+ p384 x 1,664 ops/sec @ 600μs/op
942
+ p521 x 807 ops/sec @ 1ms/op
943
+ ed25519 x 3,088 ops/sec @ 323μs/op
944
+ ed448 x 1,247 ops/sec @ 801μs/op
827
945
  ```
828
946
 
829
947
  ## Contributing & testing
@@ -836,33 +954,37 @@ ed448 x 1,146 ops/sec @ 871μs/op
836
954
  ## Upgrading
837
955
 
838
956
  Previously, the library was split into single-feature packages
839
- noble-secp256k1 and noble-ed25519. curves can be thought as a continuation of their
840
- original work. The libraries now changed their direction towards providing
841
- minimal 4kb implementations of cryptography and are not as feature-complete.
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).
842
960
 
843
- Upgrading from @noble/secp256k1 2.0 or @noble/ed25519 2.0: no changes, libraries are compatible.
961
+ Curves continue their original work. The single-feature packages changed their
962
+ direction towards providing minimal 4kb implementations of cryptography,
963
+ which means they have less features.
844
964
 
845
- Upgrading from [@noble/secp256k1](https://github.com/paulmillr/noble-secp256k1) 1.7:
965
+ Upgrading from noble-secp256k1 2.0 or noble-ed25519 2.0: no changes, libraries are compatible.
966
+
967
+ Upgrading from noble-secp256k1 1.7:
846
968
 
847
969
  - `getPublicKey`
848
- - now produce 33-byte compressed signatures by default
849
- - to use old behavior, which produced 65-byte uncompressed keys, set
850
- 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)`
851
973
  - `sign`
852
- - is now sync; use `signAsync` for async version
853
- - now returns `Signature` instance with `{ r, s, recovery }` properties
854
- - `canonical` option was renamed to `lowS`
855
- - `recovered` option has been removed because recovery bit is always returned now
856
- - `der` option has been removed. There are 2 options:
857
- 1. Use compact encoding: `fromCompact`, `toCompactRawBytes`, `toCompactHex`.
858
- Compact encoding is simply a concatenation of 32-byte r and 32-byte s.
859
- 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).
860
982
  - `verify`
861
- - `strict` option was renamed to `lowS`
983
+ - `strict` option was renamed to `lowS`
862
984
  - `getSharedSecret`
863
- - now produce 33-byte compressed signatures by default
864
- - to use old behavior, which produced 65-byte uncompressed keys, set
865
- 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)`
866
988
  - `recoverPublicKey(msg, sig, rec)` was changed to `sig.recoverPublicKey(msg)`
867
989
  - `number` type for private keys have been removed: use `bigint` instead
868
990
  - `Point` (2d xy) has been changed to `ProjectivePoint` (3d xyz)
@@ -878,40 +1000,70 @@ Upgrading from [@noble/ed25519](https://github.com/paulmillr/noble-ed25519) 1.7:
878
1000
  - `utils` were split into `utils` (same api as in noble-curves) and
879
1001
  `etc` (`sha512Sync` and others)
880
1002
  - `getSharedSecret` was moved to `x25519` module
1003
+ - `toX25519` has been moved to `edwardsToMontgomeryPub` and `edwardsToMontgomeryPriv` methods
881
1004
 
882
1005
  Upgrading from [@noble/bls12-381](https://github.com/paulmillr/noble-bls12-381):
883
1006
 
884
1007
  - Methods and classes were renamed:
885
- - PointG1 -> G1.Point, PointG2 -> G2.Point
886
- - PointG2.fromSignature -> Signature.decode, PointG2.toSignature -> Signature.encode
1008
+ - PointG1 -> G1.Point, PointG2 -> G2.Point
1009
+ - PointG2.fromSignature -> Signature.decode, PointG2.toSignature -> Signature.encode
887
1010
  - Fp2 ORDER was corrected
888
1011
 
889
1012
  ## Resources
890
1013
 
891
- Useful articles about the library or its primitives:
892
-
893
1014
  - [Learning fast elliptic-curve cryptography](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/)
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)
894
1023
  - Pairings and BLS
895
- - [BLS12-381 for the rest of us](https://hackmd.io/@benjaminion/bls12-381)
896
- - [Key concepts of pairings](https://medium.com/@alonmuroch_65570/bls-signatures-part-2-key-concepts-of-pairings-27a8a9533d0c)
897
- - Pairing over bls12-381:
898
- [part 1](https://research.nccgroup.com/2020/07/06/pairing-over-bls12-381-part-1-fields/),
899
- [part 2](https://research.nccgroup.com/2020/07/13/pairing-over-bls12-381-part-2-curves/),
900
- [part 3](https://research.nccgroup.com/2020/08/13/pairing-over-bls12-381-part-3-pairing/)
901
- - [Estimating the bit security of pairing-friendly curves](https://research.nccgroup.com/2022/02/03/estimating-the-bit-security-of-pairing-friendly-curves/)
902
-
903
- Real-world software that uses curves:
904
-
905
- - [Elliptic Curve Calculator](https://paulmillr.com/noble) online demo: add / multiply points, sign messages
906
- - Signers for web3 projects:
907
- [btc-signer](https://github.com/paulmillr/scure-btc-signer), [eth-signer](https://github.com/paulmillr/micro-eth-signer),
908
- [sol-signer](https://github.com/paulmillr/micro-sol-signer) for Solana
909
- - [scure-bip32](https://github.com/paulmillr/scure-bip32) and separate [bip32](https://github.com/bitcoinjs/bip32) HDkey libraries
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/)
1032
+
1033
+ ### Demos
1034
+
1035
+ - [Elliptic Curve Calculator](https://paulmillr.com/noble): add / multiply points, sign messages
1036
+ - [BLS threshold signatures](https://genthresh.com)
1037
+
1038
+ ### Projects using curves
1039
+
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)
1042
+ - Ethereum libraries:
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)
1053
+ - Solana libraries: [micro-sol-signer](https://github.com/paulmillr/micro-sol-signer), [solana-web3.js](https://github.com/solana-labs/solana-web3.js)
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)
910
1061
  - [ed25519-keygen](https://github.com/paulmillr/ed25519-keygen) SSH, PGP, TOR key generation
911
- - [micro-starknet](https://github.com/paulmillr/micro-starknet) stark-friendly elliptic curve algorithms.
912
- - BLS threshold sigs demo [genthresh.com](https://genthresh.com)
913
- - BLS 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)
1062
+ - [secp256k1 compatibility layer](https://github.com/ethereum/js-ethereum-cryptography/blob/2.0.0/src/secp256k1-compat.ts)
1063
+ for users who want to switch from secp256k1-node or tiny-secp256k1. Allows to see which methods map to corresponding noble code.
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)
914
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).
915
1067
 
916
1068
  ## License
917
1069