@noble/curves 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +254 -162
  2. package/lib/_shortw_utils.d.ts +75 -0
  3. package/lib/_shortw_utils.js +20 -0
  4. package/lib/{bls.d.ts → abstract/bls.d.ts} +2 -1
  5. package/lib/{bls.js → abstract/bls.js} +28 -27
  6. package/lib/{edwards.d.ts → abstract/edwards.d.ts} +17 -0
  7. package/lib/{edwards.js → abstract/edwards.js} +45 -4
  8. package/lib/{group.d.ts → abstract/group.d.ts} +2 -1
  9. package/lib/{group.js → abstract/group.js} +4 -3
  10. package/lib/abstract/hash-to-curve.d.ts +28 -0
  11. package/lib/{hashToCurve.js → abstract/hash-to-curve.js} +46 -11
  12. package/lib/{modular.d.ts → abstract/modular.d.ts} +13 -16
  13. package/lib/abstract/modular.js +337 -0
  14. package/lib/{montgomery.d.ts → abstract/montgomery.d.ts} +2 -1
  15. package/lib/{montgomery.js → abstract/montgomery.js} +17 -8
  16. package/lib/{utils.d.ts → abstract/utils.d.ts} +4 -2
  17. package/lib/{utils.js → abstract/utils.js} +1 -1
  18. package/lib/{weierstrass.d.ts → abstract/weierstrass.d.ts} +28 -16
  19. package/lib/{weierstrass.js → abstract/weierstrass.js} +261 -127
  20. package/lib/bls12-381.d.ts +66 -0
  21. package/lib/bls12-381.js +1132 -0
  22. package/lib/bn.d.ts +7 -0
  23. package/lib/bn.js +24 -0
  24. package/lib/ed25519.d.ts +48 -0
  25. package/lib/ed25519.js +385 -0
  26. package/lib/ed448.d.ts +3 -0
  27. package/lib/ed448.js +211 -0
  28. package/lib/esm/_shortw_utils.js +15 -0
  29. package/lib/esm/{bls.js → abstract/bls.js} +25 -24
  30. package/lib/esm/{edwards.js → abstract/edwards.js} +45 -4
  31. package/lib/esm/{group.js → abstract/group.js} +4 -3
  32. package/lib/esm/{hashToCurve.js → abstract/hash-to-curve.js} +43 -10
  33. package/lib/esm/abstract/modular.js +319 -0
  34. package/lib/esm/{montgomery.js → abstract/montgomery.js} +17 -8
  35. package/lib/esm/{utils.js → abstract/utils.js} +1 -1
  36. package/lib/esm/{weierstrass.js → abstract/weierstrass.js} +255 -123
  37. package/lib/esm/bls12-381.js +1129 -0
  38. package/lib/esm/bn.js +21 -0
  39. package/lib/esm/ed25519.js +381 -0
  40. package/lib/esm/ed448.js +208 -0
  41. package/lib/esm/index.js +2 -0
  42. package/lib/esm/jubjub.js +52 -0
  43. package/lib/esm/p192.js +21 -0
  44. package/lib/esm/p224.js +21 -0
  45. package/lib/esm/p256.js +39 -0
  46. package/lib/esm/p384.js +44 -0
  47. package/lib/esm/p521.js +58 -0
  48. package/lib/esm/pasta.js +29 -0
  49. package/lib/esm/secp256k1.js +293 -0
  50. package/lib/esm/stark.js +224 -0
  51. package/lib/index.d.ts +0 -0
  52. package/lib/index.js +2 -0
  53. package/lib/jubjub.d.ts +7 -0
  54. package/lib/jubjub.js +57 -0
  55. package/lib/p192.d.ts +130 -0
  56. package/lib/p192.js +24 -0
  57. package/lib/p224.d.ts +130 -0
  58. package/lib/p224.js +24 -0
  59. package/lib/p256.d.ts +130 -0
  60. package/lib/p256.js +42 -0
  61. package/lib/p384.d.ts +130 -0
  62. package/lib/p384.js +47 -0
  63. package/lib/p521.d.ts +131 -0
  64. package/lib/p521.js +61 -0
  65. package/lib/pasta.d.ts +4 -0
  66. package/lib/pasta.js +32 -0
  67. package/lib/secp256k1.d.ts +96 -0
  68. package/lib/secp256k1.js +297 -0
  69. package/lib/stark.d.ts +72 -0
  70. package/lib/stark.js +245 -0
  71. package/package.json +146 -50
  72. package/index.js +0 -1
  73. package/lib/esm/modular.js +0 -252
  74. package/lib/hashToCurve.d.ts +0 -13
  75. package/lib/modular.js +0 -267
package/README.md CHANGED
@@ -1,38 +1,44 @@
1
1
  # noble-curves
2
2
 
3
- Minimal, zero-dependency JS implementation of elliptic curve cryptography.
4
-
5
- - Short Weierstrass curve with ECDSA signatures
6
- - Twisted Edwards curve with EdDSA signatures
7
- - Montgomery curve for ECDH key agreement
8
-
9
- To keep the package minimal, no curve definitions are provided out-of-box. Use `micro-curve-definitions` module:
10
-
11
- - It provides P192, P224, P256, P384, P521, secp256k1, stark curve, bn254, pasta (pallas/vesta) short weierstrass curves
12
- - It also provides ed25519 and ed448 twisted edwards curves
13
- - Main reason for separate package is the fact hashing library (like `@noble/hashes`) is required for full functionality
14
- - We may reconsider merging packages in future, when a stable version would be ready
15
-
16
- Future plans:
17
-
18
- - hash to curve standard
19
- - point indistinguishability
20
- - pairings
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
+ - 🔍 Unique tests ensure correctness. Wycheproof vectors included
11
+ - 🔻 Tree-shaking-friendly: there is no entry point, which ensures small size of your app
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
- - No dependencies, small files
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,123 @@ 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
- import { weierstrass } from '@noble/curves/weierstrass'; // Short Weierstrass curve
48
- import { sha256 } from '@noble/hashes/sha256';
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 = randomBytes(32);
58
+ const msg = new Uint8Array(32).fill(1);
66
59
  const sig = secp256k1.sign(msg, key);
67
- secp256k1.verify(sig, msg, pub); // true
68
- sig.recoverPublicKey(msg); // == pub
69
- const someonesPubkey = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
70
- const shared = secp256k1.getSharedSecret(key, someonesPubkey);
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](#abstractedwards-twisted-edwards-curve)
88
+ - [abstract/montgomery: Montgomery curve](#abstractmontgomery-montgomery-curve)
89
+ - [abstract/weierstrass: Short Weierstrass curve](#abstractweierstrass-short-weierstrass-curve)
90
+ - [abstract/hash-to-curve: Hashing strings to curve points](#abstracthash-to-curve-hashing-strings-to-curve-points)
91
+ - [abstract/modular](#abstractmodular)
92
+ - [abstract/utils](#abstractutils)
81
93
 
82
94
  ### Overview
83
95
 
84
- * 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)
85
- * All curves expose same generic interface:
86
- * `getPublicKey()`, `sign()`, `verify()` functions
87
- * `Point` conforming to `Group` interface with add/multiply/double/negate/add/equals methods
88
- * `CURVE` object with curve variables like `Gx`, `Gy`, `P` (field), `n` (order)
89
- * `utils` object with `randomPrivateKey()`, `mod()`, `invert()` methods (`mod CURVE.P`)
90
- * All arithmetics is done with JS bigints over finite fields
91
- * Many features require hashing, which is not provided. `@noble/hashes` can be used for this purpose.
96
+ There are following zero-dependency abstract algorithms:
97
+
98
+ ```ts
99
+ import { bls } from '@noble/curves/abstract/bls';
100
+ import { twistedEdwards } from '@noble/curves/abstract/edwards';
101
+ import { montgomery } from '@noble/curves/abstract/montgomery';
102
+ import { weierstrass } from '@noble/curves/abstract/weierstrass';
103
+ import * as mod from '@noble/curves/abstract/modular';
104
+ import * as utils from '@noble/curves/abstract/utils';
105
+ ```
106
+
107
+ They allow to define a new curve in a few lines of code:
108
+
109
+ ```ts
110
+ import { Fp } from '@noble/curves/abstract/modular';
111
+ import { weierstrass } from '@noble/curves/abstract/weierstrass';
112
+ import { hmac } from '@noble/hashes/hmac';
113
+ import { sha256 } from '@noble/hashes/sha256';
114
+ import { concatBytes, randomBytes } from '@noble/hashes/utils';
115
+
116
+ const secp256k1 = weierstrass({
117
+ a: 0n,
118
+ b: 7n,
119
+ Fp: Fp(2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n),
120
+ n: 2n ** 256n - 432420386565659656852420866394968145599n,
121
+ Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
122
+ Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
123
+ hash: sha256,
124
+ hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)),
125
+ randomBytes,
126
+ });
127
+ ```
128
+
129
+ - 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)
130
+ - All curves expose same generic interface:
131
+ - `getPublicKey()`, `sign()`, `verify()` functions
132
+ - `Point` conforming to `Group` interface with add/multiply/double/negate/add/equals methods
133
+ - `CURVE` object with curve variables like `Gx`, `Gy`, `Fp` (field), `n` (order)
134
+ - `utils` object with `randomPrivateKey()`, `mod()`, `invert()` methods (`mod CURVE.P`)
135
+ - All arithmetics is done with JS bigints over finite fields, which is defined from `modular` sub-module
136
+ - Many features require hashing, which is not provided. `@noble/hashes` can be used for this purpose.
92
137
  Any other library must conform to the CHash interface:
93
- ```ts
94
- export type CHash = {
95
- (message: Uint8Array): Uint8Array;
96
- blockLen: number; outputLen: number; create(): any;
97
- };
98
- ```
99
- * w-ary non-adjacent form (wNAF) method with constant-time adjustments is used for point multiplication.
138
+ ```ts
139
+ export type CHash = {
140
+ (message: Uint8Array): Uint8Array;
141
+ blockLen: number;
142
+ outputLen: number;
143
+ create(): any;
144
+ };
145
+ ```
146
+ - w-ary non-adjacent form (wNAF) method with constant-time adjustments is used for point multiplication.
100
147
  It is possible to enable precomputes for edwards & weierstrass curves.
101
- Precomputes are calculated once (takes ~20-40ms), after that most `G` multiplications
102
- - for example, `getPublicKey()`, `sign()` and similar methods - would be much faster.
103
- Use `curve.utils.precompute()`
104
- * Special params that tune performance can be optionally provided. For example:
105
- * `sqrtMod` square root calculation, used for point decompression
106
- * `endo` endomorphism options for Koblitz curves
148
+ Precomputes are calculated once (takes ~20-40ms), after that most `G` base point multiplications:
149
+ for example, `getPublicKey()`, `sign()` and similar methods - would be much faster.
150
+ Use `curve.utils.precompute()` to adjust precomputation window size
151
+ - You could use optional special params to tune performance:
152
+ - `Fp({sqrt})` square root calculation, used for point decompression
153
+ - `endo` endomorphism options for Koblitz curves
107
154
 
108
- ### edwards: Twisted Edwards curve
155
+ ### abstract/edwards: Twisted Edwards curve
109
156
 
110
157
  Twisted Edwards curve's formula is: ax² + y² = 1 + dx²y².
111
158
 
112
- * You must specify curve params `a`, `d`, field `P`, order `n`, cofactor `h`, and coordinates `Gx`, `Gy` of generator point.
113
- * For EdDSA signatures, params `hash` is also required. `adjustScalarBytes` which instructs how to change private scalars could be specified.
159
+ - You must specify curve params `a`, `d`, field `Fp`, order `n`, cofactor `h` and coordinates `Gx`, `Gy` of generator point
160
+ - For EdDSA signatures, params `hash` is also required. `adjustScalarBytes` which instructs how to change private scalars could be specified
114
161
 
115
162
  ```typescript
116
- import { twistedEdwards } from '@noble/curves/edwards'; // Twisted Edwards curve
163
+ import { twistedEdwards } from '@noble/curves/abstract/edwards';
164
+ import { div } from '@noble/curves/abstract/modular';
117
165
  import { sha512 } from '@noble/hashes/sha512';
118
- import * as mod from '@noble/curves/modular';
119
166
 
120
167
  const ed25519 = twistedEdwards({
121
168
  a: -1n,
122
- d: mod.div(-121665n, 121666n, 2n ** 255n - 19n), // -121665n/121666n
169
+ d: div(-121665n, 121666n, 2n ** 255n - 19n), // -121665n/121666n
123
170
  P: 2n ** 255n - 19n,
124
171
  n: 2n ** 252n + 27742317777372353535851937790883648493n,
125
172
  h: 8n,
@@ -127,14 +174,19 @@ const ed25519 = twistedEdwards({
127
174
  Gy: 46316835694926478169428394003475163141307993866256225615783033603165251855960n,
128
175
  hash: sha512,
129
176
  randomBytes,
130
- adjustScalarBytes(bytes) { // optional
177
+ adjustScalarBytes(bytes) {
178
+ // optional in general, mandatory in ed25519
131
179
  bytes[0] &= 248;
132
180
  bytes[31] &= 127;
133
181
  bytes[31] |= 64;
134
182
  return bytes;
135
183
  },
136
184
  } as const);
137
- ed25519.getPublicKey(ed25519.utils.randomPrivateKey());
185
+ const key = ed25519.utils.randomPrivateKey();
186
+ const pub = ed25519.getPublicKey(key);
187
+ const msg = new TextEncoder().encode('hello world'); // strings not accepted, must be Uint8Array
188
+ const sig = ed25519.sign(msg, key);
189
+ ed25519.verify(sig, msg, pub) === true;
138
190
  ```
139
191
 
140
192
  `twistedEdwards()` returns `CurveFn` of following type:
@@ -163,7 +215,7 @@ export type CurveFn = {
163
215
  };
164
216
  ```
165
217
 
166
- ### montgomery: Montgomery curve
218
+ ### abstract/montgomery: Montgomery curve
167
219
 
168
220
  For now the module only contains methods for x-only ECDH on Curve25519 / Curve448 from RFC7748.
169
221
 
@@ -172,6 +224,8 @@ Proper Elliptic Curve Points are not implemented yet.
172
224
  You must specify curve field, `a24` special variable, `montgomeryBits`, `nByteLength`, and coordinate `u` of generator point.
173
225
 
174
226
  ```typescript
227
+ import { montgomery } from '@noble/curves/abstract/montgomery';
228
+
175
229
  const x25519 = montgomery({
176
230
  P: 2n ** 255n - 19n,
177
231
  a24: 121665n, // TODO: change to a
@@ -180,7 +234,9 @@ const x25519 = montgomery({
180
234
  Gu: '0900000000000000000000000000000000000000000000000000000000000000',
181
235
 
182
236
  // Optional params
183
- powPminus2: (x: bigint): bigint => { return mod.pow(x, P-2, P); },
237
+ powPminus2: (x: bigint): bigint => {
238
+ return mod.pow(x, P - 2, P);
239
+ },
184
240
  adjustScalarBytes(bytes) {
185
241
  bytes[0] &= 248;
186
242
  bytes[31] &= 127;
@@ -190,27 +246,27 @@ const x25519 = montgomery({
190
246
  });
191
247
  ```
192
248
 
193
- ### weierstrass: Short Weierstrass curve
249
+ ### abstract/weierstrass: Short Weierstrass curve
194
250
 
195
251
  Short Weierstrass curve's formula is: y² = x³ + ax + b. Uses deterministic ECDSA from RFC6979. You can also specify `extraEntropy` in `sign()`.
196
252
 
197
- * You must specify curve params: `a`, `b`; field `P`; curve order `n`; coordinates `Gx`, `Gy` of generator point
198
- * For ECDSA, you must specify `hash`, `hmac`. It is also possible to recover keys from signatures
199
- * For ECDH, use `getSharedSecret(privKeyA, pubKeyB)`
200
- * Optional params are `lowS` (default value), `sqrtMod` (square root chain) and `endo` (endomorphism)
253
+ - You must specify curve params: `a`, `b`, field `Fp`, order `n`, cofactor `h` and coordinates `Gx`, `Gy` of generator point
254
+ - For ECDSA, you must specify `hash`, `hmac`. It is also possible to recover keys from signatures
255
+ - For ECDH, use `getSharedSecret(privKeyA, pubKeyB)`
256
+ - Optional params are `lowS` (default value) and `endo` (endomorphism)
201
257
 
202
258
  ```typescript
203
- import { weierstrass } from '@noble/curves/weierstrass'; // Short Weierstrass curve
259
+ import { Fp } from '@noble/curves/abstract/modular';
260
+ import { weierstrass } from '@noble/curves/abstract/weierstrass'; // Short Weierstrass curve
204
261
  import { sha256 } from '@noble/hashes/sha256';
205
262
  import { hmac } from '@noble/hashes/hmac';
206
263
  import { concatBytes, randomBytes } from '@noble/hashes/utils';
207
264
 
208
265
  const secp256k1 = weierstrass({
209
- // Required params
210
266
  a: 0n,
211
267
  b: 7n,
212
- P: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn,
213
- n: 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n,
268
+ Fp: Fp(2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n),
269
+ n: 2n ** 256n - 432420386565659656852420866394968145599n,
214
270
  Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
215
271
  Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
216
272
  hash: sha256,
@@ -218,19 +274,15 @@ const secp256k1 = weierstrass({
218
274
  randomBytes,
219
275
 
220
276
  // Optional params
221
- // Cofactor
222
- h: BigInt(1),
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
277
+ h: 1n, // Cofactor
278
+ lowS: true, // Allow only low-S signatures by default in sign() and verify()
228
279
  endo: {
280
+ // Endomorphism options for Koblitz curve
229
281
  // Beta param
230
- beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
282
+ beta: 0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501een,
231
283
  // Split scalar k into k1, k2
232
284
  splitScalar: (k: bigint) => {
233
- return { k1neg: true, k1: 512n, k2neg: false, k2: 448n };
285
+ // return { k1neg: true, k1: 512n, k2neg: false, k2: 448n };
234
286
  },
235
287
  },
236
288
  });
@@ -255,14 +307,17 @@ export type CurveFn = {
255
307
  getSharedSecret: (privateA: PrivKey, publicB: PubKey, isCompressed?: boolean) => Uint8Array;
256
308
  sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => SignatureType;
257
309
  verify: (
258
- signature: Hex | SignatureType, msgHash: Hex, publicKey: PubKey, opts?: {lowS?: boolean;}
310
+ signature: Hex | SignatureType,
311
+ msgHash: Hex,
312
+ publicKey: PubKey,
313
+ opts?: { lowS?: boolean }
259
314
  ) => boolean;
260
315
  Point: PointConstructor;
261
- JacobianPoint: JacobianPointConstructor;
316
+ ProjectivePoint: ProjectivePointConstructor;
262
317
  Signature: SignatureConstructor;
263
318
  utils: {
264
- mod: (a: bigint, b?: bigint) => bigint;
265
- invert: (number: bigint, modulo?: bigint) => bigint;
319
+ mod: (a: bigint) => bigint;
320
+ invert: (number: bigint) => bigint;
266
321
  isValidPrivateKey(privateKey: PrivKey): boolean;
267
322
  hashToPrivateKey: (hash: Hex) => Uint8Array;
268
323
  randomPrivateKey: () => Uint8Array;
@@ -270,23 +325,76 @@ export type CurveFn = {
270
325
  };
271
326
  ```
272
327
 
273
- ### modular
328
+ ### abstract/hash-to-curve: Hashing strings to curve points
329
+
330
+ The module allows to hash arbitrary strings to elliptic curve points.
331
+
332
+ - `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..
333
+
334
+ ```ts
335
+ function expand_message_xmd(
336
+ msg: Uint8Array, DST: Uint8Array, lenInBytes: number, H: CHash
337
+ ): Uint8Array;
338
+ function expand_message_xof(
339
+ msg: Uint8Array, DST: Uint8Array, lenInBytes: number, k: number, H: CHash
340
+ ): Uint8Array;
341
+ ```
342
+
343
+ - `hash_to_field(msg, count, options)` [(spec)](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3)
344
+ hashes arbitrary-length byte strings to a list of one or more elements of a finite field F.
345
+ * `msg` a byte string containing the message to hash
346
+ * `count` the number of elements of F to output
347
+ * `options` `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`
348
+ * Returns `[u_0, ..., u_(count - 1)]`, a list of field elements.
349
+
350
+ ```ts
351
+ function hash_to_field(msg: Uint8Array, count: number, options: htfOpts): bigint[][];
352
+ type htfOpts = {
353
+ // DST: a domain separation tag
354
+ // defined in section 2.2.5
355
+ DST: string;
356
+ // p: the characteristic of F
357
+ // where F is a finite field of characteristic p and order q = p^m
358
+ p: bigint;
359
+ // m: the extension degree of F, m >= 1
360
+ // where F is a finite field of characteristic p and order q = p^m
361
+ m: number;
362
+ // k: the target security level for the suite in bits
363
+ // defined in section 5.1
364
+ k: number;
365
+ // option to use a message that has already been processed by
366
+ // expand_message_xmd
367
+ expand?: 'xmd' | 'xof';
368
+ // Hash functions for: expand_message_xmd is appropriate for use with a
369
+ // wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
370
+ // BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
371
+ // TODO: verify that hash is shake if expand==='xof' via types
372
+ hash: CHash;
373
+ };
374
+ ```
375
+
376
+ ### abstract/modular
274
377
 
275
378
  Modular arithmetics utilities.
276
379
 
277
380
  ```typescript
278
- import * as mod from '@noble/curves/modular';
279
- mod.mod(21n, 10n); // 21 mod 10 == 1n; fixed version of 21 % 10
280
- mod.invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse
281
- mod.div(5n, 17n, 10n); // 5/17 mod 10 == 5 * invert(17) mod 10; division
282
- mod.invertBatch([1n, 2n, 4n], 21n); // => [1n, 11n, 16n] in one inversion
283
- mod.sqrt(21n, 73n); // sqrt(21) mod 73; square root
381
+ import { Fp, mod, invert, div, invertBatch, sqrt } from '@noble/curves/abstract/modular';
382
+ const fp = Fp(2n ** 255n - 19n); // Finite field over 2^255-19
383
+ fp.mul(591n, 932n);
384
+ fp.pow(481n, 11024858120n);
385
+
386
+ // Generic non-FP utils are also available
387
+ mod(21n, 10n); // 21 mod 10 == 1n; fixed version of 21 % 10
388
+ invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse
389
+ div(5n, 17n, 10n); // 5/17 mod 10 == 5 * invert(17) mod 10; division
390
+ invertBatch([1n, 2n, 4n], 21n); // => [1n, 11n, 16n] in one inversion
391
+ sqrt(21n, 73n); // √21 mod 73; square root
284
392
  ```
285
393
 
286
- ### utils
394
+ ### abstract/utils
287
395
 
288
396
  ```typescript
289
- import * as utils from '@noble/curves/utils';
397
+ import * as utils from '@noble/curves/abstract/utils';
290
398
 
291
399
  utils.bytesToHex(Uint8Array.from([0xde, 0xad, 0xbe, 0xef]));
292
400
  utils.hexToBytes('deadbeef');
@@ -315,59 +423,43 @@ We consider infrastructure attacks like rogue NPM modules very important; that's
315
423
  Benchmark results on Apple M2 with node v18.10:
316
424
 
317
425
  ```
318
- ==== secp256k1 ====
319
- - getPublicKey1 (samples: 10000)
320
- noble_old x 8,131 ops/sec @ 122μs/op
321
- secp256k1 x 7,374 ops/sec @ 135μs/op
322
- - getPublicKey255 (samples: 10000)
323
- noble_old x 7,894 ops/sec @ 126μs/op
324
- secp256k1 x 7,327 ops/sec @ 136μs/op
325
- - sign (samples: 5000)
326
- noble_old x 5,243 ops/sec @ 190μs/op
327
- secp256k1 x 4,834 ops/sec @ 206μs/op
328
- - getSharedSecret (samples: 1000)
329
- noble_old x 653 ops/sec @ 1ms/op
330
- secp256k1 x 634 ops/sec @ 1ms/op
331
- - verify (samples: 1000)
332
- secp256k1_old x 1,038 ops/sec @ 962μs/op
333
- secp256k1 x 1,009 ops/sec @ 990μs/op
334
- ==== ed25519 ====
335
- - getPublicKey (samples: 10000)
336
- old x 8,632 ops/sec @ 115μs/op
337
- noble x 8,390 ops/sec @ 119μs/op
338
- - sign (samples: 5000)
339
- old x 4,376 ops/sec @ 228μs/op
340
- noble x 4,233 ops/sec @ 236μs/op
341
- - verify (samples: 1000)
342
- old x 865 ops/sec @ 1ms/op
343
- noble x 860 ops/sec @ 1ms/op
344
- ==== ed448 ====
345
- - getPublicKey (samples: 5000)
346
- noble x 3,224 ops/sec @ 310μs/op
347
- - sign (samples: 2500)
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
426
+ getPublicKey
427
+ secp256k1 x 5,241 ops/sec @ 190μs/op
428
+ P256 x 7,993 ops/sec @ 125μs/op
429
+ P384 x 3,819 ops/sec @ 261μs/op
430
+ P521 x 2,074 ops/sec @ 481μs/op
431
+ ed25519 x 8,390 ops/sec @ 119μs/op
432
+ ed448 x 3,224 ops/sec @ 310μs/op
433
+ sign
434
+ secp256k1 x 3,934 ops/sec @ 254μs/op
435
+ P256 x 5,327 ops/sec @ 187μs/op
436
+ P384 x 2,728 ops/sec @ 366μs/op
437
+ P521 x 1,594 ops/sec @ 626μs/op
438
+ ed25519 x 4,233 ops/sec @ 236μs/op
439
+ ed448 x 1,561 ops/sec @ 640μs/op
440
+ verify
441
+ secp256k1 x 731 ops/sec @ 1ms/op
442
+ P256 x 806 ops/sec @ 1ms/op
443
+ P384 x 353 ops/sec @ 2ms/op
444
+ P521 x 171 ops/sec @ 5ms/op
445
+ ed25519 x 860 ops/sec @ 1ms/op
446
+ ed448 x 313 ops/sec @ 3ms/op
447
+ getSharedSecret
448
+ secp256k1 x 445 ops/sec @ 2ms/op
449
+ recoverPublicKey
450
+ secp256k1 x 732 ops/sec @ 1ms/op
451
+ ==== bls12-381 ====
452
+ getPublicKey x 817 ops/sec @ 1ms/op
453
+ sign x 50 ops/sec @ 19ms/op
454
+ verify x 34 ops/sec @ 28ms/op
455
+ pairing x 89 ops/sec @ 11ms/op
364
456
  ==== stark ====
365
- - pedersen (samples: 500)
366
- old x 85 ops/sec @ 11ms/op
367
- noble x 1,216 ops/sec @ 822μs/op
368
- - verify (samples: 500)
369
- old x 302 ops/sec @ 3ms/op
370
- noble x 698 ops/sec @ 1ms/op
457
+ pedersen
458
+ old x 85 ops/sec @ 11ms/op
459
+ noble x 1,216 ops/sec @ 822μs/op
460
+ verify
461
+ old x 302 ops/sec @ 3ms/op
462
+ noble x 698 ops/sec @ 1ms/op
371
463
  ```
372
464
 
373
465
  ## 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;