@noble/curves 0.3.1 → 0.4.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 +2 -1
- package/lib/bls.d.ts +79 -0
- package/lib/bls.js +304 -0
- package/lib/edwards.d.ts +10 -6
- package/lib/edwards.js +16 -11
- package/lib/esm/bls.js +300 -0
- package/lib/esm/edwards.js +17 -12
- package/lib/esm/group.js +2 -2
- package/lib/esm/hashToCurve.js +105 -0
- package/lib/esm/modular.js +131 -50
- package/lib/esm/utils.js +25 -19
- package/lib/esm/weierstrass.js +351 -272
- package/lib/group.js +2 -2
- package/lib/hashToCurve.d.ts +13 -0
- package/lib/hashToCurve.js +112 -0
- package/lib/modular.d.ts +37 -17
- package/lib/modular.js +138 -54
- package/lib/utils.d.ts +28 -10
- package/lib/utils.js +31 -22
- package/lib/weierstrass.d.ts +106 -69
- package/lib/weierstrass.js +352 -272
- package/package.json +23 -44
- package/lib/crypto.d.ts +0 -4
- package/lib/crypto.js +0 -8
- package/lib/cryptoBrowser.d.ts +0 -4
- package/lib/cryptoBrowser.js +0 -7
- package/lib/definitions/_shortw_utils.d.ts +0 -63
- package/lib/definitions/_shortw_utils.js +0 -18
- package/lib/definitions/bn.d.ts +0 -7
- package/lib/definitions/bn.js +0 -23
- package/lib/definitions/ed25519.d.ts +0 -49
- package/lib/definitions/ed25519.js +0 -308
- package/lib/definitions/ed448.d.ts +0 -3
- package/lib/definitions/ed448.js +0 -127
- package/lib/definitions/index.d.ts +0 -0
- package/lib/definitions/index.js +0 -2
- package/lib/definitions/jubjub.d.ts +0 -7
- package/lib/definitions/jubjub.js +0 -55
- package/lib/definitions/p192.d.ts +0 -112
- package/lib/definitions/p192.js +0 -23
- package/lib/definitions/p224.d.ts +0 -112
- package/lib/definitions/p224.js +0 -24
- package/lib/definitions/p256.d.ts +0 -112
- package/lib/definitions/p256.js +0 -23
- package/lib/definitions/p384.d.ts +0 -112
- package/lib/definitions/p384.js +0 -24
- package/lib/definitions/p521.d.ts +0 -113
- package/lib/definitions/p521.js +0 -36
- package/lib/definitions/pasta.d.ts +0 -2
- package/lib/definitions/pasta.js +0 -32
- package/lib/definitions/secp256k1.d.ts +0 -87
- package/lib/definitions/secp256k1.js +0 -245
- package/lib/definitions/stark.d.ts +0 -62
- package/lib/definitions/stark.js +0 -248
- package/lib/esm/crypto.js +0 -5
- package/lib/esm/cryptoBrowser.js +0 -4
- package/lib/esm/definitions/_shortw_utils.js +0 -13
- package/lib/esm/definitions/bn.js +0 -20
- package/lib/esm/definitions/ed25519.js +0 -304
- package/lib/esm/definitions/ed448.js +0 -124
- package/lib/esm/definitions/index.js +0 -2
- package/lib/esm/definitions/jubjub.js +0 -50
- package/lib/esm/definitions/p192.js +0 -20
- package/lib/esm/definitions/p224.js +0 -21
- package/lib/esm/definitions/p256.js +0 -20
- package/lib/esm/definitions/p384.js +0 -21
- package/lib/esm/definitions/p521.js +0 -33
- package/lib/esm/definitions/pasta.js +0 -29
- package/lib/esm/definitions/secp256k1.js +0 -241
- package/lib/esm/definitions/stark.js +0 -227
package/lib/esm/modular.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
2
|
+
import * as utils from './utils.js';
|
|
2
3
|
// Utilities for modular arithmetics
|
|
3
4
|
const _0n = BigInt(0);
|
|
4
5
|
const _1n = BigInt(1);
|
|
@@ -14,6 +15,7 @@ export function mod(a, b) {
|
|
|
14
15
|
* @example
|
|
15
16
|
* powMod(2n, 6n, 11n) // 64n % 11n == 9n
|
|
16
17
|
*/
|
|
18
|
+
// TODO: use field version && remove
|
|
17
19
|
export function pow(num, power, modulo) {
|
|
18
20
|
if (modulo <= _0n || power < _0n)
|
|
19
21
|
throw new Error('Expected power/modulo > 0');
|
|
@@ -29,6 +31,7 @@ export function pow(num, power, modulo) {
|
|
|
29
31
|
return res;
|
|
30
32
|
}
|
|
31
33
|
// Does x ^ (2 ^ power) mod p. pow2(30, 4) == 30 ^ (2 ^ 4)
|
|
34
|
+
// TODO: Fp version?
|
|
32
35
|
export function pow2(x, power, modulo) {
|
|
33
36
|
let res = x;
|
|
34
37
|
while (power-- > _0n) {
|
|
@@ -60,56 +63,19 @@ export function invert(number, modulo) {
|
|
|
60
63
|
throw new Error('invert: does not exist');
|
|
61
64
|
return mod(x, modulo);
|
|
62
65
|
}
|
|
63
|
-
/**
|
|
64
|
-
* Division over finite field.
|
|
65
|
-
* `a/b mod p == a * invert(b) mod p`
|
|
66
|
-
*/
|
|
67
|
-
export function div(numerator, denominator, modulo) {
|
|
68
|
-
const num = mod(numerator, modulo);
|
|
69
|
-
const iden = invert(denominator, modulo);
|
|
70
|
-
return mod(num * iden, modulo);
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Takes a list of numbers, efficiently inverts all of them.
|
|
74
|
-
* @param nums list of bigints
|
|
75
|
-
* @param p modulo
|
|
76
|
-
* @returns list of inverted bigints
|
|
77
|
-
* @example
|
|
78
|
-
* invertBatch([1n, 2n, 4n], 21n);
|
|
79
|
-
* // => [1n, 11n, 16n]
|
|
80
|
-
*/
|
|
81
|
-
export function invertBatch(nums, modulo) {
|
|
82
|
-
const scratch = new Array(nums.length);
|
|
83
|
-
// Walk from first to last, multiply them by each other MOD p
|
|
84
|
-
const lastMultiplied = nums.reduce((acc, num, i) => {
|
|
85
|
-
if (num === _0n)
|
|
86
|
-
return acc;
|
|
87
|
-
scratch[i] = acc;
|
|
88
|
-
return mod(acc * num, modulo);
|
|
89
|
-
}, _1n);
|
|
90
|
-
// Invert last element
|
|
91
|
-
const inverted = invert(lastMultiplied, modulo);
|
|
92
|
-
// Walk from last to first, multiply them by inverted each other MOD p
|
|
93
|
-
nums.reduceRight((acc, num, i) => {
|
|
94
|
-
if (num === _0n)
|
|
95
|
-
return acc;
|
|
96
|
-
scratch[i] = mod(acc * scratch[i], modulo);
|
|
97
|
-
return mod(acc * num, modulo);
|
|
98
|
-
}, inverted);
|
|
99
|
-
return scratch;
|
|
100
|
-
}
|
|
101
66
|
/**
|
|
102
67
|
* Calculates Legendre symbol (a | p), which denotes the value of a^((p-1)/2) (mod p).
|
|
103
68
|
* * (a | p) ≡ 1 if a is a square (mod p)
|
|
104
69
|
* * (a | p) ≡ -1 if a is not a square (mod p)
|
|
105
70
|
* * (a | p) ≡ 0 if a ≡ 0 (mod p)
|
|
106
71
|
*/
|
|
107
|
-
export function legendre(num,
|
|
108
|
-
return pow(num, (
|
|
72
|
+
export function legendre(num, fieldPrime) {
|
|
73
|
+
return pow(num, (fieldPrime - _1n) / _2n, fieldPrime);
|
|
109
74
|
}
|
|
110
75
|
/**
|
|
111
76
|
* Calculates square root of a number in a finite field.
|
|
112
77
|
*/
|
|
78
|
+
// TODO: rewrite as generic Fp function && remove bls versions
|
|
113
79
|
export function sqrt(number, modulo) {
|
|
114
80
|
// prettier-ignore
|
|
115
81
|
const _3n = BigInt(3), _4n = BigInt(4), _5n = BigInt(5), _8n = BigInt(8);
|
|
@@ -118,8 +84,17 @@ export function sqrt(number, modulo) {
|
|
|
118
84
|
const p1div4 = (P + _1n) / _4n;
|
|
119
85
|
// P ≡ 3 (mod 4)
|
|
120
86
|
// sqrt n = n^((P+1)/4)
|
|
121
|
-
if (P % _4n === _3n)
|
|
122
|
-
|
|
87
|
+
if (P % _4n === _3n) {
|
|
88
|
+
// Not all roots possible!
|
|
89
|
+
// const ORDER =
|
|
90
|
+
// 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn;
|
|
91
|
+
// const NUM = 72057594037927816n;
|
|
92
|
+
// TODO: fix sqrtMod in secp256k1
|
|
93
|
+
const root = pow(n, p1div4, P);
|
|
94
|
+
if (mod(root * root, modulo) !== number)
|
|
95
|
+
throw new Error('Cannot find square root');
|
|
96
|
+
return root;
|
|
97
|
+
}
|
|
123
98
|
// P ≡ 5 (mod 8)
|
|
124
99
|
if (P % _8n === _5n) {
|
|
125
100
|
const n2 = mod(n * _2n, P);
|
|
@@ -130,7 +105,6 @@ export function sqrt(number, modulo) {
|
|
|
130
105
|
return r;
|
|
131
106
|
}
|
|
132
107
|
// Other cases: Tonelli-Shanks algorithm
|
|
133
|
-
// Check whether n is square
|
|
134
108
|
if (legendre(n, P) !== _1n)
|
|
135
109
|
throw new Error('Cannot find square root');
|
|
136
110
|
let q, s, z;
|
|
@@ -162,10 +136,117 @@ export function sqrt(number, modulo) {
|
|
|
162
136
|
}
|
|
163
137
|
// Little-endian check for first LE bit (last BE bit);
|
|
164
138
|
export const isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n) === _1n;
|
|
165
|
-
//
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
139
|
+
// prettier-ignore
|
|
140
|
+
const FIELD_FIELDS = [
|
|
141
|
+
'create', 'isValid', 'isZero', 'negate', 'invert', 'sqrt', 'square',
|
|
142
|
+
'equals', 'add', 'subtract', 'multiply', 'pow', 'div',
|
|
143
|
+
'addN', 'subtractN', 'multiplyN', 'squareN'
|
|
144
|
+
];
|
|
145
|
+
export function validateField(field) {
|
|
146
|
+
for (const i of ['ORDER', 'MASK']) {
|
|
147
|
+
if (typeof field[i] !== 'bigint')
|
|
148
|
+
throw new Error(`Invalid field param ${i}=${field[i]} (${typeof field[i]})`);
|
|
149
|
+
}
|
|
150
|
+
for (const i of ['BYTES', 'BITS']) {
|
|
151
|
+
if (typeof field[i] !== 'number')
|
|
152
|
+
throw new Error(`Invalid field param ${i}=${field[i]} (${typeof field[i]})`);
|
|
153
|
+
}
|
|
154
|
+
for (const i of FIELD_FIELDS) {
|
|
155
|
+
if (typeof field[i] !== 'function')
|
|
156
|
+
throw new Error(`Invalid field param ${i}=${field[i]} (${typeof field[i]})`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// Generic field functions
|
|
160
|
+
export function FpPow(f, num, power) {
|
|
161
|
+
// Should have same speed as pow for bigints
|
|
162
|
+
// TODO: benchmark!
|
|
163
|
+
if (power < _0n)
|
|
164
|
+
throw new Error('Expected power > 0');
|
|
165
|
+
if (power === _0n)
|
|
166
|
+
return f.ONE;
|
|
167
|
+
if (power === _1n)
|
|
168
|
+
return num;
|
|
169
|
+
let p = f.ONE;
|
|
170
|
+
let d = num;
|
|
171
|
+
while (power > _0n) {
|
|
172
|
+
if (power & _1n)
|
|
173
|
+
p = f.multiply(p, d);
|
|
174
|
+
d = f.square(d);
|
|
175
|
+
power >>= 1n;
|
|
176
|
+
}
|
|
177
|
+
return p;
|
|
178
|
+
}
|
|
179
|
+
export function FpInvertBatch(f, nums) {
|
|
180
|
+
const tmp = new Array(nums.length);
|
|
181
|
+
// Walk from first to last, multiply them by each other MOD p
|
|
182
|
+
const lastMultiplied = nums.reduce((acc, num, i) => {
|
|
183
|
+
if (f.isZero(num))
|
|
184
|
+
return acc;
|
|
185
|
+
tmp[i] = acc;
|
|
186
|
+
return f.multiply(acc, num);
|
|
187
|
+
}, f.ONE);
|
|
188
|
+
// Invert last element
|
|
189
|
+
const inverted = f.invert(lastMultiplied);
|
|
190
|
+
// Walk from last to first, multiply them by inverted each other MOD p
|
|
191
|
+
nums.reduceRight((acc, num, i) => {
|
|
192
|
+
if (f.isZero(num))
|
|
193
|
+
return acc;
|
|
194
|
+
tmp[i] = f.multiply(acc, tmp[i]);
|
|
195
|
+
return f.multiply(acc, num);
|
|
196
|
+
}, inverted);
|
|
197
|
+
return tmp;
|
|
198
|
+
}
|
|
199
|
+
export function FpDiv(f, lhs, rhs) {
|
|
200
|
+
return f.multiply(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.invert(rhs));
|
|
201
|
+
}
|
|
202
|
+
// NOTE: very fragile, always bench. Major performance points:
|
|
203
|
+
// - NonNormalized ops
|
|
204
|
+
// - Object.freeze
|
|
205
|
+
// - same shape of object (don't add/remove keys)
|
|
206
|
+
export function Fp(ORDER, bitLen, isLE = false, redef = {}) {
|
|
207
|
+
if (ORDER <= _0n)
|
|
208
|
+
throw new Error(`Expected Fp ORDER > 0, got ${ORDER}`);
|
|
209
|
+
const { nBitLength: BITS, nByteLength: BYTES } = utils.nLength(ORDER, bitLen);
|
|
210
|
+
if (BYTES > 2048)
|
|
211
|
+
throw new Error('Field lengths over 2048 bytes are not supported');
|
|
212
|
+
const sqrtP = (num) => sqrt(num, ORDER);
|
|
213
|
+
const f = Object.freeze({
|
|
214
|
+
ORDER,
|
|
215
|
+
BITS,
|
|
216
|
+
BYTES,
|
|
217
|
+
MASK: utils.bitMask(BITS),
|
|
218
|
+
ZERO: _0n,
|
|
219
|
+
ONE: _1n,
|
|
220
|
+
create: (num) => mod(num, ORDER),
|
|
221
|
+
isValid: (num) => {
|
|
222
|
+
if (typeof num !== 'bigint')
|
|
223
|
+
throw new Error(`Invalid field element: expected bigint, got ${typeof num}`);
|
|
224
|
+
return _0n <= num && num < ORDER;
|
|
225
|
+
},
|
|
226
|
+
isZero: (num) => num === _0n,
|
|
227
|
+
isOdd: (num) => (num & _1n) === _1n,
|
|
228
|
+
negate: (num) => mod(-num, ORDER),
|
|
229
|
+
equals: (lhs, rhs) => lhs === rhs,
|
|
230
|
+
square: (num) => mod(num * num, ORDER),
|
|
231
|
+
add: (lhs, rhs) => mod(lhs + rhs, ORDER),
|
|
232
|
+
subtract: (lhs, rhs) => mod(lhs - rhs, ORDER),
|
|
233
|
+
multiply: (lhs, rhs) => mod(lhs * rhs, ORDER),
|
|
234
|
+
pow: (num, power) => FpPow(f, num, power),
|
|
235
|
+
div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),
|
|
236
|
+
// Same as above, but doesn't normalize
|
|
237
|
+
squareN: (num) => num * num,
|
|
238
|
+
addN: (lhs, rhs) => lhs + rhs,
|
|
239
|
+
subtractN: (lhs, rhs) => lhs - rhs,
|
|
240
|
+
multiplyN: (lhs, rhs) => lhs * rhs,
|
|
241
|
+
invert: (num) => invert(num, ORDER),
|
|
242
|
+
sqrt: redef.sqrt || sqrtP,
|
|
243
|
+
invertBatch: (lst) => FpInvertBatch(f, lst),
|
|
244
|
+
toBytes: (num) => isLE ? utils.numberToBytesLE(num, BYTES) : utils.numberToBytesBE(num, BYTES),
|
|
245
|
+
fromBytes: (bytes) => {
|
|
246
|
+
if (bytes.length !== BYTES)
|
|
247
|
+
throw new Error(`Fp.fromBytes: expected ${BYTES}, got ${bytes.length}`);
|
|
248
|
+
return isLE ? utils.bytesToNumberLE(bytes) : utils.bytesToNumberBE(bytes);
|
|
249
|
+
},
|
|
250
|
+
});
|
|
251
|
+
return Object.freeze(f);
|
|
252
|
+
}
|
package/lib/esm/utils.js
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import * as mod from './modular.js';
|
|
3
|
+
const _0n = BigInt(0);
|
|
4
|
+
const _1n = BigInt(1);
|
|
5
|
+
const _2n = BigInt(2);
|
|
5
6
|
export function validateOpts(curve) {
|
|
6
|
-
|
|
7
|
+
mod.validateField(curve.Fp);
|
|
8
|
+
for (const i of ['n', 'h']) {
|
|
7
9
|
if (typeof curve[i] !== 'bigint')
|
|
8
10
|
throw new Error(`Invalid curve param ${i}=${curve[i]} (${typeof curve[i]})`);
|
|
9
11
|
}
|
|
12
|
+
if (!curve.Fp.isValid(curve.Gx))
|
|
13
|
+
throw new Error('Invalid generator X coordinate Fp element');
|
|
14
|
+
if (!curve.Fp.isValid(curve.Gy))
|
|
15
|
+
throw new Error('Invalid generator Y coordinate Fp element');
|
|
10
16
|
for (const i of ['nBitLength', 'nByteLength']) {
|
|
11
17
|
if (curve[i] === undefined)
|
|
12
18
|
continue; // Optional
|
|
@@ -16,7 +22,6 @@ export function validateOpts(curve) {
|
|
|
16
22
|
// Set defaults
|
|
17
23
|
return Object.freeze({ ...nLength(curve.n, curve.nBitLength), ...curve });
|
|
18
24
|
}
|
|
19
|
-
import * as mod from './modular.js';
|
|
20
25
|
const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'));
|
|
21
26
|
export function bytesToHex(uint8a) {
|
|
22
27
|
if (!(uint8a instanceof Uint8Array))
|
|
@@ -106,7 +111,6 @@ export function nLength(n, nBitLength) {
|
|
|
106
111
|
* @param hash hash output from sha512, or a similar function
|
|
107
112
|
* @returns valid private scalar
|
|
108
113
|
*/
|
|
109
|
-
const _1n = BigInt(1);
|
|
110
114
|
export function hashToPrivateScalar(hash, CURVE_ORDER, isLE = false) {
|
|
111
115
|
hash = ensureBytes(hash);
|
|
112
116
|
const orderLen = nLength(CURVE_ORDER).nByteLength;
|
|
@@ -125,17 +129,19 @@ export function equalBytes(b1, b2) {
|
|
|
125
129
|
return false;
|
|
126
130
|
return true;
|
|
127
131
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
else if (crypto.node) {
|
|
136
|
-
return new Uint8Array(crypto.node.randomBytes(bytesLength).buffer);
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
throw new Error("The environment doesn't have randomBytes function");
|
|
140
|
-
}
|
|
132
|
+
// Bit operations
|
|
133
|
+
// Amount of bits inside bigint (Same as n.toString(2).length)
|
|
134
|
+
export function bitLen(n) {
|
|
135
|
+
let len;
|
|
136
|
+
for (len = 0; n > 0n; n >>= _1n, len += 1)
|
|
137
|
+
;
|
|
138
|
+
return len;
|
|
141
139
|
}
|
|
140
|
+
// Gets single bit at position. NOTE: first bit position is 0 (same as arrays)
|
|
141
|
+
// Same as !!+Array.from(n.toString(2)).reverse()[pos]
|
|
142
|
+
export const bitGet = (n, pos) => (n >> BigInt(pos)) & 1n;
|
|
143
|
+
// Sets single bit at position
|
|
144
|
+
export const bitSet = (n, pos, value) => n | ((value ? _1n : _0n) << BigInt(pos));
|
|
145
|
+
// Return mask for N bits (Same as BigInt(`0b${Array(i).fill('1').join('')}`))
|
|
146
|
+
// Not using ** operator with bigints for old engines.
|
|
147
|
+
export const bitMask = (n) => (_2n << BigInt(n - 1)) - _1n;
|