@noble/curves 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +295 -258
- package/abstract/bls.d.ts +27 -10
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +60 -10
- package/abstract/bls.js.map +1 -1
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.js.map +1 -1
- package/abstract/hash-to-curve.d.ts +2 -2
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +22 -16
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.d.ts +51 -11
- package/abstract/modular.d.ts.map +1 -1
- package/abstract/modular.js +79 -21
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +5 -7
- package/abstract/montgomery.js.map +1 -1
- package/abstract/poseidon.d.ts.map +1 -1
- package/abstract/poseidon.js +39 -41
- package/abstract/poseidon.js.map +1 -1
- package/abstract/utils.d.ts +3 -1
- package/abstract/utils.d.ts.map +1 -1
- package/abstract/utils.js +56 -31
- package/abstract/utils.js.map +1 -1
- package/abstract/weierstrass.d.ts +25 -28
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +17 -15
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +142 -88
- package/bls12-381.js.map +1 -1
- package/bn254.d.ts +3 -2
- package/bn254.d.ts.map +1 -1
- package/bn254.js +3 -2
- package/bn254.js.map +1 -1
- package/ed25519.d.ts +5 -2
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +17 -8
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +53 -2
- package/ed448.d.ts.map +1 -1
- package/ed448.js +216 -29
- package/ed448.js.map +1 -1
- package/esm/abstract/bls.js +61 -11
- package/esm/abstract/bls.js.map +1 -1
- package/esm/abstract/curve.js.map +1 -1
- package/esm/abstract/edwards.js.map +1 -1
- package/esm/abstract/hash-to-curve.js +23 -17
- package/esm/abstract/hash-to-curve.js.map +1 -1
- package/esm/abstract/modular.js +75 -20
- package/esm/abstract/modular.js.map +1 -1
- package/esm/abstract/montgomery.js +5 -7
- package/esm/abstract/montgomery.js.map +1 -1
- package/esm/abstract/poseidon.js +39 -41
- package/esm/abstract/poseidon.js.map +1 -1
- package/esm/abstract/utils.js +54 -30
- package/esm/abstract/utils.js.map +1 -1
- package/esm/abstract/weierstrass.js +17 -15
- package/esm/abstract/weierstrass.js.map +1 -1
- package/esm/bls12-381.js +143 -89
- package/esm/bls12-381.js.map +1 -1
- package/esm/bn254.js +3 -2
- package/esm/bn254.js.map +1 -1
- package/esm/ed25519.js +17 -8
- package/esm/ed25519.js.map +1 -1
- package/esm/ed448.js +218 -32
- package/esm/ed448.js.map +1 -1
- package/esm/jubjub.js +1 -1
- package/esm/jubjub.js.map +1 -1
- package/esm/p256.js +2 -2
- package/esm/p256.js.map +1 -1
- package/esm/p384.js +2 -2
- package/esm/p384.js.map +1 -1
- package/esm/p521.js +3 -3
- package/esm/p521.js.map +1 -1
- package/esm/package.json +1 -4
- package/esm/secp256k1.js +6 -6
- package/esm/secp256k1.js.map +1 -1
- package/jubjub.js.map +1 -1
- package/p256.js +2 -2
- package/p256.js.map +1 -1
- package/p384.js +2 -2
- package/p384.js.map +1 -1
- package/p521.js +3 -3
- package/p521.js.map +1 -1
- package/package.json +7 -6
- package/secp256k1.js +6 -6
- package/secp256k1.js.map +1 -1
- package/src/abstract/bls.ts +120 -22
- package/src/abstract/hash-to-curve.ts +24 -17
- package/src/abstract/modular.ts +81 -22
- package/src/abstract/montgomery.ts +4 -6
- package/src/abstract/poseidon.ts +39 -40
- package/src/abstract/utils.ts +55 -26
- package/src/abstract/weierstrass.ts +29 -18
- package/src/bls12-381.ts +132 -75
- package/src/bn254.ts +3 -2
- package/src/ed25519.ts +19 -8
- package/src/ed448.ts +267 -34
- package/src/jubjub.ts +1 -1
package/README.md
CHANGED
|
@@ -2,33 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
Audited & minimal JS implementation of elliptic curve cryptography.
|
|
4
4
|
|
|
5
|
-
- 🔒 [**Audited**](#security) by
|
|
5
|
+
- 🔒 [**Audited**](#security) by independent security firms
|
|
6
6
|
- 🔻 Tree-shaking-friendly: use only what's necessary, other code won't be included
|
|
7
7
|
- 🏎 Ultra-fast, hand-optimized for caveats of JS engines
|
|
8
8
|
- 🔍 Unique tests ensure correctness: property-based, cross-library and Wycheproof vectors, fuzzing
|
|
9
9
|
- ➰ Short Weierstrass, Edwards, Montgomery curves
|
|
10
10
|
- ✍️ ECDSA, EdDSA, Schnorr, BLS signature schemes, ECDH key agreement
|
|
11
|
-
- 🔖 SUF-CMA
|
|
12
|
-
- #️⃣
|
|
13
|
-
for encoding or hashing an arbitrary string to an elliptic curve point
|
|
11
|
+
- 🔖 SUF-CMA, SBS (non-repudiation), ZIP215 (consensus friendliness) features for ed25519
|
|
12
|
+
- #️⃣ hash-to-curve for encoding or hashing an arbitrary string to an elliptic curve point
|
|
14
13
|
- 🧜♂️ Poseidon ZK-friendly hash
|
|
15
14
|
|
|
16
|
-
Check out [Upgrading](#upgrading) if you've previously used single-feature noble
|
|
17
|
-
packages. See [Resources](#resources) for articles and real-world software that uses curves.
|
|
18
|
-
|
|
19
15
|
### This library belongs to _noble_ crypto
|
|
20
16
|
|
|
21
17
|
> **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools.
|
|
22
18
|
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
- All
|
|
27
|
-
|
|
28
|
-
[curves](https://github.com/paulmillr/noble-curves)
|
|
29
|
-
(4kb versions [secp256k1](https://github.com/paulmillr/noble-secp256k1),
|
|
30
|
-
[ed25519](https://github.com/paulmillr/noble-ed25519)),
|
|
19
|
+
- Zero or minimal dependencies
|
|
20
|
+
- Highly readable TypeScript / JS code
|
|
21
|
+
- PGP-signed releases and transparent NPM builds
|
|
22
|
+
- All libraries:
|
|
23
|
+
[ciphers](https://github.com/paulmillr/noble-ciphers),
|
|
24
|
+
[curves](https://github.com/paulmillr/noble-curves),
|
|
31
25
|
[hashes](https://github.com/paulmillr/noble-hashes)
|
|
26
|
+
- [Check out homepage](https://paulmillr.com/noble/)
|
|
27
|
+
for reading resources, documentation and apps built with noble
|
|
32
28
|
|
|
33
29
|
## Usage
|
|
34
30
|
|
|
@@ -36,36 +32,56 @@ packages. See [Resources](#resources) for articles and real-world software that
|
|
|
36
32
|
|
|
37
33
|
We support all major platforms and runtimes.
|
|
38
34
|
For [Deno](https://deno.land), ensure to use [npm specifier](https://deno.land/manual@v1.28.0/node/npm_specifiers).
|
|
39
|
-
For React Native, you may need a [polyfill for
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
The library is tree-shaking-friendly and does not expose root entry point as
|
|
43
|
-
`@noble/curves`. Instead, you need to import specific primitives.
|
|
44
|
-
This is done to ensure small size of your apps.
|
|
35
|
+
For React Native, you may need a [polyfill for getRandomValues](https://github.com/LinusU/react-native-get-random-values).
|
|
36
|
+
A standalone file [noble-curves.js](https://github.com/paulmillr/noble-curves/releases) is also available.
|
|
45
37
|
|
|
46
|
-
|
|
38
|
+
```js
|
|
39
|
+
// import * from '@noble/curves'; // Error: use sub-imports, to ensure small app size
|
|
40
|
+
import { secp256k1 } from '@noble/curves/secp256k1'; // ESM and Common.js
|
|
41
|
+
// import { secp256k1 } from 'npm:@noble/curves@1.2.0/secp256k1'; // Deno
|
|
42
|
+
```
|
|
47
43
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
44
|
+
- [Implementations](#implementations)
|
|
45
|
+
- [ECDSA signature scheme](#ecdsa-signature-scheme)
|
|
46
|
+
- [ECDSA public key recovery & extra entropy](#ecdsa-public-key-recovery--extra-entropy)
|
|
47
|
+
- [ECDH: Elliptic Curve Diffie-Hellman](#ecdh-elliptic-curve-diffie-hellman)
|
|
48
|
+
- [Schnorr signatures over secp256k1, BIP340](#schnorr-signatures-over-secp256k1-bip340)
|
|
49
|
+
- [ed25519, X25519, ristretto255](#ed25519-x25519-ristretto255)
|
|
50
|
+
- [ed448, X448, decaf448](#ed448-x448-decaf448)
|
|
51
|
+
- [bls12-381](#bls12-381)
|
|
52
|
+
- [All available imports](#all-available-imports)
|
|
53
|
+
- [Accessing a curve's variables](#accessing-a-curves-variables)
|
|
54
|
+
- [Abstract API](#abstract-api)
|
|
55
|
+
- [weierstrass: Short Weierstrass curve](#weierstrass-short-weierstrass-curve)
|
|
56
|
+
- [edwards: Twisted Edwards curve](#edwards-twisted-edwards-curve)
|
|
57
|
+
- [montgomery: Montgomery curve](#montgomery-montgomery-curve)
|
|
58
|
+
- [bls: Barreto-Lynn-Scott curves](#bls-barreto-lynn-scott-curves)
|
|
59
|
+
- [hash-to-curve: Hashing strings to curve points](#hash-to-curve-hashing-strings-to-curve-points)
|
|
60
|
+
- [poseidon: Poseidon hash](#poseidon-poseidon-hash)
|
|
61
|
+
- [modular: Modular arithmetics utilities](#modular-modular-arithmetics-utilities)
|
|
62
|
+
- [Creating private keys from hashes](#creating-private-keys-from-hashes)
|
|
63
|
+
- [utils: Useful utilities](#utils-useful-utilities)
|
|
64
|
+
- [Security](#security)
|
|
65
|
+
- [Speed](#speed)
|
|
66
|
+
- [Upgrading](#upgrading)
|
|
67
|
+
- [Contributing & testing](#contributing--testing)
|
|
68
|
+
- [Resources](#resources)
|
|
56
69
|
|
|
57
70
|
### Implementations
|
|
58
71
|
|
|
59
|
-
|
|
72
|
+
Implementations use [noble-hashes](https://github.com/paulmillr/noble-hashes).
|
|
73
|
+
If you want to use a different hashing library, [abstract API](#abstract-api) doesn't depend on them.
|
|
74
|
+
|
|
75
|
+
#### ECDSA signature scheme
|
|
76
|
+
|
|
77
|
+
Generic example that works for all curves, shown for secp256k1:
|
|
60
78
|
|
|
61
79
|
```ts
|
|
62
|
-
|
|
63
|
-
import { secp256k1 } from '@noble/curves/secp256k1'; // ESM and Common.js
|
|
64
|
-
// import { secp256k1 } from 'npm:@noble/curves@1.2.0/secp256k1'; // Deno
|
|
80
|
+
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
65
81
|
const priv = secp256k1.utils.randomPrivateKey();
|
|
66
82
|
const pub = secp256k1.getPublicKey(priv);
|
|
67
|
-
const msg = new Uint8Array(32).fill(1);
|
|
68
|
-
const sig = secp256k1.sign(msg, priv);
|
|
83
|
+
const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa
|
|
84
|
+
const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available
|
|
69
85
|
const isValid = secp256k1.verify(sig, msg, pub) === true;
|
|
70
86
|
|
|
71
87
|
// hex strings are also supported besides Uint8Arrays:
|
|
@@ -73,29 +89,24 @@ const privHex = '46c930bc7bb4db7f55da20798697421b98c4175a52c630294d75a84b9c12623
|
|
|
73
89
|
const pub2 = secp256k1.getPublicKey(privHex);
|
|
74
90
|
```
|
|
75
91
|
|
|
76
|
-
####
|
|
92
|
+
#### ECDSA public key recovery & extra entropy
|
|
77
93
|
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
import { pallas, vesta } from '@noble/curves/pasta';
|
|
86
|
-
import { bls12_381 } from '@noble/curves/bls12-381';
|
|
87
|
-
import { bn254 } from '@noble/curves/bn254';
|
|
88
|
-
import { jubjub } from '@noble/curves/jubjub';
|
|
94
|
+
```ts
|
|
95
|
+
// let sig = secp256k1.Signature.fromCompact(sigHex); // or .fromDER(sigDERHex)
|
|
96
|
+
// sig = sig.addRecoveryBit(bit); // bit is not serialized into compact / der format
|
|
97
|
+
sig.recoverPublicKey(msg).toRawBytes(); // === pub; // public key recovery
|
|
98
|
+
|
|
99
|
+
// extraEntropy https://moderncrypto.org/mail-archive/curves/2017/000925.html
|
|
100
|
+
const sigImprovedSecurity = secp256k1.sign(msg, priv, { extraEntropy: true });
|
|
89
101
|
```
|
|
90
102
|
|
|
91
|
-
####
|
|
103
|
+
#### ECDH: Elliptic Curve Diffie-Hellman
|
|
92
104
|
|
|
93
105
|
```ts
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
sig.recoverPublicKey(msg) === pub; // public key recovery
|
|
106
|
+
// 1. The output includes parity byte. Strip it using shared.slice(1)
|
|
107
|
+
// 2. The output is not hashed. More secure way is sha256(shared) or hkdf(shared)
|
|
97
108
|
const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
|
|
98
|
-
const shared = secp256k1.getSharedSecret(priv, someonesPub);
|
|
109
|
+
const shared = secp256k1.getSharedSecret(priv, someonesPub);
|
|
99
110
|
```
|
|
100
111
|
|
|
101
112
|
#### Schnorr signatures over secp256k1 (BIP340)
|
|
@@ -129,7 +140,6 @@ It has SUF-CMA (strong unforgeability under chosen message attacks).
|
|
|
129
140
|
and additionally provides non-repudiation with SBS [(Strongly Binding Signatures)](https://eprint.iacr.org/2020/1244).
|
|
130
141
|
|
|
131
142
|
X25519 follows [RFC7748](https://www.rfc-editor.org/rfc/rfc7748).
|
|
132
|
-
ristretto255 follows [irtf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448).
|
|
133
143
|
|
|
134
144
|
```ts
|
|
135
145
|
// Variants from RFC8032: with context, prehashed
|
|
@@ -147,17 +157,36 @@ x25519.getPublicKey(x25519.utils.randomPrivateKey());
|
|
|
147
157
|
import { edwardsToMontgomeryPub, edwardsToMontgomeryPriv } from '@noble/curves/ed25519';
|
|
148
158
|
edwardsToMontgomeryPub(ed25519.getPublicKey(ed25519.utils.randomPrivateKey()));
|
|
149
159
|
edwardsToMontgomeryPriv(ed25519.utils.randomPrivateKey());
|
|
160
|
+
```
|
|
150
161
|
|
|
162
|
+
ristretto255 follows [irtf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448).
|
|
163
|
+
|
|
164
|
+
```ts
|
|
151
165
|
// hash-to-curve, ristretto255
|
|
152
|
-
import {
|
|
166
|
+
import { utf8ToBytes } from '@noble/hashes/utils';
|
|
167
|
+
import { sha512 } from '@noble/hashes/sha512';
|
|
168
|
+
import {
|
|
169
|
+
hashToCurve,
|
|
170
|
+
encodeToCurve,
|
|
171
|
+
RistrettoPoint,
|
|
172
|
+
hashToRistretto255,
|
|
173
|
+
} from '@noble/curves/ed25519';
|
|
174
|
+
|
|
175
|
+
const msg = utf8ToBytes('Ristretto is traditionally a short shot of espresso coffee');
|
|
176
|
+
hashToCurve(msg);
|
|
177
|
+
|
|
153
178
|
const rp = RistrettoPoint.fromHex(
|
|
154
179
|
'6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919'
|
|
155
180
|
);
|
|
156
|
-
RistrettoPoint.
|
|
157
|
-
|
|
181
|
+
RistrettoPoint.BASE.multiply(2n).add(rp).subtract(RistrettoPoint.BASE).toRawBytes();
|
|
182
|
+
RistrettoPoint.ZERO.equals(dp) === false;
|
|
183
|
+
// pre-hashed hash-to-curve
|
|
184
|
+
RistrettoPoint.hashToCurve(sha512(msg));
|
|
185
|
+
// full hash-to-curve including domain separation tag
|
|
186
|
+
hashToRistretto255(msg, { DST: 'ristretto255_XMD:SHA-512_R255MAP_RO_' });
|
|
158
187
|
```
|
|
159
188
|
|
|
160
|
-
#### ed448, X448
|
|
189
|
+
#### ed448, X448, decaf448
|
|
161
190
|
|
|
162
191
|
```ts
|
|
163
192
|
import { ed448 } from '@noble/curves/ed448';
|
|
@@ -167,17 +196,65 @@ const msg = new TextEncoder().encode('whatsup');
|
|
|
167
196
|
const sig = ed448.sign(msg, priv);
|
|
168
197
|
ed448.verify(sig, msg, pub);
|
|
169
198
|
|
|
170
|
-
|
|
199
|
+
// Variants from RFC8032: prehashed
|
|
200
|
+
import { ed448ph } from '@noble/curves/ed448';
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
ECDH using Curve448 aka X448, follows [RFC7748](https://www.rfc-editor.org/rfc/rfc7748).
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
import { x448 } from '@noble/curves/ed448';
|
|
171
207
|
x448.getSharedSecret(priv, pub) === x448.scalarMult(priv, pub); // aliases
|
|
172
208
|
x448.getPublicKey(priv) === x448.scalarMultBase(priv);
|
|
209
|
+
|
|
210
|
+
// ed448 => x448 conversion
|
|
211
|
+
import { edwardsToMontgomeryPub } from '@noble/curves/ed448';
|
|
212
|
+
edwardsToMontgomeryPub(ed448.getPublicKey(ed448.utils.randomPrivateKey()));
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
decaf448 follows [irtf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448).
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
import { utf8ToBytes } from '@noble/hashes/utils';
|
|
219
|
+
import { shake256 } from '@noble/hashes/sha3';
|
|
220
|
+
import { hashToCurve, encodeToCurve, DecafPoint, hashToDecaf448 } from '@noble/curves/ed448';
|
|
221
|
+
|
|
222
|
+
const msg = utf8ToBytes('Ristretto is traditionally a short shot of espresso coffee');
|
|
223
|
+
hashToCurve(msg);
|
|
224
|
+
|
|
225
|
+
const dp = DecafPoint.fromHex(
|
|
226
|
+
'c898eb4f87f97c564c6fd61fc7e49689314a1f818ec85eeb3bd5514ac816d38778f69ef347a89fca817e66defdedce178c7cc709b2116e75'
|
|
227
|
+
);
|
|
228
|
+
DecafPoint.BASE.multiply(2n).add(dp).subtract(DecafPoint.BASE).toRawBytes();
|
|
229
|
+
DecafPoint.ZERO.equals(dp) === false;
|
|
230
|
+
// pre-hashed hash-to-curve
|
|
231
|
+
DecafPoint.hashToCurve(shake256(msg, { dkLen: 112 }));
|
|
232
|
+
// full hash-to-curve including domain separation tag
|
|
233
|
+
hashToDecaf448(msg, { DST: 'decaf448_XOF:SHAKE256_D448MAP_RO_' });
|
|
173
234
|
```
|
|
174
235
|
|
|
175
|
-
Same RFC7748 / RFC8032 are followed.
|
|
236
|
+
Same RFC7748 / RFC8032 / IRTF draft are followed.
|
|
176
237
|
|
|
177
238
|
#### bls12-381
|
|
178
239
|
|
|
179
240
|
See [abstract/bls](#abstractbls-barreto-lynn-scott-curves).
|
|
180
241
|
|
|
242
|
+
#### All available imports
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
import { secp256k1, schnorr } from '@noble/curves/secp256k1';
|
|
246
|
+
import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519';
|
|
247
|
+
import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448';
|
|
248
|
+
import { p256 } from '@noble/curves/p256';
|
|
249
|
+
import { p384 } from '@noble/curves/p384';
|
|
250
|
+
import { p521 } from '@noble/curves/p521';
|
|
251
|
+
import { pallas, vesta } from '@noble/curves/pasta';
|
|
252
|
+
import { bls12_381 } from '@noble/curves/bls12-381';
|
|
253
|
+
import { bn254 } from '@noble/curves/bn254'; // also known as alt_bn128
|
|
254
|
+
import { jubjub } from '@noble/curves/jubjub';
|
|
255
|
+
import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils';
|
|
256
|
+
```
|
|
257
|
+
|
|
181
258
|
#### Accessing a curve's variables
|
|
182
259
|
|
|
183
260
|
```ts
|
|
@@ -199,18 +276,7 @@ Precomputes are enabled for weierstrass and edwards BASE points of a curve. You
|
|
|
199
276
|
could precompute any other point (e.g. for ECDH) using `utils.precompute()`
|
|
200
277
|
method: check out examples.
|
|
201
278
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
- [abstract/weierstrass: Short Weierstrass curve](#abstractweierstrass-short-weierstrass-curve)
|
|
205
|
-
- [abstract/edwards: Twisted Edwards curve](#abstractedwards-twisted-edwards-curve)
|
|
206
|
-
- [abstract/montgomery: Montgomery curve](#abstractmontgomery-montgomery-curve)
|
|
207
|
-
- [abstract/bls: Barreto-Lynn-Scott curves](#abstractbls-barreto-lynn-scott-curves)
|
|
208
|
-
- [abstract/hash-to-curve: Hashing strings to curve points](#abstracthash-to-curve-hashing-strings-to-curve-points)
|
|
209
|
-
- [abstract/poseidon: Poseidon hash](#abstractposeidon-poseidon-hash)
|
|
210
|
-
- [abstract/modular: Modular arithmetics utilities](#abstractmodular-modular-arithmetics-utilities)
|
|
211
|
-
- [abstract/utils: General utilities](#abstractutils-general-utilities)
|
|
212
|
-
|
|
213
|
-
### abstract/weierstrass: Short Weierstrass curve
|
|
279
|
+
### weierstrass: Short Weierstrass curve
|
|
214
280
|
|
|
215
281
|
```ts
|
|
216
282
|
import { weierstrass } from '@noble/curves/abstract/weierstrass';
|
|
@@ -233,7 +299,7 @@ const secq256k1 = weierstrass({
|
|
|
233
299
|
randomBytes,
|
|
234
300
|
});
|
|
235
301
|
|
|
236
|
-
// Replace weierstrass with weierstrassPoints if you don't need ECDSA, hash, hmac, randomBytes
|
|
302
|
+
// Replace weierstrass() with weierstrassPoints() if you don't need ECDSA, hash, hmac, randomBytes
|
|
237
303
|
```
|
|
238
304
|
|
|
239
305
|
Short Weierstrass curve's formula is `y² = x³ + ax + b`. `weierstrass`
|
|
@@ -252,8 +318,17 @@ type CHash = {
|
|
|
252
318
|
outputLen: number;
|
|
253
319
|
create(): any;
|
|
254
320
|
};
|
|
321
|
+
|
|
322
|
+
// example
|
|
323
|
+
function sha256(message: Uint8Array) { return _internal_lowlvl(message) }
|
|
324
|
+
sha256.outputLen = 32; // 32 bytes of output for sha2-256
|
|
255
325
|
```
|
|
256
326
|
|
|
327
|
+
**Message hash** is expected instead of message itself:
|
|
328
|
+
|
|
329
|
+
- `sign(msgHash, privKey)` is default behavior, assuming you pre-hash msg with sha2, or other hash
|
|
330
|
+
- `sign(msg, privKey, {prehash: true})` option can be used if you want to pass the message itself
|
|
331
|
+
|
|
257
332
|
**Weierstrass points:**
|
|
258
333
|
|
|
259
334
|
1. Exported as `ProjectivePoint`
|
|
@@ -349,6 +424,7 @@ More examples:
|
|
|
349
424
|
const priv = secq256k1.utils.randomPrivateKey();
|
|
350
425
|
secq256k1.getPublicKey(priv); // Convert private key to public.
|
|
351
426
|
const sig = secq256k1.sign(msg, priv); // Sign msg with private key.
|
|
427
|
+
const sig2 = secq256k1.sign(msg, priv, { prehash: true }); // hash(msg)
|
|
352
428
|
secq256k1.verify(sig, msg, priv); // Verify if sig is correct.
|
|
353
429
|
|
|
354
430
|
const Point = secq256k1.ProjectivePoint;
|
|
@@ -371,7 +447,7 @@ const fast = secq256k1.utils.precompute(8, Point.fromHex(someonesPubKey));
|
|
|
371
447
|
fast.multiply(privKey); // much faster ECDH now
|
|
372
448
|
```
|
|
373
449
|
|
|
374
|
-
###
|
|
450
|
+
### edwards: Twisted Edwards curve
|
|
375
451
|
|
|
376
452
|
```ts
|
|
377
453
|
import { twistedEdwards } from '@noble/curves/abstract/edwards';
|
|
@@ -461,7 +537,7 @@ interface ExtPointConstructor extends GroupConstructor<ExtPointType> {
|
|
|
461
537
|
}
|
|
462
538
|
```
|
|
463
539
|
|
|
464
|
-
###
|
|
540
|
+
### montgomery: Montgomery curve
|
|
465
541
|
|
|
466
542
|
```typescript
|
|
467
543
|
import { montgomery } from '@noble/curves/abstract/montgomery';
|
|
@@ -488,7 +564,7 @@ Proper Elliptic Curve Points are not implemented yet.
|
|
|
488
564
|
|
|
489
565
|
You must specify curve params `Fp`, `a`, `Gu` coordinate of u, `montgomeryBits` and `nByteLength`.
|
|
490
566
|
|
|
491
|
-
###
|
|
567
|
+
### bls: Barreto-Lynn-Scott curves
|
|
492
568
|
|
|
493
569
|
The module abstracts BLS (Barreto-Lynn-Scott) pairing-friendly elliptic curve construction.
|
|
494
570
|
They allow to construct [zk-SNARKs](https://z.cash/technology/zksnarks/) and
|
|
@@ -496,6 +572,10 @@ use aggregated, batch-verifiable
|
|
|
496
572
|
[threshold signatures](https://medium.com/snigirev.stepan/bls-signatures-better-than-schnorr-5a7fe30ea716),
|
|
497
573
|
using Boneh-Lynn-Shacham signature scheme.
|
|
498
574
|
|
|
575
|
+
The module doesn't expose `CURVE` property: use `G1.CURVE`, `G2.CURVE` instead.
|
|
576
|
+
Only BLS12-381 is implemented currently.
|
|
577
|
+
Defining BLS12-377 and BLS24 should be straightforward.
|
|
578
|
+
|
|
499
579
|
Main methods and properties are:
|
|
500
580
|
|
|
501
581
|
- `getPublicKey(privateKey)`
|
|
@@ -507,8 +587,13 @@ Main methods and properties are:
|
|
|
507
587
|
- `Signature` property with `fromHex`, `toHex` methods
|
|
508
588
|
- `fields` containing `Fp`, `Fp2`, `Fp6`, `Fp12`, `Fr`
|
|
509
589
|
|
|
510
|
-
|
|
511
|
-
|
|
590
|
+
The default BLS uses short public keys (with public keys in G1 and signatures in G2).
|
|
591
|
+
Short signatures (public keys in G2 and signatures in G1) is also supported, using:
|
|
592
|
+
|
|
593
|
+
- `getPublicKeyForShortSignatures(privateKey)`
|
|
594
|
+
- `signShortSignature(message, privateKey)`
|
|
595
|
+
- `verifyShortSignature(signature, message, publicKey)`
|
|
596
|
+
- `aggregateShortSignatures(signatures)`
|
|
512
597
|
|
|
513
598
|
```ts
|
|
514
599
|
import { bls12_381 as bls } from '@noble/curves/bls12-381';
|
|
@@ -539,66 +624,22 @@ const aggSignature3 = bls.aggregateSignatures(signatures3);
|
|
|
539
624
|
const isValid3 = bls.verifyBatch(aggSignature3, messages, publicKeys);
|
|
540
625
|
console.log({ publicKeys, signatures3, aggSignature3, isValid3 });
|
|
541
626
|
|
|
542
|
-
//
|
|
543
|
-
|
|
544
|
-
|
|
627
|
+
// Pairings, with and without final exponentiation
|
|
628
|
+
bls.pairing(PointG1, PointG2);
|
|
629
|
+
bls.pairing(PointG1, PointG2, false);
|
|
630
|
+
bls.fields.Fp12.finalExponentiate(bls.fields.Fp12.mul(PointG1, PointG2));
|
|
545
631
|
|
|
546
|
-
//
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
632
|
+
// Others
|
|
633
|
+
bls.G1.ProjectivePoint.BASE, bls.G2.ProjectivePoint.BASE
|
|
634
|
+
bls.fields.Fp, bls.fields.Fp2, bls.fields.Fp12, bls.fields.Fr
|
|
635
|
+
bls.params.x, bls.params.r, bls.params.G1b, bls.params.G2b
|
|
550
636
|
|
|
551
|
-
|
|
552
|
-
getPublicKey: (privateKey: PrivKey) => Uint8Array;
|
|
553
|
-
sign: {
|
|
554
|
-
(message: Hex, privateKey: PrivKey): Uint8Array;
|
|
555
|
-
(message: ProjPointType<Fp2>, privateKey: PrivKey): ProjPointType<Fp2>;
|
|
556
|
-
};
|
|
557
|
-
verify: (
|
|
558
|
-
signature: Hex | ProjPointType<Fp2>,
|
|
559
|
-
message: Hex | ProjPointType<Fp2>,
|
|
560
|
-
publicKey: Hex | ProjPointType<Fp>
|
|
561
|
-
) => boolean;
|
|
562
|
-
verifyBatch: (
|
|
563
|
-
signature: Hex | ProjPointType<Fp2>,
|
|
564
|
-
messages: (Hex | ProjPointType<Fp2>)[],
|
|
565
|
-
publicKeys: (Hex | ProjPointType<Fp>)[]
|
|
566
|
-
) => boolean;
|
|
567
|
-
aggregatePublicKeys: {
|
|
568
|
-
(publicKeys: Hex[]): Uint8Array;
|
|
569
|
-
(publicKeys: ProjPointType<Fp>[]): ProjPointType<Fp>;
|
|
570
|
-
};
|
|
571
|
-
aggregateSignatures: {
|
|
572
|
-
(signatures: Hex[]): Uint8Array;
|
|
573
|
-
(signatures: ProjPointType<Fp2>[]): ProjPointType<Fp2>;
|
|
574
|
-
};
|
|
575
|
-
millerLoop: (ell: [Fp2, Fp2, Fp2][], g1: [Fp, Fp]) => Fp12;
|
|
576
|
-
pairing: (P: ProjPointType<Fp>, Q: ProjPointType<Fp2>, withFinalExponent?: boolean) => Fp12;
|
|
577
|
-
G1: CurvePointsRes<Fp> & ReturnType<typeof htf.createHasher<Fp>>;
|
|
578
|
-
G2: CurvePointsRes<Fp2> & ReturnType<typeof htf.createHasher<Fp2>>;
|
|
579
|
-
Signature: SignatureCoder<Fp2>;
|
|
580
|
-
params: {
|
|
581
|
-
x: bigint;
|
|
582
|
-
r: bigint;
|
|
583
|
-
G1b: bigint;
|
|
584
|
-
G2b: Fp2;
|
|
585
|
-
};
|
|
586
|
-
fields: {
|
|
587
|
-
Fp: IField<Fp>;
|
|
588
|
-
Fp2: IField<Fp2>;
|
|
589
|
-
Fp6: IField<Fp6>;
|
|
590
|
-
Fp12: IField<Fp12>;
|
|
591
|
-
Fr: IField<bigint>;
|
|
592
|
-
};
|
|
593
|
-
utils: {
|
|
594
|
-
randomPrivateKey: () => Uint8Array;
|
|
595
|
-
calcPairingPrecomputes: (p: AffinePoint<Fp2>) => [Fp2, Fp2, Fp2][];
|
|
596
|
-
};
|
|
637
|
+
// hash-to-curve examples can be seen below
|
|
597
638
|
```
|
|
598
639
|
|
|
599
|
-
###
|
|
640
|
+
### hash-to-curve: Hashing strings to curve points
|
|
600
641
|
|
|
601
|
-
The module allows to hash arbitrary strings to elliptic curve points. Implements [
|
|
642
|
+
The module allows to hash arbitrary strings to elliptic curve points. Implements [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380).
|
|
602
643
|
|
|
603
644
|
Every curve has exported `hashToCurve` and `encodeToCurve` methods. You should always prefer `hashToCurve` for security:
|
|
604
645
|
|
|
@@ -614,19 +655,17 @@ bls12_381.G1.hashToCurve(randomBytes(), { DST: 'another' });
|
|
|
614
655
|
bls12_381.G2.hashToCurve(randomBytes(), { DST: 'custom' });
|
|
615
656
|
```
|
|
616
657
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
`expand_message_xmd` [(spec)](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.4.1) produces a uniformly random byte string using a cryptographic hash function H that outputs b bits.
|
|
620
|
-
|
|
621
|
-
Hash must conform to `CHash` interface (see [weierstrass section](#abstractweierstrass-short-weierstrass-curve)).
|
|
658
|
+
Low-level methods from the spec:
|
|
622
659
|
|
|
623
660
|
```ts
|
|
661
|
+
// produces a uniformly random byte string using a cryptographic hash function H that outputs b bits.
|
|
624
662
|
function expand_message_xmd(
|
|
625
663
|
msg: Uint8Array,
|
|
626
664
|
DST: Uint8Array,
|
|
627
665
|
lenInBytes: number,
|
|
628
|
-
H: CHash
|
|
666
|
+
H: CHash // For CHash see abstract/weierstrass docs section
|
|
629
667
|
): Uint8Array;
|
|
668
|
+
// produces a uniformly random byte string using an extendable-output function (XOF) H.
|
|
630
669
|
function expand_message_xof(
|
|
631
670
|
msg: Uint8Array,
|
|
632
671
|
DST: Uint8Array,
|
|
@@ -634,13 +673,9 @@ function expand_message_xof(
|
|
|
634
673
|
k: number,
|
|
635
674
|
H: CHash
|
|
636
675
|
): Uint8Array;
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
`hash_to_field(msg, count, options)`
|
|
640
|
-
[(spec)](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3)
|
|
641
|
-
hashes arbitrary-length byte strings to a list of one or more elements of a finite field F.
|
|
676
|
+
// Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F
|
|
677
|
+
function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][];
|
|
642
678
|
|
|
643
|
-
```ts
|
|
644
679
|
/**
|
|
645
680
|
* * `DST` is a domain separation tag, defined in section 2.2.5
|
|
646
681
|
* * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m
|
|
@@ -651,26 +686,16 @@ hashes arbitrary-length byte strings to a list of one or more elements of a fini
|
|
|
651
686
|
*/
|
|
652
687
|
type UnicodeOrBytes = string | Uint8Array;
|
|
653
688
|
type Opts = {
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
689
|
+
DST: UnicodeOrBytes;
|
|
690
|
+
p: bigint;
|
|
691
|
+
m: number;
|
|
692
|
+
k: number;
|
|
693
|
+
expand?: 'xmd' | 'xof';
|
|
694
|
+
hash: CHash;
|
|
660
695
|
};
|
|
661
|
-
|
|
662
|
-
/**
|
|
663
|
-
* Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F
|
|
664
|
-
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3
|
|
665
|
-
* @param msg a byte string containing the message to hash
|
|
666
|
-
* @param count the number of elements of F to output
|
|
667
|
-
* @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above
|
|
668
|
-
* @returns [u_0, ..., u_(count - 1)], a list of field elements.
|
|
669
|
-
*/
|
|
670
|
-
function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][];
|
|
671
696
|
```
|
|
672
697
|
|
|
673
|
-
###
|
|
698
|
+
### poseidon: Poseidon hash
|
|
674
699
|
|
|
675
700
|
Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash.
|
|
676
701
|
|
|
@@ -694,7 +719,7 @@ type PoseidonOpts = {
|
|
|
694
719
|
const instance = poseidon(opts: PoseidonOpts);
|
|
695
720
|
```
|
|
696
721
|
|
|
697
|
-
###
|
|
722
|
+
### modular: Modular arithmetics utilities
|
|
698
723
|
|
|
699
724
|
```ts
|
|
700
725
|
import * as mod from '@noble/curves/abstract/modular';
|
|
@@ -710,30 +735,41 @@ mod.invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse
|
|
|
710
735
|
mod.invertBatch([1n, 2n, 4n], 21n); // => [1n, 11n, 16n] in one inversion
|
|
711
736
|
```
|
|
712
737
|
|
|
713
|
-
|
|
738
|
+
Field operations are not constant-time: they are using JS bigints, see [security](#security).
|
|
739
|
+
The fact is mostly irrelevant, but the important method to keep in mind is `pow`,
|
|
740
|
+
which may leak exponent bits, when used naïvely.
|
|
741
|
+
|
|
742
|
+
`mod.Field` is always **field over prime**. Non-prime fields aren't supported for now.
|
|
743
|
+
We don't test for prime-ness for speed and because algorithms are probabilistic anyway.
|
|
744
|
+
Initializing a non-prime field could make your app suspectible to
|
|
745
|
+
DoS (infilite loop) on Tonelli-Shanks square root calculation.
|
|
746
|
+
|
|
747
|
+
Unlike `mod.invert`, `mod.invertBatch` won't throw on `0`: make sure to throw an error yourself.
|
|
714
748
|
|
|
715
|
-
|
|
716
|
-
Even though p256 or secp256k1 may have 32-byte private keys,
|
|
717
|
-
and sha256 output is also 32-byte, you can't just use it and reduce it modulo `CURVE.n`.
|
|
749
|
+
#### Creating private keys from hashes
|
|
718
750
|
|
|
719
|
-
|
|
751
|
+
You can't simply make a 32-byte private key from a 32-byte hash.
|
|
752
|
+
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/).
|
|
720
753
|
|
|
721
|
-
To
|
|
722
|
-
|
|
754
|
+
To make the bias negligible, we follow [FIPS 186-5 A.2](https://csrc.nist.gov/publications/detail/fips/186/5/final)
|
|
755
|
+
and [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380#section-5.2).
|
|
756
|
+
This means, for 32-byte key, we would need 48-byte hash to get 2^-128 bias, which matches curve security level.
|
|
723
757
|
|
|
724
|
-
|
|
725
|
-
|
|
758
|
+
`hashToPrivateScalar()` that hashes to **private key** was created for this purpose.
|
|
759
|
+
Use [abstract/hash-to-curve](#abstracthash-to-curve-hashing-strings-to-curve-points)
|
|
760
|
+
if you need to hash to **public key**.
|
|
726
761
|
|
|
727
762
|
```ts
|
|
728
763
|
import { p256 } from '@noble/curves/p256';
|
|
729
764
|
import { sha256 } from '@noble/hashes/sha256';
|
|
730
765
|
import { hkdf } from '@noble/hashes/hkdf';
|
|
766
|
+
import * as mod from '@noble/curves/abstract/modular';
|
|
731
767
|
const someKey = new Uint8Array(32).fill(2); // Needs to actually be random, not .fill(2)
|
|
732
|
-
const derived = hkdf(sha256, someKey, undefined, 'application',
|
|
768
|
+
const derived = hkdf(sha256, someKey, undefined, 'application', 48); // 48 bytes for 32-byte priv
|
|
733
769
|
const validPrivateKey = mod.hashToPrivateScalar(derived, p256.CURVE.n);
|
|
734
770
|
```
|
|
735
771
|
|
|
736
|
-
###
|
|
772
|
+
### utils: Useful utilities
|
|
737
773
|
|
|
738
774
|
```ts
|
|
739
775
|
import * as utils from '@noble/curves/abstract/utils';
|
|
@@ -755,25 +791,61 @@ utils.equalBytes(Uint8Array.from([0xde]), Uint8Array.from([0xde]));
|
|
|
755
791
|
|
|
756
792
|
## Security
|
|
757
793
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
-
|
|
772
|
-
|
|
773
|
-
|
|
794
|
+
The library has been independently audited:
|
|
795
|
+
|
|
796
|
+
- at version 1.2.0, in Sep 2023, by [Kudelski Security](https://kudelskisecurity.com)
|
|
797
|
+
- PDFs: [offline](./audit/2023-09-kudelski-audit-starknet.pdf)
|
|
798
|
+
- [Changes since audit](https://github.com/paulmillr/noble-curves/compare/1.2.0..main)
|
|
799
|
+
- Scope: [scure-starknet](https://github.com/paulmillr/scure-starknet) and its related
|
|
800
|
+
abstract modules of noble-curves: `curve`, `modular`, `poseidon`, `weierstrass`
|
|
801
|
+
- The audit has been funded by [Starkware](https://starkware.co)
|
|
802
|
+
- at version 0.7.3, in Feb 2023, by [Trail of Bits](https://www.trailofbits.com)
|
|
803
|
+
- PDFs: [online](https://github.com/trailofbits/publications/blob/master/reviews/2023-01-ryanshea-noblecurveslibrary-securityreview.pdf),
|
|
804
|
+
[offline](./audit/2023-01-trailofbits-audit-curves.pdf)
|
|
805
|
+
- [Changes since audit](https://github.com/paulmillr/noble-curves/compare/0.7.3..main)
|
|
806
|
+
- Scope: abstract modules `curve`, `hash-to-curve`, `modular`, `poseidon`, `utils`, `weierstrass` and
|
|
807
|
+
top-level modules `_shortw_utils` and `secp256k1`
|
|
808
|
+
- The audit has been funded by [Ryan Shea](https://www.shea.io)
|
|
809
|
+
|
|
810
|
+
It is tested against property-based, cross-library and Wycheproof vectors,
|
|
811
|
+
and has fuzzing by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz).
|
|
812
|
+
|
|
813
|
+
If you see anything unusual: investigate and report.
|
|
814
|
+
|
|
815
|
+
### Constant-timeness
|
|
816
|
+
|
|
817
|
+
_JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard to
|
|
818
|
+
achieve [timing attack](https://en.wikipedia.org/wiki/Timing_attack) resistance
|
|
819
|
+
in a scripting language. Which means _any other JS library can't have
|
|
820
|
+
constant-timeness_. Even statically typed Rust, a language without GC,
|
|
821
|
+
[makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security)
|
|
822
|
+
for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones.
|
|
823
|
+
Use low-level libraries & languages. Nonetheless we're targetting algorithmic constant time.
|
|
824
|
+
|
|
825
|
+
### Supply chain security
|
|
826
|
+
|
|
827
|
+
* **Commits** are signed with PGP keys, to prevent forgery. Make sure to verify commit signatures.
|
|
828
|
+
* **Releases** are transparent and built on GitHub CI. Make sure to verify [provenance](https://docs.npmjs.com/generating-provenance-statements) logs
|
|
829
|
+
* **Rare releasing** is followed to ensure less re-audit need for end-users
|
|
830
|
+
* **Dependencies** are minimized and locked-down:
|
|
831
|
+
- If your app has 500 dependencies, any dep could get hacked and you'll be downloading
|
|
832
|
+
malware with every install. We make sure to use as few dependencies as possible
|
|
833
|
+
- We prevent automatic dependency updates by locking-down version ranges. Every update is checked with `npm-diff`
|
|
834
|
+
- One dependency [noble-hashes](https://github.com/paulmillr/noble-hashes) is used, by the same author, to provide hashing functionality
|
|
835
|
+
* **Dev Dependencies** are only used if you want to contribute to the repo. They are disabled for end-users:
|
|
836
|
+
- scure-base, scure-bip32, scure-bip39, micro-bmark and micro-should are developed by the same author and follow identical security practices
|
|
837
|
+
- prettier (linter), fast-check (property-based testing) and typescript are used for code quality, vector generation and ts compilation. The packages are big, which makes it hard to audit their source code thoroughly and fully
|
|
838
|
+
|
|
839
|
+
### Randomness
|
|
840
|
+
|
|
841
|
+
We're deferring to built-in
|
|
774
842
|
[crypto.getRandomValues](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues)
|
|
775
843
|
which is considered cryptographically secure (CSPRNG).
|
|
776
844
|
|
|
845
|
+
In the past, browsers had bugs that made it weak: it may happen again.
|
|
846
|
+
Implementing a userspace CSPRNG to get resilient to the weakness
|
|
847
|
+
is even worse: there is no reliable userspace source of quality entropy.
|
|
848
|
+
|
|
777
849
|
## Speed
|
|
778
850
|
|
|
779
851
|
Benchmark results on Apple M2 with node v20:
|
|
@@ -855,45 +927,41 @@ ed25519 x 3,088 ops/sec @ 323μs/op
|
|
|
855
927
|
ed448 x 1,247 ops/sec @ 801μs/op
|
|
856
928
|
```
|
|
857
929
|
|
|
858
|
-
## Contributing & testing
|
|
859
|
-
|
|
860
|
-
1. Clone the repository
|
|
861
|
-
2. `npm install` to install build dependencies like TypeScript
|
|
862
|
-
3. `npm run build` to compile TypeScript code
|
|
863
|
-
4. `npm run test` will execute all main tests
|
|
864
|
-
|
|
865
930
|
## Upgrading
|
|
866
931
|
|
|
867
932
|
Previously, the library was split into single-feature packages
|
|
868
|
-
noble-secp256k1
|
|
933
|
+
[noble-secp256k1](https://github.com/paulmillr/noble-secp256k1),
|
|
934
|
+
[noble-ed25519](https://github.com/paulmillr/noble-ed25519) and
|
|
935
|
+
[noble-bls12-381](https://github.com/paulmillr/noble-bls12-381).
|
|
869
936
|
|
|
870
937
|
Curves continue their original work. The single-feature packages changed their
|
|
871
938
|
direction towards providing minimal 4kb implementations of cryptography,
|
|
872
939
|
which means they have less features.
|
|
873
940
|
|
|
874
|
-
Upgrading from
|
|
941
|
+
Upgrading from noble-secp256k1 2.0 or noble-ed25519 2.0: no changes, libraries are compatible.
|
|
875
942
|
|
|
876
|
-
Upgrading from
|
|
943
|
+
Upgrading from noble-secp256k1 1.7:
|
|
877
944
|
|
|
878
945
|
- `getPublicKey`
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
946
|
+
- now produce 33-byte compressed signatures by default
|
|
947
|
+
- to use old behavior, which produced 65-byte uncompressed keys, set
|
|
948
|
+
argument `isCompressed` to `false`: `getPublicKey(priv, false)`
|
|
882
949
|
- `sign`
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
950
|
+
- is now sync
|
|
951
|
+
- now returns `Signature` instance with `{ r, s, recovery }` properties
|
|
952
|
+
- `canonical` option was renamed to `lowS`
|
|
953
|
+
- `recovered` option has been removed because recovery bit is always returned now
|
|
954
|
+
- `der` option has been removed. There are 2 options:
|
|
955
|
+
1. Use compact encoding: `fromCompact`, `toCompactRawBytes`, `toCompactHex`.
|
|
956
|
+
Compact encoding is simply a concatenation of 32-byte r and 32-byte s.
|
|
957
|
+
2. If you must use DER encoding, switch to noble-curves (see above).
|
|
891
958
|
- `verify`
|
|
892
|
-
|
|
959
|
+
- is now sync
|
|
960
|
+
- `strict` option was renamed to `lowS`
|
|
893
961
|
- `getSharedSecret`
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
962
|
+
- now produce 33-byte compressed signatures by default
|
|
963
|
+
- to use old behavior, which produced 65-byte uncompressed keys, set
|
|
964
|
+
argument `isCompressed` to `false`: `getSharedSecret(a, b, false)`
|
|
897
965
|
- `recoverPublicKey(msg, sig, rec)` was changed to `sig.recoverPublicKey(msg)`
|
|
898
966
|
- `number` type for private keys have been removed: use `bigint` instead
|
|
899
967
|
- `Point` (2d xy) has been changed to `ProjectivePoint` (3d xyz)
|
|
@@ -914,53 +982,22 @@ Upgrading from [@noble/ed25519](https://github.com/paulmillr/noble-ed25519) 1.7:
|
|
|
914
982
|
Upgrading from [@noble/bls12-381](https://github.com/paulmillr/noble-bls12-381):
|
|
915
983
|
|
|
916
984
|
- Methods and classes were renamed:
|
|
917
|
-
|
|
918
|
-
|
|
985
|
+
- PointG1 -> G1.Point, PointG2 -> G2.Point
|
|
986
|
+
- PointG2.fromSignature -> Signature.decode, PointG2.toSignature -> Signature.encode
|
|
919
987
|
- Fp2 ORDER was corrected
|
|
920
988
|
|
|
989
|
+
## Contributing & testing
|
|
990
|
+
|
|
991
|
+
1. Clone the repository
|
|
992
|
+
2. `npm install` to install build dependencies like TypeScript
|
|
993
|
+
3. `npm run build` to compile TypeScript code
|
|
994
|
+
4. `npm run test` will execute all main tests
|
|
995
|
+
|
|
921
996
|
## Resources
|
|
922
997
|
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
- [Taming the many EdDSAs](https://csrc.nist.gov/csrc/media/Presentations/2023/crclub-2023-03-08/images-media/20230308-crypto-club-slides--taming-the-many-EdDSAs.pdf)
|
|
927
|
-
that describes concepts of Strong UnForgeability under Chosen Message Attacks and Strongly Binding Signatures
|
|
928
|
-
- Pairings and BLS
|
|
929
|
-
- [BLS signatures for busy people](https://gist.github.com/paulmillr/18b802ad219b1aee34d773d08ec26ca2)
|
|
930
|
-
- [BLS12-381 for the rest of us](https://hackmd.io/@benjaminion/bls12-381)
|
|
931
|
-
- [Key concepts of pairings](https://medium.com/@alonmuroch_65570/bls-signatures-part-2-key-concepts-of-pairings-27a8a9533d0c)
|
|
932
|
-
- Pairing over bls12-381:
|
|
933
|
-
[part 1](https://research.nccgroup.com/2020/07/06/pairing-over-bls12-381-part-1-fields/),
|
|
934
|
-
[part 2](https://research.nccgroup.com/2020/07/13/pairing-over-bls12-381-part-2-curves/),
|
|
935
|
-
[part 3](https://research.nccgroup.com/2020/08/13/pairing-over-bls12-381-part-3-pairing/)
|
|
936
|
-
- [Estimating the bit security of pairing-friendly curves](https://research.nccgroup.com/2022/02/03/estimating-the-bit-security-of-pairing-friendly-curves/)
|
|
937
|
-
|
|
938
|
-
Online demos:
|
|
939
|
-
|
|
940
|
-
- [Elliptic Curve Calculator](https://paulmillr.com/noble): add / multiply points, sign messages
|
|
941
|
-
- [BLS threshold signatures](https://genthresh.com)
|
|
942
|
-
|
|
943
|
-
Projects using noble-curves:
|
|
944
|
-
|
|
945
|
-
- [scure-bip32](https://github.com/paulmillr/scure-bip32) and separate [bip32](https://github.com/bitcoinjs/bip32) HDkey libraries
|
|
946
|
-
- Ethereum libraries:
|
|
947
|
-
- [ethereum-cryptography](https://github.com/ethereum/js-ethereum-cryptography)
|
|
948
|
-
- [@ethereumjs](https://github.com/ethereumjs/ethereumjs-monorepo)
|
|
949
|
-
- [micro-eth-signer](https://github.com/paulmillr/micro-eth-signer)
|
|
950
|
-
- [ethers](https://github.com/ethers-io/ethers.js) (old noble-secp256k1 for now)
|
|
951
|
-
- [viem.sh](https://viem.sh)
|
|
952
|
-
- [metamask's eth-sig-util](https://github.com/MetaMask/eth-sig-util)
|
|
953
|
-
- [gridplus lattice sdk](https://github.com/GridPlus/lattice-eth2-utils)
|
|
954
|
-
- Bitcoin libraries: [scure-btc-signer](https://github.com/paulmillr/scure-btc-signer)
|
|
955
|
-
- Solana libraries: [micro-sol-signer](https://github.com/paulmillr/micro-sol-signer), [solana-web3.js](https://github.com/solana-labs/solana-web3.js)
|
|
956
|
-
- [polkadot.js](https://github.com/polkadot-js/common), [micro-starknet](https://github.com/paulmillr/micro-starknet)
|
|
957
|
-
- [protonmail](https://github.com/ProtonMail/WebClients) (old noble-ed25519 for now)
|
|
958
|
-
- [did-jwt](https://github.com/decentralized-identity/did-jwt), [hpke-js](https://github.com/dajiaji/hpke-js), [nostr-tools](https://github.com/nbd-wtf/nostr-tools)
|
|
959
|
-
- [ed25519-keygen](https://github.com/paulmillr/ed25519-keygen) SSH, PGP, TOR key generation
|
|
960
|
-
- [secp256k1 compatibility layer](https://github.com/ethereum/js-ethereum-cryptography/blob/2.0.0/src/secp256k1-compat.ts)
|
|
961
|
-
for users who want to switch from secp256k1-node or tiny-secp256k1. Allows to see which methods map to corresponding noble code.
|
|
962
|
-
- [BLS BBS signatures](https://github.com/Wind4Greg/BBS-Draft-Checks) following [draft-irtf-cfrg-bbs-signatures-latest](https://identity.foundation/bbs-signature/draft-irtf-cfrg-bbs-signatures.html)
|
|
963
|
-
- [KZG trusted setup ceremony](https://github.com/dsrvlabs/czg-keremony)
|
|
998
|
+
Check out [paulmillr.com/noble](https://paulmillr.com/noble/)
|
|
999
|
+
for useful resources, articles, documentation and demos
|
|
1000
|
+
related to the library.
|
|
964
1001
|
|
|
965
1002
|
## License
|
|
966
1003
|
|