@noble/curves 1.8.1 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/README.md +305 -433
  2. package/_shortw_utils.d.ts +2 -2
  3. package/_shortw_utils.js +2 -2
  4. package/abstract/bls.d.ts +5 -5
  5. package/abstract/bls.d.ts.map +1 -1
  6. package/abstract/bls.js +15 -16
  7. package/abstract/bls.js.map +1 -1
  8. package/abstract/curve.d.ts +11 -3
  9. package/abstract/curve.d.ts.map +1 -1
  10. package/abstract/curve.js +81 -78
  11. package/abstract/curve.js.map +1 -1
  12. package/abstract/edwards.d.ts +2 -2
  13. package/abstract/edwards.d.ts.map +1 -1
  14. package/abstract/edwards.js +58 -71
  15. package/abstract/edwards.js.map +1 -1
  16. package/abstract/hash-to-curve.d.ts +15 -9
  17. package/abstract/hash-to-curve.d.ts.map +1 -1
  18. package/abstract/hash-to-curve.js +49 -39
  19. package/abstract/hash-to-curve.js.map +1 -1
  20. package/abstract/modular.d.ts +11 -8
  21. package/abstract/modular.d.ts.map +1 -1
  22. package/abstract/modular.js +79 -67
  23. package/abstract/modular.js.map +1 -1
  24. package/abstract/montgomery.d.ts.map +1 -1
  25. package/abstract/montgomery.js +13 -12
  26. package/abstract/montgomery.js.map +1 -1
  27. package/abstract/poseidon.d.ts +40 -3
  28. package/abstract/poseidon.d.ts.map +1 -1
  29. package/abstract/poseidon.js +186 -7
  30. package/abstract/poseidon.js.map +1 -1
  31. package/abstract/tower.d.ts +2 -2
  32. package/abstract/tower.d.ts.map +1 -1
  33. package/abstract/tower.js +16 -17
  34. package/abstract/tower.js.map +1 -1
  35. package/abstract/utils.d.ts +5 -2
  36. package/abstract/utils.d.ts.map +1 -1
  37. package/abstract/utils.js +27 -14
  38. package/abstract/utils.js.map +1 -1
  39. package/abstract/weierstrass.d.ts +21 -9
  40. package/abstract/weierstrass.d.ts.map +1 -1
  41. package/abstract/weierstrass.js +103 -86
  42. package/abstract/weierstrass.js.map +1 -1
  43. package/bls12-381.d.ts +1 -1
  44. package/bls12-381.js +41 -41
  45. package/bls12-381.js.map +1 -1
  46. package/bn254.d.ts +3 -2
  47. package/bn254.d.ts.map +1 -1
  48. package/bn254.js +39 -29
  49. package/bn254.js.map +1 -1
  50. package/ed25519.d.ts +9 -6
  51. package/ed25519.d.ts.map +1 -1
  52. package/ed25519.js +70 -71
  53. package/ed25519.js.map +1 -1
  54. package/ed448.d.ts +7 -6
  55. package/ed448.d.ts.map +1 -1
  56. package/ed448.js +54 -56
  57. package/ed448.js.map +1 -1
  58. package/esm/_shortw_utils.d.ts +2 -2
  59. package/esm/_shortw_utils.js +1 -1
  60. package/esm/abstract/bls.d.ts +5 -5
  61. package/esm/abstract/bls.d.ts.map +1 -1
  62. package/esm/abstract/bls.js +6 -7
  63. package/esm/abstract/bls.js.map +1 -1
  64. package/esm/abstract/curve.d.ts +11 -3
  65. package/esm/abstract/curve.d.ts.map +1 -1
  66. package/esm/abstract/curve.js +77 -74
  67. package/esm/abstract/curve.js.map +1 -1
  68. package/esm/abstract/edwards.d.ts +2 -2
  69. package/esm/abstract/edwards.d.ts.map +1 -1
  70. package/esm/abstract/edwards.js +39 -52
  71. package/esm/abstract/edwards.js.map +1 -1
  72. package/esm/abstract/hash-to-curve.d.ts +15 -9
  73. package/esm/abstract/hash-to-curve.d.ts.map +1 -1
  74. package/esm/abstract/hash-to-curve.js +33 -23
  75. package/esm/abstract/hash-to-curve.js.map +1 -1
  76. package/esm/abstract/modular.d.ts +11 -8
  77. package/esm/abstract/modular.d.ts.map +1 -1
  78. package/esm/abstract/modular.js +71 -59
  79. package/esm/abstract/modular.js.map +1 -1
  80. package/esm/abstract/montgomery.d.ts.map +1 -1
  81. package/esm/abstract/montgomery.js +4 -3
  82. package/esm/abstract/montgomery.js.map +1 -1
  83. package/esm/abstract/poseidon.d.ts +40 -3
  84. package/esm/abstract/poseidon.d.ts.map +1 -1
  85. package/esm/abstract/poseidon.js +180 -5
  86. package/esm/abstract/poseidon.js.map +1 -1
  87. package/esm/abstract/tower.d.ts +2 -2
  88. package/esm/abstract/tower.d.ts.map +1 -1
  89. package/esm/abstract/tower.js +8 -9
  90. package/esm/abstract/tower.js.map +1 -1
  91. package/esm/abstract/utils.d.ts +5 -2
  92. package/esm/abstract/utils.d.ts.map +1 -1
  93. package/esm/abstract/utils.js +26 -13
  94. package/esm/abstract/utils.js.map +1 -1
  95. package/esm/abstract/weierstrass.d.ts +21 -9
  96. package/esm/abstract/weierstrass.d.ts.map +1 -1
  97. package/esm/abstract/weierstrass.js +76 -59
  98. package/esm/abstract/weierstrass.js.map +1 -1
  99. package/esm/bls12-381.d.ts +1 -1
  100. package/esm/bls12-381.js +9 -9
  101. package/esm/bls12-381.js.map +1 -1
  102. package/esm/bn254.d.ts +3 -2
  103. package/esm/bn254.d.ts.map +1 -1
  104. package/esm/bn254.js +17 -7
  105. package/esm/bn254.js.map +1 -1
  106. package/esm/ed25519.d.ts +9 -6
  107. package/esm/ed25519.d.ts.map +1 -1
  108. package/esm/ed25519.js +25 -26
  109. package/esm/ed25519.js.map +1 -1
  110. package/esm/ed448.d.ts +7 -6
  111. package/esm/ed448.d.ts.map +1 -1
  112. package/esm/ed448.js +17 -19
  113. package/esm/ed448.js.map +1 -1
  114. package/esm/jubjub.d.ts +7 -4
  115. package/esm/jubjub.d.ts.map +1 -1
  116. package/esm/jubjub.js +7 -60
  117. package/esm/jubjub.js.map +1 -1
  118. package/esm/misc.d.ts +21 -0
  119. package/esm/misc.d.ts.map +1 -0
  120. package/esm/misc.js +107 -0
  121. package/esm/misc.js.map +1 -0
  122. package/esm/nist.d.ts +29 -0
  123. package/esm/nist.d.ts.map +1 -0
  124. package/esm/nist.js +120 -0
  125. package/esm/nist.js.map +1 -0
  126. package/esm/p256.d.ts +9 -8
  127. package/esm/p256.d.ts.map +1 -1
  128. package/esm/p256.js +6 -43
  129. package/esm/p256.js.map +1 -1
  130. package/esm/p384.d.ts +10 -8
  131. package/esm/p384.d.ts.map +1 -1
  132. package/esm/p384.js +7 -47
  133. package/esm/p384.js.map +1 -1
  134. package/esm/p521.d.ts +6 -6
  135. package/esm/p521.d.ts.map +1 -1
  136. package/esm/p521.js +6 -55
  137. package/esm/p521.js.map +1 -1
  138. package/esm/pasta.d.ts +5 -7
  139. package/esm/pasta.d.ts.map +1 -1
  140. package/esm/pasta.js +5 -33
  141. package/esm/pasta.js.map +1 -1
  142. package/esm/secp256k1.d.ts +15 -10
  143. package/esm/secp256k1.d.ts.map +1 -1
  144. package/esm/secp256k1.js +21 -18
  145. package/esm/secp256k1.js.map +1 -1
  146. package/jubjub.d.ts +7 -4
  147. package/jubjub.d.ts.map +1 -1
  148. package/jubjub.js +8 -63
  149. package/jubjub.js.map +1 -1
  150. package/misc.d.ts +21 -0
  151. package/misc.d.ts.map +1 -0
  152. package/misc.js +112 -0
  153. package/misc.js.map +1 -0
  154. package/nist.d.ts +29 -0
  155. package/nist.d.ts.map +1 -0
  156. package/nist.js +123 -0
  157. package/nist.js.map +1 -0
  158. package/p256.d.ts +9 -8
  159. package/p256.d.ts.map +1 -1
  160. package/p256.js +5 -48
  161. package/p256.js.map +1 -1
  162. package/p384.d.ts +10 -8
  163. package/p384.d.ts.map +1 -1
  164. package/p384.js +6 -52
  165. package/p384.js.map +1 -1
  166. package/p521.d.ts +6 -6
  167. package/p521.d.ts.map +1 -1
  168. package/p521.js +5 -60
  169. package/p521.js.map +1 -1
  170. package/package.json +116 -12
  171. package/pasta.d.ts +5 -7
  172. package/pasta.d.ts.map +1 -1
  173. package/pasta.js +6 -34
  174. package/pasta.js.map +1 -1
  175. package/secp256k1.d.ts +15 -10
  176. package/secp256k1.d.ts.map +1 -1
  177. package/secp256k1.js +60 -57
  178. package/secp256k1.js.map +1 -1
  179. package/src/_shortw_utils.ts +2 -2
  180. package/src/abstract/bls.ts +10 -10
  181. package/src/abstract/curve.ts +89 -80
  182. package/src/abstract/edwards.ts +56 -63
  183. package/src/abstract/hash-to-curve.ts +49 -39
  184. package/src/abstract/modular.ts +68 -59
  185. package/src/abstract/montgomery.ts +4 -3
  186. package/src/abstract/poseidon.ts +208 -13
  187. package/src/abstract/tower.ts +9 -10
  188. package/src/abstract/utils.ts +28 -15
  189. package/src/abstract/weierstrass.ts +105 -87
  190. package/src/bls12-381.ts +10 -10
  191. package/src/bn254.ts +18 -8
  192. package/src/ed25519.ts +31 -28
  193. package/src/ed448.ts +24 -21
  194. package/src/jubjub.ts +8 -63
  195. package/src/misc.ts +123 -0
  196. package/src/nist.ts +154 -0
  197. package/src/p256.ts +6 -49
  198. package/src/p384.ts +8 -53
  199. package/src/p521.ts +6 -70
  200. package/src/pasta.ts +5 -39
  201. package/src/secp256k1.ts +25 -20
package/README.md CHANGED
@@ -40,40 +40,40 @@ Take a glance at [GitHub Discussions](https://github.com/paulmillr/noble-curves/
40
40
 
41
41
  > `deno add jsr:@noble/curves`
42
42
 
43
- > `deno doc jsr:@noble/curves` # command-line documentation
43
+ > `deno doc jsr:@noble/curves` # command-line documentation
44
44
 
45
45
  We support all major platforms and runtimes.
46
46
  For React Native, you may need a [polyfill for getRandomValues](https://github.com/LinusU/react-native-get-random-values).
47
47
  A standalone file [noble-curves.js](https://github.com/paulmillr/noble-curves/releases) is also available.
48
48
 
49
- ```js
49
+ ```ts
50
50
  // import * from '@noble/curves'; // Error: use sub-imports, to ensure small app size
51
- import { secp256k1 } from '@noble/curves/secp256k1'; // ESM and Common.js
52
- // import { secp256k1 } from 'npm:@noble/curves@1.6.0/secp256k1'; // Deno
51
+ import { secp256k1, schnorr } from '@noble/curves/secp256k1';
52
+ import { ed25519, ed25519ph, ed25519ctx, x25519 } from '@noble/curves/ed25519';
53
+ import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448';
54
+ import { p256 } from '@noble/curves/p256';
55
+ import { p384 } from '@noble/curves/p384';
56
+ import { p521 } from '@noble/curves/p521';
57
+ import { bls12_381 } from '@noble/curves/bls12-381';
58
+ import { bn254 } from '@noble/curves/bn254'; // also known as alt_bn128
59
+ import { jubjub, babyjubjub } from '@noble/curves/misc';
60
+ import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils';
53
61
  ```
54
62
 
55
- - [Implementations](#implementations)
56
- - [ECDSA signatures over secp256k1 and others](#ecdsa-signatures-over-secp256k1-and-others)
57
- - [ECDSA public key recovery & extra entropy](#ecdsa-public-key-recovery--extra-entropy)
58
- - [ECDH: Elliptic Curve Diffie-Hellman](#ecdh-elliptic-curve-diffie-hellman)
59
- - [Schnorr signatures over secp256k1, BIP340](#schnorr-signatures-over-secp256k1-bip340)
60
- - [ed25519, X25519, ristretto255](#ed25519-x25519-ristretto255)
61
- - [ed448, X448, decaf448](#ed448-x448-decaf448)
62
- - [bls12-381](#bls12-381)
63
- - [bn254 aka alt_bn128](#bn254-aka-alt_bn128)
64
- - [Multi-scalar-multiplication](#multi-scalar-multiplication)
65
- - [Accessing a curve's variables](#accessing-a-curves-variables)
66
- - [All available imports](#all-available-imports)
63
+ - [ECDSA signatures over secp256k1 and others](#ecdsa-signatures-over-secp256k1-and-others)
64
+ - [Hedged ECDSA with noise](#hedged-ecdsa-with-noise)
65
+ - [ECDH: Diffie-Hellman shared secrets](#ecdh-diffie-hellman-shared-secrets)
66
+ - [secp256k1 Schnorr signatures from BIP340](#secp256k1-schnorr-signatures-from-bip340)
67
+ - [ed25519](#ed25519) / [X25519](#x25519) / [ristretto255](#ristretto255)
68
+ - [ed448](#ed448) / [X448](#x448) / [decaf448](#decaf448)
69
+ - [bls12-381](#bls12-381)
70
+ - [bn254 aka alt_bn128](#bn254-aka-alt_bn128)
71
+ - [misc curves](#misc-curves)
72
+ - [Low-level methods](#low-level-methods)
67
73
  - [Abstract API](#abstract-api)
68
- - [weierstrass: Short Weierstrass curve](#weierstrass-short-weierstrass-curve)
69
- - [edwards: Twisted Edwards curve](#edwards-twisted-edwards-curve)
70
- - [montgomery: Montgomery curve](#montgomery-montgomery-curve)
71
- - [bls: Barreto-Lynn-Scott curves](#bls-barreto-lynn-scott-curves)
72
- - [hash-to-curve: Hashing strings to curve points](#hash-to-curve-hashing-strings-to-curve-points)
73
- - [poseidon: Poseidon hash](#poseidon-poseidon-hash)
74
- - [modular: Modular arithmetics utilities](#modular-modular-arithmetics-utilities)
75
- - [Creating private keys from hashes](#creating-private-keys-from-hashes)
76
- - [utils: Useful utilities](#utils-useful-utilities)
74
+ - [weierstrass](#weierstrass-short-weierstrass-curve), [edwards](#edwards-twisted-edwards-curve), [montgomery](#montgomery-montgomery-curve), [bls](#bls-barreto-lynn-scott-curves)
75
+ - [hash-to-curve](#hash-to-curve-hashing-strings-to-curve-points), [poseidon](#poseidon-poseidon-hash)
76
+ - [modular](#modular-modular-arithmetics-utilities), [utils](#utils-useful-utilities)
77
77
  - [Security](#security)
78
78
  - [Speed](#speed)
79
79
  - [Upgrading](#upgrading)
@@ -82,9 +82,6 @@ import { secp256k1 } from '@noble/curves/secp256k1'; // ESM and Common.js
82
82
 
83
83
  ### Implementations
84
84
 
85
- Implementations use [noble-hashes](https://github.com/paulmillr/noble-hashes).
86
- If you want to use a different hashing library, [abstract API](#abstract-api) doesn't depend on them.
87
-
88
85
  #### ECDSA signatures over secp256k1 and others
89
86
 
90
87
  ```ts
@@ -100,31 +97,40 @@ const isValid = secp256k1.verify(sig, msg, pub) === true;
100
97
  // hex strings are also supported besides Uint8Array-s:
101
98
  const privHex = '46c930bc7bb4db7f55da20798697421b98c4175a52c630294d75a84b9c126236';
102
99
  const pub2 = secp256k1.getPublicKey(privHex);
100
+
101
+ // public key recovery
102
+ // let sig = secp256k1.Signature.fromCompact(sigHex); // or .fromDER(sigDERHex)
103
+ // sig = sig.addRecoveryBit(bit); // bit is not serialized into compact / der format
104
+ sig.recoverPublicKey(msg).toRawBytes(); // === pub; // public key recovery
103
105
  ```
104
106
 
105
107
  The same code would work for NIST P256 (secp256r1), P384 (secp384r1) & P521 (secp521r1).
106
108
 
107
- #### ECDSA public key recovery & extra entropy
109
+ #### Hedged ECDSA with noise
108
110
 
109
111
  ```ts
110
- // let sig = secp256k1.Signature.fromCompact(sigHex); // or .fromDER(sigDERHex)
111
- // sig = sig.addRecoveryBit(bit); // bit is not serialized into compact / der format
112
- sig.recoverPublicKey(msg).toRawBytes(); // === pub; // public key recovery
113
-
114
- // extraEntropy https://moderncrypto.org/mail-archive/curves/2017/000925.html
115
- const sigImprovedSecurity = secp256k1.sign(msg, priv, { extraEntropy: true });
112
+ const noisySignature = secp256k1.sign(msg, priv, { extraEntropy: true });
113
+ const ent = new Uint8Array(32).fill(3); // set custom entropy
114
+ const noisySignature2 = secp256k1.sign(msg, priv, { extraEntropy: ent });
116
115
  ```
117
116
 
118
- #### ECDH: Elliptic Curve Diffie-Hellman
117
+ Hedged ECDSA is add-on, providing improved protection against fault attacks.
118
+ It adds noise to signatures. The technique is used by default in BIP340; we also implement them
119
+ optionally for ECDSA. Check out blog post
120
+ [Deterministic signatures are not your friends](https://paulmillr.com/posts/deterministic-signatures/)
121
+ and [spec draft](https://datatracker.ietf.org/doc/draft-irtf-cfrg-det-sigs-with-noise/).
122
+
123
+ #### ECDH: Diffie-Hellman shared secrets
119
124
 
120
125
  ```ts
121
- // 1. The output includes parity byte. Strip it using shared.slice(1)
122
- // 2. The output is not hashed. More secure way is sha256(shared) or hkdf(shared)
123
126
  const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
124
127
  const shared = secp256k1.getSharedSecret(priv, someonesPub);
128
+ // NOTE:
129
+ // - `shared` includes parity byte: strip it using shared.slice(1)
130
+ // - `shared` is not hashed: more secure way is sha256(shared) or hkdf(shared)
125
131
  ```
126
132
 
127
- #### Schnorr signatures over secp256k1 (BIP340)
133
+ #### secp256k1 Schnorr signatures from BIP340
128
134
 
129
135
  ```ts
130
136
  import { schnorr } from '@noble/curves/secp256k1';
@@ -135,7 +141,7 @@ const sig = schnorr.sign(msg, priv);
135
141
  const isValid = schnorr.verify(sig, msg, pub);
136
142
  ```
137
143
 
138
- #### ed25519, X25519, ristretto255
144
+ #### ed25519
139
145
 
140
146
  ```ts
141
147
  import { ed25519 } from '@noble/curves/ed25519';
@@ -144,23 +150,22 @@ const pub = ed25519.getPublicKey(priv);
144
150
  const msg = new TextEncoder().encode('hello');
145
151
  const sig = ed25519.sign(msg, priv);
146
152
  ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215
147
- ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5
153
+ ed25519.verify(sig, msg, pub, { zip215: false }); // SBS / e-voting / RFC8032 / FIPS 186-5
154
+
155
+ // Variants from RFC8032: with context, prehashed
156
+ import { ed25519ctx, ed25519ph } from '@noble/curves/ed25519';
148
157
  ```
149
158
 
150
- Default `verify` behavior follows [ZIP215](https://zips.z.cash/zip-0215) and
151
- [can be used in consensus-critical applications](https://hdevalence.ca/blog/2020-10-04-its-25519am).
152
- It has SUF-CMA (strong unforgeability under chosen message attacks).
153
- `zip215: false` option switches verification criteria to strict
154
- [RFC8032](https://www.rfc-editor.org/rfc/rfc8032) / [FIPS 186-5](https://csrc.nist.gov/publications/detail/fips/186/5/final)
155
- and additionally provides [non-repudiation with SBS](#edwards-twisted-edwards-curve).
159
+ Default `verify` behavior follows ZIP215 and
160
+ can be used in consensus-critical applications.
161
+ If you need SBS (Strongly Binding Signatures) and FIPS 186-5 compliance,
162
+ use `zip215: false`. Check out [Edwards Signatures section for more info](#edwards-twisted-edwards-curve).
163
+ Both options have SUF-CMA (strong unforgeability under chosen message attacks).
156
164
 
157
- X25519 follows [RFC7748](https://www.rfc-editor.org/rfc/rfc7748).
165
+ #### X25519
158
166
 
159
167
  ```ts
160
- // Variants from RFC8032: with context, prehashed
161
- import { ed25519ctx, ed25519ph } from '@noble/curves/ed25519';
162
-
163
- // ECDH using curve25519 aka x25519
168
+ // X25519 aka ECDH on Curve25519 from [RFC7748](https://www.rfc-editor.org/rfc/rfc7748)
164
169
  import { x25519 } from '@noble/curves/ed25519';
165
170
  const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4';
166
171
  const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c';
@@ -174,10 +179,10 @@ edwardsToMontgomeryPub(ed25519.getPublicKey(ed25519.utils.randomPrivateKey()));
174
179
  edwardsToMontgomeryPriv(ed25519.utils.randomPrivateKey());
175
180
  ```
176
181
 
177
- ristretto255 follows [irtf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448).
182
+ #### ristretto255
178
183
 
179
184
  ```ts
180
- // hash-to-curve, ristretto255
185
+ // ristretto255 from [RFC9496](https://www.rfc-editor.org/rfc/rfc9496)
181
186
  import { utf8ToBytes } from '@noble/hashes/utils';
182
187
  import { sha512 } from '@noble/hashes/sha512';
183
188
  import {
@@ -201,7 +206,7 @@ RistrettoPoint.hashToCurve(sha512(msg));
201
206
  hashToRistretto255(msg, { DST: 'ristretto255_XMD:SHA-512_R255MAP_RO_' });
202
207
  ```
203
208
 
204
- #### ed448, X448, decaf448
209
+ #### ed448
205
210
 
206
211
  ```ts
207
212
  import { ed448 } from '@noble/curves/ed448';
@@ -215,9 +220,10 @@ ed448.verify(sig, msg, pub);
215
220
  import { ed448ph } from '@noble/curves/ed448';
216
221
  ```
217
222
 
218
- ECDH using Curve448 aka X448, follows [RFC7748](https://www.rfc-editor.org/rfc/rfc7748).
223
+ #### X448
219
224
 
220
225
  ```ts
226
+ // X448 aka ECDH on Curve448 from [RFC7748](https://www.rfc-editor.org/rfc/rfc7748)
221
227
  import { x448 } from '@noble/curves/ed448';
222
228
  x448.getSharedSecret(priv, pub) === x448.scalarMult(priv, pub); // aliases
223
229
  x448.getPublicKey(priv) === x448.scalarMultBase(priv);
@@ -227,9 +233,10 @@ import { edwardsToMontgomeryPub } from '@noble/curves/ed448';
227
233
  edwardsToMontgomeryPub(ed448.getPublicKey(ed448.utils.randomPrivateKey()));
228
234
  ```
229
235
 
230
- decaf448 follows [irtf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448).
236
+ #### decaf448
231
237
 
232
238
  ```ts
239
+ // decaf448 from [RFC9496](https://www.rfc-editor.org/rfc/rfc9496)
233
240
  import { utf8ToBytes } from '@noble/hashes/utils';
234
241
  import { shake256 } from '@noble/hashes/sha3';
235
242
  import { hashToCurve, encodeToCurve, DecafPoint, hashToDecaf448 } from '@noble/curves/ed448';
@@ -248,8 +255,6 @@ DecafPoint.hashToCurve(shake256(msg, { dkLen: 112 }));
248
255
  hashToDecaf448(msg, { DST: 'decaf448_XOF:SHAKE256_D448MAP_RO_' });
249
256
  ```
250
257
 
251
- Same RFC7748 / RFC8032 / IRTF draft are followed.
252
-
253
258
  #### bls12-381
254
259
 
255
260
  ```ts
@@ -275,7 +280,10 @@ const signatureEth = bls.sign(message, privateKey, htfEthereum);
275
280
  const isValidEth = bls.verify(signature, message, publicKey, htfEthereum);
276
281
 
277
282
  // Aggregation
278
- const aggregatedKey = bls.aggregatePublicKeys([bls.utils.randomPrivateKey(), bls.utils.randomPrivateKey()])
283
+ const aggregatedKey = bls.aggregatePublicKeys([
284
+ bls.utils.randomPrivateKey(),
285
+ bls.utils.randomPrivateKey(),
286
+ ]);
279
287
  // const aggregatedSig = bls.aggregateSignatures(sigs)
280
288
 
281
289
  // Pairings, with and without final exponentiation
@@ -296,19 +304,17 @@ For example usage, check out [the implementation of BLS EVM precompiles](https:/
296
304
  ```ts
297
305
  import { bn254 } from '@noble/curves/bn254';
298
306
 
299
- console.log(
300
- bn254.G1,
301
- bn254.G2,
302
- bn254.pairing
303
- )
307
+ console.log(bn254.G1, bn254.G2, bn254.pairing);
304
308
  ```
305
309
 
306
310
  The API mirrors [BLS](#bls12-381). The curve was previously called alt_bn128.
307
311
  The implementation is compatible with [EIP-196](https://eips.ethereum.org/EIPS/eip-196) and
308
312
  [EIP-197](https://eips.ethereum.org/EIPS/eip-197).
309
313
 
310
- Keep in mind that we don't implement Point methods toHex / toRawBytes. It's because
311
- different implementations of bn254 do it differently - there is no standard. Points of divergence:
314
+ We don't implement Point methods toHex / toRawBytes.
315
+ To work around this limitation, has to initialize points on their own from BigInts.
316
+ Reason it's not implemented is because [there is no standard](https://github.com/privacy-scaling-explorations/halo2curves/issues/109).
317
+ Points of divergence:
312
318
 
313
319
  - Endianness: LE vs BE (byte-swapped)
314
320
  - Flags as first hex bits (similar to BLS) vs no-flags
@@ -316,49 +322,43 @@ different implementations of bn254 do it differently - there is no standard. Poi
316
322
 
317
323
  For example usage, check out [the implementation of bn254 EVM precompiles](https://github.com/paulmillr/noble-curves/blob/3ed792f8ad9932765b84d1064afea8663a255457/test/bn254.test.js#L697).
318
324
 
319
- #### Multi-scalar-multiplication
325
+ #### misc curves
320
326
 
321
327
  ```ts
322
- import { secp256k1 } from '@noble/curves/secp256k1';
323
- const p = secp256k1.ProjectivePoint;
324
- const points = [p.BASE, p.BASE.multiply(2n), p.BASE.multiply(4n), p.BASE.multiply(8n)];
325
- p.msm(points, [3n, 5n, 7n, 11n]).equals(p.BASE.multiply(129n)); // 129*G
328
+ import { jubjub, babyjubjub } from '@noble/curves/misc';
326
329
  ```
327
330
 
328
- Pippenger algorithm is used underneath.
329
- Multi-scalar-multiplication (MSM) is basically `(Pa + Qb + Rc + ...)`.
330
- It's 10-30x faster vs naive addition for large amount of points.
331
+ Miscellaneous, rarely used curves are contained in the module.
332
+ Jubjub curves have Fp over scalar fields of other curves. They are friendly to ZK proofs.
333
+ jubjub Fp = bls n. babyjubjub Fp = bn254 n.
331
334
 
332
- #### Accessing a curve's variables
335
+ #### Low-level methods
333
336
 
334
337
  ```ts
335
338
  import { secp256k1 } from '@noble/curves/secp256k1';
339
+
340
+ // Curve's variables
336
341
  // Every curve has `CURVE` object that contains its parameters, field, and others
337
342
  console.log(secp256k1.CURVE.p); // field modulus
338
343
  console.log(secp256k1.CURVE.n); // curve order
339
344
  console.log(secp256k1.CURVE.a, secp256k1.CURVE.b); // equation params
340
345
  console.log(secp256k1.CURVE.Gx, secp256k1.CURVE.Gy); // base point coordinates
341
- ```
342
-
343
346
 
344
- #### All available imports
345
-
346
- ```typescript
347
- import { secp256k1, schnorr } from '@noble/curves/secp256k1';
348
- import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519';
349
- import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448';
350
- import { p256 } from '@noble/curves/p256';
351
- import { p384 } from '@noble/curves/p384';
352
- import { p521 } from '@noble/curves/p521';
353
- import { pallas, vesta } from '@noble/curves/pasta';
354
- import { bls12_381 } from '@noble/curves/bls12-381';
355
- import { bn254 } from '@noble/curves/bn254'; // also known as alt_bn128
356
- import { jubjub } from '@noble/curves/jubjub';
357
- import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils';
347
+ // MSM
348
+ const p = secp256k1.ProjectivePoint;
349
+ const points = [p.BASE, p.BASE.multiply(2n), p.BASE.multiply(4n), p.BASE.multiply(8n)];
350
+ p.msm(points, [3n, 5n, 7n, 11n]).equals(p.BASE.multiply(129n)); // 129*G
358
351
  ```
359
352
 
353
+ Multi-scalar-multiplication (MSM) is basically `(Pa + Qb + Rc + ...)`.
354
+ It's 10-30x faster vs naive addition for large amount of points.
355
+ Pippenger algorithm is used underneath.
356
+
360
357
  ## Abstract API
361
358
 
359
+ Implementations use [noble-hashes](https://github.com/paulmillr/noble-hashes).
360
+ If you want to use a different hashing library, abstract API doesn't depend on them.
361
+
362
362
  Abstract API allows to define custom curves. All arithmetics is done with JS
363
363
  bigints over finite fields, which is defined from `modular` sub-module. For
364
364
  scalar multiplication, we use
@@ -371,171 +371,69 @@ method: check out examples.
371
371
 
372
372
  ```ts
373
373
  import { weierstrass } from '@noble/curves/abstract/weierstrass';
374
- import { Field } from '@noble/curves/abstract/modular'; // finite field for mod arithmetics
375
- import { sha256 } from '@noble/hashes/sha256'; // 3rd-party sha256() of type utils.CHash
376
- import { hmac } from '@noble/hashes/hmac'; // 3rd-party hmac() that will accept sha256()
377
- import { concatBytes, randomBytes } from '@noble/hashes/utils'; // 3rd-party utilities
374
+ import { Field } from '@noble/curves/abstract/modular';
375
+ import { sha256 } from '@noble/hashes/sha256';
376
+ import { hmac } from '@noble/hashes/hmac';
377
+ import { concatBytes, randomBytes } from '@noble/hashes/utils';
378
378
 
379
- const hmacSha256 = (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs));
379
+ const hmacSha256 = (key: Uint8Array, ...msgs: Uint8Array[]) =>
380
+ hmac(sha256, key, concatBytes(...msgs));
380
381
 
381
- // secq256k1: cycle of secp256k1 with Fp/N flipped.
382
+ // secQ (not secP) - secq256k1 is a cycle of secp256k1 with Fp/N flipped.
382
383
  // https://personaelabs.org/posts/spartan-ecdsa
383
384
  // https://zcash.github.io/halo2/background/curves.html#cycles-of-curves
384
385
  const secq256k1 = weierstrass({
385
- // Curve equation params a, b
386
386
  a: 0n,
387
387
  b: 7n,
388
- // Field over which we'll do calculations
389
388
  Fp: Field(2n ** 256n - 432420386565659656852420866394968145599n),
390
- // Curve order, total count of valid points in the field.
391
389
  n: 2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n,
392
- // Base point (x, y) aka generator point
393
390
  Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
394
391
  Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
395
-
396
392
  hash: sha256,
397
393
  hmac: hmacSha256,
398
394
  randomBytes,
399
395
  });
400
396
 
401
- // NIST secp192r1 aka p192 https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/secg/secp192r1
397
+ // NIST secp192r1 aka p192
398
+ // https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/secg/secp192r1
402
399
  const secp192r1 = weierstrass({
403
- a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffc'),
404
- b: BigInt('0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1'),
405
- Fp: Field(BigInt('0xfffffffffffffffffffffffffffffffeffffffffffffffff')),
406
- n: BigInt('0xffffffffffffffffffffffff99def836146bc9b1b4d22831'),
407
- Gx: BigInt('0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'),
408
- Gy: BigInt('0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811'),
409
- h: BigInt(1),
400
+ a: 0xfffffffffffffffffffffffffffffffefffffffffffffffcn,
401
+ b: 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1n,
402
+ Fp: Field(0xfffffffffffffffffffffffffffffffeffffffffffffffffn),
403
+ n: 0xffffffffffffffffffffffff99def836146bc9b1b4d22831n,
404
+ Gx: 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012n,
405
+ Gy: 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811n,
410
406
  hash: sha256,
411
407
  hmac: hmacSha256,
412
408
  randomBytes,
413
409
  });
414
-
415
-
416
- // Replace weierstrass() with weierstrassPoints() if you don't need ECDSA, hash, hmac, randomBytes
417
410
  ```
418
411
 
419
412
  Short Weierstrass curve's formula is `y² = x³ + ax + b`. `weierstrass`
420
413
  expects arguments `a`, `b`, field `Fp`, curve order `n`, cofactor `h`
421
414
  and coordinates `Gx`, `Gy` of generator point.
422
-
423
- **`k` generation** is done deterministically, following
424
- [RFC6979](https://www.rfc-editor.org/rfc/rfc6979). It is suggested to use `extraEntropy`
425
- option, which incorporates randomness into signatures to increase their security.
426
-
427
- For k generation, specifying `hmac` & `hash` is required,
428
- which in our implementations is done by noble-hashes. If
429
- you're using different hashing library, make sure to wrap it in the following interface:
430
-
431
- ```ts
432
- type CHash = {
433
- (message: Uint8Array): Uint8Array;
434
- blockLen: number;
435
- outputLen: number;
436
- create(): any;
437
- };
438
-
439
- // example
440
- function sha256(message: Uint8Array) {
441
- return _internal_lowlvl(message);
442
- }
443
- sha256.outputLen = 32; // 32 bytes of output for sha2-256
444
- ```
445
-
446
- **Message hash** is expected instead of message itself:
447
-
448
- - `sign(msgHash, privKey)` is default behavior, assuming you pre-hash msg with sha2, or other hash
449
- - `sign(msg, privKey, {prehash: true})` option can be used if you want to pass the message itself
415
+ `hmac` and `hash` must be specified for deterministic `k` generation.
450
416
 
451
417
  **Weierstrass points:**
452
418
 
453
- 1. Exported as `ProjectivePoint`
454
- 2. Represented in projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z)
455
- 3. Use complete exception-free formulas for addition and doubling
456
- 4. Can be decoded/encoded from/to Uint8Array / hex strings using
457
- `ProjectivePoint.fromHex` and `ProjectivePoint#toRawBytes()`
458
- 5. Have `assertValidity()` which checks for being on-curve
459
- 6. Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates
460
-
461
- ```ts
462
- // `weierstrassPoints()` returns `CURVE` and `ProjectivePoint`
463
- // `weierstrass()` returns `CurveFn`
464
- type SignOpts = { lowS?: boolean; prehash?: boolean; extraEntropy: boolean | Uint8Array };
465
- type CurveFn = {
466
- CURVE: ReturnType<typeof validateOpts>;
467
- getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array;
468
- getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array;
469
- sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => SignatureType;
470
- verify: (
471
- signature: Hex | SignatureType,
472
- msgHash: Hex,
473
- publicKey: Hex,
474
- opts?: { lowS?: boolean; prehash?: boolean; format?: 'compact' | 'der' }
475
- ) => boolean;
476
- ProjectivePoint: ProjectivePointConstructor;
477
- Signature: SignatureConstructor;
478
- utils: {
479
- normPrivateKeyToScalar: (key: PrivKey) => bigint;
480
- isValidPrivateKey(key: PrivKey): boolean;
481
- randomPrivateKey: () => Uint8Array;
482
- precompute: (windowSize?: number, point?: ProjPointType<bigint>) => ProjPointType<bigint>;
483
- };
484
- };
485
-
486
- // T is usually bigint, but can be something else like complex numbers in BLS curves
487
- interface ProjPointType<T> extends Group<ProjPointType<T>> {
488
- readonly px: T;
489
- readonly py: T;
490
- readonly pz: T;
491
- get x(): bigint;
492
- get y(): bigint;
493
- multiply(scalar: bigint): ProjPointType<T>;
494
- multiplyUnsafe(scalar: bigint): ProjPointType<T>;
495
- multiplyAndAddUnsafe(Q: ProjPointType<T>, a: bigint, b: bigint): ProjPointType<T> | undefined;
496
- toAffine(iz?: T): AffinePoint<T>;
497
- isTorsionFree(): boolean;
498
- clearCofactor(): ProjPointType<T>;
499
- assertValidity(): void;
500
- hasEvenY(): boolean;
501
- toRawBytes(isCompressed?: boolean): Uint8Array;
502
- toHex(isCompressed?: boolean): string;
503
- }
504
- // Static methods for 3d XYZ points
505
- interface ProjConstructor<T> extends GroupConstructor<ProjPointType<T>> {
506
- new (x: T, y: T, z: T): ProjPointType<T>;
507
- fromAffine(p: AffinePoint<T>): ProjPointType<T>;
508
- fromHex(hex: Hex): ProjPointType<T>;
509
- fromPrivateKey(privateKey: PrivKey): ProjPointType<T>;
510
- msm(points: ProjPointType[], scalars: bigint[]): ProjPointType<T>;
511
- }
512
- ```
513
-
514
- **ECDSA signatures** are represented by `Signature` instances and can be
515
- described by the interface:
516
-
517
- ```ts
518
- interface SignatureType {
519
- readonly r: bigint;
520
- readonly s: bigint;
521
- readonly recovery?: number;
522
- assertValidity(): void;
523
- addRecoveryBit(recovery: number): SignatureType;
524
- hasHighS(): boolean;
525
- normalizeS(): SignatureType;
526
- recoverPublicKey(msgHash: Hex): ProjPointType<bigint>;
527
- toCompactRawBytes(): Uint8Array;
528
- toCompactHex(): string;
529
- // DER-encoded
530
- toDERRawBytes(): Uint8Array;
531
- toDERHex(): string;
532
- }
533
- type SignatureConstructor = {
534
- new (r: bigint, s: bigint): SignatureType;
535
- fromCompact(hex: Hex): SignatureType;
536
- fromDER(hex: Hex): SignatureType;
537
- };
538
- ```
419
+ - Are exported as `ProjectivePoint`
420
+ - Are represented in projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z)
421
+ - Use complete exception-free formulas for addition and doubling
422
+ - Can be decoded/encoded from/to Uint8Array / hex strings using
423
+ `ProjectivePoint.fromHex` and `ProjectivePoint#toRawBytes()`
424
+ - Have `assertValidity()` which checks for being on-curve
425
+ - Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates
426
+
427
+ **ECDSA signatures:**
428
+
429
+ - Are represented by `Signature` instances with `r, s` and optional `recovery` properties
430
+ - Have `recoverPublicKey()`, `toCompactRawBytes()` and `toDERRawBytes()` methods
431
+ - Can be prehashed, or non-prehashed:
432
+ - `sign(msgHash, privKey)` (default, prehash: false) - you did hashing before
433
+ - `sign(msg, privKey, {prehash: true})` - curves will do hashing for you
434
+ - Are generated deterministically, following [RFC6979](https://www.rfc-editor.org/rfc/rfc6979).
435
+ - Consider [hedged ECDSA with noise](#hedged-ecdsa-with-noise) for adding randomness into
436
+ for signatures, to get improved security against fault attacks.
539
437
 
540
438
  More examples:
541
439
 
@@ -599,101 +497,43 @@ const ed25519 = twistedEdwards({
599
497
  } as const);
600
498
  ```
601
499
 
602
- Twisted Edwards curve's formula is `ax² + y² = 1 + dx²y²`. You must specify `a`, `d`, field `Fp`, order `n`, cofactor `h`
500
+ Twisted Edwards curve's formula is `ax² + y² = 1 + dx²y²`.
501
+ You must specify `a`, `d`, field `Fp`, order `n`, cofactor `h`
603
502
  and coordinates `Gx`, `Gy` of generator point.
604
-
605
- For EdDSA signatures, `hash` param required. `adjustScalarBytes` which instructs how to change private scalars could be specified.
606
-
607
- We support [non-repudiation](https://eprint.iacr.org/2020/1244), which help in following scenarios:
608
-
609
- - Contract Signing: if A signed an agreement with B using key that allows repudiation, it can later claim that it signed a different contract
610
- - E-voting: malicious voters may pick keys that allow repudiation in order to deny results
611
- - Blockchains: transaction of amount X might also be valid for a different amount Y
503
+ For EdDSA signatures, `hash` param required.
504
+ `adjustScalarBytes` which instructs how to change private scalars could be specified.
612
505
 
613
506
  **Edwards points:**
614
507
 
615
- 1. Exported as `ExtendedPoint`
616
- 2. Represented in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z)
617
- 3. Use complete exception-free formulas for addition and doubling
618
- 4. Can be decoded/encoded from/to Uint8Array / hex strings using `ExtendedPoint.fromHex` and `ExtendedPoint#toRawBytes()`
619
- 5. Have `assertValidity()` which checks for being on-curve
620
- 6. Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates
621
- 7. Have `isTorsionFree()`, `clearCofactor()` and `isSmallOrder()` utilities to handle torsions
622
-
623
- ```ts
624
- // `twistedEdwards()` returns `CurveFn` of following type:
625
- type CurveFn = {
626
- CURVE: ReturnType<typeof validateOpts>;
627
- getPublicKey: (privateKey: Hex) => Uint8Array;
628
- sign: (message: Hex, privateKey: Hex, context?: Hex) => Uint8Array;
629
- verify: (sig: SigType, message: Hex, publicKey: Hex, context?: Hex) => boolean;
630
- ExtendedPoint: ExtPointConstructor;
631
- utils: {
632
- randomPrivateKey: () => Uint8Array;
633
- getExtendedPublicKey: (key: PrivKey) => {
634
- head: Uint8Array;
635
- prefix: Uint8Array;
636
- scalar: bigint;
637
- point: PointType;
638
- pointBytes: Uint8Array;
639
- };
640
- };
641
- };
642
-
643
- interface ExtPointType extends Group<ExtPointType> {
644
- readonly ex: bigint;
645
- readonly ey: bigint;
646
- readonly ez: bigint;
647
- readonly et: bigint;
648
- get x(): bigint;
649
- get y(): bigint;
650
- assertValidity(): void;
651
- multiply(scalar: bigint): ExtPointType;
652
- multiplyUnsafe(scalar: bigint): ExtPointType;
653
- isSmallOrder(): boolean;
654
- isTorsionFree(): boolean;
655
- clearCofactor(): ExtPointType;
656
- toAffine(iz?: bigint): AffinePoint<bigint>;
657
- toRawBytes(isCompressed?: boolean): Uint8Array;
658
- toHex(isCompressed?: boolean): string;
659
- }
660
- // Static methods of Extended Point with coordinates in X, Y, Z, T
661
- interface ExtPointConstructor extends GroupConstructor<ExtPointType> {
662
- new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType;
663
- fromAffine(p: AffinePoint<bigint>): ExtPointType;
664
- fromHex(hex: Hex): ExtPointType;
665
- fromPrivateKey(privateKey: Hex): ExtPointType;
666
- msm(points: ExtPointType[], scalars: bigint[]): ExtPointType;
667
- }
668
- ```
508
+ - Are exported as `ExtendedPoint`
509
+ - Are represented in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z)
510
+ - Use complete exception-free formulas for addition and doubling
511
+ - Can be decoded/encoded from/to Uint8Array / hex strings using `ExtendedPoint.fromHex` and `ExtendedPoint#toRawBytes()`
512
+ - Have `assertValidity()` which checks for being on-curve
513
+ - Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates
514
+ - Have `isTorsionFree()`, `clearCofactor()` and `isSmallOrder()` utilities to handle torsions
515
+
516
+ **EdDSA signatures:**
517
+
518
+ - `zip215: true` is default behavior. It has slightly looser verification logic
519
+ to be [consensus-friendly](https://hdevalence.ca/blog/2020-10-04-its-25519am), following [ZIP215](https://zips.z.cash/zip-0215) rules
520
+ - `zip215: false` switches verification criteria to strict
521
+ [RFC8032](https://www.rfc-editor.org/rfc/rfc8032) / [FIPS 186-5](https://csrc.nist.gov/publications/detail/fips/186/5/final)
522
+ and additionally provides [non-repudiation with SBS](https://eprint.iacr.org/2020/1244),
523
+ which is useful for:
524
+ - Contract Signing: if A signed an agreement with B using key that allows repudiation, it can later claim that it signed a different contract
525
+ - E-voting: malicious voters may pick keys that allow repudiation in order to deny results
526
+ - Blockchains: transaction of amount X might also be valid for a different amount Y
527
+ - Both modes have SUF-CMA (strong unforgeability under chosen message attacks).
528
+
529
+ Check out [RFC9496](https://datatracker.ietf.org/doc/html/rfc9496) for description of
530
+ ristretto and decaf groups which we implement.
669
531
 
670
532
  ### montgomery: Montgomery curve
671
533
 
672
- ```typescript
673
- import { montgomery } from '@noble/curves/abstract/montgomery';
674
- import { Field } from '@noble/curves/abstract/modular';
675
-
676
- const x25519 = montgomery({
677
- a: 486662n,
678
- Gu: 9n,
679
- P: 2n ** 255n - 19n,
680
- montgomeryBits: 255,
681
- nByteLength: 32,
682
- // Optional param
683
- adjustScalarBytes(bytes) {
684
- bytes[0] &= 248;
685
- bytes[31] &= 127;
686
- bytes[31] |= 64;
687
- return bytes;
688
- },
689
- });
690
- ```
691
-
692
534
  The module contains methods for x-only ECDH on Curve25519 / Curve448 from RFC7748.
693
535
  Proper Elliptic Curve Points are not implemented yet.
694
536
 
695
- You must specify curve params `Fp`, `a`, `Gu` coordinate of u, `montgomeryBits` and `nByteLength`.
696
-
697
537
  ### bls: Barreto-Lynn-Scott curves
698
538
 
699
539
  The module abstracts BLS (Barreto-Lynn-Scott) pairing-friendly elliptic curve construction.
@@ -769,26 +609,36 @@ type Opts = {
769
609
 
770
610
  ### poseidon: Poseidon hash
771
611
 
772
- Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash.
612
+ Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash:
613
+ permutation and sponge.
773
614
 
774
615
  There are many poseidon variants with different constants.
775
616
  We don't provide them: you should construct them manually.
776
617
  Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example.
777
618
 
778
619
  ```ts
779
- import { poseidon } from '@noble/curves/abstract/poseidon';
780
-
781
- type PoseidonOpts = {
782
- Fp: Field<bigint>;
783
- t: number;
784
- roundsFull: number;
785
- roundsPartial: number;
786
- sboxPower?: number;
787
- reversePartialPowIdx?: boolean;
788
- mds: bigint[][];
789
- roundConstants: bigint[][];
620
+ import { poseidon, poseidonSponge } from '@noble/curves/abstract/poseidon';
621
+
622
+ const rate = 2;
623
+ const capacity = 1;
624
+ const { mds, roundConstants } = poseidon.grainGenConstants({
625
+ Fp,
626
+ t: rate + capacity,
627
+ roundsFull: 8,
628
+ roundsPartial: 31,
629
+ });
630
+ const opts = {
631
+ Fp,
632
+ rate,
633
+ capacity,
634
+ sboxPower: 17,
635
+ mds,
636
+ roundConstants,
637
+ roundsFull: 8,
638
+ roundsPartial: 31,
790
639
  };
791
- const instance = poseidon(opts: PoseidonOpts);
640
+ const permutation = poseidon.poseidon(opts);
641
+ const sponge = poseidon.poseidonSponge(opts); // use carefully, not specced
792
642
  ```
793
643
 
794
644
  ### modular: Modular arithmetics utilities
@@ -889,33 +739,37 @@ The library has been independently audited:
889
739
  - The audit has been funded by [Ryan Shea](https://www.shea.io)
890
740
 
891
741
  It is tested against property-based, cross-library and Wycheproof vectors,
892
- and has fuzzing by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz).
742
+ and is being fuzzed in [the separate repo](https://github.com/paulmillr/fuzzing).
893
743
 
894
744
  If you see anything unusual: investigate and report.
895
745
 
896
746
  ### Constant-timeness
897
747
 
898
- _JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard to
899
- achieve [timing attack](https://en.wikipedia.org/wiki/Timing_attack) resistance
748
+ We're targetting algorithmic constant time. _JIT-compiler_ and _Garbage Collector_ make "constant time"
749
+ extremely hard to achieve [timing attack](https://en.wikipedia.org/wiki/Timing_attack) resistance
900
750
  in a scripting language. Which means _any other JS library can't have
901
751
  constant-timeness_. Even statically typed Rust, a language without GC,
902
752
  [makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security)
903
753
  for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones.
904
- Use low-level libraries & languages. Nonetheless we're targetting algorithmic constant time.
754
+ Use low-level libraries & languages.
905
755
 
906
756
  ### Supply chain security
907
757
 
908
- - **Commits** are signed with PGP keys, to prevent forgery. Make sure to verify commit signatures.
758
+ - **Commits** are signed with PGP keys, to prevent forgery. Make sure to verify commit signatures
909
759
  - **Releases** are transparent and built on GitHub CI. Make sure to verify [provenance](https://docs.npmjs.com/generating-provenance-statements) logs
760
+ - Use GitHub CLI to verify single-file builds:
761
+ `gh attestation verify --owner paulmillr noble-curves.js`
910
762
  - **Rare releasing** is followed to ensure less re-audit need for end-users
911
- - **Dependencies** are minimized and locked-down:
912
- - If your app has 500 dependencies, any dep could get hacked and you'll be downloading
913
- malware with every install. We make sure to use as few dependencies as possible
914
- - We prevent automatic dependency updates by locking-down version ranges. Every update is checked with `npm-diff`
915
- - One dependency [noble-hashes](https://github.com/paulmillr/noble-hashes) is used, by the same author, to provide hashing functionality
916
- - **Dev Dependencies** are only used if you want to contribute to the repo. They are disabled for end-users:
917
- - scure-base, scure-bip32, scure-bip39, micro-bmark and micro-should are developed by the same author and follow identical security practices
918
- - prettier (linter), fast-check (property-based testing) and typescript are used for code quality, vector generation and ts compilation. The packages are big, which makes it hard to audit their source code thoroughly and fully
763
+ - **Dependencies** are minimized and locked-down: any dependency could get hacked and users will be downloading malware with every install.
764
+ - We make sure to use as few dependencies as possible
765
+ - Automatic dep updates are prevented by locking-down version ranges; diffs are checked with `npm-diff`
766
+ - **Dev Dependencies** are disabled for end-users; they are only used to develop / build the source code
767
+
768
+ For this package, there is 1 dependency; and a few dev dependencies:
769
+
770
+ - [noble-hashes](https://github.com/paulmillr/noble-hashes) provides cryptographic hashing functionality
771
+ - micro-bmark, micro-should and jsbt are used for benchmarking / testing / build tooling and developed by the same author
772
+ - prettier, fast-check and typescript are used for code quality / test generation / ts compilation. It's hard to audit their source code thoroughly and fully because of their size
919
773
 
920
774
  ### Randomness
921
775
 
@@ -939,96 +793,114 @@ NIST prohibits classical cryptography (RSA, DSA, ECDSA, ECDH) [after 2035](https
939
793
 
940
794
  ## Speed
941
795
 
942
- Benchmark results on Apple M2 with node v22:
943
-
944
- ```
945
- secp256k1
946
- init x 68 ops/sec @ 14ms/op
947
- getPublicKey x 6,839 ops/sec @ 146μs/op
948
- sign x 5,226 ops/sec @ 191μs/op
949
- verify x 893 ops/sec @ 1ms/op
950
- getSharedSecret x 538 ops/sec @ 1ms/op
951
- recoverPublicKey x 923 ops/sec @ 1ms/op
952
- schnorr.sign x 700 ops/sec @ 1ms/op
953
- schnorr.verify x 919 ops/sec @ 1ms/op
954
-
955
- ed25519
956
- init x 51 ops/sec @ 19ms/op
957
- getPublicKey x 9,809 ops/sec @ 101μs/op
958
- sign x 4,976 ops/sec @ 200μs/op
959
- verify x 1,018 ops/sec @ 981μs/op
960
-
961
- ed448
962
- init x 19 ops/sec @ 50ms/op
963
- getPublicKey x 3,723 ops/sec @ 268μs/op
964
- sign x 1,759 ops/sec @ 568μs/op
965
- verify x 344 ops/sec @ 2ms/op
966
-
967
- p256
968
- init x 39 ops/sec @ 25ms/op
969
- getPublicKey x 6,518 ops/sec @ 153μs/op
970
- sign x 5,148 ops/sec @ 194μs/op
971
- verify x 609 ops/sec @ 1ms/op
972
-
973
- p384
974
- init x 17 ops/sec @ 57ms/op
975
- getPublicKey x 2,933 ops/sec @ 340μs/op
976
- sign x 2,327 ops/sec @ 429μs/op
977
- verify x 244 ops/sec @ 4ms/op
978
-
979
- p521
980
- init x 8 ops/sec @ 112ms/op
981
- getPublicKey x 1,484 ops/sec @ 673μs/op
982
- sign x 1,264 ops/sec @ 790μs/op
983
- verify x 124 ops/sec @ 8ms/op
984
-
985
- ristretto255
986
- add x 680,735 ops/sec @ 1μs/op
987
- multiply x 10,766 ops/sec @ 92μs/op
988
- encode x 15,835 ops/sec @ 63μs/op
989
- decode x 15,972 ops/sec @ 62μs/op
990
-
991
- decaf448
992
- add x 345,303 ops/sec @ 2μs/op
993
- multiply x 300 ops/sec @ 3ms/op
994
- encode x 5,987 ops/sec @ 167μs/op
995
- decode x 5,892 ops/sec @ 169μs/op
996
-
997
- ecdh
998
- ├─x25519 x 1,477 ops/sec @ 676μs/op
999
- ├─secp256k1 x 537 ops/sec @ 1ms/op
1000
- ├─p256 x 512 ops/sec @ 1ms/op
1001
- ├─p384 x 198 ops/sec @ 5ms/op
1002
- ├─p521 x 99 ops/sec @ 10ms/op
1003
- └─x448 x 504 ops/sec @ 1ms/op
1004
-
1005
- bls12-381
1006
- init x 36 ops/sec @ 27ms/op
1007
- getPublicKey x 960 ops/sec @ 1ms/op
1008
- sign x 60 ops/sec @ 16ms/op
1009
- verify x 47 ops/sec @ 21ms/op
1010
- pairing x 125 ops/sec @ 7ms/op
1011
- pairing10 x 40 ops/sec @ 24ms/op ± 23.27% (min: 21ms, max: 48ms)
1012
- MSM 4096 scalars x points x 0 ops/sec @ 4655ms/op
1013
- aggregatePublicKeys/8 x 129 ops/sec @ 7ms/op
1014
- aggregatePublicKeys/32 x 34 ops/sec @ 28ms/op
1015
- aggregatePublicKeys/128 x 8 ops/sec @ 113ms/op
1016
- aggregatePublicKeys/512 x 2 ops/sec @ 449ms/op
1017
- aggregatePublicKeys/2048 x 0 ops/sec @ 1792ms/op
1018
- aggregateSignatures/8 x 62 ops/sec @ 15ms/op
1019
- aggregateSignatures/32 x 16 ops/sec @ 60ms/op
1020
- aggregateSignatures/128 x 4 ops/sec @ 238ms/op
1021
- aggregateSignatures/512 x 1 ops/sec @ 946ms/op
1022
- aggregateSignatures/2048 x 0 ops/sec @ 3774ms/op
1023
-
1024
- hash-to-curve
1025
- hash_to_field x 91,600 ops/sec @ 10μs/op
1026
- secp256k1 x 2,373 ops/sec @ 421μs/op
1027
- p256 x 4,310 ops/sec @ 231μs/op
1028
- p384 x 1,664 ops/sec @ 600μs/op
1029
- p521 x 807 ops/sec @ 1ms/op
1030
- ed25519 x 3,088 ops/sec @ 323μs/op
1031
- ed448 x 1,247 ops/sec @ 801μs/op
796
+ ```sh
797
+ npm run bench:install && npm run bench
798
+ ```
799
+
800
+ During first call of most methods, `init` is done, which calculates base point precomputes.
801
+ The method consumes 20MB+ of memory and takes some time.
802
+ You can adjust how many precomputes are generated,
803
+ by using `_setWindowSize`. Check out the source code.
804
+
805
+ Benchmark results on Apple M4:
806
+
807
+ ```
808
+ # secp256k1
809
+ init 10ms
810
+ getPublicKey x 9,099 ops/sec @ 109μs/op
811
+ sign x 7,182 ops/sec @ 139μs/op
812
+ verify x 1,188 ops/sec @ 841μs/op
813
+ getSharedSecret x 735 ops/sec @ 1ms/op
814
+ recoverPublicKey x 1,265 ops/sec @ 790μs/op
815
+ schnorr.sign x 957 ops/sec @ 1ms/op
816
+ schnorr.verify x 1,210 ops/sec @ 825μs/op
817
+
818
+ # ed25519
819
+ init 14ms
820
+ getPublicKey x 14,216 ops/sec @ 70μs/op
821
+ sign x 6,849 ops/sec @ 145μs/op
822
+ verify x 1,400 ops/sec @ 713μs/op
823
+
824
+ # ed448
825
+ init 37ms
826
+ getPublicKey x 5,273 ops/sec @ 189μs/op
827
+ sign x 2,494 ops/sec @ 400μs/op
828
+ verify x 476 ops/sec @ 2ms/op
829
+
830
+ # p256
831
+ init 17ms
832
+ getPublicKey x 8,977 ops/sec @ 111μs/op
833
+ sign x 7,236 ops/sec @ 138μs/op
834
+ verify x 877 ops/sec @ 1ms/op
835
+
836
+ # p384
837
+ init 42ms
838
+ getPublicKey x 4,084 ops/sec @ 244μs/op
839
+ sign x 3,247 ops/sec @ 307μs/op
840
+ verify x 331 ops/sec @ 3ms/op
841
+
842
+ # p521
843
+ init 83ms
844
+ getPublicKey x 2,049 ops/sec @ 487μs/op
845
+ sign x 1,748 ops/sec @ 571μs/op
846
+ verify x 170 ops/sec @ 5ms/op
847
+
848
+ # ristretto255
849
+ add x 931,966 ops/sec @ 1μs/op
850
+ multiply x 15,444 ops/sec @ 64μs/op
851
+ encode x 21,367 ops/sec @ 46μs/op
852
+ decode x 21,715 ops/sec @ 46μs/op
853
+
854
+ # decaf448
855
+ add x 478,011 ops/sec @ 2μs/op
856
+ multiply x 416 ops/sec @ 2ms/op
857
+ encode x 8,562 ops/sec @ 116μs/op
858
+ decode x 8,636 ops/sec @ 115μs/op
859
+
860
+ # ECDH
861
+ x25519 x 1,981 ops/sec @ 504μs/op
862
+ x448 x 743 ops/sec @ 1ms/op
863
+ secp256k1 x 728 ops/sec @ 1ms/op
864
+ p256 x 705 ops/sec @ 1ms/op
865
+ p384 x 268 ops/sec @ 3ms/op
866
+ p521 x 137 ops/sec @ 7ms/op
867
+
868
+ # hash-to-curve
869
+ hashToPrivateScalar x 1,754,385 ops/sec @ 570ns/op
870
+ hash_to_field x 135,703 ops/sec @ 7μs/op
871
+ hashToCurve secp256k1 x 3,194 ops/sec @ 313μs/op
872
+ hashToCurve p256 x 5,962 ops/sec @ 167μs/op
873
+ hashToCurve p384 x 2,230 ops/sec @ 448μs/op
874
+ hashToCurve p521 x 1,063 ops/sec @ 940μs/op
875
+ hashToCurve ed25519 x 4,047 ops/sec @ 247μs/op
876
+ hashToCurve ed448 x 1,691 ops/sec @ 591μs/op
877
+ hash_to_ristretto255 x 8,733 ops/sec @ 114μs/op
878
+ hash_to_decaf448 x 3,882 ops/sec @ 257μs/op
879
+
880
+ # modular over secp256k1 P field
881
+ invert a x 866,551 ops/sec @ 1μs/op
882
+ invert b x 693,962 ops/sec @ 1μs/op
883
+ sqrt p = 3 mod 4 x 25,738 ops/sec @ 38μs/op
884
+ sqrt tonneli-shanks x 847 ops/sec @ 1ms/op
885
+
886
+ # bls12-381
887
+ init 22ms
888
+ getPublicKey x 1,325 ops/sec @ 754μs/op
889
+ sign x 80 ops/sec @ 12ms/op
890
+ verify x 62 ops/sec @ 15ms/op
891
+ pairing x 166 ops/sec @ 6ms/op
892
+ pairing10 x 54 ops/sec @ 18ms/op ± 23.48% (15ms..36ms)
893
+ MSM 4096 scalars x points 3286ms
894
+ aggregatePublicKeys/8 x 173 ops/sec @ 5ms/op
895
+ aggregatePublicKeys/32 x 46 ops/sec @ 21ms/op
896
+ aggregatePublicKeys/128 x 11 ops/sec @ 84ms/op
897
+ aggregatePublicKeys/512 x 2 ops/sec @ 335ms/op
898
+ aggregatePublicKeys/2048 x 0 ops/sec @ 1346ms/op
899
+ aggregateSignatures/8 x 82 ops/sec @ 12ms/op
900
+ aggregateSignatures/32 x 21 ops/sec @ 45ms/op
901
+ aggregateSignatures/128 x 5 ops/sec @ 178ms/op
902
+ aggregateSignatures/512 x 1 ops/sec @ 705ms/op
903
+ aggregateSignatures/2048 x 0 ops/sec @ 2823ms/op
1032
904
  ```
1033
905
 
1034
906
  ## Upgrading
@@ -1092,10 +964,10 @@ Upgrading from [@noble/bls12-381](https://github.com/paulmillr/noble-bls12-381):
1092
964
 
1093
965
  ## Contributing & testing
1094
966
 
1095
- * `npm install && npm run build && npm test` will build the code and run tests.
1096
- * `npm run lint` / `npm run format` will run linter / fix linter issues.
1097
- * `npm run bench` will run benchmarks, which may need their deps first (`npm run bench:install`)
1098
- * `cd build && npm install && npm run build:release` will build single file
967
+ - `npm install && npm run build && npm test` will build the code and run tests.
968
+ - `npm run lint` / `npm run format` will run linter / fix linter issues.
969
+ - `npm run bench` will run benchmarks, which may need their deps first (`npm run bench:install`)
970
+ - `npm run build:release` will build single file
1099
971
 
1100
972
  Check out [github.com/paulmillr/guidelines](https://github.com/paulmillr/guidelines)
1101
973
  for general coding practices and rules.