@noble/curves 0.5.1 → 0.5.2
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 +1 -4
- package/lib/_shortw_utils.d.ts +2 -6
- package/lib/abstract/bls.d.ts +17 -8
- package/lib/abstract/bls.js +15 -78
- package/lib/abstract/edwards.d.ts +7 -16
- package/lib/abstract/edwards.js +89 -106
- package/lib/abstract/modular.js +26 -23
- package/lib/abstract/montgomery.js +1 -1
- package/lib/abstract/utils.d.ts +5 -3
- package/lib/abstract/utils.js +22 -14
- package/lib/abstract/weierstrass.d.ts +8 -8
- package/lib/abstract/weierstrass.js +209 -168
- package/lib/bls12-381.d.ts +1 -0
- package/lib/bls12-381.js +13 -8
- package/lib/ed25519.js +5 -5
- package/lib/ed448.js +2 -1
- package/lib/esm/abstract/bls.js +19 -82
- package/lib/esm/abstract/edwards.js +90 -107
- package/lib/esm/abstract/modular.js +26 -23
- package/lib/esm/abstract/montgomery.js +2 -4
- package/lib/esm/abstract/utils.js +20 -13
- package/lib/esm/abstract/weierstrass.js +210 -169
- package/lib/esm/bls12-381.js +12 -7
- package/lib/esm/ed25519.js +5 -5
- package/lib/esm/ed448.js +2 -1
- package/lib/esm/jubjub.js +5 -4
- package/lib/esm/secp256k1.js +22 -25
- package/lib/esm/stark.js +3 -2
- package/lib/jubjub.d.ts +1 -0
- package/lib/jubjub.js +5 -4
- package/lib/p192.d.ts +4 -12
- package/lib/p224.d.ts +4 -12
- package/lib/p256.d.ts +4 -12
- package/lib/p384.d.ts +4 -12
- package/lib/p521.d.ts +4 -12
- package/lib/secp256k1.d.ts +2 -6
- package/lib/secp256k1.js +22 -25
- package/lib/stark.d.ts +0 -2
- package/lib/stark.js +3 -2
- package/package.json +2 -2
|
@@ -55,6 +55,7 @@ export function invert(number, modulo) {
|
|
|
55
55
|
// prettier-ignore
|
|
56
56
|
let x = _0n, y = _1n, u = _1n, v = _0n;
|
|
57
57
|
while (a !== _0n) {
|
|
58
|
+
// JIT applies optimization if those two lines follow each other
|
|
58
59
|
const q = b / a;
|
|
59
60
|
const r = b % a;
|
|
60
61
|
const m = x - u * q;
|
|
@@ -68,7 +69,8 @@ export function invert(number, modulo) {
|
|
|
68
69
|
return mod(x, modulo);
|
|
69
70
|
}
|
|
70
71
|
// Tonelli-Shanks algorithm
|
|
71
|
-
// https://eprint.iacr.org/2012/685.pdf (page 12)
|
|
72
|
+
// Paper 1: https://eprint.iacr.org/2012/685.pdf (page 12)
|
|
73
|
+
// Paper 2: Square Roots from 1; 24, 51, 10 to Dan Shanks
|
|
72
74
|
export function tonelliShanks(P) {
|
|
73
75
|
// Legendre constant: used to calculate Legendre symbol (a | p),
|
|
74
76
|
// which denotes the value of a^((p-1)/2) (mod p).
|
|
@@ -78,7 +80,7 @@ export function tonelliShanks(P) {
|
|
|
78
80
|
const legendreC = (P - _1n) / _2n;
|
|
79
81
|
let Q, S, Z;
|
|
80
82
|
// Step 1: By factoring out powers of 2 from p - 1,
|
|
81
|
-
// find q and s such that p - 1 =
|
|
83
|
+
// find q and s such that p - 1 = q*(2^s) with q odd
|
|
82
84
|
for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++)
|
|
83
85
|
;
|
|
84
86
|
// Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq
|
|
@@ -97,31 +99,32 @@ export function tonelliShanks(P) {
|
|
|
97
99
|
// Slow-path
|
|
98
100
|
const Q1div2 = (Q + _1n) / _2n;
|
|
99
101
|
return function tonelliSlow(Fp, n) {
|
|
100
|
-
// Step 0: Check that n is indeed a square: (n | p)
|
|
101
|
-
if (Fp.pow(n, legendreC)
|
|
102
|
+
// Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1
|
|
103
|
+
if (Fp.pow(n, legendreC) === Fp.negate(Fp.ONE))
|
|
102
104
|
throw new Error('Cannot find square root');
|
|
103
|
-
let
|
|
104
|
-
|
|
105
|
-
let
|
|
106
|
-
let
|
|
107
|
-
let
|
|
108
|
-
while (!Fp.equals(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
105
|
+
let r = S;
|
|
106
|
+
// TODO: will fail at Fp2/etc
|
|
107
|
+
let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q); // will update both x and b
|
|
108
|
+
let x = Fp.pow(n, Q1div2); // first guess at the square root
|
|
109
|
+
let b = Fp.pow(n, Q); // first guess at the fudge factor
|
|
110
|
+
while (!Fp.equals(b, Fp.ONE)) {
|
|
111
|
+
if (Fp.equals(b, Fp.ZERO))
|
|
112
|
+
return Fp.ZERO; // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0)
|
|
113
|
+
// Find m such b^(2^m)==1
|
|
114
|
+
let m = 1;
|
|
115
|
+
for (let t2 = Fp.square(b); m < r; m++) {
|
|
116
|
+
if (Fp.equals(t2, Fp.ONE))
|
|
114
117
|
break;
|
|
115
|
-
// t2 *= t2
|
|
116
|
-
t2 = Fp.square(t2);
|
|
118
|
+
t2 = Fp.square(t2); // t2 *= t2
|
|
117
119
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
// NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow
|
|
121
|
+
const ge = Fp.pow(g, _1n << BigInt(r - m - 1)); // ge = 2^(r-m-1)
|
|
122
|
+
g = Fp.square(ge); // g = ge * ge
|
|
123
|
+
x = Fp.mul(x, ge); // x *= ge
|
|
124
|
+
b = Fp.mul(b, g); // b *= g
|
|
125
|
+
r = m;
|
|
123
126
|
}
|
|
124
|
-
return
|
|
127
|
+
return x;
|
|
125
128
|
};
|
|
126
129
|
}
|
|
127
130
|
export function FpSqrt(P) {
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
2
2
|
import * as mod from './modular.js';
|
|
3
|
-
import { ensureBytes, numberToBytesLE, bytesToNumberLE,
|
|
4
|
-
// nLength,
|
|
5
|
-
} from './utils.js';
|
|
3
|
+
import { ensureBytes, numberToBytesLE, bytesToNumberLE, isPositiveInt } from './utils.js';
|
|
6
4
|
const _0n = BigInt(0);
|
|
7
5
|
const _1n = BigInt(1);
|
|
8
6
|
function validateOpts(curve) {
|
|
@@ -13,7 +11,7 @@ function validateOpts(curve) {
|
|
|
13
11
|
for (const i of ['montgomeryBits', 'nByteLength']) {
|
|
14
12
|
if (curve[i] === undefined)
|
|
15
13
|
continue; // Optional
|
|
16
|
-
if (!
|
|
14
|
+
if (!isPositiveInt(curve[i]))
|
|
17
15
|
throw new Error(`Invalid curve param ${i}=${curve[i]} (${typeof curve[i]})`);
|
|
18
16
|
}
|
|
19
17
|
for (const fn of ['adjustScalarBytes', 'domain', 'powPminus2']) {
|
|
@@ -3,21 +3,27 @@ import * as mod from './modular.js';
|
|
|
3
3
|
const _0n = BigInt(0);
|
|
4
4
|
const _1n = BigInt(1);
|
|
5
5
|
const _2n = BigInt(2);
|
|
6
|
+
// Bans floats and integers above 2^53-1
|
|
7
|
+
export function isPositiveInt(num) {
|
|
8
|
+
return typeof num === 'number' && Number.isSafeInteger(num) && num > 0;
|
|
9
|
+
}
|
|
6
10
|
export function validateOpts(curve) {
|
|
7
11
|
mod.validateField(curve.Fp);
|
|
8
12
|
for (const i of ['n', 'h']) {
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
const val = curve[i];
|
|
14
|
+
if (typeof val !== 'bigint')
|
|
15
|
+
throw new Error(`Invalid curve param ${i}=${val} (${typeof val})`);
|
|
11
16
|
}
|
|
12
17
|
if (!curve.Fp.isValid(curve.Gx))
|
|
13
18
|
throw new Error('Invalid generator X coordinate Fp element');
|
|
14
19
|
if (!curve.Fp.isValid(curve.Gy))
|
|
15
20
|
throw new Error('Invalid generator Y coordinate Fp element');
|
|
16
21
|
for (const i of ['nBitLength', 'nByteLength']) {
|
|
17
|
-
|
|
22
|
+
const val = curve[i];
|
|
23
|
+
if (val === undefined)
|
|
18
24
|
continue; // Optional
|
|
19
|
-
if (!
|
|
20
|
-
throw new Error(`Invalid curve param ${i}=${
|
|
25
|
+
if (!isPositiveInt(val))
|
|
26
|
+
throw new Error(`Invalid curve param ${i}=${val} (${typeof val})`);
|
|
21
27
|
}
|
|
22
28
|
// Set defaults
|
|
23
29
|
return Object.freeze({ ...nLength(curve.n, curve.nBitLength), ...curve });
|
|
@@ -104,21 +110,22 @@ export function nLength(n, nBitLength) {
|
|
|
104
110
|
return { nBitLength: _nBitLength, nByteLength };
|
|
105
111
|
}
|
|
106
112
|
/**
|
|
113
|
+
* FIPS 186 B.4.1-compliant "constant-time" private key generation utility.
|
|
107
114
|
* Can take (n+8) or more bytes of uniform input e.g. from CSPRNG or KDF
|
|
108
115
|
* and convert them into private scalar, with the modulo bias being neglible.
|
|
109
|
-
*
|
|
116
|
+
* Needs at least 40 bytes of input for 32-byte private key.
|
|
110
117
|
* https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
|
|
111
|
-
* @param hash hash output from
|
|
118
|
+
* @param hash hash output from SHA3 or a similar function
|
|
112
119
|
* @returns valid private scalar
|
|
113
120
|
*/
|
|
114
|
-
export function hashToPrivateScalar(hash,
|
|
121
|
+
export function hashToPrivateScalar(hash, groupOrder, isLE = false) {
|
|
115
122
|
hash = ensureBytes(hash);
|
|
116
|
-
const
|
|
117
|
-
const minLen =
|
|
118
|
-
if (
|
|
119
|
-
throw new Error(
|
|
123
|
+
const hashLen = hash.length;
|
|
124
|
+
const minLen = nLength(groupOrder).nByteLength + 8;
|
|
125
|
+
if (minLen < 24 || hashLen < minLen || hashLen > 1024)
|
|
126
|
+
throw new Error(`hashToPrivateScalar: expected ${minLen}-1024 bytes of input, got ${hashLen}`);
|
|
120
127
|
const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash);
|
|
121
|
-
return mod.mod(num,
|
|
128
|
+
return mod.mod(num, groupOrder - _1n) + _1n;
|
|
122
129
|
}
|
|
123
130
|
export function equalBytes(b1, b2) {
|
|
124
131
|
// We don't care about timing attacks here
|