@noble/curves 0.6.2 → 0.6.4
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 +32 -28
- package/lib/_shortw_utils.d.ts +2 -1
- package/lib/abstract/curve.d.ts +9 -5
- package/lib/abstract/curve.js +21 -8
- package/lib/abstract/hash-to-curve.d.ts +0 -1
- package/lib/abstract/hash-to-curve.js +10 -17
- package/lib/abstract/weierstrass.d.ts +2 -1
- package/lib/abstract/weierstrass.js +10 -2
- package/lib/esm/abstract/curve.js +21 -8
- package/lib/esm/abstract/hash-to-curve.js +10 -16
- package/lib/esm/abstract/weierstrass.js +10 -2
- package/lib/p192.d.ts +4 -2
- package/lib/p224.d.ts +4 -2
- package/lib/p256.d.ts +4 -2
- package/lib/p384.d.ts +4 -2
- package/lib/p521.d.ts +4 -2
- package/lib/secp256k1.d.ts +2 -1
- package/lib/stark.d.ts +2 -1
- package/package.json +4 -6
package/README.md
CHANGED
|
@@ -22,8 +22,7 @@ Package consists of two parts:
|
|
|
22
22
|
|
|
23
23
|
Curves incorporate work from previous noble packages
|
|
24
24
|
([secp256k1](https://github.com/paulmillr/noble-secp256k1),
|
|
25
|
-
[ed25519](https://github.com/paulmillr/noble-ed25519),
|
|
26
|
-
[bls12-381](https://github.com/paulmillr/noble-bls12-381)),
|
|
25
|
+
[ed25519](https://github.com/paulmillr/noble-ed25519)),
|
|
27
26
|
which had security audits and were developed from 2019 to 2022.
|
|
28
27
|
Check out [Upgrading](#upgrading) section if you've used them before.
|
|
29
28
|
|
|
@@ -31,14 +30,14 @@ Check out [Upgrading](#upgrading) section if you've used them before.
|
|
|
31
30
|
|
|
32
31
|
> **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools.
|
|
33
32
|
|
|
34
|
-
-
|
|
33
|
+
- Protection against supply chain attacks
|
|
35
34
|
- Easily auditable TypeScript/JS code
|
|
36
35
|
- Supported in all major browsers and stable node.js versions
|
|
37
36
|
- All releases are signed with PGP keys
|
|
38
37
|
- Check out [homepage](https://paulmillr.com/noble/) & all libraries:
|
|
39
|
-
[curves](https://github.com/paulmillr/noble-curves)
|
|
40
|
-
[
|
|
41
|
-
[
|
|
38
|
+
[curves](https://github.com/paulmillr/noble-curves)
|
|
39
|
+
([secp256k1](https://github.com/paulmillr/noble-secp256k1),
|
|
40
|
+
[ed25519](https://github.com/paulmillr/noble-ed25519)),
|
|
42
41
|
[hashes](https://github.com/paulmillr/noble-hashes)
|
|
43
42
|
|
|
44
43
|
## Usage
|
|
@@ -48,23 +47,7 @@ Use NPM in node.js / browser, or include single file from
|
|
|
48
47
|
|
|
49
48
|
> npm install @noble/curves
|
|
50
49
|
|
|
51
|
-
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.
|
|
52
|
-
|
|
53
|
-
```ts
|
|
54
|
-
// Common.js and ECMAScript Modules (ESM)
|
|
55
|
-
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
56
|
-
|
|
57
|
-
const key = secp256k1.utils.randomPrivateKey();
|
|
58
|
-
const pub = secp256k1.getPublicKey(key);
|
|
59
|
-
const msg = new Uint8Array(32).fill(1);
|
|
60
|
-
const sig = secp256k1.sign(msg, key);
|
|
61
|
-
secp256k1.verify(sig, msg, pub) === true;
|
|
62
|
-
sig.recoverPublicKey(msg) === pub;
|
|
63
|
-
const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
|
|
64
|
-
const shared = secp256k1.getSharedSecret(key, someonesPub);
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
All curves:
|
|
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. All curves:
|
|
68
51
|
|
|
69
52
|
```ts
|
|
70
53
|
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
@@ -80,7 +63,25 @@ import { bn254 } from '@noble/curves/bn';
|
|
|
80
63
|
import { jubjub } from '@noble/curves/jubjub';
|
|
81
64
|
```
|
|
82
65
|
|
|
83
|
-
|
|
66
|
+
Every curve can be used in the following way:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { secp256k1 } from '@noble/curves/secp256k1'; // Common.js and ECMAScript Modules (ESM)
|
|
70
|
+
|
|
71
|
+
const key = secp256k1.utils.randomPrivateKey();
|
|
72
|
+
const pub = secp256k1.getPublicKey(key);
|
|
73
|
+
const msg = new Uint8Array(32).fill(1);
|
|
74
|
+
const sig = secp256k1.sign(msg, key);
|
|
75
|
+
// weierstrass curves should use extraEntropy: https://moderncrypto.org/mail-archive/curves/2017/000925.html
|
|
76
|
+
const sigImprovedSecurity = secp256k1.sign(msg, key, { extraEntropy: true });
|
|
77
|
+
secp256k1.verify(sig, msg, pub) === true;
|
|
78
|
+
// secp, p*, pasta curves allow pub recovery
|
|
79
|
+
sig.recoverPublicKey(msg) === pub;
|
|
80
|
+
const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
|
|
81
|
+
const shared = secp256k1.getSharedSecret(key, someonesPub);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
To define a custom curve, check out docs below.
|
|
84
85
|
|
|
85
86
|
## API
|
|
86
87
|
|
|
@@ -109,17 +110,20 @@ import * as utils from '@noble/curves/abstract/utils';
|
|
|
109
110
|
They allow to define a new curve in a few lines of code:
|
|
110
111
|
|
|
111
112
|
```ts
|
|
112
|
-
import {
|
|
113
|
+
import { Field } from '@noble/curves/abstract/modular';
|
|
113
114
|
import { weierstrass } from '@noble/curves/abstract/weierstrass';
|
|
114
115
|
import { hmac } from '@noble/hashes/hmac';
|
|
115
116
|
import { sha256 } from '@noble/hashes/sha256';
|
|
116
117
|
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
|
117
118
|
|
|
118
|
-
|
|
119
|
+
// secq (NOT secp) 256k1: cycle of secp256k1 with Fp/N flipped.
|
|
120
|
+
// https://zcash.github.io/halo2/background/curves.html#cycles-of-curves
|
|
121
|
+
// https://personaelabs.org/posts/spartan-ecdsa
|
|
122
|
+
const secq256k1 = weierstrass({
|
|
119
123
|
a: 0n,
|
|
120
124
|
b: 7n,
|
|
121
|
-
Fp:
|
|
122
|
-
n: 2n ** 256n -
|
|
125
|
+
Fp: Field(2n ** 256n - 432420386565659656852420866394968145599n),
|
|
126
|
+
n: 2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n,
|
|
123
127
|
Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
|
|
124
128
|
Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
|
|
125
129
|
hash: sha256,
|
package/lib/_shortw_utils.d.ts
CHANGED
|
@@ -51,10 +51,11 @@ export declare function createCurve(curveDef: CurveDef, defHash: CHash): Readonl
|
|
|
51
51
|
ProjectivePoint: import("./abstract/weierstrass.js").ProjConstructor<bigint>;
|
|
52
52
|
Signature: import("./abstract/weierstrass.js").SignatureConstructor;
|
|
53
53
|
utils: {
|
|
54
|
-
|
|
54
|
+
normPrivateKeyToScalar: (key: import("./abstract/utils.js").PrivKey) => bigint;
|
|
55
55
|
isValidPrivateKey(privateKey: import("./abstract/utils.js").PrivKey): boolean;
|
|
56
56
|
hashToPrivateKey: (hash: import("./abstract/utils.js").Hex) => Uint8Array;
|
|
57
57
|
randomPrivateKey: () => Uint8Array;
|
|
58
|
+
precompute: (windowSize?: number | undefined, point?: import("./abstract/weierstrass.js").ProjPointType<bigint> | undefined) => import("./abstract/weierstrass.js").ProjPointType<bigint>;
|
|
58
59
|
};
|
|
59
60
|
}>;
|
|
60
61
|
export {};
|
package/lib/abstract/curve.d.ts
CHANGED
|
@@ -26,15 +26,19 @@ export declare function wNAF<T extends Group<T>>(c: GroupConstructor<T>, bits: n
|
|
|
26
26
|
/**
|
|
27
27
|
* Creates a wNAF precomputation window. Used for caching.
|
|
28
28
|
* Default window size is set by `utils.precompute()` and is equal to 8.
|
|
29
|
-
*
|
|
30
|
-
*
|
|
29
|
+
* Number of precomputed points depends on the curve size:
|
|
30
|
+
* 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
|
|
31
|
+
* - 𝑊 is the window size
|
|
32
|
+
* - 𝑛 is the bitlength of the curve order.
|
|
33
|
+
* For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
|
|
34
|
+
* @returns precomputed point tables flattened to a single array
|
|
31
35
|
*/
|
|
32
36
|
precomputeWindow(elm: T, W: number): Group<T>[];
|
|
33
37
|
/**
|
|
34
|
-
* Implements w-ary non-adjacent form
|
|
38
|
+
* Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
|
|
35
39
|
* @param W window size
|
|
36
|
-
* @param
|
|
37
|
-
* @param n
|
|
40
|
+
* @param precomputes precomputed tables
|
|
41
|
+
* @param n scalar (we don't check here, but should be less than curve order)
|
|
38
42
|
* @returns real and fake (for const-time) points
|
|
39
43
|
*/
|
|
40
44
|
wNAF(W: number, precomputes: T[], n: bigint): {
|
package/lib/abstract/curve.js
CHANGED
|
@@ -7,8 +7,17 @@ const modular_js_1 = require("./modular.js");
|
|
|
7
7
|
const utils_js_1 = require("./utils.js");
|
|
8
8
|
const _0n = BigInt(0);
|
|
9
9
|
const _1n = BigInt(1);
|
|
10
|
-
// Elliptic curve multiplication of Point by scalar.
|
|
11
|
-
//
|
|
10
|
+
// Elliptic curve multiplication of Point by scalar. Fragile.
|
|
11
|
+
// Scalars should always be less than curve order: this should be checked inside of a curve itself.
|
|
12
|
+
// Creates precomputation tables for fast multiplication:
|
|
13
|
+
// - private scalar is split by fixed size windows of W bits
|
|
14
|
+
// - every window point is collected from window's table & added to accumulator
|
|
15
|
+
// - since windows are different, same point inside tables won't be accessed more than once per calc
|
|
16
|
+
// - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar)
|
|
17
|
+
// - +1 window is neccessary for wNAF
|
|
18
|
+
// - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication
|
|
19
|
+
// TODO: Research returning 2d JS array of windows, instead of a single window. This would allow
|
|
20
|
+
// windows to be in different memory locations
|
|
12
21
|
function wNAF(c, bits) {
|
|
13
22
|
const constTimeNegate = (condition, item) => {
|
|
14
23
|
const neg = item.negate();
|
|
@@ -36,8 +45,12 @@ function wNAF(c, bits) {
|
|
|
36
45
|
/**
|
|
37
46
|
* Creates a wNAF precomputation window. Used for caching.
|
|
38
47
|
* Default window size is set by `utils.precompute()` and is equal to 8.
|
|
39
|
-
*
|
|
40
|
-
*
|
|
48
|
+
* Number of precomputed points depends on the curve size:
|
|
49
|
+
* 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
|
|
50
|
+
* - 𝑊 is the window size
|
|
51
|
+
* - 𝑛 is the bitlength of the curve order.
|
|
52
|
+
* For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
|
|
53
|
+
* @returns precomputed point tables flattened to a single array
|
|
41
54
|
*/
|
|
42
55
|
precomputeWindow(elm, W) {
|
|
43
56
|
const { windows, windowSize } = opts(W);
|
|
@@ -57,14 +70,14 @@ function wNAF(c, bits) {
|
|
|
57
70
|
return points;
|
|
58
71
|
},
|
|
59
72
|
/**
|
|
60
|
-
* Implements w-ary non-adjacent form
|
|
73
|
+
* Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
|
|
61
74
|
* @param W window size
|
|
62
|
-
* @param
|
|
63
|
-
* @param n
|
|
75
|
+
* @param precomputes precomputed tables
|
|
76
|
+
* @param n scalar (we don't check here, but should be less than curve order)
|
|
64
77
|
* @returns real and fake (for const-time) points
|
|
65
78
|
*/
|
|
66
79
|
wNAF(W, precomputes, n) {
|
|
67
|
-
// TODO: maybe check that scalar is less than group order? wNAF
|
|
80
|
+
// TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise
|
|
68
81
|
// But need to carefully remove other checks before wNAF. ORDER == bits here
|
|
69
82
|
const { windows, windowSize } = opts(W);
|
|
70
83
|
let p = c.ZERO;
|
|
@@ -11,7 +11,6 @@ export declare type Opts = {
|
|
|
11
11
|
expand?: 'xmd' | 'xof';
|
|
12
12
|
hash: CHash;
|
|
13
13
|
};
|
|
14
|
-
export declare function validateOpts(opts: Opts): void;
|
|
15
14
|
export declare function stringToBytes(str: string): Uint8Array;
|
|
16
15
|
export declare function expand_message_xmd(msg: Uint8Array, DST: Uint8Array, lenInBytes: number, H: CHash): Uint8Array;
|
|
17
16
|
export declare function expand_message_xof(msg: Uint8Array, DST: Uint8Array, lenInBytes: number, k: number, H: CHash): Uint8Array;
|
|
@@ -1,23 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.hashToCurve = exports.isogenyMap = exports.hash_to_field = exports.expand_message_xof = exports.expand_message_xmd = exports.stringToBytes =
|
|
3
|
+
exports.hashToCurve = exports.isogenyMap = exports.hash_to_field = exports.expand_message_xof = exports.expand_message_xmd = exports.stringToBytes = void 0;
|
|
4
4
|
const modular_js_1 = require("./modular.js");
|
|
5
5
|
const utils_js_1 = require("./utils.js");
|
|
6
|
-
function validateOpts(opts) {
|
|
7
|
-
if (typeof opts.DST !== 'string')
|
|
8
|
-
throw new Error('Invalid htf/DST');
|
|
9
|
-
if (typeof opts.p !== 'bigint')
|
|
10
|
-
throw new Error('Invalid htf/p');
|
|
11
|
-
if (typeof opts.m !== 'number')
|
|
12
|
-
throw new Error('Invalid htf/m');
|
|
13
|
-
if (typeof opts.k !== 'number')
|
|
14
|
-
throw new Error('Invalid htf/k');
|
|
15
|
-
if (opts.expand !== 'xmd' && opts.expand !== 'xof' && opts.expand !== undefined)
|
|
16
|
-
throw new Error('Invalid htf/expand');
|
|
17
|
-
if (typeof opts.hash !== 'function' || !Number.isSafeInteger(opts.hash.outputLen))
|
|
18
|
-
throw new Error('Invalid htf/hash function');
|
|
19
|
-
}
|
|
20
|
-
exports.validateOpts = validateOpts;
|
|
21
6
|
function stringToBytes(str) {
|
|
22
7
|
if (typeof str !== 'string') {
|
|
23
8
|
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
|
|
@@ -143,7 +128,15 @@ function isogenyMap(field, map) {
|
|
|
143
128
|
}
|
|
144
129
|
exports.isogenyMap = isogenyMap;
|
|
145
130
|
function hashToCurve(Point, mapToCurve, def) {
|
|
146
|
-
|
|
131
|
+
(0, utils_js_1.validateObject)(def, {
|
|
132
|
+
DST: 'string',
|
|
133
|
+
p: 'bigint',
|
|
134
|
+
m: 'isSafeInteger',
|
|
135
|
+
k: 'isSafeInteger',
|
|
136
|
+
hash: 'hash',
|
|
137
|
+
});
|
|
138
|
+
if (def.expand !== 'xmd' && def.expand !== 'xof' && def.expand !== undefined)
|
|
139
|
+
throw new Error('Invalid htf/expand');
|
|
147
140
|
if (typeof mapToCurve !== 'function')
|
|
148
141
|
throw new Error('hashToCurve: mapToCurve() has not been defined');
|
|
149
142
|
return {
|
|
@@ -158,10 +158,11 @@ export declare type CurveFn = {
|
|
|
158
158
|
ProjectivePoint: ProjConstructor<bigint>;
|
|
159
159
|
Signature: SignatureConstructor;
|
|
160
160
|
utils: {
|
|
161
|
-
|
|
161
|
+
normPrivateKeyToScalar: (key: PrivKey) => bigint;
|
|
162
162
|
isValidPrivateKey(privateKey: PrivKey): boolean;
|
|
163
163
|
hashToPrivateKey: (hash: Hex) => Uint8Array;
|
|
164
164
|
randomPrivateKey: () => Uint8Array;
|
|
165
|
+
precompute: (windowSize?: number, point?: ProjPointType<bigint>) => ProjPointType<bigint>;
|
|
165
166
|
};
|
|
166
167
|
};
|
|
167
168
|
export declare function weierstrass(curveDef: CurveType): CurveFn;
|
|
@@ -708,7 +708,7 @@ function weierstrass(curveDef) {
|
|
|
708
708
|
return false;
|
|
709
709
|
}
|
|
710
710
|
},
|
|
711
|
-
|
|
711
|
+
normPrivateKeyToScalar: normalizePrivateKey,
|
|
712
712
|
/**
|
|
713
713
|
* Converts some bytes to a valid private key. Needs at least (nBitLength+64) bytes.
|
|
714
714
|
*/
|
|
@@ -842,7 +842,15 @@ function weierstrass(curveDef) {
|
|
|
842
842
|
const r = modN(q.x); // r = q.x mod n
|
|
843
843
|
if (r === _0n)
|
|
844
844
|
return;
|
|
845
|
-
|
|
845
|
+
// X blinding according to https://tches.iacr.org/index.php/TCHES/article/view/7337/6509
|
|
846
|
+
// b * m + b * r * d ∈ [0,q−1] exposed via side-channel, but d (private scalar) is not.
|
|
847
|
+
// NOTE: there is still probable some leak in multiplication, since it is not constant-time
|
|
848
|
+
const b = ut.bytesToNumberBE(utils.randomPrivateKey()); // random scalar, b ∈ [1,q−1]
|
|
849
|
+
const bi = invN(b); // b^-1
|
|
850
|
+
const bdr = modN(b * d * r); // b * d * r
|
|
851
|
+
const bm = modN(b * m); // b * m
|
|
852
|
+
const mrx = modN(bi * modN(bdr + bm)); // b^-1(bm + bdr) -> m + rd
|
|
853
|
+
const s = modN(ik * mrx); // s = k^-1(m + rd) mod n
|
|
846
854
|
if (s === _0n)
|
|
847
855
|
return;
|
|
848
856
|
let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n); // recovery bit (2 or 3, when q.x > n)
|
|
@@ -4,8 +4,17 @@ import { validateField, nLength } from './modular.js';
|
|
|
4
4
|
import { validateObject } from './utils.js';
|
|
5
5
|
const _0n = BigInt(0);
|
|
6
6
|
const _1n = BigInt(1);
|
|
7
|
-
// Elliptic curve multiplication of Point by scalar.
|
|
8
|
-
//
|
|
7
|
+
// Elliptic curve multiplication of Point by scalar. Fragile.
|
|
8
|
+
// Scalars should always be less than curve order: this should be checked inside of a curve itself.
|
|
9
|
+
// Creates precomputation tables for fast multiplication:
|
|
10
|
+
// - private scalar is split by fixed size windows of W bits
|
|
11
|
+
// - every window point is collected from window's table & added to accumulator
|
|
12
|
+
// - since windows are different, same point inside tables won't be accessed more than once per calc
|
|
13
|
+
// - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar)
|
|
14
|
+
// - +1 window is neccessary for wNAF
|
|
15
|
+
// - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication
|
|
16
|
+
// TODO: Research returning 2d JS array of windows, instead of a single window. This would allow
|
|
17
|
+
// windows to be in different memory locations
|
|
9
18
|
export function wNAF(c, bits) {
|
|
10
19
|
const constTimeNegate = (condition, item) => {
|
|
11
20
|
const neg = item.negate();
|
|
@@ -33,8 +42,12 @@ export function wNAF(c, bits) {
|
|
|
33
42
|
/**
|
|
34
43
|
* Creates a wNAF precomputation window. Used for caching.
|
|
35
44
|
* Default window size is set by `utils.precompute()` and is equal to 8.
|
|
36
|
-
*
|
|
37
|
-
*
|
|
45
|
+
* Number of precomputed points depends on the curve size:
|
|
46
|
+
* 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
|
|
47
|
+
* - 𝑊 is the window size
|
|
48
|
+
* - 𝑛 is the bitlength of the curve order.
|
|
49
|
+
* For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
|
|
50
|
+
* @returns precomputed point tables flattened to a single array
|
|
38
51
|
*/
|
|
39
52
|
precomputeWindow(elm, W) {
|
|
40
53
|
const { windows, windowSize } = opts(W);
|
|
@@ -54,14 +67,14 @@ export function wNAF(c, bits) {
|
|
|
54
67
|
return points;
|
|
55
68
|
},
|
|
56
69
|
/**
|
|
57
|
-
* Implements w-ary non-adjacent form
|
|
70
|
+
* Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
|
|
58
71
|
* @param W window size
|
|
59
|
-
* @param
|
|
60
|
-
* @param n
|
|
72
|
+
* @param precomputes precomputed tables
|
|
73
|
+
* @param n scalar (we don't check here, but should be less than curve order)
|
|
61
74
|
* @returns real and fake (for const-time) points
|
|
62
75
|
*/
|
|
63
76
|
wNAF(W, precomputes, n) {
|
|
64
|
-
// TODO: maybe check that scalar is less than group order? wNAF
|
|
77
|
+
// TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise
|
|
65
78
|
// But need to carefully remove other checks before wNAF. ORDER == bits here
|
|
66
79
|
const { windows, windowSize } = opts(W);
|
|
67
80
|
let p = c.ZERO;
|
|
@@ -1,19 +1,5 @@
|
|
|
1
1
|
import { mod } from './modular.js';
|
|
2
|
-
import { concatBytes, ensureBytes } from './utils.js';
|
|
3
|
-
export function validateOpts(opts) {
|
|
4
|
-
if (typeof opts.DST !== 'string')
|
|
5
|
-
throw new Error('Invalid htf/DST');
|
|
6
|
-
if (typeof opts.p !== 'bigint')
|
|
7
|
-
throw new Error('Invalid htf/p');
|
|
8
|
-
if (typeof opts.m !== 'number')
|
|
9
|
-
throw new Error('Invalid htf/m');
|
|
10
|
-
if (typeof opts.k !== 'number')
|
|
11
|
-
throw new Error('Invalid htf/k');
|
|
12
|
-
if (opts.expand !== 'xmd' && opts.expand !== 'xof' && opts.expand !== undefined)
|
|
13
|
-
throw new Error('Invalid htf/expand');
|
|
14
|
-
if (typeof opts.hash !== 'function' || !Number.isSafeInteger(opts.hash.outputLen))
|
|
15
|
-
throw new Error('Invalid htf/hash function');
|
|
16
|
-
}
|
|
2
|
+
import { concatBytes, ensureBytes, validateObject } from './utils.js';
|
|
17
3
|
export function stringToBytes(str) {
|
|
18
4
|
if (typeof str !== 'string') {
|
|
19
5
|
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
|
|
@@ -134,7 +120,15 @@ export function isogenyMap(field, map) {
|
|
|
134
120
|
};
|
|
135
121
|
}
|
|
136
122
|
export function hashToCurve(Point, mapToCurve, def) {
|
|
137
|
-
|
|
123
|
+
validateObject(def, {
|
|
124
|
+
DST: 'string',
|
|
125
|
+
p: 'bigint',
|
|
126
|
+
m: 'isSafeInteger',
|
|
127
|
+
k: 'isSafeInteger',
|
|
128
|
+
hash: 'hash',
|
|
129
|
+
});
|
|
130
|
+
if (def.expand !== 'xmd' && def.expand !== 'xof' && def.expand !== undefined)
|
|
131
|
+
throw new Error('Invalid htf/expand');
|
|
138
132
|
if (typeof mapToCurve !== 'function')
|
|
139
133
|
throw new Error('hashToCurve: mapToCurve() has not been defined');
|
|
140
134
|
return {
|
|
@@ -704,7 +704,7 @@ export function weierstrass(curveDef) {
|
|
|
704
704
|
return false;
|
|
705
705
|
}
|
|
706
706
|
},
|
|
707
|
-
|
|
707
|
+
normPrivateKeyToScalar: normalizePrivateKey,
|
|
708
708
|
/**
|
|
709
709
|
* Converts some bytes to a valid private key. Needs at least (nBitLength+64) bytes.
|
|
710
710
|
*/
|
|
@@ -838,7 +838,15 @@ export function weierstrass(curveDef) {
|
|
|
838
838
|
const r = modN(q.x); // r = q.x mod n
|
|
839
839
|
if (r === _0n)
|
|
840
840
|
return;
|
|
841
|
-
|
|
841
|
+
// X blinding according to https://tches.iacr.org/index.php/TCHES/article/view/7337/6509
|
|
842
|
+
// b * m + b * r * d ∈ [0,q−1] exposed via side-channel, but d (private scalar) is not.
|
|
843
|
+
// NOTE: there is still probable some leak in multiplication, since it is not constant-time
|
|
844
|
+
const b = ut.bytesToNumberBE(utils.randomPrivateKey()); // random scalar, b ∈ [1,q−1]
|
|
845
|
+
const bi = invN(b); // b^-1
|
|
846
|
+
const bdr = modN(b * d * r); // b * d * r
|
|
847
|
+
const bm = modN(b * m); // b * m
|
|
848
|
+
const mrx = modN(bi * modN(bdr + bm)); // b^-1(bm + bdr) -> m + rd
|
|
849
|
+
const s = modN(ik * mrx); // s = k^-1(m + rd) mod n
|
|
842
850
|
if (s === _0n)
|
|
843
851
|
return;
|
|
844
852
|
let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n); // recovery bit (2 or 3, when q.x > n)
|
package/lib/p192.d.ts
CHANGED
|
@@ -42,10 +42,11 @@ export declare const P192: Readonly<{
|
|
|
42
42
|
ProjectivePoint: import("./abstract/weierstrass.js").ProjConstructor<bigint>;
|
|
43
43
|
Signature: import("./abstract/weierstrass.js").SignatureConstructor;
|
|
44
44
|
utils: {
|
|
45
|
-
|
|
45
|
+
normPrivateKeyToScalar: (key: import("./abstract/utils.js").PrivKey) => bigint;
|
|
46
46
|
isValidPrivateKey(privateKey: import("./abstract/utils.js").PrivKey): boolean;
|
|
47
47
|
hashToPrivateKey: (hash: import("./abstract/utils.js").Hex) => Uint8Array;
|
|
48
48
|
randomPrivateKey: () => Uint8Array;
|
|
49
|
+
precompute: (windowSize?: number | undefined, point?: import("./abstract/weierstrass.js").ProjPointType<bigint> | undefined) => import("./abstract/weierstrass.js").ProjPointType<bigint>;
|
|
49
50
|
};
|
|
50
51
|
}>;
|
|
51
52
|
export declare const secp192r1: Readonly<{
|
|
@@ -92,9 +93,10 @@ export declare const secp192r1: Readonly<{
|
|
|
92
93
|
ProjectivePoint: import("./abstract/weierstrass.js").ProjConstructor<bigint>;
|
|
93
94
|
Signature: import("./abstract/weierstrass.js").SignatureConstructor;
|
|
94
95
|
utils: {
|
|
95
|
-
|
|
96
|
+
normPrivateKeyToScalar: (key: import("./abstract/utils.js").PrivKey) => bigint;
|
|
96
97
|
isValidPrivateKey(privateKey: import("./abstract/utils.js").PrivKey): boolean;
|
|
97
98
|
hashToPrivateKey: (hash: import("./abstract/utils.js").Hex) => Uint8Array;
|
|
98
99
|
randomPrivateKey: () => Uint8Array;
|
|
100
|
+
precompute: (windowSize?: number | undefined, point?: import("./abstract/weierstrass.js").ProjPointType<bigint> | undefined) => import("./abstract/weierstrass.js").ProjPointType<bigint>;
|
|
99
101
|
};
|
|
100
102
|
}>;
|
package/lib/p224.d.ts
CHANGED
|
@@ -42,10 +42,11 @@ export declare const P224: Readonly<{
|
|
|
42
42
|
ProjectivePoint: import("./abstract/weierstrass.js").ProjConstructor<bigint>;
|
|
43
43
|
Signature: import("./abstract/weierstrass.js").SignatureConstructor;
|
|
44
44
|
utils: {
|
|
45
|
-
|
|
45
|
+
normPrivateKeyToScalar: (key: import("./abstract/utils.js").PrivKey) => bigint;
|
|
46
46
|
isValidPrivateKey(privateKey: import("./abstract/utils.js").PrivKey): boolean;
|
|
47
47
|
hashToPrivateKey: (hash: import("./abstract/utils.js").Hex) => Uint8Array;
|
|
48
48
|
randomPrivateKey: () => Uint8Array;
|
|
49
|
+
precompute: (windowSize?: number | undefined, point?: import("./abstract/weierstrass.js").ProjPointType<bigint> | undefined) => import("./abstract/weierstrass.js").ProjPointType<bigint>;
|
|
49
50
|
};
|
|
50
51
|
}>;
|
|
51
52
|
export declare const secp224r1: Readonly<{
|
|
@@ -92,9 +93,10 @@ export declare const secp224r1: Readonly<{
|
|
|
92
93
|
ProjectivePoint: import("./abstract/weierstrass.js").ProjConstructor<bigint>;
|
|
93
94
|
Signature: import("./abstract/weierstrass.js").SignatureConstructor;
|
|
94
95
|
utils: {
|
|
95
|
-
|
|
96
|
+
normPrivateKeyToScalar: (key: import("./abstract/utils.js").PrivKey) => bigint;
|
|
96
97
|
isValidPrivateKey(privateKey: import("./abstract/utils.js").PrivKey): boolean;
|
|
97
98
|
hashToPrivateKey: (hash: import("./abstract/utils.js").Hex) => Uint8Array;
|
|
98
99
|
randomPrivateKey: () => Uint8Array;
|
|
100
|
+
precompute: (windowSize?: number | undefined, point?: import("./abstract/weierstrass.js").ProjPointType<bigint> | undefined) => import("./abstract/weierstrass.js").ProjPointType<bigint>;
|
|
99
101
|
};
|
|
100
102
|
}>;
|
package/lib/p256.d.ts
CHANGED
|
@@ -43,10 +43,11 @@ export declare const P256: Readonly<{
|
|
|
43
43
|
ProjectivePoint: import("./abstract/weierstrass.js").ProjConstructor<bigint>;
|
|
44
44
|
Signature: import("./abstract/weierstrass.js").SignatureConstructor;
|
|
45
45
|
utils: {
|
|
46
|
-
|
|
46
|
+
normPrivateKeyToScalar: (key: import("./abstract/utils.js").PrivKey) => bigint;
|
|
47
47
|
isValidPrivateKey(privateKey: import("./abstract/utils.js").PrivKey): boolean;
|
|
48
48
|
hashToPrivateKey: (hash: import("./abstract/utils.js").Hex) => Uint8Array;
|
|
49
49
|
randomPrivateKey: () => Uint8Array;
|
|
50
|
+
precompute: (windowSize?: number | undefined, point?: import("./abstract/weierstrass.js").ProjPointType<bigint> | undefined) => import("./abstract/weierstrass.js").ProjPointType<bigint>;
|
|
50
51
|
};
|
|
51
52
|
}>;
|
|
52
53
|
export declare const secp256r1: Readonly<{
|
|
@@ -93,10 +94,11 @@ export declare const secp256r1: Readonly<{
|
|
|
93
94
|
ProjectivePoint: import("./abstract/weierstrass.js").ProjConstructor<bigint>;
|
|
94
95
|
Signature: import("./abstract/weierstrass.js").SignatureConstructor;
|
|
95
96
|
utils: {
|
|
96
|
-
|
|
97
|
+
normPrivateKeyToScalar: (key: import("./abstract/utils.js").PrivKey) => bigint;
|
|
97
98
|
isValidPrivateKey(privateKey: import("./abstract/utils.js").PrivKey): boolean;
|
|
98
99
|
hashToPrivateKey: (hash: import("./abstract/utils.js").Hex) => Uint8Array;
|
|
99
100
|
randomPrivateKey: () => Uint8Array;
|
|
101
|
+
precompute: (windowSize?: number | undefined, point?: import("./abstract/weierstrass.js").ProjPointType<bigint> | undefined) => import("./abstract/weierstrass.js").ProjPointType<bigint>;
|
|
100
102
|
};
|
|
101
103
|
}>;
|
|
102
104
|
declare const hashToCurve: (msg: import("./abstract/utils.js").Hex, options?: htf.htfBasicOpts | undefined) => htf.H2CPoint<bigint>, encodeToCurve: (msg: import("./abstract/utils.js").Hex, options?: htf.htfBasicOpts | undefined) => htf.H2CPoint<bigint>;
|
package/lib/p384.d.ts
CHANGED
|
@@ -43,10 +43,11 @@ export declare const P384: Readonly<{
|
|
|
43
43
|
ProjectivePoint: import("./abstract/weierstrass.js").ProjConstructor<bigint>;
|
|
44
44
|
Signature: import("./abstract/weierstrass.js").SignatureConstructor;
|
|
45
45
|
utils: {
|
|
46
|
-
|
|
46
|
+
normPrivateKeyToScalar: (key: import("./abstract/utils.js").PrivKey) => bigint;
|
|
47
47
|
isValidPrivateKey(privateKey: import("./abstract/utils.js").PrivKey): boolean;
|
|
48
48
|
hashToPrivateKey: (hash: import("./abstract/utils.js").Hex) => Uint8Array;
|
|
49
49
|
randomPrivateKey: () => Uint8Array;
|
|
50
|
+
precompute: (windowSize?: number | undefined, point?: import("./abstract/weierstrass.js").ProjPointType<bigint> | undefined) => import("./abstract/weierstrass.js").ProjPointType<bigint>;
|
|
50
51
|
};
|
|
51
52
|
}>;
|
|
52
53
|
export declare const secp384r1: Readonly<{
|
|
@@ -93,10 +94,11 @@ export declare const secp384r1: Readonly<{
|
|
|
93
94
|
ProjectivePoint: import("./abstract/weierstrass.js").ProjConstructor<bigint>;
|
|
94
95
|
Signature: import("./abstract/weierstrass.js").SignatureConstructor;
|
|
95
96
|
utils: {
|
|
96
|
-
|
|
97
|
+
normPrivateKeyToScalar: (key: import("./abstract/utils.js").PrivKey) => bigint;
|
|
97
98
|
isValidPrivateKey(privateKey: import("./abstract/utils.js").PrivKey): boolean;
|
|
98
99
|
hashToPrivateKey: (hash: import("./abstract/utils.js").Hex) => Uint8Array;
|
|
99
100
|
randomPrivateKey: () => Uint8Array;
|
|
101
|
+
precompute: (windowSize?: number | undefined, point?: import("./abstract/weierstrass.js").ProjPointType<bigint> | undefined) => import("./abstract/weierstrass.js").ProjPointType<bigint>;
|
|
100
102
|
};
|
|
101
103
|
}>;
|
|
102
104
|
declare const hashToCurve: (msg: import("./abstract/utils.js").Hex, options?: htf.htfBasicOpts | undefined) => htf.H2CPoint<bigint>, encodeToCurve: (msg: import("./abstract/utils.js").Hex, options?: htf.htfBasicOpts | undefined) => htf.H2CPoint<bigint>;
|
package/lib/p521.d.ts
CHANGED
|
@@ -43,10 +43,11 @@ export declare const P521: Readonly<{
|
|
|
43
43
|
ProjectivePoint: import("./abstract/weierstrass.js").ProjConstructor<bigint>;
|
|
44
44
|
Signature: import("./abstract/weierstrass.js").SignatureConstructor;
|
|
45
45
|
utils: {
|
|
46
|
-
|
|
46
|
+
normPrivateKeyToScalar: (key: import("./abstract/utils.js").PrivKey) => bigint;
|
|
47
47
|
isValidPrivateKey(privateKey: import("./abstract/utils.js").PrivKey): boolean;
|
|
48
48
|
hashToPrivateKey: (hash: import("./abstract/utils.js").Hex) => Uint8Array;
|
|
49
49
|
randomPrivateKey: () => Uint8Array;
|
|
50
|
+
precompute: (windowSize?: number | undefined, point?: import("./abstract/weierstrass.js").ProjPointType<bigint> | undefined) => import("./abstract/weierstrass.js").ProjPointType<bigint>;
|
|
50
51
|
};
|
|
51
52
|
}>;
|
|
52
53
|
export declare const secp521r1: Readonly<{
|
|
@@ -93,10 +94,11 @@ export declare const secp521r1: Readonly<{
|
|
|
93
94
|
ProjectivePoint: import("./abstract/weierstrass.js").ProjConstructor<bigint>;
|
|
94
95
|
Signature: import("./abstract/weierstrass.js").SignatureConstructor;
|
|
95
96
|
utils: {
|
|
96
|
-
|
|
97
|
+
normPrivateKeyToScalar: (key: import("./abstract/utils.js").PrivKey) => bigint;
|
|
97
98
|
isValidPrivateKey(privateKey: import("./abstract/utils.js").PrivKey): boolean;
|
|
98
99
|
hashToPrivateKey: (hash: import("./abstract/utils.js").Hex) => Uint8Array;
|
|
99
100
|
randomPrivateKey: () => Uint8Array;
|
|
101
|
+
precompute: (windowSize?: number | undefined, point?: import("./abstract/weierstrass.js").ProjPointType<bigint> | undefined) => import("./abstract/weierstrass.js").ProjPointType<bigint>;
|
|
100
102
|
};
|
|
101
103
|
}>;
|
|
102
104
|
declare const hashToCurve: (msg: import("./abstract/utils.js").Hex, options?: htf.htfBasicOpts | undefined) => htf.H2CPoint<bigint>, encodeToCurve: (msg: import("./abstract/utils.js").Hex, options?: htf.htfBasicOpts | undefined) => htf.H2CPoint<bigint>;
|
package/lib/secp256k1.d.ts
CHANGED
|
@@ -46,10 +46,11 @@ export declare const secp256k1: Readonly<{
|
|
|
46
46
|
ProjectivePoint: import("./abstract/weierstrass.js").ProjConstructor<bigint>;
|
|
47
47
|
Signature: import("./abstract/weierstrass.js").SignatureConstructor;
|
|
48
48
|
utils: {
|
|
49
|
-
|
|
49
|
+
normPrivateKeyToScalar: (key: PrivKey) => bigint;
|
|
50
50
|
isValidPrivateKey(privateKey: PrivKey): boolean;
|
|
51
51
|
hashToPrivateKey: (hash: Hex) => Uint8Array;
|
|
52
52
|
randomPrivateKey: () => Uint8Array;
|
|
53
|
+
precompute: (windowSize?: number | undefined, point?: PointType<bigint> | undefined) => PointType<bigint>;
|
|
53
54
|
};
|
|
54
55
|
}>;
|
|
55
56
|
declare function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array;
|
package/lib/stark.d.ts
CHANGED
|
@@ -40,10 +40,11 @@ declare const CURVE: Readonly<{
|
|
|
40
40
|
readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
41
41
|
}>, ProjectivePoint: import("./abstract/weierstrass.js").ProjConstructor<bigint>, Signature: import("./abstract/weierstrass.js").SignatureConstructor;
|
|
42
42
|
export declare const utils: {
|
|
43
|
-
|
|
43
|
+
normPrivateKeyToScalar: (key: cutils.PrivKey) => bigint;
|
|
44
44
|
isValidPrivateKey(privateKey: cutils.PrivKey): boolean;
|
|
45
45
|
hashToPrivateKey: (hash: cutils.Hex) => Uint8Array;
|
|
46
46
|
randomPrivateKey: () => Uint8Array;
|
|
47
|
+
precompute: (windowSize?: number | undefined, point?: ProjPointType<bigint> | undefined) => ProjPointType<bigint>;
|
|
47
48
|
};
|
|
48
49
|
export { CURVE, Signature, ProjectivePoint, getPublicKey0x as getPublicKey, getSharedSecret0x as getSharedSecret, sign0x as sign, verify0x as verify, };
|
|
49
50
|
export declare const bytesToHexEth: (uint8a: Uint8Array) => string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noble/curves",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
4
4
|
"description": "Minimal, auditable JS implementation of elliptic curve cryptography",
|
|
5
5
|
"files": [
|
|
6
6
|
"lib"
|
|
@@ -21,19 +21,17 @@
|
|
|
21
21
|
},
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@noble/hashes": "1.
|
|
24
|
+
"@noble/hashes": "1.2.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@rollup/plugin-node-resolve": "13.3.0",
|
|
28
27
|
"@scure/base": "~1.1.1",
|
|
29
|
-
"@scure/bip32": "~1.1.
|
|
30
|
-
"@scure/bip39": "~1.1.
|
|
28
|
+
"@scure/bip32": "~1.1.5",
|
|
29
|
+
"@scure/bip39": "~1.1.1",
|
|
31
30
|
"@types/node": "18.11.3",
|
|
32
31
|
"fast-check": "3.0.0",
|
|
33
32
|
"micro-bmark": "0.3.0",
|
|
34
33
|
"micro-should": "0.4.0",
|
|
35
34
|
"prettier": "2.8.3",
|
|
36
|
-
"rollup": "2.75.5",
|
|
37
35
|
"typescript": "4.7.3"
|
|
38
36
|
},
|
|
39
37
|
"main": "index.js",
|