@noble/curves 1.9.1 → 1.9.3
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.
- package/README.md +238 -227
- package/_shortw_utils.d.ts +8 -5
- package/_shortw_utils.d.ts.map +1 -1
- package/_shortw_utils.js +3 -8
- package/_shortw_utils.js.map +1 -1
- package/abstract/bls.d.ts +123 -62
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +219 -163
- package/abstract/bls.js.map +1 -1
- package/abstract/curve.d.ts +142 -21
- package/abstract/curve.d.ts.map +1 -1
- package/abstract/curve.js +224 -143
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.d.ts +190 -49
- package/abstract/edwards.d.ts.map +1 -1
- package/abstract/edwards.js +322 -136
- package/abstract/edwards.js.map +1 -1
- package/abstract/fft.d.ts +12 -10
- package/abstract/fft.d.ts.map +1 -1
- package/abstract/fft.js +12 -13
- package/abstract/fft.js.map +1 -1
- package/abstract/hash-to-curve.d.ts +31 -13
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +34 -19
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.d.ts +31 -13
- package/abstract/modular.d.ts.map +1 -1
- package/abstract/modular.js +125 -52
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts +18 -5
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +23 -6
- package/abstract/montgomery.js.map +1 -1
- package/abstract/poseidon.d.ts +5 -13
- package/abstract/poseidon.d.ts.map +1 -1
- package/abstract/poseidon.js +12 -7
- package/abstract/poseidon.js.map +1 -1
- package/abstract/tower.d.ts +23 -49
- package/abstract/tower.d.ts.map +1 -1
- package/abstract/tower.js +9 -3
- package/abstract/tower.js.map +1 -1
- package/abstract/utils.d.ts +1 -115
- package/abstract/utils.d.ts.map +1 -1
- package/abstract/utils.js +17 -371
- package/abstract/utils.js.map +1 -1
- package/abstract/weierstrass.d.ts +206 -124
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +747 -604
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts +2 -0
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +504 -466
- package/bls12-381.js.map +1 -1
- package/bn254.d.ts +2 -0
- package/bn254.d.ts.map +1 -1
- package/bn254.js +44 -32
- package/bn254.js.map +1 -1
- package/ed25519.d.ts +55 -66
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +172 -186
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +60 -57
- package/ed448.d.ts.map +1 -1
- package/ed448.js +172 -166
- package/ed448.js.map +1 -1
- package/esm/_shortw_utils.d.ts +8 -5
- package/esm/_shortw_utils.d.ts.map +1 -1
- package/esm/_shortw_utils.js +3 -8
- package/esm/_shortw_utils.js.map +1 -1
- package/esm/abstract/bls.d.ts +123 -62
- package/esm/abstract/bls.d.ts.map +1 -1
- package/esm/abstract/bls.js +220 -164
- package/esm/abstract/bls.js.map +1 -1
- package/esm/abstract/curve.d.ts +142 -21
- package/esm/abstract/curve.d.ts.map +1 -1
- package/esm/abstract/curve.js +219 -143
- package/esm/abstract/curve.js.map +1 -1
- package/esm/abstract/edwards.d.ts +190 -49
- package/esm/abstract/edwards.d.ts.map +1 -1
- package/esm/abstract/edwards.js +320 -138
- package/esm/abstract/edwards.js.map +1 -1
- package/esm/abstract/fft.d.ts +12 -10
- package/esm/abstract/fft.d.ts.map +1 -1
- package/esm/abstract/fft.js +10 -11
- package/esm/abstract/fft.js.map +1 -1
- package/esm/abstract/hash-to-curve.d.ts +31 -13
- package/esm/abstract/hash-to-curve.d.ts.map +1 -1
- package/esm/abstract/hash-to-curve.js +33 -19
- package/esm/abstract/hash-to-curve.js.map +1 -1
- package/esm/abstract/modular.d.ts +31 -13
- package/esm/abstract/modular.d.ts.map +1 -1
- package/esm/abstract/modular.js +124 -51
- package/esm/abstract/modular.js.map +1 -1
- package/esm/abstract/montgomery.d.ts +18 -5
- package/esm/abstract/montgomery.d.ts.map +1 -1
- package/esm/abstract/montgomery.js +23 -6
- package/esm/abstract/montgomery.js.map +1 -1
- package/esm/abstract/poseidon.d.ts +5 -13
- package/esm/abstract/poseidon.d.ts.map +1 -1
- package/esm/abstract/poseidon.js +12 -7
- package/esm/abstract/poseidon.js.map +1 -1
- package/esm/abstract/tower.d.ts +23 -49
- package/esm/abstract/tower.d.ts.map +1 -1
- package/esm/abstract/tower.js +9 -3
- package/esm/abstract/tower.js.map +1 -1
- package/esm/abstract/utils.d.ts +1 -115
- package/esm/abstract/utils.d.ts.map +1 -1
- package/esm/abstract/utils.js +3 -344
- package/esm/abstract/utils.js.map +1 -1
- package/esm/abstract/weierstrass.d.ts +206 -124
- package/esm/abstract/weierstrass.d.ts.map +1 -1
- package/esm/abstract/weierstrass.js +743 -605
- package/esm/abstract/weierstrass.js.map +1 -1
- package/esm/bls12-381.d.ts +2 -0
- package/esm/bls12-381.d.ts.map +1 -1
- package/esm/bls12-381.js +503 -465
- package/esm/bls12-381.js.map +1 -1
- package/esm/bn254.d.ts +2 -0
- package/esm/bn254.d.ts.map +1 -1
- package/esm/bn254.js +41 -29
- package/esm/bn254.js.map +1 -1
- package/esm/ed25519.d.ts +55 -66
- package/esm/ed25519.d.ts.map +1 -1
- package/esm/ed25519.js +170 -183
- package/esm/ed25519.js.map +1 -1
- package/esm/ed448.d.ts +60 -57
- package/esm/ed448.d.ts.map +1 -1
- package/esm/ed448.js +169 -162
- package/esm/ed448.js.map +1 -1
- package/esm/index.js +7 -9
- package/esm/index.js.map +1 -1
- package/esm/jubjub.d.ts +3 -3
- package/esm/jubjub.d.ts.map +1 -1
- package/esm/jubjub.js +3 -3
- package/esm/jubjub.js.map +1 -1
- package/esm/misc.d.ts +3 -5
- package/esm/misc.d.ts.map +1 -1
- package/esm/misc.js +31 -29
- package/esm/misc.js.map +1 -1
- package/esm/nist.d.ts +7 -22
- package/esm/nist.d.ts.map +1 -1
- package/esm/nist.js +106 -101
- package/esm/nist.js.map +1 -1
- package/esm/p256.d.ts +7 -3
- package/esm/p256.d.ts.map +1 -1
- package/esm/p256.js +4 -0
- package/esm/p256.js.map +1 -1
- package/esm/p384.d.ts +7 -4
- package/esm/p384.d.ts.map +1 -1
- package/esm/p384.js +4 -1
- package/esm/p384.js.map +1 -1
- package/esm/p521.d.ts +7 -3
- package/esm/p521.d.ts.map +1 -1
- package/esm/p521.js +4 -0
- package/esm/p521.js.map +1 -1
- package/esm/secp256k1.d.ts +38 -21
- package/esm/secp256k1.d.ts.map +1 -1
- package/esm/secp256k1.js +112 -104
- package/esm/secp256k1.js.map +1 -1
- package/esm/utils.d.ts +96 -0
- package/esm/utils.d.ts.map +1 -0
- package/esm/utils.js +279 -0
- package/esm/utils.js.map +1 -0
- package/index.js +7 -9
- package/index.js.map +1 -1
- package/jubjub.d.ts +3 -3
- package/jubjub.d.ts.map +1 -1
- package/jubjub.js +3 -3
- package/jubjub.js.map +1 -1
- package/misc.d.ts +3 -5
- package/misc.d.ts.map +1 -1
- package/misc.js +35 -33
- package/misc.js.map +1 -1
- package/nist.d.ts +7 -22
- package/nist.d.ts.map +1 -1
- package/nist.js +106 -101
- package/nist.js.map +1 -1
- package/p256.d.ts +7 -3
- package/p256.d.ts.map +1 -1
- package/p256.js +4 -0
- package/p256.js.map +1 -1
- package/p384.d.ts +7 -4
- package/p384.d.ts.map +1 -1
- package/p384.js +4 -1
- package/p384.js.map +1 -1
- package/p521.d.ts +7 -3
- package/p521.d.ts.map +1 -1
- package/p521.js +4 -0
- package/p521.js.map +1 -1
- package/package.json +17 -6
- package/secp256k1.d.ts +38 -21
- package/secp256k1.d.ts.map +1 -1
- package/secp256k1.js +112 -104
- package/secp256k1.js.map +1 -1
- package/src/_shortw_utils.ts +6 -15
- package/src/abstract/bls.ts +428 -251
- package/src/abstract/curve.ts +307 -149
- package/src/abstract/edwards.ts +555 -203
- package/src/abstract/fft.ts +30 -19
- package/src/abstract/hash-to-curve.ts +75 -34
- package/src/abstract/modular.ts +131 -59
- package/src/abstract/montgomery.ts +44 -15
- package/src/abstract/poseidon.ts +22 -18
- package/src/abstract/tower.ts +40 -71
- package/src/abstract/utils.ts +3 -378
- package/src/abstract/weierstrass.ts +1086 -746
- package/src/bls12-381.ts +549 -490
- package/src/bn254.ts +47 -35
- package/src/ed25519.ts +214 -216
- package/src/ed448.ts +251 -220
- package/src/index.ts +7 -9
- package/src/jubjub.ts +3 -3
- package/src/misc.ts +41 -40
- package/src/nist.ts +161 -126
- package/src/p256.ts +7 -3
- package/src/p384.ts +7 -5
- package/src/p521.ts +7 -3
- package/src/secp256k1.ts +145 -115
- package/src/utils.ts +328 -0
- package/utils.d.ts +96 -0
- package/utils.d.ts.map +1 -0
- package/utils.js +313 -0
- package/utils.js.map +1 -0
package/README.md
CHANGED
|
@@ -5,11 +5,12 @@ 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: cross-library
|
|
9
|
-
- ➰
|
|
10
|
-
- ✍️
|
|
11
|
-
- 🔖 SUF-CMA, SBS
|
|
12
|
-
-
|
|
8
|
+
- 🔍 Reliable: tested against cross-library, wycheproof and acvp vectors
|
|
9
|
+
- ➰ Weierstrass, Edwards, Montgomery curves; ECDSA, EdDSA, Schnorr, BLS signatures
|
|
10
|
+
- ✍️ ECDH, hash-to-curve, OPRF, Poseidon ZK-friendly hash
|
|
11
|
+
- 🔖 Non-repudiation (SUF-CMA, SBS) & consensus-friendliness (ZIP215) in ed25519, ed448
|
|
12
|
+
- 🥈 Optional, friendly wrapper over native WebCrypto
|
|
13
|
+
- 🪶 36KB (gzipped) including bundled hashes, 11KB for single-curve build
|
|
13
14
|
|
|
14
15
|
Curves have 4KB sister projects
|
|
15
16
|
[secp256k1](https://github.com/paulmillr/noble-secp256k1) & [ed25519](https://github.com/paulmillr/noble-ed25519).
|
|
@@ -48,14 +49,14 @@ A standalone file [noble-curves.js](https://github.com/paulmillr/noble-curves/re
|
|
|
48
49
|
|
|
49
50
|
```ts
|
|
50
51
|
// import * from '@noble/curves'; // Error: use sub-imports, to ensure small app size
|
|
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, p384, p521 } from '@noble/curves/nist';
|
|
55
|
-
import { bls12_381 } from '@noble/curves/bls12-381';
|
|
56
|
-
import { bn254 } from '@noble/curves/bn254';
|
|
57
|
-
import { jubjub, babyjubjub } from '@noble/curves/misc';
|
|
58
|
-
import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils';
|
|
52
|
+
import { secp256k1, schnorr } from '@noble/curves/secp256k1.js';
|
|
53
|
+
import { ed25519, ed25519ph, ed25519ctx, x25519 } from '@noble/curves/ed25519.js';
|
|
54
|
+
import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448.js';
|
|
55
|
+
import { p256, p384, p521 } from '@noble/curves/nist.js';
|
|
56
|
+
import { bls12_381 } from '@noble/curves/bls12-381.js';
|
|
57
|
+
import { bn254 } from '@noble/curves/bn254.js';
|
|
58
|
+
import { jubjub, babyjubjub } from '@noble/curves/misc.js';
|
|
59
|
+
import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils.js';
|
|
59
60
|
```
|
|
60
61
|
|
|
61
62
|
- [ECDSA signatures over secp256k1 and others](#ecdsa-signatures-over-secp256k1-and-others)
|
|
@@ -69,8 +70,12 @@ import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/
|
|
|
69
70
|
- [misc curves](#misc-curves)
|
|
70
71
|
- [Low-level methods](#low-level-methods)
|
|
71
72
|
- [Abstract API](#abstract-api)
|
|
72
|
-
- [weierstrass](#weierstrass-short-weierstrass-curve), [
|
|
73
|
-
- [
|
|
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)
|
|
74
79
|
- [modular](#modular-modular-arithmetics-utilities)
|
|
75
80
|
- [fft](#fft-fast-fourier-transform)
|
|
76
81
|
- [Creating private keys from hashes](#creating-private-keys-from-hashes)
|
|
@@ -86,8 +91,8 @@ import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/
|
|
|
86
91
|
#### ECDSA signatures over secp256k1 and others
|
|
87
92
|
|
|
88
93
|
```ts
|
|
89
|
-
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
90
|
-
// import { p256 } from '@noble/curves/nist'; // or p384 / p521
|
|
94
|
+
import { secp256k1 } from '@noble/curves/secp256k1.js';
|
|
95
|
+
// import { p256 } from '@noble/curves/nist.js'; // or p384 / p521
|
|
91
96
|
|
|
92
97
|
const priv = secp256k1.utils.randomPrivateKey();
|
|
93
98
|
const pub = secp256k1.getPublicKey(priv);
|
|
@@ -134,7 +139,7 @@ const shared = secp256k1.getSharedSecret(priv, someonesPub);
|
|
|
134
139
|
#### secp256k1 Schnorr signatures from BIP340
|
|
135
140
|
|
|
136
141
|
```ts
|
|
137
|
-
import { schnorr } from '@noble/curves/secp256k1';
|
|
142
|
+
import { schnorr } from '@noble/curves/secp256k1.js';
|
|
138
143
|
const priv = schnorr.utils.randomPrivateKey();
|
|
139
144
|
const pub = schnorr.getPublicKey(priv);
|
|
140
145
|
const msg = new TextEncoder().encode('hello');
|
|
@@ -145,7 +150,7 @@ const isValid = schnorr.verify(sig, msg, pub);
|
|
|
145
150
|
#### ed25519
|
|
146
151
|
|
|
147
152
|
```ts
|
|
148
|
-
import { ed25519 } from '@noble/curves/ed25519';
|
|
153
|
+
import { ed25519 } from '@noble/curves/ed25519.js';
|
|
149
154
|
const priv = ed25519.utils.randomPrivateKey();
|
|
150
155
|
const pub = ed25519.getPublicKey(priv);
|
|
151
156
|
const msg = new TextEncoder().encode('hello');
|
|
@@ -154,7 +159,7 @@ ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215
|
|
|
154
159
|
ed25519.verify(sig, msg, pub, { zip215: false }); // SBS / e-voting / RFC8032 / FIPS 186-5
|
|
155
160
|
|
|
156
161
|
// Variants from RFC8032: with context, prehashed
|
|
157
|
-
import { ed25519ctx, ed25519ph } from '@noble/curves/ed25519';
|
|
162
|
+
import { ed25519ctx, ed25519ph } from '@noble/curves/ed25519.js';
|
|
158
163
|
```
|
|
159
164
|
|
|
160
165
|
Default `verify` behavior follows ZIP215 and
|
|
@@ -167,7 +172,7 @@ Both options have SUF-CMA (strong unforgeability under chosen message attacks).
|
|
|
167
172
|
|
|
168
173
|
```ts
|
|
169
174
|
// X25519 aka ECDH on Curve25519 from [RFC7748](https://www.rfc-editor.org/rfc/rfc7748)
|
|
170
|
-
import { x25519 } from '@noble/curves/ed25519';
|
|
175
|
+
import { x25519 } from '@noble/curves/ed25519.js';
|
|
171
176
|
const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4';
|
|
172
177
|
const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c';
|
|
173
178
|
x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases
|
|
@@ -175,7 +180,7 @@ x25519.getPublicKey(priv) === x25519.scalarMultBase(priv);
|
|
|
175
180
|
x25519.getPublicKey(x25519.utils.randomPrivateKey());
|
|
176
181
|
|
|
177
182
|
// ed25519 => x25519 conversion
|
|
178
|
-
import { edwardsToMontgomeryPub, edwardsToMontgomeryPriv } from '@noble/curves/ed25519';
|
|
183
|
+
import { edwardsToMontgomeryPub, edwardsToMontgomeryPriv } from '@noble/curves/ed25519.js';
|
|
179
184
|
edwardsToMontgomeryPub(ed25519.getPublicKey(ed25519.utils.randomPrivateKey()));
|
|
180
185
|
edwardsToMontgomeryPriv(ed25519.utils.randomPrivateKey());
|
|
181
186
|
```
|
|
@@ -183,17 +188,15 @@ edwardsToMontgomeryPriv(ed25519.utils.randomPrivateKey());
|
|
|
183
188
|
#### ristretto255
|
|
184
189
|
|
|
185
190
|
```ts
|
|
186
|
-
|
|
187
|
-
import { utf8ToBytes } from '@noble/hashes/utils';
|
|
188
|
-
import { sha512 } from '@noble/hashes/sha512';
|
|
191
|
+
import { sha512 } from '@noble/hashes/sha2.js';
|
|
189
192
|
import {
|
|
190
193
|
hashToCurve,
|
|
191
194
|
encodeToCurve,
|
|
192
195
|
RistrettoPoint,
|
|
193
196
|
hashToRistretto255,
|
|
194
|
-
} from '@noble/curves/ed25519';
|
|
197
|
+
} from '@noble/curves/ed25519.js';
|
|
195
198
|
|
|
196
|
-
const msg =
|
|
199
|
+
const msg = new TextEncoder().encode('Ristretto is traditionally a short shot of espresso coffee');
|
|
197
200
|
hashToCurve(msg);
|
|
198
201
|
|
|
199
202
|
const rp = RistrettoPoint.fromHex(
|
|
@@ -207,10 +210,12 @@ RistrettoPoint.hashToCurve(sha512(msg));
|
|
|
207
210
|
hashToRistretto255(msg, { DST: 'ristretto255_XMD:SHA-512_R255MAP_RO_' });
|
|
208
211
|
```
|
|
209
212
|
|
|
213
|
+
Check out [RFC9496](https://www.rfc-editor.org/rfc/rfc9496) more info on ristretto255.
|
|
214
|
+
|
|
210
215
|
#### ed448
|
|
211
216
|
|
|
212
217
|
```ts
|
|
213
|
-
import { ed448 } from '@noble/curves/ed448';
|
|
218
|
+
import { ed448 } from '@noble/curves/ed448.js';
|
|
214
219
|
const priv = ed448.utils.randomPrivateKey();
|
|
215
220
|
const pub = ed448.getPublicKey(priv);
|
|
216
221
|
const msg = new TextEncoder().encode('whatsup');
|
|
@@ -218,19 +223,19 @@ const sig = ed448.sign(msg, priv);
|
|
|
218
223
|
ed448.verify(sig, msg, pub);
|
|
219
224
|
|
|
220
225
|
// Variants from RFC8032: prehashed
|
|
221
|
-
import { ed448ph } from '@noble/curves/ed448';
|
|
226
|
+
import { ed448ph } from '@noble/curves/ed448.js';
|
|
222
227
|
```
|
|
223
228
|
|
|
224
229
|
#### X448
|
|
225
230
|
|
|
226
231
|
```ts
|
|
227
232
|
// X448 aka ECDH on Curve448 from [RFC7748](https://www.rfc-editor.org/rfc/rfc7748)
|
|
228
|
-
import { x448 } from '@noble/curves/ed448';
|
|
233
|
+
import { x448 } from '@noble/curves/ed448.js';
|
|
229
234
|
x448.getSharedSecret(priv, pub) === x448.scalarMult(priv, pub); // aliases
|
|
230
235
|
x448.getPublicKey(priv) === x448.scalarMultBase(priv);
|
|
231
236
|
|
|
232
237
|
// ed448 => x448 conversion
|
|
233
|
-
import { edwardsToMontgomeryPub } from '@noble/curves/ed448';
|
|
238
|
+
import { edwardsToMontgomeryPub } from '@noble/curves/ed448.js';
|
|
234
239
|
edwardsToMontgomeryPub(ed448.getPublicKey(ed448.utils.randomPrivateKey()));
|
|
235
240
|
```
|
|
236
241
|
|
|
@@ -238,11 +243,10 @@ edwardsToMontgomeryPub(ed448.getPublicKey(ed448.utils.randomPrivateKey()));
|
|
|
238
243
|
|
|
239
244
|
```ts
|
|
240
245
|
// decaf448 from [RFC9496](https://www.rfc-editor.org/rfc/rfc9496)
|
|
241
|
-
import {
|
|
242
|
-
import {
|
|
243
|
-
import { hashToCurve, encodeToCurve, DecafPoint, hashToDecaf448 } from '@noble/curves/ed448';
|
|
246
|
+
import { shake256 } from '@noble/hashes/sha3.js';
|
|
247
|
+
import { hashToCurve, encodeToCurve, DecafPoint, hashToDecaf448 } from '@noble/curves/ed448.js';
|
|
244
248
|
|
|
245
|
-
const msg =
|
|
249
|
+
const msg = new TextEncoder().encode('Ristretto is traditionally a short shot of espresso coffee');
|
|
246
250
|
hashToCurve(msg);
|
|
247
251
|
|
|
248
252
|
const dp = DecafPoint.fromHex(
|
|
@@ -256,34 +260,41 @@ DecafPoint.hashToCurve(shake256(msg, { dkLen: 112 }));
|
|
|
256
260
|
hashToDecaf448(msg, { DST: 'decaf448_XOF:SHAKE256_D448MAP_RO_' });
|
|
257
261
|
```
|
|
258
262
|
|
|
263
|
+
Check out [RFC9496](https://www.rfc-editor.org/rfc/rfc9496) more info on decaf448.
|
|
264
|
+
|
|
259
265
|
#### bls12-381
|
|
260
266
|
|
|
261
267
|
```ts
|
|
262
|
-
import { bls12_381
|
|
263
|
-
|
|
264
|
-
// G1 keys, G2 signatures
|
|
265
|
-
const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c';
|
|
266
|
-
const message = '64726e3da8';
|
|
267
|
-
const publicKey = bls.getPublicKey(privateKey);
|
|
268
|
-
const signature = bls.sign(message, privateKey);
|
|
269
|
-
const isValid = bls.verify(signature, message, publicKey);
|
|
270
|
-
console.log({ publicKey, signature, isValid });
|
|
268
|
+
import { bls12_381 } from '@noble/curves/bls12-381.js';
|
|
269
|
+
import { hexToBytes } from '@noble/curves/abstract/utils.js';
|
|
271
270
|
|
|
272
|
-
//
|
|
273
|
-
|
|
274
|
-
//
|
|
275
|
-
// verifyShortSignature(signature, message, publicKey)
|
|
276
|
-
// aggregateShortSignatures(signatures)
|
|
271
|
+
// private keys are 32 bytes
|
|
272
|
+
const privKey = hexToBytes('67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c');
|
|
273
|
+
// const privKey = bls12_381.utils.randomPrivateKey();
|
|
277
274
|
|
|
278
|
-
//
|
|
279
|
-
const
|
|
280
|
-
const
|
|
281
|
-
|
|
275
|
+
// Long signatures (G2), short public keys (G1)
|
|
276
|
+
const blsl = bls12_381.longSignatures;
|
|
277
|
+
const publicKey = blsl.getPublicKey(privateKey);
|
|
278
|
+
// Sign msg with custom (Ethereum) DST
|
|
279
|
+
const msg = new TextEncoder().encode('hello');
|
|
280
|
+
const DST = 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_';
|
|
281
|
+
const msgp = blsl.hash(msg, DST);
|
|
282
|
+
const signature = blsl.sign(msgp, privateKey);
|
|
283
|
+
const isValid = blsl.verify(signature, msgp, publicKey);
|
|
284
|
+
console.log({ publicKey, signature, isValid });
|
|
285
|
+
|
|
286
|
+
// Short signatures (G1), long public keys (G2)
|
|
287
|
+
const blss = bls12_381.shortSignatures;
|
|
288
|
+
const publicKey2 = blss.getPublicKey(privateKey);
|
|
289
|
+
const msgp2 = blss.hash(new TextEncoder().encode('hello'), 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_')
|
|
290
|
+
const signature2 = blss.sign(msgp2, privateKey);
|
|
291
|
+
const isValid2 = blss.verify(signature2, msgp2, publicKey);
|
|
292
|
+
console.log({ publicKey2, signature2, isValid2 });
|
|
282
293
|
|
|
283
294
|
// Aggregation
|
|
284
|
-
const aggregatedKey =
|
|
285
|
-
|
|
286
|
-
|
|
295
|
+
const aggregatedKey = bls12_381.longSignatures.aggregatePublicKeys([
|
|
296
|
+
bls12_381.utils.randomPrivateKey(),
|
|
297
|
+
bls12_381.utils.randomPrivateKey(),
|
|
287
298
|
]);
|
|
288
299
|
// const aggregatedSig = bls.aggregateSignatures(sigs)
|
|
289
300
|
|
|
@@ -303,7 +314,7 @@ For example usage, check out [the implementation of BLS EVM precompiles](https:/
|
|
|
303
314
|
#### bn254 aka alt_bn128
|
|
304
315
|
|
|
305
316
|
```ts
|
|
306
|
-
import { bn254 } from '@noble/curves/bn254';
|
|
317
|
+
import { bn254 } from '@noble/curves/bn254.js';
|
|
307
318
|
|
|
308
319
|
console.log(bn254.G1, bn254.G2, bn254.pairing);
|
|
309
320
|
```
|
|
@@ -326,109 +337,89 @@ For example usage, check out [the implementation of bn254 EVM precompiles](https
|
|
|
326
337
|
#### misc curves
|
|
327
338
|
|
|
328
339
|
```ts
|
|
329
|
-
import { jubjub, babyjubjub } from '@noble/curves/misc';
|
|
340
|
+
import { jubjub, babyjubjub } from '@noble/curves/misc.js';
|
|
330
341
|
```
|
|
331
342
|
|
|
332
343
|
Miscellaneous, rarely used curves are contained in the module.
|
|
333
344
|
Jubjub curves have Fp over scalar fields of other curves. They are friendly to ZK proofs.
|
|
334
345
|
jubjub Fp = bls n. babyjubjub Fp = bn254 n.
|
|
335
346
|
|
|
336
|
-
#### Low-level methods
|
|
337
|
-
|
|
338
|
-
```ts
|
|
339
|
-
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
340
|
-
|
|
341
|
-
// Curve's variables
|
|
342
|
-
// Every curve has `CURVE` object that contains its parameters, field, and others
|
|
343
|
-
console.log(secp256k1.CURVE.p); // field modulus
|
|
344
|
-
console.log(secp256k1.CURVE.n); // curve order
|
|
345
|
-
console.log(secp256k1.CURVE.a, secp256k1.CURVE.b); // equation params
|
|
346
|
-
console.log(secp256k1.CURVE.Gx, secp256k1.CURVE.Gy); // base point coordinates
|
|
347
|
-
|
|
348
|
-
// MSM
|
|
349
|
-
const p = secp256k1.ProjectivePoint;
|
|
350
|
-
const points = [p.BASE, p.BASE.multiply(2n), p.BASE.multiply(4n), p.BASE.multiply(8n)];
|
|
351
|
-
p.msm(points, [3n, 5n, 7n, 11n]).equals(p.BASE.multiply(129n)); // 129*G
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
Multi-scalar-multiplication (MSM) is basically `(Pa + Qb + Rc + ...)`.
|
|
355
|
-
It's 10-30x faster vs naive addition for large amount of points.
|
|
356
|
-
Pippenger algorithm is used underneath.
|
|
357
|
-
|
|
358
347
|
## Abstract API
|
|
359
348
|
|
|
360
|
-
Implementations use [noble-hashes](https://github.com/paulmillr/noble-hashes).
|
|
361
|
-
If you want to use a different hashing library, abstract API doesn't depend on them.
|
|
362
|
-
|
|
363
349
|
Abstract API allows to define custom curves. All arithmetics is done with JS
|
|
364
|
-
bigints over finite fields, which is defined from `modular` sub-module.
|
|
365
|
-
scalar multiplication, we use
|
|
350
|
+
bigints over finite fields, which is defined from `modular` sub-module.
|
|
351
|
+
For scalar multiplication, we use
|
|
366
352
|
[precomputed tables with w-ary non-adjacent form (wNAF)](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/).
|
|
367
|
-
Precomputes are enabled for weierstrass and edwards BASE points of a curve.
|
|
368
|
-
|
|
369
|
-
|
|
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.
|
|
370
356
|
|
|
371
|
-
### weierstrass: Short Weierstrass curve
|
|
372
357
|
|
|
373
|
-
|
|
374
|
-
import { weierstrass } from '@noble/curves/abstract/weierstrass';
|
|
375
|
-
import { Field } from '@noble/curves/abstract/modular';
|
|
376
|
-
import { sha256 } from '@noble/hashes/sha256';
|
|
377
|
-
import { hmac } from '@noble/hashes/hmac';
|
|
378
|
-
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
|
379
|
-
|
|
380
|
-
const hmacSha256 = (key: Uint8Array, ...msgs: Uint8Array[]) =>
|
|
381
|
-
hmac(sha256, key, concatBytes(...msgs));
|
|
382
|
-
|
|
383
|
-
// secQ (not secP) - secq256k1 is a cycle of secp256k1 with Fp/N flipped.
|
|
384
|
-
// https://personaelabs.org/posts/spartan-ecdsa
|
|
385
|
-
// https://zcash.github.io/halo2/background/curves.html#cycles-of-curves
|
|
386
|
-
const secq256k1 = weierstrass({
|
|
387
|
-
a: 0n,
|
|
388
|
-
b: 7n,
|
|
389
|
-
Fp: Field(2n ** 256n - 432420386565659656852420866394968145599n),
|
|
390
|
-
n: 2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n,
|
|
391
|
-
Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
|
|
392
|
-
Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
|
|
393
|
-
hash: sha256,
|
|
394
|
-
hmac: hmacSha256,
|
|
395
|
-
randomBytes,
|
|
396
|
-
});
|
|
358
|
+
### weierstrass: Short Weierstrass curve
|
|
397
359
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
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,
|
|
401
367
|
a: 0xfffffffffffffffffffffffffffffffefffffffffffffffcn,
|
|
402
368
|
b: 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1n,
|
|
403
|
-
Fp: Field(0xfffffffffffffffffffffffffffffffeffffffffffffffffn),
|
|
404
|
-
n: 0xffffffffffffffffffffffff99def836146bc9b1b4d22831n,
|
|
405
369
|
Gx: 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012n,
|
|
406
370
|
Gy: 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811n,
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
randomBytes,
|
|
410
|
-
});
|
|
371
|
+
};
|
|
372
|
+
const p192_Point = weierstrass(p192_CURVE);
|
|
411
373
|
```
|
|
412
374
|
|
|
413
375
|
Short Weierstrass curve's formula is `y² = x³ + ax + b`. `weierstrass`
|
|
414
|
-
expects arguments `a`, `b`, field `
|
|
415
|
-
and coordinates `Gx`, `Gy` of generator point.
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
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
|
|
380
|
+
|
|
381
|
+
```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
|
+
```
|
|
419
405
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
406
|
+
#### ECDSA signatures
|
|
407
|
+
|
|
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);
|
|
417
|
+
```
|
|
427
418
|
|
|
428
|
-
|
|
419
|
+
ECDSA signatures:
|
|
429
420
|
|
|
430
421
|
- Are represented by `Signature` instances with `r, s` and optional `recovery` properties
|
|
431
|
-
- Have `recoverPublicKey()`, `
|
|
422
|
+
- Have `recoverPublicKey()`, `toBytes()` with optional `format: 'compact' | 'der'`
|
|
432
423
|
- Can be prehashed, or non-prehashed:
|
|
433
424
|
- `sign(msgHash, privKey)` (default, prehash: false) - you did hashing before
|
|
434
425
|
- `sign(msg, privKey, {prehash: true})` - curves will do hashing for you
|
|
@@ -436,85 +427,66 @@ and coordinates `Gx`, `Gy` of generator point.
|
|
|
436
427
|
- Consider [hedged ECDSA with noise](#hedged-ecdsa-with-noise) for adding randomness into
|
|
437
428
|
for signatures, to get improved security against fault attacks.
|
|
438
429
|
|
|
439
|
-
More examples:
|
|
440
|
-
|
|
441
|
-
```typescript
|
|
442
|
-
// All curves expose same generic interface.
|
|
443
|
-
const priv = secq256k1.utils.randomPrivateKey();
|
|
444
|
-
secq256k1.getPublicKey(priv); // Convert private key to public.
|
|
445
|
-
const sig = secq256k1.sign(msg, priv); // Sign msg with private key.
|
|
446
|
-
const sig2 = secq256k1.sign(msg, priv, { prehash: true }); // hash(msg)
|
|
447
|
-
secq256k1.verify(sig, msg, priv); // Verify if sig is correct.
|
|
448
|
-
|
|
449
|
-
// Default behavior is "try DER, then try compact if fails". Can be explicit:
|
|
450
|
-
secq256k1.verify(sig.toCompactHex(), msg, priv, { format: 'compact' });
|
|
451
|
-
|
|
452
|
-
const Point = secq256k1.ProjectivePoint;
|
|
453
|
-
const point = Point.BASE; // Elliptic curve Point class and BASE point static var.
|
|
454
|
-
point.add(point).equals(point.double()); // add(), equals(), double() methods
|
|
455
|
-
point.subtract(point).equals(Point.ZERO); // subtract() method, ZERO static var
|
|
456
|
-
point.negate(); // Flips point over x/y coordinate.
|
|
457
|
-
point.multiply(31415n); // Multiplication of Point by scalar.
|
|
458
|
-
|
|
459
|
-
point.assertValidity(); // Checks for being on-curve
|
|
460
|
-
point.toAffine(); // Converts to 2d affine xy coordinates
|
|
461
|
-
|
|
462
|
-
secq256k1.CURVE.n;
|
|
463
|
-
secq256k1.CURVE.p;
|
|
464
|
-
secq256k1.CURVE.Fp.mod();
|
|
465
|
-
secq256k1.CURVE.hash();
|
|
466
|
-
|
|
467
|
-
// precomputes
|
|
468
|
-
const fast = secq256k1.utils.precompute(8, Point.fromHex(someonesPubKey));
|
|
469
|
-
fast.multiply(privKey); // much faster ECDH now
|
|
470
|
-
```
|
|
471
|
-
|
|
472
430
|
### edwards: Twisted Edwards curve
|
|
473
431
|
|
|
474
432
|
```ts
|
|
475
|
-
import {
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
const Fp = Field(2n ** 255n - 19n);
|
|
481
|
-
const ed25519 = twistedEdwards({
|
|
482
|
-
a: Fp.create(-1n),
|
|
483
|
-
d: Fp.div(-121665n, 121666n), // -121665n/121666n mod p
|
|
484
|
-
Fp: Fp,
|
|
485
|
-
n: 2n ** 252n + 27742317777372353535851937790883648493n,
|
|
433
|
+
import { edwards } from '@noble/curves/abstract/edwards.js';
|
|
434
|
+
const ed25519_CURVE = {
|
|
435
|
+
p: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,
|
|
436
|
+
n: 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn,
|
|
486
437
|
h: 8n,
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
bytes[0] &= 248;
|
|
494
|
-
bytes[31] &= 127;
|
|
495
|
-
bytes[31] |= 64;
|
|
496
|
-
return bytes;
|
|
497
|
-
},
|
|
498
|
-
} as const);
|
|
438
|
+
a: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffecn,
|
|
439
|
+
d: 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n,
|
|
440
|
+
Gx: 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an,
|
|
441
|
+
Gy: 0x6666666666666666666666666666666666666666666666666666666666666658n,
|
|
442
|
+
};
|
|
443
|
+
const ed25519_Point = edwards(ed25519_CURVE);
|
|
499
444
|
```
|
|
500
445
|
|
|
501
446
|
Twisted Edwards curve's formula is `ax² + y² = 1 + dx²y²`.
|
|
502
|
-
You must specify `a`, `d`, field `
|
|
503
|
-
and coordinates `Gx`, `Gy` of generator point.
|
|
504
|
-
|
|
505
|
-
|
|
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
|
+
```
|
|
476
|
+
|
|
477
|
+
#### EdDSA signatures
|
|
506
478
|
|
|
507
|
-
|
|
479
|
+
```js
|
|
480
|
+
const ed25519 = eddsa(ed25519_Point, { hash: sha512 });
|
|
481
|
+
// ed25519.getPublicKey();
|
|
482
|
+
// ed25519.sign();
|
|
483
|
+
// ed25519.verify();
|
|
484
|
+
```
|
|
508
485
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
- Use complete exception-free formulas for addition and doubling
|
|
512
|
-
- Can be decoded/encoded from/to Uint8Array / hex strings using `ExtendedPoint.fromHex` and `ExtendedPoint#toRawBytes()`
|
|
513
|
-
- Have `assertValidity()` which checks for being on-curve
|
|
514
|
-
- Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates
|
|
515
|
-
- Have `isTorsionFree()`, `clearCofactor()` and `isSmallOrder()` utilities to handle torsions
|
|
486
|
+
We define ed25519, ed448; user can use custom curves with EdDSA,
|
|
487
|
+
but EdDSA in general is not defined. Check out `edwards.ts` source code.
|
|
516
488
|
|
|
517
|
-
|
|
489
|
+
For EdDSA signatures:
|
|
518
490
|
|
|
519
491
|
- `zip215: true` is default behavior. It has slightly looser verification logic
|
|
520
492
|
to be [consensus-friendly](https://hdevalence.ca/blog/2020-10-04-its-25519am), following [ZIP215](https://zips.z.cash/zip-0215) rules
|
|
@@ -527,9 +499,6 @@ For EdDSA signatures, `hash` param required.
|
|
|
527
499
|
- Blockchains: transaction of amount X might also be valid for a different amount Y
|
|
528
500
|
- Both modes have SUF-CMA (strong unforgeability under chosen message attacks).
|
|
529
501
|
|
|
530
|
-
Check out [RFC9496](https://www.rfc-editor.org/rfc/rfc9496) for description of
|
|
531
|
-
ristretto and decaf groups which we implement.
|
|
532
|
-
|
|
533
502
|
### montgomery: Montgomery curve
|
|
534
503
|
|
|
535
504
|
The module contains methods for x-only ECDH on Curve25519 / Curve448 from RFC7748.
|
|
@@ -557,13 +526,13 @@ The module allows to hash arbitrary strings to elliptic curve points. Implements
|
|
|
557
526
|
Every curve has exported `hashToCurve` and `encodeToCurve` methods. You should always prefer `hashToCurve` for security:
|
|
558
527
|
|
|
559
528
|
```ts
|
|
560
|
-
import { hashToCurve, encodeToCurve } from '@noble/curves/secp256k1';
|
|
561
|
-
import { randomBytes } from '@noble/hashes/utils';
|
|
529
|
+
import { hashToCurve, encodeToCurve } from '@noble/curves/secp256k1.js';
|
|
530
|
+
import { randomBytes } from '@noble/hashes/utils.js';
|
|
562
531
|
hashToCurve('0102abcd');
|
|
563
532
|
console.log(hashToCurve(randomBytes()));
|
|
564
533
|
console.log(encodeToCurve(randomBytes()));
|
|
565
534
|
|
|
566
|
-
import { bls12_381 } from '@noble/curves/bls12-381';
|
|
535
|
+
import { bls12_381 } from '@noble/curves/bls12-381.js';
|
|
567
536
|
bls12_381.G1.hashToCurve(randomBytes(), { DST: 'another' });
|
|
568
537
|
bls12_381.G2.hashToCurve(randomBytes(), { DST: 'custom' });
|
|
569
538
|
```
|
|
@@ -615,10 +584,10 @@ permutation and sponge.
|
|
|
615
584
|
|
|
616
585
|
There are many poseidon variants with different constants.
|
|
617
586
|
We don't provide them: you should construct them manually.
|
|
618
|
-
Check out [
|
|
587
|
+
Check out [scure-starknet](https://github.com/paulmillr/scure-starknet) package for a proper example.
|
|
619
588
|
|
|
620
589
|
```ts
|
|
621
|
-
import { poseidon, poseidonSponge } from '@noble/curves/abstract/poseidon';
|
|
590
|
+
import { poseidon, poseidonSponge } from '@noble/curves/abstract/poseidon.js';
|
|
622
591
|
|
|
623
592
|
const rate = 2;
|
|
624
593
|
const capacity = 1;
|
|
@@ -645,7 +614,7 @@ const sponge = poseidon.poseidonSponge(opts); // use carefully, not specced
|
|
|
645
614
|
### modular: Modular arithmetics utilities
|
|
646
615
|
|
|
647
616
|
```ts
|
|
648
|
-
import * as mod from '@noble/curves/abstract/modular';
|
|
617
|
+
import * as mod from '@noble/curves/abstract/modular.js';
|
|
649
618
|
|
|
650
619
|
// Finite Field utils
|
|
651
620
|
const fp = mod.Field(2n ** 255n - 19n); // Finite field over 2^255-19
|
|
@@ -695,10 +664,10 @@ Use [abstract/hash-to-curve](#hash-to-curve-hashing-strings-to-curve-points)
|
|
|
695
664
|
if you need to hash to **public key**.
|
|
696
665
|
|
|
697
666
|
```ts
|
|
698
|
-
import { p256 } from '@noble/curves/nist';
|
|
699
|
-
import { sha256 } from '@noble/hashes/
|
|
700
|
-
import { hkdf } from '@noble/hashes/hkdf';
|
|
701
|
-
import * as mod from '@noble/curves/abstract/modular';
|
|
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';
|
|
702
671
|
const someKey = new Uint8Array(32).fill(2); // Needs to actually be random, not .fill(2)
|
|
703
672
|
const derived = hkdf(sha256, someKey, undefined, 'application', 48); // 48 bytes for 32-byte priv
|
|
704
673
|
const validPrivateKey = mod.hashToPrivateScalar(derived, p256.CURVE.n);
|
|
@@ -707,7 +676,7 @@ const validPrivateKey = mod.hashToPrivateScalar(derived, p256.CURVE.n);
|
|
|
707
676
|
### utils: Useful utilities
|
|
708
677
|
|
|
709
678
|
```ts
|
|
710
|
-
import * as utils from '@noble/curves/abstract/utils';
|
|
679
|
+
import * as utils from '@noble/curves/abstract/utils.js';
|
|
711
680
|
|
|
712
681
|
utils.bytesToHex(Uint8Array.from([0xde, 0xad, 0xbe, 0xef]));
|
|
713
682
|
utils.hexToBytes('deadbeef');
|
|
@@ -724,6 +693,11 @@ utils.nLength(255n);
|
|
|
724
693
|
utils.equalBytes(Uint8Array.from([0xde]), Uint8Array.from([0xde]));
|
|
725
694
|
```
|
|
726
695
|
|
|
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
|
+
|
|
727
701
|
## Security
|
|
728
702
|
|
|
729
703
|
The library has been independently audited:
|
|
@@ -763,6 +737,30 @@ constant-timeness_. Even statically typed Rust, a language without GC,
|
|
|
763
737
|
for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones.
|
|
764
738
|
Use low-level libraries & languages.
|
|
765
739
|
|
|
740
|
+
### Memory dumping
|
|
741
|
+
|
|
742
|
+
Use low-level languages instead of JS / WASM if your goal is absolute security.
|
|
743
|
+
|
|
744
|
+
The library mostly uses Uint8Arrays and bigints.
|
|
745
|
+
|
|
746
|
+
- Uint8Arrays have `.fill(0)` which instructs to fill content with zeroes
|
|
747
|
+
but there are no guarantees in JS
|
|
748
|
+
- bigints are immutable and don't have a method to zeroize their content:
|
|
749
|
+
a user needs to wait until the next garbage collection cycle
|
|
750
|
+
- hex strings are also immutable: there is no way to zeroize them
|
|
751
|
+
- `await fn()` will write all internal variables to memory. With
|
|
752
|
+
async functions there are no guarantees when the code
|
|
753
|
+
chunk would be executed. Which means attacker can have
|
|
754
|
+
plenty of time to read data from memory.
|
|
755
|
+
|
|
756
|
+
This means some secrets could stay in memory longer than anticipated.
|
|
757
|
+
However, if an attacker can read application memory, it's doomed anyway:
|
|
758
|
+
there is no way to guarantee anything about zeroizing sensitive data without
|
|
759
|
+
complex tests-suite which will dump process memory and verify that there is
|
|
760
|
+
no sensitive data left. For JS it means testing all browsers (including mobile).
|
|
761
|
+
And, of course, it will be useless without using the same
|
|
762
|
+
test-suite in the actual application that consumes the library.
|
|
763
|
+
|
|
766
764
|
### Supply chain security
|
|
767
765
|
|
|
768
766
|
- **Commits** are signed with PGP keys, to prevent forgery. Make sure to verify commit signatures
|
|
@@ -807,10 +805,12 @@ NIST prohibits classical cryptography (RSA, DSA, ECDSA, ECDH) [after 2035](https
|
|
|
807
805
|
npm run bench:install && npm run bench
|
|
808
806
|
```
|
|
809
807
|
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
808
|
+
noble-curves spends 10+ ms to generate 20MB+ of base point precomputes.
|
|
809
|
+
This is done **one-time** per curve.
|
|
810
|
+
|
|
811
|
+
The generation is deferred until any method (pubkey, sign, verify) is called.
|
|
812
|
+
User can force precompute generation by manually calling `Point.BASE.precompute(windowSize, false)`.
|
|
813
|
+
Check out the source code.
|
|
814
814
|
|
|
815
815
|
Benchmark results on Apple M4:
|
|
816
816
|
|
|
@@ -915,6 +915,17 @@ aggregateSignatures/2048 x 0 ops/sec @ 2823ms/op
|
|
|
915
915
|
|
|
916
916
|
## Upgrading
|
|
917
917
|
|
|
918
|
+
Supported node.js versions:
|
|
919
|
+
|
|
920
|
+
- v2: v20.19+ (ESM-only)
|
|
921
|
+
- v1: v14.21+ (ESM & CJS)
|
|
922
|
+
|
|
923
|
+
### curves v1 => curves v2
|
|
924
|
+
|
|
925
|
+
WIP. Changelog of v2, when upgrading from curves v1.
|
|
926
|
+
|
|
927
|
+
### noble-secp256k1 v1 => curves v1
|
|
928
|
+
|
|
918
929
|
Previously, the library was split into single-feature packages
|
|
919
930
|
[noble-secp256k1](https://github.com/paulmillr/noble-secp256k1),
|
|
920
931
|
[noble-ed25519](https://github.com/paulmillr/noble-ed25519) and
|
|
@@ -924,10 +935,6 @@ Curves continue their original work. The single-feature packages changed their
|
|
|
924
935
|
direction towards providing minimal 4kb implementations of cryptography,
|
|
925
936
|
which means they have less features.
|
|
926
937
|
|
|
927
|
-
Upgrading from noble-secp256k1 2.0 or noble-ed25519 2.0: no changes, libraries are compatible.
|
|
928
|
-
|
|
929
|
-
Upgrading from noble-secp256k1 1.7:
|
|
930
|
-
|
|
931
938
|
- `getPublicKey`
|
|
932
939
|
- now produce 33-byte compressed signatures by default
|
|
933
940
|
- to use old behavior, which produced 65-byte uncompressed keys, set
|
|
@@ -954,6 +961,8 @@ Upgrading from noble-secp256k1 1.7:
|
|
|
954
961
|
- `utils` were split into `utils` (same api as in noble-curves) and
|
|
955
962
|
`etc` (`hmacSha256Sync` and others)
|
|
956
963
|
|
|
964
|
+
### noble-ed25519 v1 => curves v1
|
|
965
|
+
|
|
957
966
|
Upgrading from [@noble/ed25519](https://github.com/paulmillr/noble-ed25519) 1.7:
|
|
958
967
|
|
|
959
968
|
- Methods are now sync by default
|
|
@@ -965,6 +974,8 @@ Upgrading from [@noble/ed25519](https://github.com/paulmillr/noble-ed25519) 1.7:
|
|
|
965
974
|
- `getSharedSecret` was moved to `x25519` module
|
|
966
975
|
- `toX25519` has been moved to `edwardsToMontgomeryPub` and `edwardsToMontgomeryPriv` methods
|
|
967
976
|
|
|
977
|
+
### noble-bls12-381 => curves v1
|
|
978
|
+
|
|
968
979
|
Upgrading from [@noble/bls12-381](https://github.com/paulmillr/noble-bls12-381):
|
|
969
980
|
|
|
970
981
|
- Methods and classes were renamed:
|