@noble/curves 0.4.0 → 0.5.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 +203 -162
- package/lib/_shortw_utils.d.ts +75 -0
- package/lib/_shortw_utils.js +20 -0
- package/lib/{bls.d.ts → abstract/bls.d.ts} +2 -1
- package/lib/{bls.js → abstract/bls.js} +28 -27
- package/lib/{edwards.d.ts → abstract/edwards.d.ts} +17 -0
- package/lib/{edwards.js → abstract/edwards.js} +45 -4
- package/lib/{group.d.ts → abstract/group.d.ts} +2 -1
- package/lib/{group.js → abstract/group.js} +4 -3
- package/lib/{hashToCurve.d.ts → abstract/hash-to-curve.d.ts} +6 -0
- package/lib/{hashToCurve.js → abstract/hash-to-curve.js} +15 -2
- package/lib/{modular.d.ts → abstract/modular.d.ts} +10 -4
- package/lib/{modular.js → abstract/modular.js} +110 -19
- package/lib/{montgomery.d.ts → abstract/montgomery.d.ts} +2 -1
- package/lib/{montgomery.js → abstract/montgomery.js} +17 -8
- package/lib/{utils.d.ts → abstract/utils.d.ts} +1 -1
- package/lib/{utils.js → abstract/utils.js} +1 -1
- package/lib/{weierstrass.d.ts → abstract/weierstrass.d.ts} +28 -16
- package/lib/{weierstrass.js → abstract/weierstrass.js} +261 -127
- package/lib/bls12-381.d.ts +66 -0
- package/lib/bls12-381.js +1132 -0
- package/lib/bn.d.ts +7 -0
- package/lib/bn.js +24 -0
- package/lib/ed25519.d.ts +48 -0
- package/lib/ed25519.js +322 -0
- package/lib/ed448.d.ts +3 -0
- package/lib/ed448.js +128 -0
- package/lib/esm/_shortw_utils.js +15 -0
- package/lib/esm/{bls.js → abstract/bls.js} +25 -24
- package/lib/esm/{edwards.js → abstract/edwards.js} +45 -4
- package/lib/esm/{group.js → abstract/group.js} +4 -3
- package/lib/esm/{hashToCurve.js → abstract/hash-to-curve.js} +13 -1
- package/lib/esm/{modular.js → abstract/modular.js} +108 -18
- package/lib/esm/{montgomery.js → abstract/montgomery.js} +17 -8
- package/lib/esm/{utils.js → abstract/utils.js} +1 -1
- package/lib/esm/{weierstrass.js → abstract/weierstrass.js} +255 -123
- package/lib/esm/bls12-381.js +1129 -0
- package/lib/esm/bn.js +21 -0
- package/lib/esm/ed25519.js +318 -0
- package/lib/esm/ed448.js +125 -0
- package/lib/esm/index.js +2 -0
- package/lib/esm/jubjub.js +52 -0
- package/lib/esm/p192.js +21 -0
- package/lib/esm/p224.js +21 -0
- package/lib/esm/p256.js +39 -0
- package/lib/esm/p384.js +44 -0
- package/lib/esm/p521.js +58 -0
- package/lib/esm/pasta.js +29 -0
- package/lib/esm/secp256k1.js +290 -0
- package/lib/esm/stark.js +222 -0
- package/lib/index.d.ts +0 -0
- package/lib/index.js +2 -0
- package/lib/jubjub.d.ts +7 -0
- package/lib/jubjub.js +57 -0
- package/lib/p192.d.ts +130 -0
- package/lib/p192.js +24 -0
- package/lib/p224.d.ts +130 -0
- package/lib/p224.js +24 -0
- package/lib/p256.d.ts +130 -0
- package/lib/p256.js +42 -0
- package/lib/p384.d.ts +130 -0
- package/lib/p384.js +47 -0
- package/lib/p521.d.ts +131 -0
- package/lib/p521.js +61 -0
- package/lib/pasta.d.ts +4 -0
- package/lib/pasta.js +32 -0
- package/lib/secp256k1.d.ts +96 -0
- package/lib/secp256k1.js +294 -0
- package/lib/stark.d.ts +72 -0
- package/lib/stark.js +243 -0
- package/package.json +146 -50
- package/index.js +0 -1
package/README.md
CHANGED
|
@@ -1,38 +1,44 @@
|
|
|
1
1
|
# noble-curves
|
|
2
2
|
|
|
3
|
-
Minimal,
|
|
4
|
-
|
|
5
|
-
- Short Weierstrass
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
3
|
+
Minimal, auditable JS implementation of elliptic curve cryptography.
|
|
4
|
+
|
|
5
|
+
- Short Weierstrass, Edwards, Montgomery curves
|
|
6
|
+
- ECDSA, EdDSA, Schnorr, BLS signature schemes, ECDH key agreement
|
|
7
|
+
- [hash to curve](https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/)
|
|
8
|
+
for encoding or hashing an arbitrary string to a point on an elliptic curve
|
|
9
|
+
- Auditable, [fast](#speed)
|
|
10
|
+
- 🔻 Tree-shaking-friendly: there is no entry point, which ensures small size of your app
|
|
11
|
+
- 🔍 Unique tests ensure correctness. Wycheproof vectors included
|
|
12
|
+
|
|
13
|
+
There are two parts of the package:
|
|
14
|
+
|
|
15
|
+
1. `abstract/` directory specifies zero-dependency EC algorithms
|
|
16
|
+
2. root directory utilizes one dependency `@noble/hashes` and provides ready-to-use:
|
|
17
|
+
- NIST curves secp192r1/P192, secp224r1/P224, secp256r1/P256, secp384r1/P384, secp521r1/P521
|
|
18
|
+
- SECG curve secp256k1
|
|
19
|
+
- pairing-friendly curves bls12-381, bn254
|
|
20
|
+
- ed25519/curve25519/x25519/ristretto, edwards448/curve448/x448 RFC7748 / RFC8032 / ZIP215 stuff
|
|
21
|
+
|
|
22
|
+
Curves incorporate work from previous noble packages
|
|
23
|
+
([secp256k1](https://github.com/paulmillr/noble-secp256k1),
|
|
24
|
+
[ed25519](https://github.com/paulmillr/noble-ed25519),
|
|
25
|
+
[bls12-381](https://github.com/paulmillr/noble-bls12-381)),
|
|
26
|
+
which had security audits and were developed from 2019 to 2022.
|
|
27
|
+
The goal is to replace them with lean UMD builds based on single-codebase noble-curves.
|
|
21
28
|
|
|
22
29
|
### This library belongs to _noble_ crypto
|
|
23
30
|
|
|
24
31
|
> **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools.
|
|
25
32
|
|
|
26
|
-
-
|
|
33
|
+
- Minimal dependencies, small files
|
|
27
34
|
- Easily auditable TypeScript/JS code
|
|
28
35
|
- Supported in all major browsers and stable node.js versions
|
|
29
36
|
- All releases are signed with PGP keys
|
|
30
37
|
- Check out [homepage](https://paulmillr.com/noble/) & all libraries:
|
|
31
|
-
[secp256k1](https://github.com/paulmillr/noble-secp256k1),
|
|
38
|
+
[curves](https://github.com/paulmillr/noble-curves) ([secp256k1](https://github.com/paulmillr/noble-secp256k1),
|
|
32
39
|
[ed25519](https://github.com/paulmillr/noble-ed25519),
|
|
33
|
-
[bls12-381](https://github.com/paulmillr/noble-bls12-381),
|
|
34
|
-
[hashes](https://github.com/paulmillr/noble-hashes)
|
|
35
|
-
[curves](https://github.com/paulmillr/noble-curves)
|
|
40
|
+
[bls12-381](https://github.com/paulmillr/noble-bls12-381)),
|
|
41
|
+
[hashes](https://github.com/paulmillr/noble-hashes)
|
|
36
42
|
|
|
37
43
|
## Usage
|
|
38
44
|
|
|
@@ -44,82 +50,122 @@ Use NPM in node.js / browser, or include single file from
|
|
|
44
50
|
The library does not have an entry point. It allows you to select specific primitives and drop everything else. If you only want to use secp256k1, just use the library with rollup or other bundlers. This is done to make your bundles tiny.
|
|
45
51
|
|
|
46
52
|
```ts
|
|
47
|
-
|
|
48
|
-
import {
|
|
49
|
-
import { hmac } from '@noble/hashes/hmac';
|
|
50
|
-
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
|
51
|
-
|
|
52
|
-
const secp256k1 = weierstrass({
|
|
53
|
-
a: 0n,
|
|
54
|
-
b: 7n,
|
|
55
|
-
P: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn,
|
|
56
|
-
n: 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n,
|
|
57
|
-
Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
|
|
58
|
-
Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
|
|
59
|
-
hash: sha256,
|
|
60
|
-
hmac: (k: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)),
|
|
61
|
-
});
|
|
53
|
+
// Common.js and ECMAScript Modules (ESM)
|
|
54
|
+
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
62
55
|
|
|
63
56
|
const key = secp256k1.utils.randomPrivateKey();
|
|
64
57
|
const pub = secp256k1.getPublicKey(key);
|
|
65
|
-
const msg =
|
|
58
|
+
const msg = new Uint8Array(32).fill(1);
|
|
66
59
|
const sig = secp256k1.sign(msg, key);
|
|
67
|
-
secp256k1.verify(sig, msg, pub)
|
|
68
|
-
sig.recoverPublicKey(msg)
|
|
69
|
-
const
|
|
70
|
-
const shared = secp256k1.getSharedSecret(key,
|
|
60
|
+
secp256k1.verify(sig, msg, pub) === true;
|
|
61
|
+
sig.recoverPublicKey(msg) === pub;
|
|
62
|
+
const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
|
|
63
|
+
const shared = secp256k1.getSharedSecret(key, someonesPub);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
All curves:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
70
|
+
import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519';
|
|
71
|
+
import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448';
|
|
72
|
+
import { p256 } from '@noble/curves/p256';
|
|
73
|
+
import { p384 } from '@noble/curves/p384';
|
|
74
|
+
import { p521 } from '@noble/curves/p521';
|
|
75
|
+
import { pallas, vesta } from '@noble/curves/pasta';
|
|
76
|
+
import * as stark from '@noble/curves/stark';
|
|
77
|
+
import { bls12_381 } from '@noble/curves/bls12-381';
|
|
78
|
+
import { bn254 } from '@noble/curves/bn';
|
|
79
|
+
import { jubjub } from '@noble/curves/jubjub';
|
|
71
80
|
```
|
|
72
81
|
|
|
82
|
+
To define a custom curve, check out API below.
|
|
83
|
+
|
|
73
84
|
## API
|
|
74
85
|
|
|
75
86
|
- [Overview](#overview)
|
|
76
|
-
- [edwards: Twisted Edwards curve](#edwards-twisted-edwards-curve)
|
|
77
|
-
- [montgomery: Montgomery curve](#montgomery-montgomery-curve)
|
|
78
|
-
- [weierstrass: Short Weierstrass curve](#weierstrass-short-weierstrass-curve)
|
|
79
|
-
- [modular](#modular)
|
|
80
|
-
- [utils](#utils)
|
|
87
|
+
- [abstract/edwards: Twisted Edwards curve](#abstract/edwards-twisted-edwards-curve)
|
|
88
|
+
- [abstract/montgomery: Montgomery curve](#abstract/montgomery-montgomery-curve)
|
|
89
|
+
- [abstract/weierstrass: Short Weierstrass curve](#abstract/weierstrass-short-weierstrass-curve)
|
|
90
|
+
- [abstract/modular](#abstract/modular)
|
|
91
|
+
- [abstract/utils](#abstract/utils)
|
|
81
92
|
|
|
82
93
|
### Overview
|
|
83
94
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
*
|
|
95
|
+
There are following zero-dependency abstract algorithms:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
import { bls } from '@noble/curves/abstract/bls';
|
|
99
|
+
import { twistedEdwards } from '@noble/curves/abstract/edwards';
|
|
100
|
+
import { montgomery } from '@noble/curves/abstract/montgomery';
|
|
101
|
+
import { weierstrass } from '@noble/curves/abstract/weierstrass';
|
|
102
|
+
import * as mod from '@noble/curves/abstract/modular';
|
|
103
|
+
import * as utils from '@noble/curves/abstract/utils';
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
They allow to define a new curve in a few lines of code:
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import { Fp } from '@noble/curves/abstract/modular';
|
|
110
|
+
import { weierstrass } from '@noble/curves/abstract/weierstrass';
|
|
111
|
+
import { hmac } from '@noble/hashes/hmac';
|
|
112
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
113
|
+
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
|
114
|
+
|
|
115
|
+
const secp256k1 = weierstrass({
|
|
116
|
+
a: 0n,
|
|
117
|
+
b: 7n,
|
|
118
|
+
Fp: Fp(2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n),
|
|
119
|
+
n: 2n ** 256n - 432420386565659656852420866394968145599n,
|
|
120
|
+
Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
|
|
121
|
+
Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
|
|
122
|
+
hash: sha256,
|
|
123
|
+
hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)),
|
|
124
|
+
randomBytes,
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
- To initialize new curve, you must specify its variables, order (number of points on curve), field prime (over which the modular division would be done)
|
|
129
|
+
- All curves expose same generic interface:
|
|
130
|
+
- `getPublicKey()`, `sign()`, `verify()` functions
|
|
131
|
+
- `Point` conforming to `Group` interface with add/multiply/double/negate/add/equals methods
|
|
132
|
+
- `CURVE` object with curve variables like `Gx`, `Gy`, `Fp` (field), `n` (order)
|
|
133
|
+
- `utils` object with `randomPrivateKey()`, `mod()`, `invert()` methods (`mod CURVE.P`)
|
|
134
|
+
- All arithmetics is done with JS bigints over finite fields, which is defined from `modular` sub-module
|
|
135
|
+
- Many features require hashing, which is not provided. `@noble/hashes` can be used for this purpose.
|
|
92
136
|
Any other library must conform to the CHash interface:
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
137
|
+
```ts
|
|
138
|
+
export type CHash = {
|
|
139
|
+
(message: Uint8Array): Uint8Array;
|
|
140
|
+
blockLen: number;
|
|
141
|
+
outputLen: number;
|
|
142
|
+
create(): any;
|
|
143
|
+
};
|
|
144
|
+
```
|
|
145
|
+
- w-ary non-adjacent form (wNAF) method with constant-time adjustments is used for point multiplication.
|
|
100
146
|
It is possible to enable precomputes for edwards & weierstrass curves.
|
|
101
|
-
Precomputes are calculated once (takes ~20-40ms), after that most `G` multiplications
|
|
102
|
-
|
|
103
|
-
Use `curve.utils.precompute()`
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
147
|
+
Precomputes are calculated once (takes ~20-40ms), after that most `G` base point multiplications:
|
|
148
|
+
for example, `getPublicKey()`, `sign()` and similar methods - would be much faster.
|
|
149
|
+
Use `curve.utils.precompute()` to adjust precomputation window size
|
|
150
|
+
- You could use optional special params to tune performance:
|
|
151
|
+
- `Fp({sqrt})` square root calculation, used for point decompression
|
|
152
|
+
- `endo` endomorphism options for Koblitz curves
|
|
107
153
|
|
|
108
|
-
### edwards: Twisted Edwards curve
|
|
154
|
+
### abstract/edwards: Twisted Edwards curve
|
|
109
155
|
|
|
110
156
|
Twisted Edwards curve's formula is: ax² + y² = 1 + dx²y².
|
|
111
157
|
|
|
112
|
-
|
|
113
|
-
|
|
158
|
+
- You must specify curve params `a`, `d`, field `Fp`, order `n`, cofactor `h` and coordinates `Gx`, `Gy` of generator point
|
|
159
|
+
- For EdDSA signatures, params `hash` is also required. `adjustScalarBytes` which instructs how to change private scalars could be specified
|
|
114
160
|
|
|
115
161
|
```typescript
|
|
116
|
-
import { twistedEdwards } from '@noble/curves/edwards';
|
|
162
|
+
import { twistedEdwards } from '@noble/curves/abstract/edwards';
|
|
163
|
+
import { div } from '@noble/curves/abstract/modular';
|
|
117
164
|
import { sha512 } from '@noble/hashes/sha512';
|
|
118
|
-
import * as mod from '@noble/curves/modular';
|
|
119
165
|
|
|
120
166
|
const ed25519 = twistedEdwards({
|
|
121
167
|
a: -1n,
|
|
122
|
-
d:
|
|
168
|
+
d: div(-121665n, 121666n, 2n ** 255n - 19n), // -121665n/121666n
|
|
123
169
|
P: 2n ** 255n - 19n,
|
|
124
170
|
n: 2n ** 252n + 27742317777372353535851937790883648493n,
|
|
125
171
|
h: 8n,
|
|
@@ -127,14 +173,19 @@ const ed25519 = twistedEdwards({
|
|
|
127
173
|
Gy: 46316835694926478169428394003475163141307993866256225615783033603165251855960n,
|
|
128
174
|
hash: sha512,
|
|
129
175
|
randomBytes,
|
|
130
|
-
adjustScalarBytes(bytes) {
|
|
176
|
+
adjustScalarBytes(bytes) {
|
|
177
|
+
// optional in general, mandatory in ed25519
|
|
131
178
|
bytes[0] &= 248;
|
|
132
179
|
bytes[31] &= 127;
|
|
133
180
|
bytes[31] |= 64;
|
|
134
181
|
return bytes;
|
|
135
182
|
},
|
|
136
183
|
} as const);
|
|
137
|
-
ed25519.
|
|
184
|
+
const key = ed25519.utils.randomPrivateKey();
|
|
185
|
+
const pub = ed25519.getPublicKey(key);
|
|
186
|
+
const msg = new TextEncoder().encode('hello world'); // strings not accepted, must be Uint8Array
|
|
187
|
+
const sig = ed25519.sign(msg, key);
|
|
188
|
+
ed25519.verify(sig, msg, pub) === true;
|
|
138
189
|
```
|
|
139
190
|
|
|
140
191
|
`twistedEdwards()` returns `CurveFn` of following type:
|
|
@@ -163,7 +214,7 @@ export type CurveFn = {
|
|
|
163
214
|
};
|
|
164
215
|
```
|
|
165
216
|
|
|
166
|
-
### montgomery: Montgomery curve
|
|
217
|
+
### abstract/montgomery: Montgomery curve
|
|
167
218
|
|
|
168
219
|
For now the module only contains methods for x-only ECDH on Curve25519 / Curve448 from RFC7748.
|
|
169
220
|
|
|
@@ -172,6 +223,8 @@ Proper Elliptic Curve Points are not implemented yet.
|
|
|
172
223
|
You must specify curve field, `a24` special variable, `montgomeryBits`, `nByteLength`, and coordinate `u` of generator point.
|
|
173
224
|
|
|
174
225
|
```typescript
|
|
226
|
+
import { montgomery } from '@noble/curves/abstract/montgomery';
|
|
227
|
+
|
|
175
228
|
const x25519 = montgomery({
|
|
176
229
|
P: 2n ** 255n - 19n,
|
|
177
230
|
a24: 121665n, // TODO: change to a
|
|
@@ -180,7 +233,9 @@ const x25519 = montgomery({
|
|
|
180
233
|
Gu: '0900000000000000000000000000000000000000000000000000000000000000',
|
|
181
234
|
|
|
182
235
|
// Optional params
|
|
183
|
-
powPminus2: (x: bigint): bigint => {
|
|
236
|
+
powPminus2: (x: bigint): bigint => {
|
|
237
|
+
return mod.pow(x, P - 2, P);
|
|
238
|
+
},
|
|
184
239
|
adjustScalarBytes(bytes) {
|
|
185
240
|
bytes[0] &= 248;
|
|
186
241
|
bytes[31] &= 127;
|
|
@@ -190,27 +245,27 @@ const x25519 = montgomery({
|
|
|
190
245
|
});
|
|
191
246
|
```
|
|
192
247
|
|
|
193
|
-
### weierstrass: Short Weierstrass curve
|
|
248
|
+
### abstract/weierstrass: Short Weierstrass curve
|
|
194
249
|
|
|
195
250
|
Short Weierstrass curve's formula is: y² = x³ + ax + b. Uses deterministic ECDSA from RFC6979. You can also specify `extraEntropy` in `sign()`.
|
|
196
251
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
252
|
+
- You must specify curve params: `a`, `b`, field `Fp`, order `n`, cofactor `h` and coordinates `Gx`, `Gy` of generator point
|
|
253
|
+
- For ECDSA, you must specify `hash`, `hmac`. It is also possible to recover keys from signatures
|
|
254
|
+
- For ECDH, use `getSharedSecret(privKeyA, pubKeyB)`
|
|
255
|
+
- Optional params are `lowS` (default value) and `endo` (endomorphism)
|
|
201
256
|
|
|
202
257
|
```typescript
|
|
203
|
-
import {
|
|
258
|
+
import { Fp } from '@noble/curves/abstract/modular';
|
|
259
|
+
import { weierstrass } from '@noble/curves/abstract/weierstrass'; // Short Weierstrass curve
|
|
204
260
|
import { sha256 } from '@noble/hashes/sha256';
|
|
205
261
|
import { hmac } from '@noble/hashes/hmac';
|
|
206
262
|
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
|
207
263
|
|
|
208
264
|
const secp256k1 = weierstrass({
|
|
209
|
-
// Required params
|
|
210
265
|
a: 0n,
|
|
211
266
|
b: 7n,
|
|
212
|
-
|
|
213
|
-
n:
|
|
267
|
+
Fp: Fp(2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n),
|
|
268
|
+
n: 2n ** 256n - 432420386565659656852420866394968145599n,
|
|
214
269
|
Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
|
|
215
270
|
Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
|
|
216
271
|
hash: sha256,
|
|
@@ -218,19 +273,15 @@ const secp256k1 = weierstrass({
|
|
|
218
273
|
randomBytes,
|
|
219
274
|
|
|
220
275
|
// Optional params
|
|
221
|
-
// Cofactor
|
|
222
|
-
|
|
223
|
-
// Allow only low-S signatures by default in sign() and verify()
|
|
224
|
-
lowS: true,
|
|
225
|
-
// More efficient curve-specific implementation of square root
|
|
226
|
-
sqrtMod(y: bigint) { return sqrt(y); },
|
|
227
|
-
// Endomorphism options
|
|
276
|
+
h: 1n, // Cofactor
|
|
277
|
+
lowS: true, // Allow only low-S signatures by default in sign() and verify()
|
|
228
278
|
endo: {
|
|
279
|
+
// Endomorphism options for Koblitz curve
|
|
229
280
|
// Beta param
|
|
230
|
-
beta:
|
|
281
|
+
beta: 0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501een,
|
|
231
282
|
// Split scalar k into k1, k2
|
|
232
283
|
splitScalar: (k: bigint) => {
|
|
233
|
-
return { k1neg: true, k1: 512n, k2neg: false, k2: 448n };
|
|
284
|
+
// return { k1neg: true, k1: 512n, k2neg: false, k2: 448n };
|
|
234
285
|
},
|
|
235
286
|
},
|
|
236
287
|
});
|
|
@@ -255,14 +306,17 @@ export type CurveFn = {
|
|
|
255
306
|
getSharedSecret: (privateA: PrivKey, publicB: PubKey, isCompressed?: boolean) => Uint8Array;
|
|
256
307
|
sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => SignatureType;
|
|
257
308
|
verify: (
|
|
258
|
-
signature: Hex | SignatureType,
|
|
309
|
+
signature: Hex | SignatureType,
|
|
310
|
+
msgHash: Hex,
|
|
311
|
+
publicKey: PubKey,
|
|
312
|
+
opts?: { lowS?: boolean }
|
|
259
313
|
) => boolean;
|
|
260
314
|
Point: PointConstructor;
|
|
261
|
-
|
|
315
|
+
ProjectivePoint: ProjectivePointConstructor;
|
|
262
316
|
Signature: SignatureConstructor;
|
|
263
317
|
utils: {
|
|
264
|
-
mod: (a: bigint
|
|
265
|
-
invert: (number: bigint
|
|
318
|
+
mod: (a: bigint) => bigint;
|
|
319
|
+
invert: (number: bigint) => bigint;
|
|
266
320
|
isValidPrivateKey(privateKey: PrivKey): boolean;
|
|
267
321
|
hashToPrivateKey: (hash: Hex) => Uint8Array;
|
|
268
322
|
randomPrivateKey: () => Uint8Array;
|
|
@@ -270,23 +324,26 @@ export type CurveFn = {
|
|
|
270
324
|
};
|
|
271
325
|
```
|
|
272
326
|
|
|
273
|
-
### modular
|
|
327
|
+
### abstract/modular
|
|
274
328
|
|
|
275
329
|
Modular arithmetics utilities.
|
|
276
330
|
|
|
277
331
|
```typescript
|
|
278
|
-
import
|
|
279
|
-
mod
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
332
|
+
import { mod, invert, div, invertBatch, sqrt, Fp } from '@noble/curves/abstract/modular';
|
|
333
|
+
mod(21n, 10n); // 21 mod 10 == 1n; fixed version of 21 % 10
|
|
334
|
+
invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse
|
|
335
|
+
div(5n, 17n, 10n); // 5/17 mod 10 == 5 * invert(17) mod 10; division
|
|
336
|
+
invertBatch([1n, 2n, 4n], 21n); // => [1n, 11n, 16n] in one inversion
|
|
337
|
+
sqrt(21n, 73n); // √21 mod 73; square root
|
|
338
|
+
const fp = Fp(2n ** 255n - 19n); // Finite field over 2^255-19
|
|
339
|
+
fp.mul(591n, 932n);
|
|
340
|
+
fp.pow(481n, 11024858120n);
|
|
284
341
|
```
|
|
285
342
|
|
|
286
|
-
### utils
|
|
343
|
+
### abstract/utils
|
|
287
344
|
|
|
288
345
|
```typescript
|
|
289
|
-
import * as utils from '@noble/curves/utils';
|
|
346
|
+
import * as utils from '@noble/curves/abstract/utils';
|
|
290
347
|
|
|
291
348
|
utils.bytesToHex(Uint8Array.from([0xde, 0xad, 0xbe, 0xef]));
|
|
292
349
|
utils.hexToBytes('deadbeef');
|
|
@@ -315,59 +372,43 @@ We consider infrastructure attacks like rogue NPM modules very important; that's
|
|
|
315
372
|
Benchmark results on Apple M2 with node v18.10:
|
|
316
373
|
|
|
317
374
|
```
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
noble x 1,561 ops/sec @ 640μs/op
|
|
349
|
-
- verify (samples: 500)
|
|
350
|
-
noble x 313 ops/sec @ 3ms/op
|
|
351
|
-
==== nist ====
|
|
352
|
-
- getPublicKey (samples: 2500)
|
|
353
|
-
P256 x 7,993 ops/sec @ 125μs/op
|
|
354
|
-
P384 x 3,819 ops/sec @ 261μs/op
|
|
355
|
-
P521 x 2,074 ops/sec @ 481μs/op
|
|
356
|
-
- sign (samples: 1000)
|
|
357
|
-
P256 x 5,327 ops/sec @ 187μs/op
|
|
358
|
-
P384 x 2,728 ops/sec @ 366μs/op
|
|
359
|
-
P521 x 1,594 ops/sec @ 626μs/op
|
|
360
|
-
- verify (samples: 250)
|
|
361
|
-
P256 x 806 ops/sec @ 1ms/op
|
|
362
|
-
P384 x 353 ops/sec @ 2ms/op
|
|
363
|
-
P521 x 171 ops/sec @ 5ms/op
|
|
375
|
+
getPublicKey
|
|
376
|
+
secp256k1 x 5,241 ops/sec @ 190μs/op
|
|
377
|
+
P256 x 7,993 ops/sec @ 125μs/op
|
|
378
|
+
P384 x 3,819 ops/sec @ 261μs/op
|
|
379
|
+
P521 x 2,074 ops/sec @ 481μs/op
|
|
380
|
+
ed25519 x 8,390 ops/sec @ 119μs/op
|
|
381
|
+
ed448 x 3,224 ops/sec @ 310μs/op
|
|
382
|
+
sign
|
|
383
|
+
secp256k1 x 3,934 ops/sec @ 254μs/op
|
|
384
|
+
P256 x 5,327 ops/sec @ 187μs/op
|
|
385
|
+
P384 x 2,728 ops/sec @ 366μs/op
|
|
386
|
+
P521 x 1,594 ops/sec @ 626μs/op
|
|
387
|
+
ed25519 x 4,233 ops/sec @ 236μs/op
|
|
388
|
+
ed448 x 1,561 ops/sec @ 640μs/op
|
|
389
|
+
verify
|
|
390
|
+
secp256k1 x 731 ops/sec @ 1ms/op
|
|
391
|
+
P256 x 806 ops/sec @ 1ms/op
|
|
392
|
+
P384 x 353 ops/sec @ 2ms/op
|
|
393
|
+
P521 x 171 ops/sec @ 5ms/op
|
|
394
|
+
ed25519 x 860 ops/sec @ 1ms/op
|
|
395
|
+
ed448 x 313 ops/sec @ 3ms/op
|
|
396
|
+
getSharedSecret
|
|
397
|
+
secp256k1 x 445 ops/sec @ 2ms/op
|
|
398
|
+
recoverPublicKey
|
|
399
|
+
secp256k1 x 732 ops/sec @ 1ms/op
|
|
400
|
+
==== bls12-381 ====
|
|
401
|
+
getPublicKey x 817 ops/sec @ 1ms/op
|
|
402
|
+
sign x 50 ops/sec @ 19ms/op
|
|
403
|
+
verify x 34 ops/sec @ 28ms/op
|
|
404
|
+
pairing x 89 ops/sec @ 11ms/op
|
|
364
405
|
==== stark ====
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
406
|
+
pedersen
|
|
407
|
+
old x 85 ops/sec @ 11ms/op
|
|
408
|
+
noble x 1,216 ops/sec @ 822μs/op
|
|
409
|
+
verify
|
|
410
|
+
old x 302 ops/sec @ 3ms/op
|
|
411
|
+
noble x 698 ops/sec @ 1ms/op
|
|
371
412
|
```
|
|
372
413
|
|
|
373
414
|
## Contributing & testing
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { randomBytes } from '@noble/hashes/utils';
|
|
2
|
+
import { CurveType } from './abstract/weierstrass.js';
|
|
3
|
+
import { CHash } from './abstract/utils.js';
|
|
4
|
+
export declare function getHash(hash: CHash): {
|
|
5
|
+
hash: CHash;
|
|
6
|
+
hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => Uint8Array;
|
|
7
|
+
randomBytes: typeof randomBytes;
|
|
8
|
+
};
|
|
9
|
+
declare type CurveDef = Readonly<Omit<CurveType, 'hash' | 'hmac' | 'randomBytes'>>;
|
|
10
|
+
export declare function createCurve(curveDef: CurveDef, defHash: CHash): Readonly<{
|
|
11
|
+
create: (hash: CHash) => import("./abstract/weierstrass.js").CurveFn;
|
|
12
|
+
CURVE: Readonly<{
|
|
13
|
+
readonly nBitLength: number;
|
|
14
|
+
readonly nByteLength: number;
|
|
15
|
+
readonly Fp: import("./abstract/modular.js").Field<bigint>;
|
|
16
|
+
readonly n: bigint;
|
|
17
|
+
readonly h: bigint;
|
|
18
|
+
readonly hEff?: bigint | undefined;
|
|
19
|
+
readonly Gx: bigint;
|
|
20
|
+
readonly Gy: bigint;
|
|
21
|
+
readonly wrapPrivateKey?: boolean | undefined;
|
|
22
|
+
readonly allowInfinityPoint?: boolean | undefined;
|
|
23
|
+
readonly a: bigint;
|
|
24
|
+
readonly b: bigint;
|
|
25
|
+
readonly normalizePrivateKey?: ((key: import("./abstract/utils.js").PrivKey) => import("./abstract/utils.js").PrivKey) | undefined;
|
|
26
|
+
readonly endo?: {
|
|
27
|
+
beta: bigint;
|
|
28
|
+
splitScalar: (k: bigint) => {
|
|
29
|
+
k1neg: boolean;
|
|
30
|
+
k1: bigint;
|
|
31
|
+
k2neg: boolean;
|
|
32
|
+
k2: bigint;
|
|
33
|
+
};
|
|
34
|
+
} | undefined;
|
|
35
|
+
readonly isTorsionFree?: ((c: import("./abstract/weierstrass.js").ProjectiveConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjectivePointType<bigint>) => boolean) | undefined;
|
|
36
|
+
readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjectiveConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjectivePointType<bigint>) => import("./abstract/weierstrass.js").ProjectivePointType<bigint>) | undefined;
|
|
37
|
+
readonly htfDefaults?: import("./abstract/hash-to-curve.js").htfOpts | undefined;
|
|
38
|
+
readonly mapToCurve?: ((scalar: bigint[]) => {
|
|
39
|
+
x: bigint;
|
|
40
|
+
y: bigint;
|
|
41
|
+
}) | undefined;
|
|
42
|
+
lowS: boolean;
|
|
43
|
+
readonly hash: CHash;
|
|
44
|
+
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
|
45
|
+
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
|
|
46
|
+
readonly truncateHash?: ((hash: Uint8Array, truncateOnly?: boolean | undefined) => bigint) | undefined;
|
|
47
|
+
}>;
|
|
48
|
+
getPublicKey: (privateKey: import("./abstract/utils.js").PrivKey, isCompressed?: boolean | undefined) => Uint8Array;
|
|
49
|
+
getSharedSecret: (privateA: import("./abstract/utils.js").PrivKey, publicB: import("./abstract/weierstrass.js").PubKey, isCompressed?: boolean | undefined) => Uint8Array;
|
|
50
|
+
sign: (msgHash: import("./abstract/utils.js").Hex, privKey: import("./abstract/utils.js").PrivKey, opts?: {
|
|
51
|
+
lowS?: boolean | undefined;
|
|
52
|
+
extraEntropy?: (true | import("./abstract/utils.js").Hex) | undefined;
|
|
53
|
+
} | undefined) => import("./abstract/weierstrass.js").SignatureType;
|
|
54
|
+
verify: (signature: import("./abstract/utils.js").Hex | import("./abstract/weierstrass.js").SignatureType, msgHash: import("./abstract/utils.js").Hex, publicKey: import("./abstract/weierstrass.js").PubKey, opts?: {
|
|
55
|
+
lowS?: boolean | undefined;
|
|
56
|
+
} | undefined) => boolean;
|
|
57
|
+
Point: import("./abstract/weierstrass.js").PointConstructor<bigint>;
|
|
58
|
+
ProjectivePoint: import("./abstract/weierstrass.js").ProjectiveConstructor<bigint>;
|
|
59
|
+
Signature: import("./abstract/weierstrass.js").SignatureConstructor;
|
|
60
|
+
utils: {
|
|
61
|
+
mod: (a: bigint, b?: bigint | undefined) => bigint;
|
|
62
|
+
invert: (number: bigint, modulo?: bigint | undefined) => bigint;
|
|
63
|
+
_bigintToBytes: (num: bigint) => Uint8Array;
|
|
64
|
+
_bigintToString: (num: bigint) => string;
|
|
65
|
+
_normalizePrivateKey: (key: import("./abstract/utils.js").PrivKey) => bigint;
|
|
66
|
+
_normalizePublicKey: (publicKey: import("./abstract/weierstrass.js").PubKey) => import("./abstract/weierstrass.js").PointType<bigint>;
|
|
67
|
+
_isWithinCurveOrder: (num: bigint) => boolean;
|
|
68
|
+
_isValidFieldElement: (num: bigint) => boolean;
|
|
69
|
+
_weierstrassEquation: (x: bigint) => bigint;
|
|
70
|
+
isValidPrivateKey(privateKey: import("./abstract/utils.js").PrivKey): boolean;
|
|
71
|
+
hashToPrivateKey: (hash: import("./abstract/utils.js").Hex) => Uint8Array;
|
|
72
|
+
randomPrivateKey: () => Uint8Array;
|
|
73
|
+
};
|
|
74
|
+
}>;
|
|
75
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createCurve = exports.getHash = void 0;
|
|
4
|
+
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
5
|
+
const hmac_1 = require("@noble/hashes/hmac");
|
|
6
|
+
const utils_1 = require("@noble/hashes/utils");
|
|
7
|
+
const weierstrass_js_1 = require("./abstract/weierstrass.js");
|
|
8
|
+
function getHash(hash) {
|
|
9
|
+
return {
|
|
10
|
+
hash,
|
|
11
|
+
hmac: (key, ...msgs) => (0, hmac_1.hmac)(hash, key, (0, utils_1.concatBytes)(...msgs)),
|
|
12
|
+
randomBytes: utils_1.randomBytes,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
exports.getHash = getHash;
|
|
16
|
+
function createCurve(curveDef, defHash) {
|
|
17
|
+
const create = (hash) => (0, weierstrass_js_1.weierstrass)({ ...curveDef, ...getHash(hash) });
|
|
18
|
+
return Object.freeze({ ...create(defHash), create });
|
|
19
|
+
}
|
|
20
|
+
exports.createCurve = createCurve;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
1
2
|
import * as mod from './modular.js';
|
|
2
3
|
import * as utils from './utils.js';
|
|
3
4
|
import { Hex, PrivKey } from './utils.js';
|
|
4
|
-
import { htfOpts, stringToBytes, hash_to_field, expand_message_xmd } from './
|
|
5
|
+
import { htfOpts, stringToBytes, hash_to_field, expand_message_xmd } from './hash-to-curve.js';
|
|
5
6
|
import { CurvePointsType, PointType, CurvePointsRes } from './weierstrass.js';
|
|
6
7
|
declare type Fp = bigint;
|
|
7
8
|
export declare type SignatureCoder<Fp2> = {
|