@noble/curves 1.9.5 → 2.0.0-beta.1

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 (211) hide show
  1. package/README.md +267 -421
  2. package/abstract/bls.d.ts +49 -111
  3. package/abstract/bls.d.ts.map +1 -1
  4. package/abstract/bls.js +108 -152
  5. package/abstract/bls.js.map +1 -1
  6. package/abstract/curve.d.ts +7 -48
  7. package/abstract/curve.d.ts.map +1 -1
  8. package/abstract/curve.js +22 -47
  9. package/abstract/curve.js.map +1 -1
  10. package/abstract/edwards.d.ts +17 -68
  11. package/abstract/edwards.d.ts.map +1 -1
  12. package/abstract/edwards.js +98 -175
  13. package/abstract/edwards.js.map +1 -1
  14. package/abstract/fft.js +14 -27
  15. package/abstract/fft.js.map +1 -1
  16. package/abstract/hash-to-curve.d.ts +11 -24
  17. package/abstract/hash-to-curve.d.ts.map +1 -1
  18. package/abstract/hash-to-curve.js +30 -35
  19. package/abstract/hash-to-curve.js.map +1 -1
  20. package/abstract/modular.d.ts +5 -17
  21. package/abstract/modular.d.ts.map +1 -1
  22. package/abstract/modular.js +166 -167
  23. package/abstract/modular.js.map +1 -1
  24. package/abstract/montgomery.d.ts +4 -9
  25. package/abstract/montgomery.d.ts.map +1 -1
  26. package/abstract/montgomery.js +17 -20
  27. package/abstract/montgomery.js.map +1 -1
  28. package/abstract/oprf.d.ts +282 -0
  29. package/abstract/oprf.d.ts.map +1 -0
  30. package/abstract/oprf.js +297 -0
  31. package/abstract/oprf.js.map +1 -0
  32. package/abstract/poseidon.js +20 -24
  33. package/abstract/poseidon.js.map +1 -1
  34. package/abstract/tower.d.ts +9 -7
  35. package/abstract/tower.d.ts.map +1 -1
  36. package/abstract/tower.js +600 -364
  37. package/abstract/tower.js.map +1 -1
  38. package/abstract/weierstrass.d.ts +12 -145
  39. package/abstract/weierstrass.d.ts.map +1 -1
  40. package/abstract/weierstrass.js +153 -377
  41. package/abstract/weierstrass.js.map +1 -1
  42. package/bls12-381.d.ts +2 -2
  43. package/bls12-381.d.ts.map +1 -1
  44. package/bls12-381.js +174 -216
  45. package/bls12-381.js.map +1 -1
  46. package/bn254.d.ts +58 -10
  47. package/bn254.d.ts.map +1 -1
  48. package/bn254.js +70 -130
  49. package/bn254.js.map +1 -1
  50. package/ed25519.d.ts +12 -31
  51. package/ed25519.d.ts.map +1 -1
  52. package/ed25519.js +104 -146
  53. package/ed25519.js.map +1 -1
  54. package/ed448.d.ts +14 -33
  55. package/ed448.d.ts.map +1 -1
  56. package/ed448.js +105 -132
  57. package/ed448.js.map +1 -1
  58. package/index.js +1 -1
  59. package/misc.d.ts +10 -14
  60. package/misc.d.ts.map +1 -1
  61. package/misc.js +51 -60
  62. package/misc.js.map +1 -1
  63. package/nist.d.ts +11 -14
  64. package/nist.d.ts.map +1 -1
  65. package/nist.js +46 -55
  66. package/nist.js.map +1 -1
  67. package/package.json +9 -224
  68. package/secp256k1.d.ts +7 -23
  69. package/secp256k1.d.ts.map +1 -1
  70. package/secp256k1.js +72 -83
  71. package/secp256k1.js.map +1 -1
  72. package/src/abstract/bls.ts +197 -344
  73. package/src/abstract/curve.ts +10 -83
  74. package/src/abstract/edwards.ts +96 -223
  75. package/src/abstract/hash-to-curve.ts +32 -45
  76. package/src/abstract/modular.ts +144 -130
  77. package/src/abstract/montgomery.ts +21 -22
  78. package/src/abstract/oprf.ts +600 -0
  79. package/src/abstract/tower.ts +627 -382
  80. package/src/abstract/weierstrass.ts +101 -482
  81. package/src/bls12-381.ts +148 -176
  82. package/src/bn254.ts +67 -122
  83. package/src/ed25519.ts +65 -118
  84. package/src/ed448.ts +63 -113
  85. package/src/index.ts +1 -1
  86. package/src/misc.ts +66 -49
  87. package/src/nist.ts +48 -57
  88. package/src/secp256k1.ts +56 -88
  89. package/src/utils.ts +41 -61
  90. package/src/webcrypto.ts +362 -0
  91. package/utils.d.ts +28 -19
  92. package/utils.d.ts.map +1 -1
  93. package/utils.js +45 -121
  94. package/utils.js.map +1 -1
  95. package/webcrypto.d.ts +47 -0
  96. package/webcrypto.d.ts.map +1 -0
  97. package/webcrypto.js +231 -0
  98. package/webcrypto.js.map +1 -0
  99. package/esm/_shortw_utils.d.ts +0 -19
  100. package/esm/_shortw_utils.d.ts.map +0 -1
  101. package/esm/_shortw_utils.js +0 -16
  102. package/esm/_shortw_utils.js.map +0 -1
  103. package/esm/abstract/bls.d.ts +0 -190
  104. package/esm/abstract/bls.d.ts.map +0 -1
  105. package/esm/abstract/bls.js +0 -408
  106. package/esm/abstract/bls.js.map +0 -1
  107. package/esm/abstract/curve.d.ts +0 -231
  108. package/esm/abstract/curve.d.ts.map +0 -1
  109. package/esm/abstract/curve.js +0 -465
  110. package/esm/abstract/curve.js.map +0 -1
  111. package/esm/abstract/edwards.d.ts +0 -237
  112. package/esm/abstract/edwards.d.ts.map +0 -1
  113. package/esm/abstract/edwards.js +0 -632
  114. package/esm/abstract/edwards.js.map +0 -1
  115. package/esm/abstract/fft.d.ts +0 -122
  116. package/esm/abstract/fft.d.ts.map +0 -1
  117. package/esm/abstract/fft.js +0 -425
  118. package/esm/abstract/fft.js.map +0 -1
  119. package/esm/abstract/hash-to-curve.d.ts +0 -102
  120. package/esm/abstract/hash-to-curve.d.ts.map +0 -1
  121. package/esm/abstract/hash-to-curve.js +0 -203
  122. package/esm/abstract/hash-to-curve.js.map +0 -1
  123. package/esm/abstract/modular.d.ts +0 -171
  124. package/esm/abstract/modular.d.ts.map +0 -1
  125. package/esm/abstract/modular.js +0 -530
  126. package/esm/abstract/modular.js.map +0 -1
  127. package/esm/abstract/montgomery.d.ts +0 -30
  128. package/esm/abstract/montgomery.d.ts.map +0 -1
  129. package/esm/abstract/montgomery.js +0 -157
  130. package/esm/abstract/montgomery.js.map +0 -1
  131. package/esm/abstract/poseidon.d.ts +0 -68
  132. package/esm/abstract/poseidon.d.ts.map +0 -1
  133. package/esm/abstract/poseidon.js +0 -296
  134. package/esm/abstract/poseidon.js.map +0 -1
  135. package/esm/abstract/tower.d.ts +0 -93
  136. package/esm/abstract/tower.d.ts.map +0 -1
  137. package/esm/abstract/tower.js +0 -502
  138. package/esm/abstract/tower.js.map +0 -1
  139. package/esm/abstract/utils.d.ts +0 -5
  140. package/esm/abstract/utils.d.ts.map +0 -1
  141. package/esm/abstract/utils.js +0 -7
  142. package/esm/abstract/utils.js.map +0 -1
  143. package/esm/abstract/weierstrass.d.ts +0 -412
  144. package/esm/abstract/weierstrass.d.ts.map +0 -1
  145. package/esm/abstract/weierstrass.js +0 -1428
  146. package/esm/abstract/weierstrass.js.map +0 -1
  147. package/esm/bls12-381.d.ts +0 -16
  148. package/esm/bls12-381.d.ts.map +0 -1
  149. package/esm/bls12-381.js +0 -738
  150. package/esm/bls12-381.js.map +0 -1
  151. package/esm/bn254.d.ts +0 -18
  152. package/esm/bn254.d.ts.map +0 -1
  153. package/esm/bn254.js +0 -246
  154. package/esm/bn254.js.map +0 -1
  155. package/esm/ed25519.d.ts +0 -106
  156. package/esm/ed25519.d.ts.map +0 -1
  157. package/esm/ed25519.js +0 -467
  158. package/esm/ed25519.js.map +0 -1
  159. package/esm/ed448.d.ts +0 -101
  160. package/esm/ed448.d.ts.map +0 -1
  161. package/esm/ed448.js +0 -448
  162. package/esm/ed448.js.map +0 -1
  163. package/esm/index.d.ts +0 -2
  164. package/esm/index.d.ts.map +0 -1
  165. package/esm/index.js +0 -17
  166. package/esm/index.js.map +0 -1
  167. package/esm/jubjub.d.ts +0 -12
  168. package/esm/jubjub.d.ts.map +0 -1
  169. package/esm/jubjub.js +0 -12
  170. package/esm/jubjub.js.map +0 -1
  171. package/esm/misc.d.ts +0 -19
  172. package/esm/misc.d.ts.map +0 -1
  173. package/esm/misc.js +0 -109
  174. package/esm/misc.js.map +0 -1
  175. package/esm/nist.d.ts +0 -21
  176. package/esm/nist.d.ts.map +0 -1
  177. package/esm/nist.js +0 -132
  178. package/esm/nist.js.map +0 -1
  179. package/esm/p256.d.ts +0 -16
  180. package/esm/p256.d.ts.map +0 -1
  181. package/esm/p256.js +0 -16
  182. package/esm/p256.js.map +0 -1
  183. package/esm/p384.d.ts +0 -16
  184. package/esm/p384.d.ts.map +0 -1
  185. package/esm/p384.js +0 -16
  186. package/esm/p384.js.map +0 -1
  187. package/esm/p521.d.ts +0 -16
  188. package/esm/p521.d.ts.map +0 -1
  189. package/esm/p521.js +0 -16
  190. package/esm/p521.js.map +0 -1
  191. package/esm/package.json +0 -4
  192. package/esm/pasta.d.ts +0 -10
  193. package/esm/pasta.d.ts.map +0 -1
  194. package/esm/pasta.js +0 -10
  195. package/esm/pasta.js.map +0 -1
  196. package/esm/secp256k1.d.ts +0 -89
  197. package/esm/secp256k1.d.ts.map +0 -1
  198. package/esm/secp256k1.js +0 -292
  199. package/esm/secp256k1.js.map +0 -1
  200. package/esm/utils.d.ts +0 -110
  201. package/esm/utils.d.ts.map +0 -1
  202. package/esm/utils.js +0 -322
  203. package/esm/utils.js.map +0 -1
  204. package/src/_shortw_utils.ts +0 -21
  205. package/src/abstract/utils.ts +0 -7
  206. package/src/jubjub.ts +0 -12
  207. package/src/p256.ts +0 -15
  208. package/src/p384.ts +0 -15
  209. package/src/p521.ts +0 -15
  210. package/src/package.json +0 -3
  211. package/src/pasta.ts +0 -9
package/README.md CHANGED
@@ -5,7 +5,7 @@ Audited & minimal JS implementation of elliptic curve cryptography.
5
5
  - 🔒 [**Audited**](#security) by independent security firms
6
6
  - 🔻 Tree-shakeable: unused code is excluded from your builds
7
7
  - 🏎 Fast: hand-optimized for caveats of JS engines
8
- - 🔍 Reliable: tested against cross-library, wycheproof and acvp vectors
8
+ - 🔍 Reliable: cross-library / wycheproof tests and fuzzing ensure correctness
9
9
  - ➰ Weierstrass, Edwards, Montgomery curves; ECDSA, EdDSA, Schnorr, BLS signatures
10
10
  - ✍️ ECDH, hash-to-curve, OPRF, Poseidon ZK-friendly hash
11
11
  - 🔖 Non-repudiation (SUF-CMA, SBS) & consensus-friendliness (ZIP215) in ed25519, ed448
@@ -56,213 +56,161 @@ import { p256, p384, p521 } from '@noble/curves/nist.js';
56
56
  import { bls12_381 } from '@noble/curves/bls12-381.js';
57
57
  import { bn254 } from '@noble/curves/bn254.js';
58
58
  import { jubjub, babyjubjub } from '@noble/curves/misc.js';
59
- import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils.js';
60
- ```
61
-
62
- - [ECDSA signatures over secp256k1 and others](#ecdsa-signatures-over-secp256k1-and-others)
63
- - [Hedged ECDSA with noise](#hedged-ecdsa-with-noise)
64
- - [ECDH: Diffie-Hellman shared secrets](#ecdh-diffie-hellman-shared-secrets)
65
- - [secp256k1 Schnorr signatures from BIP340](#secp256k1-schnorr-signatures-from-bip340)
66
- - [ed25519](#ed25519) / [X25519](#x25519) / [ristretto255](#ristretto255)
67
- - [ed448](#ed448) / [X448](#x448) / [decaf448](#decaf448)
68
- - [bls12-381](#bls12-381)
69
- - [bn254 aka alt_bn128](#bn254-aka-alt_bn128)
70
- - [misc curves](#misc-curves)
71
- - [Low-level methods](#low-level-methods)
72
- - [Abstract API](#abstract-api)
73
- - [weierstrass](#weierstrass-short-weierstrass-curve), [Projective Point](#projective-weierstrass-point), [ECDSA signatures](#ecdsa-signatures)
74
- - [edwards](#edwards-twisted-edwards-curve), [Extended Point](#extended-edwards-point), [EdDSA signatures](#eddsa-signatures)
75
- - [montgomery](#montgomery-montgomery-curve)
76
- - [bls](#bls-barreto-lynn-scott-curves)
77
- - [hash-to-curve](#hash-to-curve-hashing-strings-to-curve-points)
78
- - [poseidon](#poseidon-poseidon-hash)
79
- - [modular](#modular-modular-arithmetics-utilities)
80
- - [fft](#fft-fast-fourier-transform)
81
- - [Creating private keys from hashes](#creating-private-keys-from-hashes)
82
- - [utils](#utils-useful-utilities)
83
- - [Security](#security)
84
- - [Speed](#speed)
85
- - [Upgrading](#upgrading)
86
- - [Contributing & testing](#contributing--testing)
87
- - [License](#license)
88
-
89
- ### Implementations
90
-
91
- #### ECDSA signatures over secp256k1 and others
92
59
 
93
- ```ts
94
- import { secp256k1 } from '@noble/curves/secp256k1.js';
95
- // import { p256 } from '@noble/curves/nist.js'; // or p384 / p521
96
-
97
- const priv = secp256k1.utils.randomPrivateKey();
98
- const pub = secp256k1.getPublicKey(priv);
99
- const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa
100
- const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available
101
- const isValid = secp256k1.verify(sig, msg, pub) === true;
60
+ // hash-to-curve
61
+ import { secp256k1_hasher } from '@noble/curves/secp256k1.js';
62
+ import { p256_hasher, p384_hasher, p521_hasher } from '@noble/curves/nist.js';
63
+ import { ristretto255_hasher } from '@noble/curves/ed25519.js';
64
+ import { decaf448_hasher } from '@noble/curves/ed448.js';
102
65
 
103
- // hex strings are also supported besides Uint8Array-s:
104
- const privHex = '46c930bc7bb4db7f55da20798697421b98c4175a52c630294d75a84b9c126236';
105
- const pub2 = secp256k1.getPublicKey(privHex);
66
+ // OPRFs
67
+ import { p256_oprf, p384_oprf, p521_oprf } from '@noble/curves/nist.js';
68
+ import { ristretto255_oprf } from '@noble/curves/ed25519.js';
69
+ import { decaf448_orpf } from '@noble/curves/ed448.js';
106
70
 
107
- // public key recovery
108
- // let sig = secp256k1.Signature.fromCompact(sigHex); // or .fromDER(sigDERHex)
109
- // sig = sig.addRecoveryBit(bit); // bit is not serialized into compact / der format
110
- sig.recoverPublicKey(msg).toRawBytes(); // === pub; // public key recovery
71
+ // utils
72
+ import { weierstrass, ecdsa } from '@noble/curves/abstract/weierstrass.js';
73
+ import { edwards, eddsa } from '@noble/curves/abstract/edwards.js';
74
+ import { poseidon, poseidonSponge } from '@noble/curves/abstract/poseidon.js';
75
+ import { Field, mod, pow } from '@noble/curves/abstract/modular.js';
76
+ import { FFT, poly } from '@noble/curves/abstract/fft.js';
77
+ import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils.js';
111
78
  ```
112
79
 
113
- The same code would work for NIST P256 (secp256r1), P384 (secp384r1) & P521 (secp521r1).
114
-
115
- #### Hedged ECDSA with noise
116
-
117
- ```ts
118
- const noisySignature = secp256k1.sign(msg, priv, { extraEntropy: true });
119
- const ent = new Uint8Array(32).fill(3); // set custom entropy
120
- const noisySignature2 = secp256k1.sign(msg, priv, { extraEntropy: ent });
121
- ```
122
80
 
123
- Hedged ECDSA is add-on, providing improved protection against fault attacks.
124
- It adds noise to signatures. The technique is used by default in BIP340; we also implement them
125
- optionally for ECDSA. Check out blog post
126
- [Deterministic signatures are not your friends](https://paulmillr.com/posts/deterministic-signatures/)
127
- and [spec draft](https://datatracker.ietf.org/doc/draft-irtf-cfrg-det-sigs-with-noise/).
81
+ ### ECDSA, EdDSA, Schnorr signatures
128
82
 
129
- #### ECDH: Diffie-Hellman shared secrets
83
+ #### secp256k1, p256, p384, p521, ed25519, ed448
130
84
 
131
- ```ts
132
- const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
133
- const shared = secp256k1.getSharedSecret(priv, someonesPub);
134
- // NOTE:
135
- // - `shared` includes parity byte: strip it using shared.slice(1)
136
- // - `shared` is not hashed: more secure way is sha256(shared) or hkdf(shared)
137
- ```
138
-
139
- #### secp256k1 Schnorr signatures from BIP340
140
-
141
- ```ts
142
- import { schnorr } from '@noble/curves/secp256k1.js';
143
- const priv = schnorr.utils.randomPrivateKey();
144
- const pub = schnorr.getPublicKey(priv);
145
- const msg = new TextEncoder().encode('hello');
146
- const sig = schnorr.sign(msg, priv);
147
- const isValid = schnorr.verify(sig, msg, pub);
148
- ```
85
+ ```js
86
+ import { secp256k1, schnorr } from '@noble/curves/secp256k1.js';
87
+ import { p256, p384, p521 } from '@noble/curves/nist.js';
88
+ import { ed25519 } from '@noble/curves/ed25519.js';
89
+ import { ed448 } from '@noble/curves/ed448.js';
149
90
 
150
- #### ed25519
91
+ import { hexToBytes, utf8ToBytes } from '@noble/curves/utils.js';
151
92
 
152
- ```ts
153
- import { ed25519 } from '@noble/curves/ed25519.js';
154
- const priv = ed25519.utils.randomPrivateKey();
155
- const pub = ed25519.getPublicKey(priv);
156
- const msg = new TextEncoder().encode('hello');
157
- const sig = ed25519.sign(msg, priv);
158
- ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215
159
- ed25519.verify(sig, msg, pub, { zip215: false }); // SBS / e-voting / RFC8032 / FIPS 186-5
93
+ for (const curve of [secp256k1, schnorr, p256, p384, p521, ed25519, ed448]) {
94
+ const { secretKey, publicKey } = curve.keygen();
95
+ const msg = utf8ToBytes('hello noble');
96
+ const sig = curve.sign(msg, secretKey);
97
+ const isValid = curve.verify(sig, msg, publicKey);
98
+ console.log(curve, secretKey, publicKey, sig);
99
+ }
160
100
 
161
- // Variants from RFC8032: with context, prehashed
162
- import { ed25519ctx, ed25519ph } from '@noble/curves/ed25519.js';
101
+ // Specific private key
102
+ const priv2 = hexToBytes('46c930bc7bb4db7f55da20798697421b98c4175a52c630294d75a84b9c126236');
103
+ const pub2 = secp256k1.getPublicKey(priv2);
163
104
  ```
164
105
 
165
- Default `verify` behavior follows ZIP215 and
166
- can be used in consensus-critical applications.
167
- If you need SBS (Strongly Binding Signatures) and FIPS 186-5 compliance,
168
- use `zip215: false`. Check out [Edwards Signatures section for more info](#edwards-twisted-edwards-curve).
169
- Both options have SUF-CMA (strong unforgeability under chosen message attacks).
106
+ - We provide NIST P256 (same as secp256r1 / prime256v1), P384 (secp384r1) & P521 (secp521r1),
107
+ their hash-to-curve methods, and OPRFs.
108
+ - ECDSA signatures conform to ....
109
+ - EdDSA conform to RFC8032.
110
+ - Schnorr is only available for secp256k1 and conforms to BIP340.
170
111
 
171
- #### X25519
112
+ #### ristretto255, decaf448
172
113
 
173
114
  ```ts
174
- // X25519 aka ECDH on Curve25519 from [RFC7748](https://www.rfc-editor.org/rfc/rfc7748)
175
- import { x25519 } from '@noble/curves/ed25519.js';
176
- const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4';
177
- const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c';
178
- x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases
179
- x25519.getPublicKey(priv) === x25519.scalarMultBase(priv);
180
- x25519.getPublicKey(x25519.utils.randomPrivateKey());
181
-
182
- // ed25519 => x25519 conversion
183
- import { edwardsToMontgomeryPub, edwardsToMontgomeryPriv } from '@noble/curves/ed25519.js';
184
- edwardsToMontgomeryPub(ed25519.getPublicKey(ed25519.utils.randomPrivateKey()));
185
- edwardsToMontgomeryPriv(ed25519.utils.randomPrivateKey());
186
- ```
187
-
188
- #### ristretto255
115
+ import { ristretto255, ristretto255_hasher, ristretto255_oprf } from '@noble/curves/ed25519.js';
116
+ import { decaf448, decaf448_hasher, decaf448_oprf } from '@noble/curves/ed448.js';
189
117
 
190
- ```ts
191
118
  import { sha512 } from '@noble/hashes/sha2.js';
192
- import {
193
- hashToCurve,
194
- encodeToCurve,
195
- RistrettoPoint,
196
- hashToRistretto255,
197
- } from '@noble/curves/ed25519.js';
119
+ import { shake256 } from '@noble/hashes/sha3.js';
198
120
 
199
121
  const msg = new TextEncoder().encode('Ristretto is traditionally a short shot of espresso coffee');
200
122
  hashToCurve(msg);
201
123
 
202
- const rp = RistrettoPoint.fromHex(
203
- '6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919'
124
+ const dp = DecafPoint.fromHex(
125
+ 'c898eb4f87f97c564c6fd61fc7e49689314a1f818ec85eeb3bd5514ac816d38778f69ef347a89fca817e66defdedce178c7cc709b2116e75'
204
126
  );
205
- RistrettoPoint.BASE.multiply(2n).add(rp).subtract(RistrettoPoint.BASE).toRawBytes();
206
- RistrettoPoint.ZERO.equals(dp) === false;
127
+ DecafPoint.BASE.multiply(2n).add(dp).subtract(DecafPoint.BASE).toBytes();
128
+ DecafPoint.ZERO.equals(dp) === false;
207
129
  // pre-hashed hash-to-curve
208
- RistrettoPoint.hashToCurve(sha512(msg));
130
+ DecafPoint.hashToCurve(shake256(msg, { dkLen: 112 }));
209
131
  // full hash-to-curve including domain separation tag
210
- hashToRistretto255(msg, { DST: 'ristretto255_XMD:SHA-512_R255MAP_RO_' });
132
+ hashToDecaf448(msg, { DST: 'decaf448_XOF:SHAKE256_D448MAP_RO_' });
211
133
  ```
212
134
 
213
- Check out [RFC9496](https://www.rfc-editor.org/rfc/rfc9496) more info on ristretto255.
135
+ Check out [RFC9496](https://www.rfc-editor.org/rfc/rfc9496) more info on ristretto255 & decaf448.
214
136
 
215
- #### ed448
137
+ #### Prehashed signing
216
138
 
217
- ```ts
218
- import { ed448 } from '@noble/curves/ed448.js';
219
- const priv = ed448.utils.randomPrivateKey();
220
- const pub = ed448.getPublicKey(priv);
221
- const msg = new TextEncoder().encode('whatsup');
222
- const sig = ed448.sign(msg, priv);
223
- ed448.verify(sig, msg, pub);
224
-
225
- // Variants from RFC8032: prehashed
226
- import { ed448ph } from '@noble/curves/ed448.js';
227
- ```
139
+ #### Hedged ECDSA with noise
228
140
 
229
- #### X448
141
+ #### Consensus-friendliness vs e-voting
142
+
143
+ #### webcrypto: Friendly wrapper
144
+
145
+
146
+ ```js
147
+ const sig2 = curve.sign(msg, secretKey, { prehash: false })
148
+ const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa
149
+ const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available
150
+ const isValid = secp256k1.verify(sig, msg, pub) === true;
151
+
152
+ const isValid = ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215
153
+
154
+ // SBS / e-voting / RFC8032 / FIPS 186-5
155
+ const isValidRfc = ed25519.verify(sig, msg, pub, { zip215: false });
156
+
157
+ // Variants from RFC8032: with context, prehashed
158
+ import { ed25519ctx, ed25519ph } from '@noble/curves/ed25519.js';
230
159
 
231
- ```ts
232
- // X448 aka ECDH on Curve448 from [RFC7748](https://www.rfc-editor.org/rfc/rfc7748)
233
- import { x448 } from '@noble/curves/ed448.js';
234
- x448.getSharedSecret(priv, pub) === x448.scalarMult(priv, pub); // aliases
235
- x448.getPublicKey(priv) === x448.scalarMultBase(priv);
236
160
 
237
- // ed448 => x448 conversion
238
- import { edwardsToMontgomeryPub } from '@noble/curves/ed448.js';
239
- edwardsToMontgomeryPub(ed448.getPublicKey(ed448.utils.randomPrivateKey()));
161
+ import { secp256k1 } from '@noble/curves/secp256k1.js';
162
+ // random entropy
163
+ const sigNoisy = secp256k1.sign(msg, priv, { extraEntropy: true });
164
+ // set custom entropy
165
+ const ent = new Uint8Array(32).fill(3);
166
+ const sigNoisy2 = secp256k1.sign(msg, priv, { extraEntropy: ent });
240
167
  ```
241
168
 
242
- #### decaf448
169
+ - Hedged ECDSA is add-on, providing improved protection against fault attacks.
170
+ It adds noise to signatures.
171
+ The technique is used by default in BIP340; we also implement them optionally for ECDSA.
172
+ Check out blog post [Deterministic signatures are not your friends](https://paulmillr.com/posts/deterministic-signatures/)
173
+ and [cfrg-det-sigs-with-noise draft](https://datatracker.ietf.org/doc/draft-irtf-cfrg-det-sigs-with-noise/).
174
+ - In ed25519 & ed448, default `verify` behavior follows ZIP215 and
175
+ can be used in consensus-critical applications.
176
+ If you need SBS (Strongly Binding Signatures) and FIPS 186-5 compliance,
177
+ use `zip215: false`. Check out [Edwards Signatures section for more info](#edwards-twisted-edwards-curve).
178
+ Both options have SUF-CMA (strong unforgeability under chosen message attacks).
243
179
 
244
- ```ts
245
- // decaf448 from [RFC9496](https://www.rfc-editor.org/rfc/rfc9496)
246
- import { shake256 } from '@noble/hashes/sha3.js';
247
- import { hashToCurve, encodeToCurve, DecafPoint, hashToDecaf448 } from '@noble/curves/ed448.js';
180
+ ### ECDH: Diffie-Hellman shared secrets
248
181
 
249
- const msg = new TextEncoder().encode('Ristretto is traditionally a short shot of espresso coffee');
250
- hashToCurve(msg);
182
+ ```js
183
+ import { secp256k1 } from '@noble/curves/secp256k1.js';
184
+ import { x25519 } from '@noble/curves/ed25519.js';
185
+ import { x448 } from '@noble/curves/ed448.js';
186
+ import { p256, p384, p521 } from '@noble/curves/nist.js';
251
187
 
252
- const dp = DecafPoint.fromHex(
253
- 'c898eb4f87f97c564c6fd61fc7e49689314a1f818ec85eeb3bd5514ac816d38778f69ef347a89fca817e66defdedce178c7cc709b2116e75'
254
- );
255
- DecafPoint.BASE.multiply(2n).add(dp).subtract(DecafPoint.BASE).toRawBytes();
256
- DecafPoint.ZERO.equals(dp) === false;
257
- // pre-hashed hash-to-curve
258
- DecafPoint.hashToCurve(shake256(msg, { dkLen: 112 }));
259
- // full hash-to-curve including domain separation tag
260
- hashToDecaf448(msg, { DST: 'decaf448_XOF:SHAKE256_D448MAP_RO_' });
188
+ for (const curve of [secp256k1, schnorr, x25519, x448, p256, p384, p521]) {
189
+ const alice = curve.keygen();
190
+ const bob = curve.keygen();
191
+ const sharedKey = curve.getSharedSecret(alice.secretKey, bob.publicKey);
192
+ console.log('alice', alice, 'bob', bob, 'shared', sharedKey);
193
+ }
194
+
195
+ x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases
196
+ x25519.getPublicKey(priv) === x25519.scalarMultBase(priv);
197
+ // ed25519 => x25519 conversion
198
+ import { edwardsToMontgomeryPub, edwardsToMontgomeryPriv } from '@noble/curves/ed25519.js';
199
+ edwardsToMontgomeryPub(ed25519.getPublicKey(ed25519.utils.randomPrivateKey()));
200
+ edwardsToMontgomeryPriv(ed25519.utils.randomPrivateKey());
261
201
  ```
262
202
 
263
- Check out [RFC9496](https://www.rfc-editor.org/rfc/rfc9496) more info on decaf448.
203
+ - X25519 aka ECDH on Curve25519 from [RFC7748](https://www.rfc-editor.org/rfc/rfc7748).
204
+ - X448 aka ECDH on Curve448 from [RFC7748](https://www.rfc-editor.org/rfc/rfc7748)
205
+
206
+ > [!NOTE]
207
+ > In Weierstrass curves, shared secrets include y-parity bytes. To strip it, use `key.slice(1)`.
264
208
 
265
- #### bls12-381
209
+ > [!NOTE]
210
+ > In Weierstrass curves, shared secrets are not hashed: use hashing or KDF on top, like `sha256(shared)` or `hkdf(shared)`.
211
+
212
+
213
+ ### BLS signatures, bls12-381, bn254 aka alt_bn128
266
214
 
267
215
  ```ts
268
216
  import { bls12_381 } from '@noble/curves/bls12-381.js';
@@ -311,19 +259,11 @@ const aggregatedKey = bls12_381.longSignatures.aggregatePublicKeys([
311
259
  See [abstract/bls](#bls-barreto-lynn-scott-curves).
312
260
  For example usage, check out [the implementation of BLS EVM precompiles](https://github.com/ethereumjs/ethereumjs-monorepo/blob/361f4edbc239e795a411ac2da7e5567298b9e7e5/packages/evm/src/precompiles/bls12_381/noble.ts).
313
261
 
314
- #### bn254 aka alt_bn128
315
-
316
- ```ts
317
- import { bn254 } from '@noble/curves/bn254.js';
318
-
319
- console.log(bn254.G1, bn254.G2, bn254.pairing);
320
- ```
321
-
322
- The API mirrors [BLS](#bls12-381). The curve was previously called alt_bn128.
262
+ The BN254 API mirrors [BLS](#bls12-381). The curve was previously called alt_bn128.
323
263
  The implementation is compatible with [EIP-196](https://eips.ethereum.org/EIPS/eip-196) and
324
264
  [EIP-197](https://eips.ethereum.org/EIPS/eip-197).
325
265
 
326
- We don't implement Point methods toHex / toRawBytes.
266
+ We don't implement Point methods toBytes.
327
267
  To work around this limitation, has to initialize points on their own from BigInts.
328
268
  Reason it's not implemented is because [there is no standard](https://github.com/privacy-scaling-explorations/halo2curves/issues/109).
329
269
  Points of divergence:
@@ -334,86 +274,76 @@ Points of divergence:
334
274
 
335
275
  For example usage, check out [the implementation of bn254 EVM precompiles](https://github.com/paulmillr/noble-curves/blob/3ed792f8ad9932765b84d1064afea8663a255457/test/bn254.test.js#L697).
336
276
 
337
- #### misc curves
277
+ ### Low-level math: EC Point, modular
338
278
 
339
- ```ts
279
+ ```js
280
+ import { secp256k1, schnorr } from '@noble/curves/secp256k1.js';
281
+ import { p256, p384, p521 } from '@noble/curves/nist.js';
282
+ import { ed25519, ristretto255 } from '@noble/curves/ed25519.js';
283
+ import { ed448, decaf448 } from '@noble/curves/ed448.js';
284
+ import { bls12_381 } from '@noble/curves/bls12-381.js'
285
+ import { bn254 } from '@noble/curves/bn254.js';
340
286
  import { jubjub, babyjubjub } from '@noble/curves/misc.js';
341
- ```
342
-
343
- Miscellaneous, rarely used curves are contained in the module.
344
- Jubjub curves have Fp over scalar fields of other curves. They are friendly to ZK proofs.
345
- jubjub Fp = bls n. babyjubjub Fp = bn254 n.
346
-
347
- ## Abstract API
348
-
349
- Abstract API allows to define custom curves. All arithmetics is done with JS
350
- bigints over finite fields, which is defined from `modular` sub-module.
351
- For scalar multiplication, we use
352
- [precomputed tables with w-ary non-adjacent form (wNAF)](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/).
353
- Precomputes are enabled for weierstrass and edwards BASE points of a curve.
354
- Implementations use [noble-hashes](https://github.com/paulmillr/noble-hashes).
355
- It's always possible to use different hashing library.
356
-
357
287
 
358
- ### weierstrass: Short Weierstrass curve
359
-
360
- ```js
361
- import { weierstrass } from '@noble/curves/abstract/weierstrass.js';
362
- // NIST secp192r1 aka p192. https://www.secg.org/sec2-v2.pdf
363
- const p192_CURVE = {
364
- p: 0xfffffffffffffffffffffffffffffffeffffffffffffffffn,
365
- n: 0xffffffffffffffffffffffff99def836146bc9b1b4d22831n,
366
- h: 1n,
367
- a: 0xfffffffffffffffffffffffffffffffefffffffffffffffcn,
368
- b: 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1n,
369
- Gx: 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012n,
370
- Gy: 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811n,
371
- };
372
- const p192_Point = weierstrass(p192_CURVE);
288
+ const curves = [
289
+ secp256k1, schnorr, p256, p384, p521, ed25519, ed448,
290
+ ristretto255, decaf448,
291
+ bls12_381.G1, bls12_381.G2, bn254.G1, bn254.G2,
292
+ jubjub, babyjubjub
293
+ ];
294
+ for (const curve of curves) {
295
+ const { info, Point } = curve;
296
+ const { BASE, ZERO, Fp, Fn } = Point;
297
+ const p = BASE.multiply(2n);
298
+
299
+ // Initialization
300
+ if (info.type === 'weierstrass') {
301
+ // projective (homogeneous) coordinates: (X, Y, Z) ∋ (x=X/Z, y=Y/Z)
302
+ const p_ = new Point(BASE.X, BASE.Y, BASE.Z);
303
+ } else if (info.type === 'edwards') {
304
+ // extended coordinates: (X, Y, Z, T) ∋ (x=X/Z, y=Y/Z)
305
+ const p_ = new Point(BASE.X, BASE.Y, BASE.Z, BASE.T);
306
+ }
307
+
308
+ // Math
309
+ const p1 = p.add(p);
310
+ const p2 = p.double();
311
+ const p3 = p.subtract(p);
312
+ const p4 = p.negate();
313
+ const p5 = p.multiply(451n);
314
+
315
+ // MSM (multi-scalar multiplication)
316
+ const pa = [BASE, BASE.multiply(2n), BASE.multiply(4n), BASE.multiply(8n)];
317
+ const p6 = Point.msm(pa, [3n, 5n, 7n, 11n]);
318
+ const _true3 = p6.equals(BASE.multiply(129n)); // 129*G
319
+
320
+ const pcl = p.clearCofactor();
321
+ console.log(p.isTorsionFree(), p.isSmallOrder());
322
+
323
+ const r1 = p.toBytes();
324
+ const r1_ = Point.fromBytes(r1);
325
+ const r2 = p.toAffine();
326
+ const { x, y } = r2;
327
+ const r2_ = Point.fromAffine(r2);
328
+ }
373
329
  ```
374
330
 
375
- Short Weierstrass curve's formula is `y² = x³ + ax + b`. `weierstrass`
376
- expects arguments `a`, `b`, field characteristic `p`, curve order `n`,
377
- cofactor `h` and coordinates `Gx`, `Gy` of generator point.
378
-
379
- #### Projective Weierstrass Point
331
+ #### Modular math
380
332
 
381
333
  ```js
382
- // # weierstrass Point methods
383
- // projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z)
384
- // const p = new Point(x, y, z);
385
- const p = Point.BASE;
386
- // arithmetics
387
- p.add(p).equals(p.double());
388
- p.subtract(p).equals(Point.ZERO);
389
- p.negate();
390
- p.multiply(31415n);
391
-
392
- // decoding, encoding
393
- const b = p.toBytes();
394
- const p2 = Point.fromBytes(b);
395
- // affine conversion
396
- const { x, y } = p.toAffine();
397
- const p3 = Point.fromAffine({ x, y });
398
-
399
- // Multi-scalar-multiplication (MSM) is basically `(Pa + Qb + Rc + ...)`.
400
- // It's 10-30x faster vs naive addition for large amount of points.
401
- // Pippenger algorithm is used underneath.
402
- const points = [Point.BASE, Point.BASE.multiply(2n), Point.BASE.multiply(4n), Point.BASE.multiply(8n)];
403
- Point.msm(points, [3n, 5n, 7n, 11n]).equals(Point.BASE.multiply(129n)); // 129*G
404
- ```
334
+ import { mod, invert, Field } from '@noble/curves/abstract/modular.js';
405
335
 
406
- #### ECDSA signatures
336
+ // Finite Field utils
337
+ const fp = Field(2n ** 255n - 19n); // Finite field over 2^255-19
338
+ fp.mul(591n, 932n); // multiplication
339
+ fp.pow(481n, 11024858120n); // exponentiation
340
+ fp.div(5n, 17n); // division: 5/17 mod 2^255-19 == 5 * invert(17)
341
+ fp.inv(5n); // modular inverse
342
+ fp.sqrt(21n); // square root
407
343
 
408
- ```js
409
- import { ecdsa } from '@noble/curves/abstract/weierstrass.js';
410
- import { sha256 } from '@noble/hashes/sha2.js';
411
- const p192 = ecdsa(p192_Point, sha256);
412
- const priv = p192.utils.randomPrivateKey();
413
- const pub = p192.getPublicKey(priv);
414
- const msg = sha256(new TextEncoder().encode('custom curve'));
415
- const sig = p192.sign(msg);
416
- const isValid = p192.verify(sig, msg, pub);
344
+ // Non-Field generic utils are also available
345
+ mod(21n, 10n); // 21 mod 10 == 1n; fixed version of 21 % 10
346
+ invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse
417
347
  ```
418
348
 
419
349
  ECDSA signatures:
@@ -427,61 +357,21 @@ ECDSA signatures:
427
357
  - Consider [hedged ECDSA with noise](#hedged-ecdsa-with-noise) for adding randomness into
428
358
  for signatures, to get improved security against fault attacks.
429
359
 
430
- ### edwards: Twisted Edwards curve
431
-
432
- ```ts
433
- import { edwards } from '@noble/curves/abstract/edwards.js';
434
- const ed25519_CURVE = {
435
- p: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,
436
- n: 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn,
437
- h: 8n,
438
- a: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffecn,
439
- d: 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n,
440
- Gx: 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an,
441
- Gy: 0x6666666666666666666666666666666666666666666666666666666666666658n,
442
- };
443
- const ed25519_Point = edwards(ed25519_CURVE);
444
- ```
445
-
446
- Twisted Edwards curve's formula is `ax² + y² = 1 + dx²y²`.
447
- You must specify `a`, `d`, field characteristic `p`, curve order `n` (sometimes named as `L`),
448
- cofactor `h` and coordinates `Gx`, `Gy` of generator point.
449
-
450
- #### Extended Edwards Point
451
-
452
- ```js
453
- const Point = ed25519_Point;
454
- // extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z)
455
- // const p = new Point(x, y, z, t);
456
-
457
- const p = Point.BASE;
458
- // arithmetics
459
- p.add(p).equals(p.double());
460
- p.subtract(p).equals(Point.ZERO);
461
- p.negate();
462
- p.multiply(31415n);
463
-
464
- // decoding, encoding
465
- const b = p.toBytes();
466
- const p2 = Point.fromBytes(b);
467
- // on-curve test
468
- p.assertValidity();
469
- // affine conversion
470
- const { x, y } = p.toAffine();
471
- const p3 = Point.fromAffine({ x, y });
472
- // misc
473
- const pcl = p.clearCofactor();
474
- console.log(p.isTorsionFree(), p.isSmallOrder());
475
- ```
360
+ All arithmetics is done with JS
361
+ bigints over finite fields, which is defined from `modular` sub-module.
362
+ For scalar multiplication, we use
363
+ [precomputed tables with w-ary non-adjacent form (wNAF)](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/).
364
+ Precomputes are enabled for weierstrass and edwards BASE points of a curve.
365
+ Field operations are not constant-time: they are using JS bigints, see [security](#security).
366
+ The fact is mostly irrelevant, but the important method to keep in mind is `pow`,
367
+ which may leak exponent bits, when used naïvely.
476
368
 
477
- #### EdDSA signatures
369
+ `mod.Field` is always **field over prime number**. Non-prime fields aren't supported for now.
370
+ We don't test for prime-ness for speed and because algorithms are probabilistic anyway.
371
+ Initializing a non-prime field could make your app suspectible to
372
+ DoS (infilite loop) on Tonelli-Shanks square root calculation.
478
373
 
479
- ```js
480
- const ed25519 = eddsa(ed25519_Point, { hash: sha512 });
481
- // ed25519.getPublicKey();
482
- // ed25519.sign();
483
- // ed25519.verify();
484
- ```
374
+ Unlike `mod.inv`, `mod.invertBatch` won't throw on `0`: make sure to throw an error yourself.
485
375
 
486
376
  We define ed25519, ed448; user can use custom curves with EdDSA,
487
377
  but EdDSA in general is not defined. Check out `edwards.ts` source code.
@@ -499,84 +389,98 @@ For EdDSA signatures:
499
389
  - Blockchains: transaction of amount X might also be valid for a different amount Y
500
390
  - Both modes have SUF-CMA (strong unforgeability under chosen message attacks).
501
391
 
502
- ### montgomery: Montgomery curve
392
+ ### Making custom curves
503
393
 
504
- The module contains methods for x-only ECDH on Curve25519 / Curve448 from RFC7748.
505
- Proper Elliptic Curve Points are not implemented yet.
394
+ - Short Weierstrass curve's formula is `y² = + ax + b`. `weierstrass`
395
+ expects arguments `a`, `b`, field characteristic `p`, curve order `n`,
396
+ cofactor `h` and coordinates `Gx`, `Gy` of generator point.
397
+ - Twisted Edwards curve's formula is `ax² + y² = 1 + dx²y²`.
398
+ You must specify `a`, `d`, field characteristic `p`, curve order `n` (sometimes named as `L`),
399
+ cofactor `h` and coordinates `Gx`, `Gy` of generator point.
506
400
 
507
- ### bls: Barreto-Lynn-Scott curves
401
+ #### Custom Weierstrass curve
508
402
 
509
- The module abstracts BLS (Barreto-Lynn-Scott) pairing-friendly elliptic curve construction.
510
- They allow to construct [zk-SNARKs](https://z.cash/technology/zksnarks/) and
511
- use aggregated, batch-verifiable
512
- [threshold signatures](https://medium.com/snigirev.stepan/bls-signatures-better-than-schnorr-5a7fe30ea716),
513
- using Boneh-Lynn-Shacham signature scheme.
403
+ ```js
404
+ import { weierstrass } from '@noble/curves/abstract/weierstrass.js';
405
+ // NIST secp192r1 aka p192. https://www.secg.org/sec2-v2.pdf
406
+ const p192_CURVE = {
407
+ p: 0xfffffffffffffffffffffffffffffffeffffffffffffffffn,
408
+ n: 0xffffffffffffffffffffffff99def836146bc9b1b4d22831n,
409
+ h: 1n,
410
+ a: 0xfffffffffffffffffffffffffffffffefffffffffffffffcn,
411
+ b: 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1n,
412
+ Gx: 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012n,
413
+ Gy: 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811n,
414
+ };
415
+ const p192_Point = weierstrass(p192_CURVE);
416
+ ```
514
417
 
515
- The module doesn't expose `CURVE` property: use `G1.CURVE`, `G2.CURVE` instead.
516
- Only BLS12-381 is currently implemented.
517
- Defining BLS12-377 and BLS24 should be straightforward.
418
+ #### Custom Edwards curve
518
419
 
519
- The default BLS uses short public keys (with public keys in G1 and signatures in G2).
520
- Short signatures (public keys in G2 and signatures in G1) are also supported.
420
+ ```js
421
+ import { edwards } from '@noble/curves/abstract/edwards.js';
422
+ const ed25519_CURVE = {
423
+ p: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,
424
+ n: 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn,
425
+ h: 8n,
426
+ a: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffecn,
427
+ d: 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n,
428
+ Gx: 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an,
429
+ Gy: 0x6666666666666666666666666666666666666666666666666666666666666658n,
430
+ };
431
+ const ed25519_Point = edwards(ed25519_CURVE);
432
+ ```
521
433
 
522
- ### hash-to-curve: Hashing strings to curve points
434
+ #### Custom ECDSA, requires curve and hash
523
435
 
524
- The module allows to hash arbitrary strings to elliptic curve points. Implements [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380).
436
+ ```js
437
+ import { ecdsa } from '@noble/curves/abstract/weierstrass.js';
438
+ import { sha256 } from '@noble/hashes/sha2.js';
439
+ const p192 = ecdsa(p192_Point, sha256);
440
+ const p192_sha224 = ecdsa(p192.Point, sha224);
441
+ const keys = p192.keygen();
442
+ const msg = new TextEncoder().encode('custom curve');
443
+ const sig = p192.sign(msg, keys.secretKey);
444
+ const isValid = p192.verify(sig, msg, keys.publicKey);
445
+ // const ed25519 = eddsa(ed25519_Point, { hash: sha512 });
446
+ ```
525
447
 
526
- Every curve has exported `hashToCurve` and `encodeToCurve` methods. You should always prefer `hashToCurve` for security:
448
+ ### hash-to-curve: hashing to curve points
527
449
 
528
450
  ```ts
529
- import { hashToCurve, encodeToCurve } from '@noble/curves/secp256k1.js';
530
- import { randomBytes } from '@noble/hashes/utils.js';
531
- hashToCurve('0102abcd');
532
- console.log(hashToCurve(randomBytes()));
533
- console.log(encodeToCurve(randomBytes()));
451
+ import { secp256k1_hasher } from '@noble/curves/secp256k1.js';
452
+ import { p256_hasher, p384_hasher, p521_hasher } from '@noble/curves/nist.js';
453
+ import { ristretto255_hasher } from '@noble/curves/ed25519.js';
454
+ import { decaf448_hasher } from '@noble/curves/ed448.js';
534
455
 
535
456
  import { bls12_381 } from '@noble/curves/bls12-381.js';
536
457
  bls12_381.G1.hashToCurve(randomBytes(), { DST: 'another' });
537
458
  bls12_381.G2.hashToCurve(randomBytes(), { DST: 'custom' });
459
+
460
+ import { expand_message_xmd, expand_message_xof, hash_to_field } from '@noble/curves/abstract/hash-to-curve.js';
538
461
  ```
539
462
 
540
- Low-level methods from the spec:
463
+ The module allows to hash arbitrary strings to elliptic curve points. Implements [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380).
541
464
 
542
- ```ts
543
- // produces a uniformly random byte string using a cryptographic hash function H that outputs b bits.
544
- function expand_message_xmd(
545
- msg: Uint8Array,
546
- DST: Uint8Array,
547
- lenInBytes: number,
548
- H: CHash // For CHash see abstract/weierstrass docs section
549
- ): Uint8Array;
550
- // produces a uniformly random byte string using an extendable-output function (XOF) H.
551
- function expand_message_xof(
552
- msg: Uint8Array,
553
- DST: Uint8Array,
554
- lenInBytes: number,
555
- k: number,
556
- H: CHash
557
- ): Uint8Array;
558
- // Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F
559
- function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][];
560
-
561
- /**
562
- * * `DST` is a domain separation tag, defined in section 2.2.5
563
- * * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m
564
- * * `m` is extension degree (1 for prime fields)
565
- * * `k` is the target security target in bits (e.g. 128), from section 5.1
566
- * * `expand` is `xmd` (SHA2, SHA3, BLAKE) or `xof` (SHAKE, BLAKE-XOF)
567
- * * `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props
568
- */
569
- type UnicodeOrBytes = string | Uint8Array;
570
- type Opts = {
571
- DST: UnicodeOrBytes;
572
- p: bigint;
573
- m: number;
574
- k: number;
575
- expand?: 'xmd' | 'xof';
576
- hash: CHash;
577
- };
465
+ Every curve has exported `hashToCurve` and `encodeToCurve` methods. You should always prefer `hashToCurve` for security:
466
+
467
+ ### oprf: oblivious pseudorandom functions
468
+
469
+ ```js
470
+ import { p256_oprf, p384_oprf, p521_oprf } from '@noble/curves/nist.js';
471
+ import { ristretto255_oprf } from '@noble/curves/ed25519.js';
472
+ import { decaf448_orpf } from '@noble/curves/ed448.js';
578
473
  ```
579
474
 
475
+ We provide OPRFs, conforming to [RFC 9497](https://www.rfc-editor.org/rfc/rfc9497).
476
+
477
+ OPRF allows to interactively create an `Output = PRF(Input, serverSecretKey)`:
478
+
479
+ - Server cannot calculate Output by itself: it doesn't know Input
480
+ - Client cannot calculate Output by itself: it doesn't know server secretKey
481
+ - An attacker interception the communication can't restore Input/Output/serverSecretKey and can't
482
+ link Input to some value.
483
+
580
484
  ### poseidon: Poseidon hash
581
485
 
582
486
  Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash:
@@ -611,36 +515,6 @@ const permutation = poseidon.poseidon(opts);
611
515
  const sponge = poseidon.poseidonSponge(opts); // use carefully, not specced
612
516
  ```
613
517
 
614
- ### modular: Modular arithmetics utilities
615
-
616
- ```ts
617
- import * as mod from '@noble/curves/abstract/modular.js';
618
-
619
- // Finite Field utils
620
- const fp = mod.Field(2n ** 255n - 19n); // Finite field over 2^255-19
621
- fp.mul(591n, 932n); // multiplication
622
- fp.pow(481n, 11024858120n); // exponentiation
623
- fp.div(5n, 17n); // division: 5/17 mod 2^255-19 == 5 * invert(17)
624
- fp.inv(5n); // modular inverse
625
- fp.sqrt(21n); // square root
626
-
627
- // Non-Field generic utils are also available
628
- mod.mod(21n, 10n); // 21 mod 10 == 1n; fixed version of 21 % 10
629
- mod.invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse
630
- mod.invertBatch([1n, 2n, 4n], 21n); // => [1n, 11n, 16n] in one inversion
631
- ```
632
-
633
- Field operations are not constant-time: they are using JS bigints, see [security](#security).
634
- The fact is mostly irrelevant, but the important method to keep in mind is `pow`,
635
- which may leak exponent bits, when used naïvely.
636
-
637
- `mod.Field` is always **field over prime number**. Non-prime fields aren't supported for now.
638
- We don't test for prime-ness for speed and because algorithms are probabilistic anyway.
639
- Initializing a non-prime field could make your app suspectible to
640
- DoS (infilite loop) on Tonelli-Shanks square root calculation.
641
-
642
- Unlike `mod.inv`, `mod.invertBatch` won't throw on `0`: make sure to throw an error yourself.
643
-
644
518
  ### fft: Fast Fourier Transform
645
519
 
646
520
  Experimental implementation of NTT / FFT (Fast Fourier Transform) over finite fields.
@@ -650,30 +524,7 @@ API may change at any time. The code has not been audited. Feature requests are
650
524
  import * as fft from '@noble/curves/abstract/fft.js';
651
525
  ```
652
526
 
653
- #### Creating private keys from hashes
654
-
655
- You can't simply make a 32-byte private key from a 32-byte hash.
656
- Doing so will make the key [biased](https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/).
657
-
658
- To make the bias negligible, we follow [FIPS 186-5 A.2](https://csrc.nist.gov/publications/detail/fips/186/5/final)
659
- and [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380#section-5.2).
660
- This means, for 32-byte key, we would need 48-byte hash to get 2^-128 bias, which matches curve security level.
661
-
662
- `hashToPrivateScalar()` that hashes to **private key** was created for this purpose.
663
- Use [abstract/hash-to-curve](#hash-to-curve-hashing-strings-to-curve-points)
664
- if you need to hash to **public key**.
665
-
666
- ```ts
667
- import { p256 } from '@noble/curves/nist.js';
668
- import { sha256 } from '@noble/hashes/sha2.js';
669
- import { hkdf } from '@noble/hashes/hkdf.js';
670
- import * as mod from '@noble/curves/abstract/modular.js';
671
- const someKey = new Uint8Array(32).fill(2); // Needs to actually be random, not .fill(2)
672
- const derived = hkdf(sha256, someKey, undefined, 'application', 48); // 48 bytes for 32-byte priv
673
- const validPrivateKey = mod.hashToPrivateScalar(derived, p256.CURVE.n);
674
- ```
675
-
676
- ### utils: Useful utilities
527
+ ### utils: byte shuffling, conversion
677
528
 
678
529
  ```ts
679
530
  import * as utils from '@noble/curves/abstract/utils.js';
@@ -693,11 +544,6 @@ utils.nLength(255n);
693
544
  utils.equalBytes(Uint8Array.from([0xde]), Uint8Array.from([0xde]));
694
545
  ```
695
546
 
696
- ### Unreleased bits
697
-
698
- - `test/unreleased-xeddsa.ts` contains implementation of XEd25519, defined by Signal
699
- - `test/misc/endomorphism.js` contains tool for generation of endomorphism params for Koblitz curves
700
-
701
547
  ## Security
702
548
 
703
549
  The library has been independently audited:
@@ -723,7 +569,7 @@ The library has been independently audited:
723
569
  - The audit has been funded by [Ryan Shea](https://www.shea.io)
724
570
 
725
571
  It is tested against property-based, cross-library and Wycheproof vectors,
726
- and is being fuzzed in [the separate repo](https://github.com/paulmillr/fuzzing).
572
+ and is being fuzzed in [the separate repo](https://github.com/paulmillr/integration-tests).
727
573
 
728
574
  If you see anything unusual: investigate and report.
729
575