@noble/curves 0.6.4 → 0.7.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 (172) hide show
  1. package/README.md +429 -281
  2. package/{lib/_shortw_utils.d.ts → _shortw_utils.d.ts} +1 -0
  3. package/_shortw_utils.d.ts.map +1 -0
  4. package/{lib/_shortw_utils.js → _shortw_utils.js} +2 -0
  5. package/_shortw_utils.js.map +1 -0
  6. package/{lib/abstract → abstract}/bls.d.ts +4 -9
  7. package/abstract/bls.d.ts.map +1 -0
  8. package/{lib/abstract → abstract}/bls.js +12 -25
  9. package/abstract/bls.js.map +1 -0
  10. package/{lib/abstract → abstract}/curve.d.ts +1 -0
  11. package/abstract/curve.d.ts.map +1 -0
  12. package/{lib/abstract → abstract}/curve.js +1 -0
  13. package/abstract/curve.js.map +1 -0
  14. package/{lib/abstract → abstract}/edwards.d.ts +1 -0
  15. package/abstract/edwards.d.ts.map +1 -0
  16. package/{lib/abstract → abstract}/edwards.js +9 -15
  17. package/abstract/edwards.js.map +1 -0
  18. package/{lib/abstract → abstract}/hash-to-curve.d.ts +5 -5
  19. package/abstract/hash-to-curve.d.ts.map +1 -0
  20. package/{lib/abstract → abstract}/hash-to-curve.js +41 -38
  21. package/abstract/hash-to-curve.js.map +1 -0
  22. package/{lib/abstract → abstract}/modular.d.ts +1 -0
  23. package/abstract/modular.d.ts.map +1 -0
  24. package/{lib/abstract → abstract}/modular.js +2 -1
  25. package/abstract/modular.js.map +1 -0
  26. package/{lib/abstract → abstract}/montgomery.d.ts +1 -0
  27. package/abstract/montgomery.d.ts.map +1 -0
  28. package/{lib/abstract → abstract}/montgomery.js +3 -2
  29. package/abstract/montgomery.js.map +1 -0
  30. package/{lib/abstract → abstract}/poseidon.d.ts +1 -0
  31. package/abstract/poseidon.d.ts.map +1 -0
  32. package/{lib/abstract → abstract}/poseidon.js +1 -0
  33. package/abstract/poseidon.js.map +1 -0
  34. package/{lib/abstract → abstract}/utils.d.ts +12 -1
  35. package/abstract/utils.d.ts.map +1 -0
  36. package/{lib/abstract → abstract}/utils.js +96 -10
  37. package/abstract/utils.js.map +1 -0
  38. package/{lib/abstract → abstract}/weierstrass.d.ts +4 -3
  39. package/abstract/weierstrass.d.ts.map +1 -0
  40. package/{lib/abstract → abstract}/weierstrass.js +45 -91
  41. package/abstract/weierstrass.js.map +1 -0
  42. package/{lib/bls12-381.d.ts → bls12-381.d.ts} +1 -0
  43. package/bls12-381.d.ts.map +1 -0
  44. package/{lib/bls12-381.js → bls12-381.js} +41 -7
  45. package/bls12-381.js.map +1 -0
  46. package/{lib/bn.d.ts → bn.d.ts} +1 -0
  47. package/bn.d.ts.map +1 -0
  48. package/{lib/bn.js → bn.js} +1 -0
  49. package/bn.js.map +1 -0
  50. package/{lib/ed25519.d.ts → ed25519.d.ts} +2 -1
  51. package/ed25519.d.ts.map +1 -0
  52. package/{lib/ed25519.js → ed25519.js} +4 -3
  53. package/ed25519.js.map +1 -0
  54. package/{lib/ed448.d.ts → ed448.d.ts} +2 -1
  55. package/ed448.d.ts.map +1 -0
  56. package/{lib/ed448.js → ed448.js} +2 -1
  57. package/ed448.js.map +1 -0
  58. package/{lib/esm → esm}/_shortw_utils.js +2 -0
  59. package/esm/_shortw_utils.js.map +1 -0
  60. package/{lib/esm → esm}/abstract/bls.js +13 -26
  61. package/esm/abstract/bls.js.map +1 -0
  62. package/{lib/esm → esm}/abstract/curve.js +1 -0
  63. package/esm/abstract/curve.js.map +1 -0
  64. package/{lib/esm → esm}/abstract/edwards.js +9 -15
  65. package/esm/abstract/edwards.js.map +1 -0
  66. package/{lib/esm → esm}/abstract/hash-to-curve.js +40 -36
  67. package/esm/abstract/hash-to-curve.js.map +1 -0
  68. package/{lib/esm → esm}/abstract/modular.js +2 -1
  69. package/esm/abstract/modular.js.map +1 -0
  70. package/{lib/esm → esm}/abstract/montgomery.js +3 -2
  71. package/esm/abstract/montgomery.js.map +1 -0
  72. package/{lib/esm → esm}/abstract/poseidon.js +1 -0
  73. package/esm/abstract/poseidon.js.map +1 -0
  74. package/{lib/esm → esm}/abstract/utils.js +93 -9
  75. package/esm/abstract/utils.js.map +1 -0
  76. package/{lib/esm → esm}/abstract/weierstrass.js +45 -91
  77. package/esm/abstract/weierstrass.js.map +1 -0
  78. package/{lib/esm → esm}/bls12-381.js +41 -7
  79. package/esm/bls12-381.js.map +1 -0
  80. package/{lib/esm → esm}/bn.js +1 -0
  81. package/esm/bn.js.map +1 -0
  82. package/{lib/esm → esm}/ed25519.js +5 -4
  83. package/esm/ed25519.js.map +1 -0
  84. package/{lib/esm → esm}/ed448.js +2 -1
  85. package/esm/ed448.js.map +1 -0
  86. package/{lib → esm}/index.js +1 -0
  87. package/esm/index.js.map +1 -0
  88. package/{lib/esm → esm}/jubjub.js +1 -0
  89. package/esm/jubjub.js.map +1 -0
  90. package/{lib/esm → esm}/p192.js +1 -0
  91. package/esm/p192.js.map +1 -0
  92. package/{lib/esm → esm}/p224.js +1 -0
  93. package/esm/p224.js.map +1 -0
  94. package/{lib/esm → esm}/p256.js +2 -1
  95. package/esm/p256.js.map +1 -0
  96. package/{lib/esm → esm}/p384.js +2 -1
  97. package/esm/p384.js.map +1 -0
  98. package/{lib/esm → esm}/p521.js +2 -1
  99. package/esm/p521.js.map +1 -0
  100. package/{lib/esm → esm}/package.json +0 -0
  101. package/{lib/esm → esm}/pasta.js +1 -0
  102. package/esm/pasta.js.map +1 -0
  103. package/{lib/esm → esm}/secp256k1.js +41 -50
  104. package/esm/secp256k1.js.map +1 -0
  105. package/{lib/esm → esm}/stark.js +1 -0
  106. package/esm/stark.js.map +1 -0
  107. package/index.d.ts +1 -0
  108. package/index.d.ts.map +1 -0
  109. package/index.js +3 -0
  110. package/index.js.map +1 -0
  111. package/{lib/jubjub.d.ts → jubjub.d.ts} +1 -0
  112. package/jubjub.d.ts.map +1 -0
  113. package/{lib/jubjub.js → jubjub.js} +1 -0
  114. package/jubjub.js.map +1 -0
  115. package/{lib/p192.d.ts → p192.d.ts} +1 -0
  116. package/p192.d.ts.map +1 -0
  117. package/{lib/p192.js → p192.js} +1 -0
  118. package/p192.js.map +1 -0
  119. package/{lib/p224.d.ts → p224.d.ts} +1 -0
  120. package/p224.d.ts.map +1 -0
  121. package/{lib/p224.js → p224.js} +1 -0
  122. package/p224.js.map +1 -0
  123. package/{lib/p256.d.ts → p256.d.ts} +2 -1
  124. package/p256.d.ts.map +1 -0
  125. package/{lib/p256.js → p256.js} +2 -1
  126. package/p256.js.map +1 -0
  127. package/{lib/p384.d.ts → p384.d.ts} +2 -1
  128. package/p384.d.ts.map +1 -0
  129. package/{lib/p384.js → p384.js} +2 -1
  130. package/p384.js.map +1 -0
  131. package/{lib/p521.d.ts → p521.d.ts} +2 -1
  132. package/p521.d.ts.map +1 -0
  133. package/{lib/p521.js → p521.js} +2 -1
  134. package/p521.js.map +1 -0
  135. package/package.json +84 -79
  136. package/{lib/pasta.d.ts → pasta.d.ts} +1 -0
  137. package/pasta.d.ts.map +1 -0
  138. package/{lib/pasta.js → pasta.js} +1 -0
  139. package/pasta.js.map +1 -0
  140. package/{lib/secp256k1.d.ts → secp256k1.d.ts} +15 -5
  141. package/secp256k1.d.ts.map +1 -0
  142. package/{lib/secp256k1.js → secp256k1.js} +38 -47
  143. package/secp256k1.js.map +1 -0
  144. package/src/_shortw_utils.ts +20 -0
  145. package/src/abstract/bls.ts +376 -0
  146. package/src/abstract/curve.ts +199 -0
  147. package/src/abstract/edwards.ts +479 -0
  148. package/src/abstract/hash-to-curve.ts +220 -0
  149. package/src/abstract/modular.ts +417 -0
  150. package/src/abstract/montgomery.ts +184 -0
  151. package/src/abstract/poseidon.ts +119 -0
  152. package/src/abstract/utils.ts +246 -0
  153. package/src/abstract/weierstrass.ts +1175 -0
  154. package/src/bls12-381.ts +1274 -0
  155. package/src/bn.ts +21 -0
  156. package/src/ed25519.ts +428 -0
  157. package/src/ed448.ts +241 -0
  158. package/{lib/esm/index.js → src/index.ts} +0 -1
  159. package/src/jubjub.ts +58 -0
  160. package/src/p192.ts +25 -0
  161. package/src/p224.ts +25 -0
  162. package/src/p256.ts +53 -0
  163. package/src/p384.ts +57 -0
  164. package/src/p521.ts +57 -0
  165. package/src/pasta.ts +31 -0
  166. package/src/secp256k1.ts +260 -0
  167. package/src/stark.ts +356 -0
  168. package/{lib/stark.d.ts → stark.d.ts} +1 -0
  169. package/stark.d.ts.map +1 -0
  170. package/{lib/stark.js → stark.js} +1 -0
  171. package/stark.js.map +1 -0
  172. package/lib/index.d.ts +0 -0
package/README.md CHANGED
@@ -1,36 +1,35 @@
1
1
  # noble-curves
2
2
 
3
- Minimal, auditable JS implementation of elliptic curve cryptography.
3
+ Audited & minimal JS implementation of elliptic curve cryptography.
4
4
 
5
+ - **noble** family, zero dependencies
5
6
  - Short Weierstrass, Edwards, Montgomery curves
6
7
  - ECDSA, EdDSA, Schnorr, BLS signature schemes, ECDH key agreement
7
- - [hash to curve](https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/)
8
- for encoding or hashing an arbitrary string to a point on an elliptic curve
9
- - [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash
8
+ - #️⃣ [hash to curve](https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/)
9
+ for encoding or hashing an arbitrary string to an elliptic curve point
10
+ - 🧜‍♂️ [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash
10
11
  - 🏎 [Ultra-fast](#speed), hand-optimized for caveats of JS engines
11
12
  - 🔍 Unique tests ensure correctness. Wycheproof vectors included
12
13
  - 🔻 Tree-shaking-friendly: there is no entry point, which ensures small size of your app
13
14
 
14
15
  Package consists of two parts:
15
16
 
16
- 1. `abstract/` directory specifies zero-dependency EC algorithms
17
- 2. root directory utilizes one dependency `@noble/hashes` and provides ready-to-use:
17
+ 1. [Abstract](#abstract-api), zero-dependency EC algorithms
18
+ 2. [Implementations](#implementations), utilizing one dependency `@noble/hashes`, providing ready-to-use:
18
19
  - NIST curves secp192r1/P192, secp224r1/P224, secp256r1/P256, secp384r1/P384, secp521r1/P521
19
20
  - SECG curve secp256k1
21
+ - ed25519/curve25519/x25519/ristretto255, edwards448/curve448/x448 RFC7748 / RFC8032 / ZIP215 stuff
20
22
  - pairing-friendly curves bls12-381, bn254
21
- - ed25519/curve25519/x25519/ristretto, edwards448/curve448/x448 RFC7748 / RFC8032 / ZIP215 stuff
22
23
 
23
- Curves incorporate work from previous noble packages
24
- ([secp256k1](https://github.com/paulmillr/noble-secp256k1),
25
- [ed25519](https://github.com/paulmillr/noble-ed25519)),
26
- which had security audits and were developed from 2019 to 2022.
27
- Check out [Upgrading](#upgrading) section if you've used them before.
24
+ Check out [Upgrading](#upgrading) if you've previously used single-feature noble packages
25
+ ([secp256k1](https://github.com/paulmillr/noble-secp256k1), [ed25519](https://github.com/paulmillr/noble-ed25519)).
26
+ See [In the wild](#in-the-wild) for real-world software that uses curves.
28
27
 
29
28
  ### This library belongs to _noble_ crypto
30
29
 
31
30
  > **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools.
32
31
 
33
- - Protection against supply chain attacks
32
+ - No dependencies, protection against supply chain attacks
34
33
  - Easily auditable TypeScript/JS code
35
34
  - Supported in all major browsers and stable node.js versions
36
35
  - All releases are signed with PGP keys
@@ -42,15 +41,41 @@ Check out [Upgrading](#upgrading) section if you've used them before.
42
41
 
43
42
  ## Usage
44
43
 
45
- Use NPM in node.js / browser, or include single file from
46
- [GitHub's releases page](https://github.com/paulmillr/noble-curves/releases):
44
+ Use NPM for browser / node.js:
47
45
 
48
46
  > npm install @noble/curves
49
47
 
50
- The library does not have an entry point. It allows you to select specific primitives and drop everything else. If you only want to use secp256k1, just use the library with rollup or other bundlers. This is done to make your bundles tiny. All curves:
48
+ For [Deno](https://deno.land), use it with npm specifier. In browser, you could also include the single file from
49
+ [GitHub's releases page](https://github.com/paulmillr/noble-curves/releases).
50
+
51
+ The library is tree-shaking-friendly and does not expose root entry point as `import * from '@noble/curves'`.
52
+ Instead, you need to import specific primitives. This is done to ensure small size of your apps.
53
+
54
+ ### Implementations
55
+
56
+ Each curve can be used in the following way:
51
57
 
52
58
  ```ts
53
- import { secp256k1 } from '@noble/curves/secp256k1';
59
+ import { secp256k1 } from '@noble/curves/secp256k1'; // ECMAScript Modules (ESM) and Common.js
60
+ // import { secp256k1 } from 'npm:@noble/curves@1.2.0/secp256k1'; // Deno
61
+ const priv = secp256k1.utils.randomPrivateKey();
62
+ const pub = secp256k1.getPublicKey(priv);
63
+ const msg = new Uint8Array(32).fill(1);
64
+ const sig = secp256k1.sign(msg, priv);
65
+ secp256k1.verify(sig, msg, pub) === true;
66
+
67
+ const privHex = '46c930bc7bb4db7f55da20798697421b98c4175a52c630294d75a84b9c126236'
68
+ const pub2 = secp256k1.getPublicKey(privHex); // keys & other inputs can be Uint8Array-s or hex strings
69
+
70
+ // Follows hash-to-curve specification to encode arbitrary hashes to EC points
71
+ import { hashToCurve, encodeToCurve } from '@noble/curves/secp256k1';
72
+ hashToCurve('0102abcd');
73
+ ```
74
+
75
+ All curves:
76
+
77
+ ```typescript
78
+ import { secp256k1, schnorr } from '@noble/curves/secp256k1';
54
79
  import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519';
55
80
  import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448';
56
81
  import { p256 } from '@noble/curves/p256';
@@ -63,63 +88,208 @@ import { bn254 } from '@noble/curves/bn';
63
88
  import { jubjub } from '@noble/curves/jubjub';
64
89
  ```
65
90
 
66
- Every curve can be used in the following way:
91
+ Weierstrass curves feature recovering public keys from signatures and ECDH key agreement:
67
92
 
68
93
  ```ts
69
- import { secp256k1 } from '@noble/curves/secp256k1'; // Common.js and ECMAScript Modules (ESM)
70
-
71
- const key = secp256k1.utils.randomPrivateKey();
72
- const pub = secp256k1.getPublicKey(key);
73
- const msg = new Uint8Array(32).fill(1);
74
- const sig = secp256k1.sign(msg, key);
75
- // weierstrass curves should use extraEntropy: https://moderncrypto.org/mail-archive/curves/2017/000925.html
76
- const sigImprovedSecurity = secp256k1.sign(msg, key, { extraEntropy: true });
77
- secp256k1.verify(sig, msg, pub) === true;
78
- // secp, p*, pasta curves allow pub recovery
79
- sig.recoverPublicKey(msg) === pub;
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
80
97
  const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
81
- const shared = secp256k1.getSharedSecret(key, someonesPub);
98
+ const shared = secp256k1.getSharedSecret(priv, someonesPub); // ECDH (elliptic curve diffie-hellman)
99
+ ```
100
+
101
+ secp256k1 has schnorr signature implementation which follows
102
+ [BIP340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki):
103
+
104
+ ```ts
105
+ import { schnorr } from '@noble/curves/secp256k1';
106
+ const priv = schnorr.utils.randomPrivateKey();
107
+ const pub = schnorr.getPublicKey(priv);
108
+ const msg = new TextEncoder().encode('hello');
109
+ const sig = schnorr.sign(msg, priv);
110
+ const isValid = schnorr.verify(sig, msg, pub);
111
+ console.log(isValid);
82
112
  ```
83
113
 
84
- To define a custom curve, check out docs below.
114
+ ed25519 module has ed25519ctx / ed25519ph variants,
115
+ x25519 ECDH and [ristretto255](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448).
116
+ It follows [ZIP215](https://zips.z.cash/zip-0215) and [can be used in consensus-critical applications](https://hdevalence.ca/blog/2020-10-04-its-25519am):
85
117
 
86
- ## API
118
+ ```ts
119
+ import { ed25519 } from '@noble/curves/ed25519';
120
+
121
+ // Variants from RFC8032: with context, prehashed
122
+ import { ed25519ctx, ed25519ph } from '@noble/curves/ed25519';
123
+
124
+ // ECDH using curve25519 aka x25519
125
+ import { x25519 } from '@noble/curves/ed25519';
126
+ const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4';
127
+ const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c';
128
+ x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub);
129
+ x25519.getPublicKey(priv) === x25519.scalarMultBase(priv);
130
+
131
+ // hash-to-curve
132
+ import { hashToCurve, encodeToCurve } from '@noble/curves/ed25519';
133
+
134
+ import { RistrettoPoint } from '@noble/curves/ed25519';
135
+ const rp = RistrettoPoint.fromHex(
136
+ '6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919'
137
+ );
138
+ RistrettoPoint.hashToCurve('Ristretto is traditionally a short shot of espresso coffee');
139
+ // also has add(), equals(), multiply(), toRawBytes() methods
140
+ ```
141
+
142
+ ed448 module is basically the same:
143
+
144
+ ```ts
145
+ import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448';
146
+ import { hashToCurve, encodeToCurve } from '@noble/curves/ed448';
147
+ ```
148
+
149
+ BLS12-381 pairing-friendly Barreto-Lynn-Scott elliptic curve construction allows to
150
+ construct [zk-SNARKs](https://z.cash/technology/zksnarks/) at the 128-bit security
151
+ and use aggregated, batch-verifiable
152
+ [threshold signatures](https://medium.com/snigirev.stepan/bls-signatures-better-than-schnorr-5a7fe30ea716),
153
+ using Boneh-Lynn-Shacham signature scheme.
154
+
155
+ ```ts
156
+ import { bls12_381 as bls } from '@noble/curves/bls12-381';
157
+ const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c';
158
+ const message = '64726e3da8';
159
+ const publicKey = bls.getPublicKey(privateKey);
160
+ const signature = bls.sign(message, privateKey);
161
+ const isValid = bls.verify(signature, message, publicKey);
162
+ console.log({ publicKey, signature, isValid });
163
+
164
+ // Sign 1 msg with 3 keys
165
+ const privateKeys = [
166
+ '18f020b98eb798752a50ed0563b079c125b0db5dd0b1060d1c1b47d4a193e1e4',
167
+ 'ed69a8c50cf8c9836be3b67c7eeff416612d45ba39a5c099d48fa668bf558c9c',
168
+ '16ae669f3be7a2121e17d0c68c05a8f3d6bef21ec0f2315f1d7aec12484e4cf5',
169
+ ];
170
+ const messages = ['d2', '0d98', '05caf3'];
171
+ const publicKeys = privateKeys.map(bls.getPublicKey);
172
+ const signatures2 = privateKeys.map((p) => bls.sign(message, p));
173
+ const aggPubKey2 = bls.aggregatePublicKeys(publicKeys);
174
+ const aggSignature2 = bls.aggregateSignatures(signatures2);
175
+ const isValid2 = bls.verify(aggSignature2, message, aggPubKey2);
176
+ console.log({ signatures2, aggSignature2, isValid2 });
177
+
178
+ // Sign 3 msgs with 3 keys
179
+ const signatures3 = privateKeys.map((p, i) => bls.sign(messages[i], p));
180
+ const aggSignature3 = bls.aggregateSignatures(signatures3);
181
+ const isValid3 = bls.verifyBatch(aggSignature3, messages, publicKeys);
182
+ console.log({ publicKeys, signatures3, aggSignature3, isValid3 });
183
+
184
+ // Pairings
185
+ // bls.pairing(PointG1, PointG2)
186
+ ```
187
+
188
+ ## Abstract API
189
+
190
+ Abstract API allows to define custom curves. All arithmetics is done with JS bigints over finite fields,
191
+ which is defined from `modular` sub-module. For scalar multiplication, we use [precomputed tables with w-ary non-adjacent form (wNAF)](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/).
192
+ Precomputes are enabled for weierstrass and edwards BASE points of a curve. You could precompute any
193
+ other point (e.g. for ECDH) using `utils.precompute()` method.
194
+
195
+ There are following zero-dependency algorithms:
87
196
 
88
- - [Overview](#overview)
197
+ - [abstract/weierstrass: Short Weierstrass curve](#abstractweierstrass-short-weierstrass-curve)
89
198
  - [abstract/edwards: Twisted Edwards curve](#abstractedwards-twisted-edwards-curve)
90
199
  - [abstract/montgomery: Montgomery curve](#abstractmontgomery-montgomery-curve)
91
- - [abstract/weierstrass: Short Weierstrass curve](#abstractweierstrass-short-weierstrass-curve)
92
200
  - [abstract/hash-to-curve: Hashing strings to curve points](#abstracthash-to-curve-hashing-strings-to-curve-points)
93
201
  - [abstract/poseidon: Poseidon hash](#abstractposeidon-poseidon-hash)
94
- - [abstract/modular](#abstractmodular)
95
- - [abstract/utils](#abstractutils)
202
+ - [abstract/modular: Modular arithmetics utilities](#abstractmodular-modular-arithmetics-utilities)
203
+ - [abstract/utils: General utilities](#abstractutils-general-utilities)
96
204
 
97
- ### Overview
98
-
99
- There are following zero-dependency abstract algorithms:
205
+ ### abstract/weierstrass: Short Weierstrass curve
100
206
 
101
207
  ```ts
102
- import { bls } from '@noble/curves/abstract/bls';
103
- import { twistedEdwards } from '@noble/curves/abstract/edwards';
104
- import { montgomery } from '@noble/curves/abstract/montgomery';
105
208
  import { weierstrass } from '@noble/curves/abstract/weierstrass';
106
- import * as mod from '@noble/curves/abstract/modular';
107
- import * as utils from '@noble/curves/abstract/utils';
108
209
  ```
109
210
 
110
- They allow to define a new curve in a few lines of code:
211
+ Short Weierstrass curve's formula is `y² = + ax + b`. `weierstrass` expects arguments `a`, `b`, field `Fp`, curve order `n`, cofactor `h`
212
+ and coordinates `Gx`, `Gy` of generator point.
213
+
214
+ **`k` generation** is done deterministically, following [RFC6979](https://www.rfc-editor.org/rfc/rfc6979).
215
+ For this you will need `hmac` & `hash`, which in our implementations is provided by noble-hashes.
216
+ If you're using different hashing library, make sure to wrap it in the following interface:
111
217
 
112
218
  ```ts
113
- import { Field } from '@noble/curves/abstract/modular';
114
- import { weierstrass } from '@noble/curves/abstract/weierstrass';
115
- import { hmac } from '@noble/hashes/hmac';
116
- import { sha256 } from '@noble/hashes/sha256';
117
- import { concatBytes, randomBytes } from '@noble/hashes/utils';
219
+ export type CHash = {
220
+ (message: Uint8Array): Uint8Array;
221
+ blockLen: number;
222
+ outputLen: number;
223
+ create(): any;
224
+ };
225
+ ```
226
+
227
+ **Weierstrass points:**
228
+
229
+ 1. Exported as `ProjectivePoint`
230
+ 2. Represented in projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z)
231
+ 3. Use complete exception-free formulas for addition and doubling
232
+ 4. Can be decoded/encoded from/to Uint8Array / hex strings using `ProjectivePoint.fromHex` and `ProjectivePoint#toRawBytes()`
233
+ 5. Have `assertValidity()` which checks for being on-curve
234
+ 6. Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates
235
+
236
+ ```ts
237
+ // T is usually bigint, but can be something else like complex numbers in BLS curves
238
+ export interface ProjPointType<T> extends Group<ProjPointType<T>> {
239
+ readonly px: T;
240
+ readonly py: T;
241
+ readonly pz: T;
242
+ multiply(scalar: bigint): ProjPointType<T>;
243
+ multiplyUnsafe(scalar: bigint): ProjPointType<T>;
244
+ multiplyAndAddUnsafe(Q: ProjPointType<T>, a: bigint, b: bigint): ProjPointType<T> | undefined;
245
+ toAffine(iz?: T): AffinePoint<T>;
246
+ isTorsionFree(): boolean;
247
+ clearCofactor(): ProjPointType<T>;
248
+ assertValidity(): void;
249
+ hasEvenY(): boolean;
250
+ toRawBytes(isCompressed?: boolean): Uint8Array;
251
+ toHex(isCompressed?: boolean): string;
252
+ }
253
+ // Static methods for 3d XYZ points
254
+ export interface ProjConstructor<T> extends GroupConstructor<ProjPointType<T>> {
255
+ new (x: T, y: T, z: T): ProjPointType<T>;
256
+ fromAffine(p: AffinePoint<T>): ProjPointType<T>;
257
+ fromHex(hex: Hex): ProjPointType<T>;
258
+ fromPrivateKey(privateKey: PrivKey): ProjPointType<T>;
259
+ }
260
+ ```
261
+
262
+ **ECDSA signatures** are represented by `Signature` instances and can be described by the interface:
263
+
264
+ ```ts
265
+ export interface SignatureType {
266
+ readonly r: bigint;
267
+ readonly s: bigint;
268
+ readonly recovery?: number;
269
+ assertValidity(): void;
270
+ addRecoveryBit(recovery: number): SignatureType;
271
+ hasHighS(): boolean;
272
+ normalizeS(): SignatureType;
273
+ recoverPublicKey(msgHash: Hex): ProjPointType<bigint>;
274
+ toCompactRawBytes(): Uint8Array;
275
+ toCompactHex(): string;
276
+ // DER-encoded
277
+ toDERRawBytes(isCompressed?: boolean): Uint8Array;
278
+ toDERHex(isCompressed?: boolean): string;
279
+ }
280
+ ```
281
+
282
+ Example implementing [secq256k1](https://personaelabs.org/posts/spartan-ecdsa) (NOT secp256k1)
283
+ [cycle](https://zcash.github.io/halo2/background/curves.html#cycles-of-curves) of secp256k1 with Fp/N flipped.
118
284
 
119
- // secq (NOT secp) 256k1: cycle of secp256k1 with Fp/N flipped.
120
- // https://zcash.github.io/halo2/background/curves.html#cycles-of-curves
121
- // https://personaelabs.org/posts/spartan-ecdsa
285
+ ```typescript
286
+ import { weierstrass } from '@noble/curves/abstract/weierstrass';
287
+ import { Field } from '@noble/curves/abstract/modular'; // finite field, mod arithmetics done over it
288
+ import { sha256 } from '@noble/hashes/sha256'; // 3rd-party sha256() of type utils.CHash, with blockLen/outputLen
289
+ import { hmac } from '@noble/hashes/hmac'; // 3rd-party hmac() that will accept sha256()
290
+ import { concatBytes, randomBytes } from '@noble/hashes/utils'; // 3rd-party utilities
122
291
  const secq256k1 = weierstrass({
292
+ // secq256k1: cycle of secp256k1 with Fp/N flipped.
123
293
  a: 0n,
124
294
  b: 7n,
125
295
  Fp: Field(2n ** 256n - 432420386565659656852420866394968145599n),
@@ -130,42 +300,93 @@ const secq256k1 = weierstrass({
130
300
  hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)),
131
301
  randomBytes,
132
302
  });
303
+
304
+ // All curves expose same generic interface.
305
+ const priv = secq256k1.utils.randomPrivateKey();
306
+ secq256k1.getPublicKey(priv); // Convert private key to public.
307
+ const sig = secq256k1.sign(msg, priv); // Sign msg with private key.
308
+ secq256k1.verify(sig, msg, priv); // Verify if sig is correct.
309
+
310
+ const point = secq256k1.Point.BASE; // Elliptic curve Point class and BASE point static var.
311
+ point.add(point).equals(point.double()); // add(), equals(), double() methods
312
+ point.subtract(point).equals(secq256k1.Point.ZERO); // subtract() method, ZERO static var
313
+ point.negate(); // Flips point over x/y coordinate.
314
+ point.multiply(31415n); // Multiplication of Point by scalar.
315
+
316
+ point.assertValidity(); // Checks for being on-curve
317
+ point.toAffine(); // Converts to 2d affine xy coordinates
318
+
319
+ secq256k1.CURVE.n;
320
+ secq256k1.CURVE.Fp.mod();
321
+ secq256k1.CURVE.hash();
133
322
  ```
134
323
 
135
- - To initialize new curve, you must specify its variables, order (number of points on curve), field prime (over which the modular division would be done)
136
- - All curves expose same generic interface:
137
- - `getPublicKey()`, `sign()`, `verify()` functions
138
- - `Point` conforming to `Group` interface with add/multiply/double/negate/add/equals methods
139
- - `CURVE` object with curve variables like `Gx`, `Gy`, `Fp` (field), `n` (order)
140
- - `utils` object with `randomPrivateKey()`, `mod()`, `invert()` methods (`mod CURVE.P`)
141
- - All arithmetics is done with JS bigints over finite fields, which is defined from `modular` sub-module
142
- - Many features require hashing, which is not provided. `@noble/hashes` can be used for this purpose.
143
- Any other library must conform to the CHash interface:
144
- ```ts
145
- export type CHash = {
146
- (message: Uint8Array): Uint8Array;
147
- blockLen: number;
148
- outputLen: number;
149
- create(): any;
324
+ `weierstrass()` returns `CurveFn`:
325
+
326
+ ```ts
327
+ export type CurveFn = {
328
+ CURVE: ReturnType<typeof validateOpts>;
329
+ getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array;
330
+ getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array;
331
+ sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => SignatureType;
332
+ verify: (
333
+ signature: Hex | SignatureType,
334
+ msgHash: Hex,
335
+ publicKey: Hex,
336
+ opts?: { lowS?: boolean; prehash?: boolean }
337
+ ) => boolean;
338
+ ProjectivePoint: ProjectivePointConstructor;
339
+ Signature: SignatureConstructor;
340
+ utils: {
341
+ isValidPrivateKey(privateKey: PrivKey): boolean;
342
+ randomPrivateKey: () => Uint8Array;
150
343
  };
151
- ```
152
- - w-ary non-adjacent form (wNAF) method with constant-time adjustments is used for point multiplication.
153
- It is possible to enable precomputes for edwards & weierstrass curves.
154
- Precomputes are calculated once (takes ~20-40ms), after that most `G` base point multiplications:
155
- for example, `getPublicKey()`, `sign()` and similar methods - would be much faster.
156
- Use `curve.utils.precompute()` to adjust precomputation window size
157
- - You could use optional special params to tune performance:
158
- - `Fp({sqrt})` square root calculation, used for point decompression
159
- - `endo` endomorphism options for Koblitz curves
344
+ };
345
+ ```
160
346
 
161
347
  ### abstract/edwards: Twisted Edwards curve
162
348
 
163
- Twisted Edwards curve's formula is: ax² + y² = 1 + dx²y².
349
+ Twisted Edwards curve's formula is `ax² + y² = 1 + dx²y²`. You must specify `a`, `d`, field `Fp`, order `n`, cofactor `h`
350
+ and coordinates `Gx`, `Gy` of generator point.
164
351
 
165
- - You must specify curve params `a`, `d`, field `Fp`, order `n`, cofactor `h` and coordinates `Gx`, `Gy` of generator point
166
- - For EdDSA signatures, params `hash` is also required. `adjustScalarBytes` which instructs how to change private scalars could be specified
352
+ For EdDSA signatures, `hash` param required. `adjustScalarBytes` which instructs how to change private scalars could be specified.
167
353
 
168
- ```typescript
354
+ **Edwards points:**
355
+
356
+ 1. Exported as `ExtendedPoint`
357
+ 2. Represented in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z)
358
+ 3. Use complete exception-free formulas for addition and doubling
359
+ 4. Can be decoded/encoded from/to Uint8Array / hex strings using `ExtendedPoint.fromHex` and `ExtendedPoint#toRawBytes()`
360
+ 5. Have `assertValidity()` which checks for being on-curve
361
+ 6. Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates
362
+ 7. Have `isTorsionFree()`, `clearCofactor()` and `isSmallOrder()` utilities to handle torsions
363
+
364
+ ```ts
365
+ export interface ExtPointType extends Group<ExtPointType> {
366
+ readonly ex: bigint;
367
+ readonly ey: bigint;
368
+ readonly ez: bigint;
369
+ readonly et: bigint;
370
+ assertValidity(): void;
371
+ multiply(scalar: bigint): ExtPointType;
372
+ multiplyUnsafe(scalar: bigint): ExtPointType;
373
+ isSmallOrder(): boolean;
374
+ isTorsionFree(): boolean;
375
+ clearCofactor(): ExtPointType;
376
+ toAffine(iz?: bigint): AffinePoint<bigint>;
377
+ }
378
+ // Static methods of Extended Point with coordinates in X, Y, Z, T
379
+ export interface ExtPointConstructor extends GroupConstructor<ExtPointType> {
380
+ new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType;
381
+ fromAffine(p: AffinePoint<bigint>): ExtPointType;
382
+ fromHex(hex: Hex): ExtPointType;
383
+ fromPrivateKey(privateKey: Hex): ExtPointType;
384
+ }
385
+ ```
386
+
387
+ Example implementing edwards25519:
388
+
389
+ ```ts
169
390
  import { twistedEdwards } from '@noble/curves/abstract/edwards';
170
391
  import { div } from '@noble/curves/abstract/modular';
171
392
  import { sha512 } from '@noble/hashes/sha512';
@@ -181,18 +402,13 @@ const ed25519 = twistedEdwards({
181
402
  hash: sha512,
182
403
  randomBytes,
183
404
  adjustScalarBytes(bytes) {
184
- // optional in general, mandatory in ed25519
405
+ // optional; but mandatory in ed25519
185
406
  bytes[0] &= 248;
186
407
  bytes[31] &= 127;
187
408
  bytes[31] |= 64;
188
409
  return bytes;
189
410
  },
190
411
  } as const);
191
- const key = ed25519.utils.randomPrivateKey();
192
- const pub = ed25519.getPublicKey(key);
193
- const msg = new TextEncoder().encode('hello world'); // strings not accepted, must be Uint8Array
194
- const sig = ed25519.sign(msg, key);
195
- ed25519.verify(sig, msg, pub) === true;
196
412
  ```
197
413
 
198
414
  `twistedEdwards()` returns `CurveFn` of following type:
@@ -202,8 +418,7 @@ export type CurveFn = {
202
418
  CURVE: ReturnType<typeof validateOpts>;
203
419
  getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array;
204
420
  sign: (message: Hex, privateKey: Hex) => Uint8Array;
205
- verify: (sig: SigType, message: Hex, publicKey: PubKey) => boolean;
206
- Point: PointConstructor;
421
+ verify: (sig: SigType, message: Hex, publicKey: PubKey, context?: Hex) => boolean;
207
422
  ExtendedPoint: ExtendedPointConstructor;
208
423
  Signature: SignatureConstructor;
209
424
  utils: {
@@ -221,9 +436,7 @@ export type CurveFn = {
221
436
 
222
437
  ### abstract/montgomery: Montgomery curve
223
438
 
224
- For now the module only contains methods for x-only ECDH on Curve25519 / Curve448 from RFC7748.
225
-
226
- Proper Elliptic Curve Points are not implemented yet.
439
+ The module contains methods for x-only ECDH on Curve25519 / Curve448 from RFC7748. Proper Elliptic Curve Points are not implemented yet.
227
440
 
228
441
  You must specify curve field, `a24` special variable, `montgomeryBits`, `nByteLength`, and coordinate `u` of generator point.
229
442
 
@@ -250,145 +463,51 @@ const x25519 = montgomery({
250
463
  });
251
464
  ```
252
465
 
253
- ### abstract/weierstrass: Short Weierstrass curve
254
-
255
- Short Weierstrass curve's formula is: y² = x³ + ax + b. Uses deterministic ECDSA from RFC6979. You can also specify `extraEntropy` in `sign()`.
256
-
257
- - You must specify curve params: `a`, `b`, field `Fp`, order `n`, cofactor `h` and coordinates `Gx`, `Gy` of generator point
258
- - For ECDSA, you must specify `hash`, `hmac`. It is also possible to recover keys from signatures
259
- - For ECDH, use `getSharedSecret(privKeyA, pubKeyB)`
260
- - Optional params are `lowS` (default value) and `endo` (endomorphism)
261
-
262
- ```typescript
263
- import { Fp } from '@noble/curves/abstract/modular';
264
- import { weierstrass } from '@noble/curves/abstract/weierstrass'; // Short Weierstrass curve
265
- import { sha256 } from '@noble/hashes/sha256';
266
- import { hmac } from '@noble/hashes/hmac';
267
- import { concatBytes, randomBytes } from '@noble/hashes/utils';
466
+ ### abstract/hash-to-curve: Hashing strings to curve points
268
467
 
269
- const secp256k1 = weierstrass({
270
- a: 0n,
271
- b: 7n,
272
- Fp: Fp(2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n),
273
- n: 2n ** 256n - 432420386565659656852420866394968145599n,
274
- Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
275
- Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
276
- hash: sha256,
277
- hmac: (k: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)),
278
- randomBytes,
468
+ The module allows to hash arbitrary strings to elliptic curve points. Implements [hash-to-curve v11](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11).
279
469
 
280
- // Optional params
281
- h: 1n, // Cofactor
282
- lowS: true, // Allow only low-S signatures by default in sign() and verify()
283
- endo: {
284
- // Endomorphism options for Koblitz curve
285
- // Beta param
286
- beta: 0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501een,
287
- // Split scalar k into k1, k2
288
- splitScalar: (k: bigint) => {
289
- // return { k1neg: true, k1: 512n, k2neg: false, k2: 448n };
290
- },
291
- },
292
- });
470
+ `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.
293
471
 
294
- // Usage
295
- const key = secp256k1.utils.randomPrivateKey();
296
- const pub = secp256k1.getPublicKey(key);
297
- const msg = randomBytes(32);
298
- const sig = secp256k1.sign(msg, key);
299
- secp256k1.verify(sig, msg, pub); // true
300
- sig.recoverPublicKey(msg); // == pub
301
- const someonesPubkey = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
302
- const shared = secp256k1.getSharedSecret(key, someonesPubkey);
472
+ ```ts
473
+ function expand_message_xmd(msg: Uint8Array, DST: Uint8Array, lenInBytes: number, H: CHash): Uint8Array;
474
+ function expand_message_xof(msg: Uint8Array, DST: Uint8Array, lenInBytes: number, k: number, H: CHash): Uint8Array;
303
475
  ```
304
476
 
305
- `weierstrass()` returns `CurveFn`:
477
+ `hash_to_field(msg, count, options)` [(spec)](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3)
478
+ hashes arbitrary-length byte strings to a list of one or more elements of a finite field F.
479
+ _ `msg` a byte string containing the message to hash
480
+ _ `count` the number of elements of F to output
481
+ _ `options` `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`
482
+ _ Returns `[u_0, ..., u_(count - 1)]`, a list of field elements.
306
483
 
307
484
  ```ts
308
- export type CurveFn = {
309
- CURVE: ReturnType<typeof validateOpts>;
310
- getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array;
311
- getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array;
312
- sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => SignatureType;
313
- verify: (
314
- signature: Hex | SignatureType,
315
- msgHash: Hex,
316
- publicKey: Hex,
317
- opts?: { lowS?: boolean }
318
- ) => boolean;
319
- Point: PointConstructor;
320
- ProjectivePoint: ProjectivePointConstructor;
321
- Signature: SignatureConstructor;
322
- utils: {
323
- isValidPrivateKey(privateKey: PrivKey): boolean;
324
- hashToPrivateKey: (hash: Hex) => Uint8Array;
325
- randomPrivateKey: () => Uint8Array;
326
- };
485
+ function hash_to_field(msg: Uint8Array, count: number, options: htfOpts): bigint[][];
486
+ type htfOpts = {
487
+ DST: string; // a domain separation tag defined in section 2.2.5
488
+ // p: the characteristic of F
489
+ // where F is a finite field of characteristic p and order q = p^m
490
+ p: bigint;
491
+ // m: the extension degree of F, m >= 1
492
+ // where F is a finite field of characteristic p and order q = p^m
493
+ m: number;
494
+ k: number; // the target security level for the suite in bits defined in section 5.1
495
+ expand?: 'xmd' | 'xof'; // option to use a message that has already been processed by expand_message_xmd
496
+ // Hash functions for: expand_message_xmd is appropriate for use with a
497
+ // wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
498
+ // BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
499
+ // TODO: verify that hash is shake if expand==='xof' via types
500
+ hash: CHash;
327
501
  };
328
502
  ```
329
503
 
330
- ### abstract/hash-to-curve: Hashing strings to curve points
331
-
332
- The module allows to hash arbitrary strings to elliptic curve points.
333
-
334
- - `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..
335
-
336
- ```ts
337
- function expand_message_xmd(
338
- msg: Uint8Array,
339
- DST: Uint8Array,
340
- lenInBytes: number,
341
- H: CHash
342
- ): Uint8Array;
343
- function expand_message_xof(
344
- msg: Uint8Array,
345
- DST: Uint8Array,
346
- lenInBytes: number,
347
- k: number,
348
- H: CHash
349
- ): Uint8Array;
350
- ```
351
-
352
- - `hash_to_field(msg, count, options)` [(spec)](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3)
353
- hashes arbitrary-length byte strings to a list of one or more elements of a finite field F.
354
- _ `msg` a byte string containing the message to hash
355
- _ `count` the number of elements of F to output
356
- _ `options` `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`
357
- _ Returns `[u_0, ..., u_(count - 1)]`, a list of field elements.
358
-
359
- ```ts
360
- function hash_to_field(msg: Uint8Array, count: number, options: htfOpts): bigint[][];
361
- type htfOpts = {
362
- // DST: a domain separation tag
363
- // defined in section 2.2.5
364
- DST: string;
365
- // p: the characteristic of F
366
- // where F is a finite field of characteristic p and order q = p^m
367
- p: bigint;
368
- // m: the extension degree of F, m >= 1
369
- // where F is a finite field of characteristic p and order q = p^m
370
- m: number;
371
- // k: the target security level for the suite in bits
372
- // defined in section 5.1
373
- k: number;
374
- // option to use a message that has already been processed by
375
- // expand_message_xmd
376
- expand?: 'xmd' | 'xof';
377
- // Hash functions for: expand_message_xmd is appropriate for use with a
378
- // wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
379
- // BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
380
- // TODO: verify that hash is shake if expand==='xof' via types
381
- hash: CHash;
382
- };
383
- ```
384
-
385
504
  ### abstract/poseidon: Poseidon hash
386
505
 
387
506
  Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash.
388
507
 
389
- There are many poseidon instances with different constants. We don't provide them,
390
- but we provide ability to specify them manually. For actual usage, check out
391
- stark curve source code.
508
+ There are many poseidon variants with different constants.
509
+ We don't provide them: you should construct them manually.
510
+ The only variant provided resides in `stark` module: inspect it for proper usage.
392
511
 
393
512
  ```ts
394
513
  import { poseidon } from '@noble/curves/abstract/poseidon';
@@ -406,27 +525,35 @@ type PoseidonOpts = {
406
525
  const instance = poseidon(opts: PoseidonOpts);
407
526
  ```
408
527
 
409
- ### abstract/modular
528
+ ### abstract/bls
410
529
 
411
- Modular arithmetics utilities.
530
+ The module abstracts BLS (Barreto-Lynn-Scott) primitives. In theory you should be able to write BLS12-377, BLS24,
531
+ and others with it.
412
532
 
413
- ```typescript
414
- import { Fp, mod, invert, div, invertBatch, sqrt } from '@noble/curves/abstract/modular';
415
- const fp = Fp(2n ** 255n - 19n); // Finite field over 2^255-19
416
- fp.mul(591n, 932n);
417
- fp.pow(481n, 11024858120n);
533
+ ### abstract/modular: Modular arithmetics utilities
534
+
535
+ The module also contains useful `hashToPrivateScalar` method which allows to create
536
+ scalars (e.g. private keys) with the modulo bias being neglible. It follows
537
+ FIPS 186 B.4.1. Requires at least 40 bytes of input for 32-byte private key.
538
+
539
+ ```ts
540
+ import * as mod from '@noble/curves/abstract/modular';
541
+ const fp = mod.Field(2n ** 255n - 19n); // Finite field over 2^255-19
542
+ fp.mul(591n, 932n); // multiplication
543
+ fp.pow(481n, 11024858120n); // exponentiation
544
+ fp.div(5n, 17n); // division: 5/17 mod 2^255-19 == 5 * invert(17)
545
+ fp.sqrt(21n); // square root
418
546
 
419
547
  // Generic non-FP utils are also available
420
- mod(21n, 10n); // 21 mod 10 == 1n; fixed version of 21 % 10
421
- invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse
422
- div(5n, 17n, 10n); // 5/17 mod 10 == 5 * invert(17) mod 10; division
423
- invertBatch([1n, 2n, 4n], 21n); // => [1n, 11n, 16n] in one inversion
424
- sqrt(21n, 73n); // √21 mod 73; square root
548
+ mod.mod(21n, 10n); // 21 mod 10 == 1n; fixed version of 21 % 10
549
+ mod.invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse
550
+ mod.invertBatch([1n, 2n, 4n], 21n); // => [1n, 11n, 16n] in one inversion
551
+ mod.hashToPrivateScalar(sha512_of_something, secp256r1.n);
425
552
  ```
426
553
 
427
- ### abstract/utils
554
+ ### abstract/utils: General utilities
428
555
 
429
- ```typescript
556
+ ```ts
430
557
  import * as utils from '@noble/curves/abstract/utils';
431
558
 
432
559
  utils.bytesToHex(Uint8Array.from([0xde, 0xad, 0xbe, 0xef]));
@@ -439,7 +566,6 @@ utils.numberToBytesLE(123n);
439
566
  utils.numberToHexUnpadded(123n);
440
567
  utils.concatBytes(Uint8Array.from([0xde, 0xad]), Uint8Array.from([0xbe, 0xef]));
441
568
  utils.nLength(255n);
442
- utils.hashToPrivateScalar(sha512_of_something, secp256r1.n);
443
569
  utils.equalBytes(Uint8Array.from([0xde]), Uint8Array.from([0xde]));
444
570
  ```
445
571
 
@@ -447,80 +573,102 @@ utils.equalBytes(Uint8Array.from([0xde]), Uint8Array.from([0xde]));
447
573
 
448
574
  The library had no prior security audit.
449
575
 
450
- [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.
576
+ [Timing attack](https://en.wikipedia.org/wiki/Timing_attack) considerations: we are using non-CT bigints. However, _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.
451
577
 
452
- 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.
578
+ 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:
579
+
580
+ - `@scure` base, bip32, bip39 (used in tests), micro-bmark (benchmark), micro-should (testing) are developed by us
581
+ and follow the same practices such as: minimal library size, auditability, signed releases
582
+ - prettier (linter), fast-check (property-based testing),
583
+ typescript versions are locked and rarely updated. Every update is checked with `npm-diff`.
584
+ The packages are big, which makes it hard to audit their source code thoroughly and fully.
585
+ - They are only used if you clone the git repo and want to add some feature to it. End-users won't use them.
453
586
 
454
587
  ## Speed
455
588
 
456
- Benchmark results on Apple M2 with node v18.10:
589
+ Benchmark results on Apple M2 with node v19:
457
590
 
458
591
  ```
459
592
  secp256k1
460
- init x 57 ops/sec @ 17ms/op
461
- getPublicKey x 4,946 ops/sec @ 202μs/op
462
- sign x 3,914 ops/sec @ 255μs/op
463
- verify x 682 ops/sec @ 1ms/op
464
- getSharedSecret x 427 ops/sec @ 2ms/op
465
- recoverPublicKey x 683 ops/sec @ 1ms/op
466
- schnorr.sign x 539 ops/sec @ 1ms/op
467
- schnorr.verify x 716 ops/sec @ 1ms/op
593
+ init x 58 ops/sec @ 17ms/op
594
+ getPublicKey x 5,640 ops/sec @ 177μs/op
595
+ sign x 3,909 ops/sec @ 255μs/op
596
+ verify x 780 ops/sec @ 1ms/op
597
+ getSharedSecret x 465 ops/sec @ 2ms/op
598
+ recoverPublicKey x 740 ops/sec @ 1ms/op
599
+ schnorr.sign x 597 ops/sec @ 1ms/op
600
+ schnorr.verify x 775 ops/sec @ 1ms/op
468
601
 
469
602
  P256
470
- init x 30 ops/sec @ 32ms/op
471
- getPublicKey x 5,008 ops/sec @ 199μs/op
472
- sign x 3,970 ops/sec @ 251μs/op
473
- verify x 515 ops/sec @ 1ms/op
603
+ init x 31 ops/sec @ 31ms/op
604
+ getPublicKey x 5,607 ops/sec @ 178μs/op
605
+ sign x 3,930 ops/sec @ 254μs/op
606
+ verify x 540 ops/sec @ 1ms/op
474
607
 
475
608
  P384
476
- init x 14 ops/sec @ 66ms/op
477
- getPublicKey x 2,434 ops/sec @ 410μs/op
478
- sign x 1,942 ops/sec @ 514μs/op
479
- verify x 206 ops/sec @ 4ms/op
609
+ init x 15 ops/sec @ 63ms/op
610
+ getPublicKey x 2,622 ops/sec @ 381μs/op
611
+ sign x 1,913 ops/sec @ 522μs/op
612
+ verify x 222 ops/sec @ 4ms/op
480
613
 
481
614
  P521
482
- init x 7 ops/sec @ 126ms/op
483
- getPublicKey x 1,282 ops/sec @ 779μs/op
484
- sign x 1,077 ops/sec @ 928μs/op
485
- verify x 110 ops/sec @ 9ms/op
615
+ init x 8 ops/sec @ 119ms/op
616
+ getPublicKey x 1,371 ops/sec @ 729μs/op
617
+ sign x 1,090 ops/sec @ 917μs/op
618
+ verify x 118 ops/sec @ 8ms/op
486
619
 
487
620
  ed25519
488
- init x 37 ops/sec @ 26ms/op
489
- getPublicKey x 8,147 ops/sec @ 122μs/op
490
- sign x 3,979 ops/sec @ 251μs/op
491
- verify x 848 ops/sec @ 1ms/op
621
+ init x 47 ops/sec @ 20ms/op
622
+ getPublicKey x 9,414 ops/sec @ 106μs/op
623
+ sign x 4,516 ops/sec @ 221μs/op
624
+ verify x 912 ops/sec @ 1ms/op
492
625
 
493
626
  ed448
494
- init x 17 ops/sec @ 58ms/op
495
- getPublicKey x 3,083 ops/sec @ 324μs/op
496
- sign x 1,473 ops/sec @ 678μs/op
497
- verify x 323 ops/sec @ 3ms/op
498
-
499
- bls12-381
500
- init x 30 ops/sec @ 33ms/op
501
- getPublicKey x 788 ops/sec @ 1ms/op
502
- sign x 45 ops/sec @ 21ms/op
503
- verify x 32 ops/sec @ 30ms/op
504
- pairing x 88 ops/sec @ 11ms/op
627
+ init x 17 ops/sec @ 56ms/op
628
+ getPublicKey x 3,363 ops/sec @ 297μs/op
629
+ sign x 1,615 ops/sec @ 619μs/op
630
+ verify x 319 ops/sec @ 3ms/op
505
631
 
506
632
  stark
507
- init x 31 ops/sec @ 31ms/op
508
- pedersen
509
- ├─old x 84 ops/sec @ 11ms/op
510
- └─noble x 802 ops/sec @ 1ms/op
511
- poseidon x 7,466 ops/sec @ 133μs/op
512
- verify
513
- ├─old x 300 ops/sec @ 3ms/op
514
- └─noble x 474 ops/sec @ 2ms/op
633
+ init x 35 ops/sec @ 28ms/op
634
+ pedersen x 884 ops/sec @ 1ms/op
635
+ poseidon x 8,598 ops/sec @ 116μs/op
636
+ verify x 528 ops/sec @ 1ms/op
637
+
638
+ bls12-381
639
+ init x 32 ops/sec @ 30ms/op
640
+ getPublicKey 1-bit x 858 ops/sec @ 1ms/op
641
+ getPublicKey x 858 ops/sec @ 1ms/op
642
+ sign x 49 ops/sec @ 20ms/op
643
+ verify x 34 ops/sec @ 28ms/op
644
+ pairing x 94 ops/sec @ 10ms/op
645
+ aggregatePublicKeys/8 x 116 ops/sec @ 8ms/op
646
+ aggregatePublicKeys/32 x 31 ops/sec @ 31ms/op
647
+ aggregatePublicKeys/128 x 7 ops/sec @ 125ms/op
648
+ aggregateSignatures/8 x 45 ops/sec @ 22ms/op
649
+ aggregateSignatures/32 x 11 ops/sec @ 84ms/op
650
+ aggregateSignatures/128 x 3 ops/sec @ 332ms/opp
515
651
  ```
516
652
 
653
+ ## In the wild
654
+
655
+ Elliptic curve calculator: [paulmillr.com/ecc](https://paulmillr.com/ecc).
656
+
657
+ - secp256k1
658
+ - [btc-signer](https://github.com/paulmillr/micro-btc-signer), [eth-signer](https://github.com/paulmillr/micro-eth-signer)
659
+ - ed25519
660
+ - [sol-signer](https://github.com/paulmillr/micro-sol-signer)
661
+ - BLS12-381
662
+ - Threshold sigs demo [genthresh.com](https://genthresh.com)
663
+ - 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)
664
+
517
665
  ## Upgrading
518
666
 
519
- If you're coming from single-curve noble packages, the following changes need to be kept in mind:
667
+ If you're coming from single-feature noble packages, the following changes need to be kept in mind:
520
668
 
521
669
  - 2d affine (x, y) points have been removed to reduce complexity and improve speed
522
- - Removed `number` support as a type for private keys. `bigint` is still supported
523
- - `mod`, `invert` are no longer present in `utils`. Use `@noble/curves/abstract/modular.js` now.
670
+ - Removed `number` support as a type for private keys, `bigint` is still supported
671
+ - `mod`, `invert` are no longer present in `utils`: use `@noble/curves/abstract/modular`
524
672
 
525
673
  Upgrading from @noble/secp256k1 1.7:
526
674