@hyperlane-xyz/cli 26.0.0 → 27.1.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/bundle/214.index.js +4939 -0
- package/bundle/566.index.js +84663 -0
- package/bundle/{321.index.js → 617.index.js} +97 -1411
- package/bundle/673.index.js +8588 -0
- package/bundle/index.js +7202 -1454
- package/package.json +15 -14
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export const id =
|
|
2
|
-
export const ids = [
|
|
1
|
+
export const id = 617;
|
|
2
|
+
export const ids = [617];
|
|
3
3
|
export const modules = {
|
|
4
4
|
|
|
5
|
-
/***/
|
|
5
|
+
/***/ 8617:
|
|
6
6
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
7
7
|
|
|
8
8
|
|
|
@@ -19,1326 +19,12 @@ var sha2 = __webpack_require__(20707);
|
|
|
19
19
|
var esm_hmac = __webpack_require__(93952);
|
|
20
20
|
// EXTERNAL MODULE: ../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/utils.js + 1 modules
|
|
21
21
|
var esm_utils = __webpack_require__(2226);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const _0n = /* @__PURE__ */ BigInt(0);
|
|
31
|
-
const _1n = /* @__PURE__ */ BigInt(1);
|
|
32
|
-
function abool(title, value) {
|
|
33
|
-
if (typeof value !== 'boolean')
|
|
34
|
-
throw new Error(title + ' boolean expected, got ' + value);
|
|
35
|
-
}
|
|
36
|
-
// tmp name until v2
|
|
37
|
-
function _abool2(value, title = '') {
|
|
38
|
-
if (typeof value !== 'boolean') {
|
|
39
|
-
const prefix = title && `"${title}"`;
|
|
40
|
-
throw new Error(prefix + 'expected boolean, got type=' + typeof value);
|
|
41
|
-
}
|
|
42
|
-
return value;
|
|
43
|
-
}
|
|
44
|
-
// tmp name until v2
|
|
45
|
-
/** Asserts something is Uint8Array. */
|
|
46
|
-
function _abytes2(value, length, title = '') {
|
|
47
|
-
const bytes = (0,esm_utils/* isBytes */.aY)(value);
|
|
48
|
-
const len = value?.length;
|
|
49
|
-
const needsLen = length !== undefined;
|
|
50
|
-
if (!bytes || (needsLen && len !== length)) {
|
|
51
|
-
const prefix = title && `"${title}" `;
|
|
52
|
-
const ofLen = needsLen ? ` of length ${length}` : '';
|
|
53
|
-
const got = bytes ? `length=${len}` : `type=${typeof value}`;
|
|
54
|
-
throw new Error(prefix + 'expected Uint8Array' + ofLen + ', got ' + got);
|
|
55
|
-
}
|
|
56
|
-
return value;
|
|
57
|
-
}
|
|
58
|
-
// Used in weierstrass, der
|
|
59
|
-
function numberToHexUnpadded(num) {
|
|
60
|
-
const hex = num.toString(16);
|
|
61
|
-
return hex.length & 1 ? '0' + hex : hex;
|
|
62
|
-
}
|
|
63
|
-
function hexToNumber(hex) {
|
|
64
|
-
if (typeof hex !== 'string')
|
|
65
|
-
throw new Error('hex string expected, got ' + typeof hex);
|
|
66
|
-
return hex === '' ? _0n : BigInt('0x' + hex); // Big Endian
|
|
67
|
-
}
|
|
68
|
-
// BE: Big Endian, LE: Little Endian
|
|
69
|
-
function utils_bytesToNumberBE(bytes) {
|
|
70
|
-
return hexToNumber((0,esm_utils/* bytesToHex */.My)(bytes));
|
|
71
|
-
}
|
|
72
|
-
function utils_bytesToNumberLE(bytes) {
|
|
73
|
-
(0,esm_utils/* abytes */.DO)(bytes);
|
|
74
|
-
return hexToNumber((0,esm_utils/* bytesToHex */.My)(Uint8Array.from(bytes).reverse()));
|
|
75
|
-
}
|
|
76
|
-
function numberToBytesBE(n, len) {
|
|
77
|
-
return (0,esm_utils/* hexToBytes */.aT)(n.toString(16).padStart(len * 2, '0'));
|
|
78
|
-
}
|
|
79
|
-
function numberToBytesLE(n, len) {
|
|
80
|
-
return numberToBytesBE(n, len).reverse();
|
|
81
|
-
}
|
|
82
|
-
// Unpadded, rarely used
|
|
83
|
-
function numberToVarBytesBE(n) {
|
|
84
|
-
return hexToBytes_(numberToHexUnpadded(n));
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Takes hex string or Uint8Array, converts to Uint8Array.
|
|
88
|
-
* Validates output length.
|
|
89
|
-
* Will throw error for other types.
|
|
90
|
-
* @param title descriptive title for an error e.g. 'secret key'
|
|
91
|
-
* @param hex hex string or Uint8Array
|
|
92
|
-
* @param expectedLength optional, will compare to result array's length
|
|
93
|
-
* @returns
|
|
94
|
-
*/
|
|
95
|
-
function utils_ensureBytes(title, hex, expectedLength) {
|
|
96
|
-
let res;
|
|
97
|
-
if (typeof hex === 'string') {
|
|
98
|
-
try {
|
|
99
|
-
res = (0,esm_utils/* hexToBytes */.aT)(hex);
|
|
100
|
-
}
|
|
101
|
-
catch (e) {
|
|
102
|
-
throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
else if ((0,esm_utils/* isBytes */.aY)(hex)) {
|
|
106
|
-
// Uint8Array.from() instead of hash.slice() because node.js Buffer
|
|
107
|
-
// is instance of Uint8Array, and its slice() creates **mutable** copy
|
|
108
|
-
res = Uint8Array.from(hex);
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
throw new Error(title + ' must be hex string or Uint8Array');
|
|
112
|
-
}
|
|
113
|
-
const len = res.length;
|
|
114
|
-
if (typeof expectedLength === 'number' && len !== expectedLength)
|
|
115
|
-
throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len);
|
|
116
|
-
return res;
|
|
117
|
-
}
|
|
118
|
-
// Compares 2 u8a-s in kinda constant time
|
|
119
|
-
function equalBytes(a, b) {
|
|
120
|
-
if (a.length !== b.length)
|
|
121
|
-
return false;
|
|
122
|
-
let diff = 0;
|
|
123
|
-
for (let i = 0; i < a.length; i++)
|
|
124
|
-
diff |= a[i] ^ b[i];
|
|
125
|
-
return diff === 0;
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Copies Uint8Array. We can't use u8a.slice(), because u8a can be Buffer,
|
|
129
|
-
* and Buffer#slice creates mutable copy. Never use Buffers!
|
|
130
|
-
*/
|
|
131
|
-
function copyBytes(bytes) {
|
|
132
|
-
return Uint8Array.from(bytes);
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Decodes 7-bit ASCII string to Uint8Array, throws on non-ascii symbols
|
|
136
|
-
* Should be safe to use for things expected to be ASCII.
|
|
137
|
-
* Returns exact same result as utf8ToBytes for ASCII or throws.
|
|
138
|
-
*/
|
|
139
|
-
function asciiToBytes(ascii) {
|
|
140
|
-
return Uint8Array.from(ascii, (c, i) => {
|
|
141
|
-
const charCode = c.charCodeAt(0);
|
|
142
|
-
if (c.length !== 1 || charCode > 127) {
|
|
143
|
-
throw new Error(`string contains non-ASCII character "${ascii[i]}" with code ${charCode} at position ${i}`);
|
|
144
|
-
}
|
|
145
|
-
return charCode;
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
|
|
150
|
-
*/
|
|
151
|
-
// export const utf8ToBytes: typeof utf8ToBytes_ = utf8ToBytes_;
|
|
152
|
-
/**
|
|
153
|
-
* Converts bytes to string using UTF8 encoding.
|
|
154
|
-
* @example bytesToUtf8(Uint8Array.from([97, 98, 99])) // 'abc'
|
|
155
|
-
*/
|
|
156
|
-
// export const bytesToUtf8: typeof bytesToUtf8_ = bytesToUtf8_;
|
|
157
|
-
// Is positive bigint
|
|
158
|
-
const isPosBig = (n) => typeof n === 'bigint' && _0n <= n;
|
|
159
|
-
function utils_inRange(n, min, max) {
|
|
160
|
-
return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Asserts min <= n < max. NOTE: It's < max and not <= max.
|
|
164
|
-
* @example
|
|
165
|
-
* aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n)
|
|
166
|
-
*/
|
|
167
|
-
function aInRange(title, n, min, max) {
|
|
168
|
-
// Why min <= n < max and not a (min < n < max) OR b (min <= n <= max)?
|
|
169
|
-
// consider P=256n, min=0n, max=P
|
|
170
|
-
// - a for min=0 would require -1: `inRange('x', x, -1n, P)`
|
|
171
|
-
// - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)`
|
|
172
|
-
// - our way is the cleanest: `inRange('x', x, 0n, P)
|
|
173
|
-
if (!utils_inRange(n, min, max))
|
|
174
|
-
throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n);
|
|
175
|
-
}
|
|
176
|
-
// Bit operations
|
|
177
|
-
/**
|
|
178
|
-
* Calculates amount of bits in a bigint.
|
|
179
|
-
* Same as `n.toString(2).length`
|
|
180
|
-
* TODO: merge with nLength in modular
|
|
181
|
-
*/
|
|
182
|
-
function bitLen(n) {
|
|
183
|
-
let len;
|
|
184
|
-
for (len = 0; n > _0n; n >>= _1n, len += 1)
|
|
185
|
-
;
|
|
186
|
-
return len;
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Gets single bit at position.
|
|
190
|
-
* NOTE: first bit position is 0 (same as arrays)
|
|
191
|
-
* Same as `!!+Array.from(n.toString(2)).reverse()[pos]`
|
|
192
|
-
*/
|
|
193
|
-
function bitGet(n, pos) {
|
|
194
|
-
return (n >> BigInt(pos)) & _1n;
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Sets single bit at position.
|
|
198
|
-
*/
|
|
199
|
-
function bitSet(n, pos, value) {
|
|
200
|
-
return n | ((value ? _1n : _0n) << BigInt(pos));
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Calculate mask for N bits. Not using ** operator with bigints because of old engines.
|
|
204
|
-
* Same as BigInt(`0b${Array(i).fill('1').join('')}`)
|
|
205
|
-
*/
|
|
206
|
-
const utils_bitMask = (n) => (_1n << BigInt(n)) - _1n;
|
|
207
|
-
/**
|
|
208
|
-
* Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
|
|
209
|
-
* @returns function that will call DRBG until 2nd arg returns something meaningful
|
|
210
|
-
* @example
|
|
211
|
-
* const drbg = createHmacDRBG<Key>(32, 32, hmac);
|
|
212
|
-
* drbg(seed, bytesToKey); // bytesToKey must return Key or undefined
|
|
213
|
-
*/
|
|
214
|
-
function createHmacDrbg(hashLen, qByteLen, hmacFn) {
|
|
215
|
-
if (typeof hashLen !== 'number' || hashLen < 2)
|
|
216
|
-
throw new Error('hashLen must be a number');
|
|
217
|
-
if (typeof qByteLen !== 'number' || qByteLen < 2)
|
|
218
|
-
throw new Error('qByteLen must be a number');
|
|
219
|
-
if (typeof hmacFn !== 'function')
|
|
220
|
-
throw new Error('hmacFn must be a function');
|
|
221
|
-
// Step B, Step C: set hashLen to 8*ceil(hlen/8)
|
|
222
|
-
const u8n = (len) => new Uint8Array(len); // creates Uint8Array
|
|
223
|
-
const u8of = (byte) => Uint8Array.of(byte); // another shortcut
|
|
224
|
-
let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
|
|
225
|
-
let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same
|
|
226
|
-
let i = 0; // Iterations counter, will throw when over 1000
|
|
227
|
-
const reset = () => {
|
|
228
|
-
v.fill(1);
|
|
229
|
-
k.fill(0);
|
|
230
|
-
i = 0;
|
|
231
|
-
};
|
|
232
|
-
const h = (...b) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)
|
|
233
|
-
const reseed = (seed = u8n(0)) => {
|
|
234
|
-
// HMAC-DRBG reseed() function. Steps D-G
|
|
235
|
-
k = h(u8of(0x00), seed); // k = hmac(k || v || 0x00 || seed)
|
|
236
|
-
v = h(); // v = hmac(k || v)
|
|
237
|
-
if (seed.length === 0)
|
|
238
|
-
return;
|
|
239
|
-
k = h(u8of(0x01), seed); // k = hmac(k || v || 0x01 || seed)
|
|
240
|
-
v = h(); // v = hmac(k || v)
|
|
241
|
-
};
|
|
242
|
-
const gen = () => {
|
|
243
|
-
// HMAC-DRBG generate() function
|
|
244
|
-
if (i++ >= 1000)
|
|
245
|
-
throw new Error('drbg: tried 1000 values');
|
|
246
|
-
let len = 0;
|
|
247
|
-
const out = [];
|
|
248
|
-
while (len < qByteLen) {
|
|
249
|
-
v = h();
|
|
250
|
-
const sl = v.slice();
|
|
251
|
-
out.push(sl);
|
|
252
|
-
len += v.length;
|
|
253
|
-
}
|
|
254
|
-
return (0,esm_utils/* concatBytes */.Id)(...out);
|
|
255
|
-
};
|
|
256
|
-
const genUntil = (seed, pred) => {
|
|
257
|
-
reset();
|
|
258
|
-
reseed(seed); // Steps D-G
|
|
259
|
-
let res = undefined; // Step H: grind until k is in [1..n-1]
|
|
260
|
-
while (!(res = pred(gen())))
|
|
261
|
-
reseed();
|
|
262
|
-
reset();
|
|
263
|
-
return res;
|
|
264
|
-
};
|
|
265
|
-
return genUntil;
|
|
266
|
-
}
|
|
267
|
-
// Validating curves and fields
|
|
268
|
-
const validatorFns = {
|
|
269
|
-
bigint: (val) => typeof val === 'bigint',
|
|
270
|
-
function: (val) => typeof val === 'function',
|
|
271
|
-
boolean: (val) => typeof val === 'boolean',
|
|
272
|
-
string: (val) => typeof val === 'string',
|
|
273
|
-
stringOrUint8Array: (val) => typeof val === 'string' || (0,esm_utils/* isBytes */.aY)(val),
|
|
274
|
-
isSafeInteger: (val) => Number.isSafeInteger(val),
|
|
275
|
-
array: (val) => Array.isArray(val),
|
|
276
|
-
field: (val, object) => object.Fp.isValid(val),
|
|
277
|
-
hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
|
|
278
|
-
};
|
|
279
|
-
// type Record<K extends string | number | symbol, T> = { [P in K]: T; }
|
|
280
|
-
function utils_validateObject(object, validators, optValidators = {}) {
|
|
281
|
-
const checkField = (fieldName, type, isOptional) => {
|
|
282
|
-
const checkVal = validatorFns[type];
|
|
283
|
-
if (typeof checkVal !== 'function')
|
|
284
|
-
throw new Error('invalid validator function');
|
|
285
|
-
const val = object[fieldName];
|
|
286
|
-
if (isOptional && val === undefined)
|
|
287
|
-
return;
|
|
288
|
-
if (!checkVal(val, object)) {
|
|
289
|
-
throw new Error('param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val);
|
|
290
|
-
}
|
|
291
|
-
};
|
|
292
|
-
for (const [fieldName, type] of Object.entries(validators))
|
|
293
|
-
checkField(fieldName, type, false);
|
|
294
|
-
for (const [fieldName, type] of Object.entries(optValidators))
|
|
295
|
-
checkField(fieldName, type, true);
|
|
296
|
-
return object;
|
|
297
|
-
}
|
|
298
|
-
// validate type tests
|
|
299
|
-
// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 };
|
|
300
|
-
// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok!
|
|
301
|
-
// // Should fail type-check
|
|
302
|
-
// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' });
|
|
303
|
-
// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' });
|
|
304
|
-
// const z3 = validateObject(o, { test: 'boolean', z: 'bug' });
|
|
305
|
-
// const z4 = validateObject(o, { a: 'boolean', z: 'bug' });
|
|
306
|
-
function isHash(val) {
|
|
307
|
-
return typeof val === 'function' && Number.isSafeInteger(val.outputLen);
|
|
308
|
-
}
|
|
309
|
-
function _validateObject(object, fields, optFields = {}) {
|
|
310
|
-
if (!object || typeof object !== 'object')
|
|
311
|
-
throw new Error('expected valid options object');
|
|
312
|
-
function checkField(fieldName, expectedType, isOpt) {
|
|
313
|
-
const val = object[fieldName];
|
|
314
|
-
if (isOpt && val === undefined)
|
|
315
|
-
return;
|
|
316
|
-
const current = typeof val;
|
|
317
|
-
if (current !== expectedType || val === null)
|
|
318
|
-
throw new Error(`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`);
|
|
319
|
-
}
|
|
320
|
-
Object.entries(fields).forEach(([k, v]) => checkField(k, v, false));
|
|
321
|
-
Object.entries(optFields).forEach(([k, v]) => checkField(k, v, true));
|
|
322
|
-
}
|
|
323
|
-
/**
|
|
324
|
-
* throws not implemented error
|
|
325
|
-
*/
|
|
326
|
-
const notImplemented = () => {
|
|
327
|
-
throw new Error('not implemented');
|
|
328
|
-
};
|
|
329
|
-
/**
|
|
330
|
-
* Memoizes (caches) computation result.
|
|
331
|
-
* Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed.
|
|
332
|
-
*/
|
|
333
|
-
function memoized(fn) {
|
|
334
|
-
const map = new WeakMap();
|
|
335
|
-
return (arg, ...args) => {
|
|
336
|
-
const val = map.get(arg);
|
|
337
|
-
if (val !== undefined)
|
|
338
|
-
return val;
|
|
339
|
-
const computed = fn(arg, ...args);
|
|
340
|
-
map.set(arg, computed);
|
|
341
|
-
return computed;
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
|
-
//# sourceMappingURL=utils.js.map
|
|
345
|
-
;// CONCATENATED MODULE: ../../node_modules/.pnpm/@noble+curves@1.9.7/node_modules/@noble/curves/esm/abstract/modular.js
|
|
346
|
-
/**
|
|
347
|
-
* Utils for modular division and fields.
|
|
348
|
-
* Field over 11 is a finite (Galois) field is integer number operations `mod 11`.
|
|
349
|
-
* There is no division: it is replaced by modular multiplicative inverse.
|
|
350
|
-
* @module
|
|
351
|
-
*/
|
|
352
|
-
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
353
|
-
|
|
354
|
-
// prettier-ignore
|
|
355
|
-
const modular_0n = BigInt(0), modular_1n = BigInt(1), _2n = /* @__PURE__ */ BigInt(2), _3n = /* @__PURE__ */ BigInt(3);
|
|
356
|
-
// prettier-ignore
|
|
357
|
-
const _4n = /* @__PURE__ */ BigInt(4), _5n = /* @__PURE__ */ BigInt(5), _7n = /* @__PURE__ */ BigInt(7);
|
|
358
|
-
// prettier-ignore
|
|
359
|
-
const _8n = /* @__PURE__ */ BigInt(8), _9n = /* @__PURE__ */ BigInt(9), _16n = /* @__PURE__ */ BigInt(16);
|
|
360
|
-
// Calculates a modulo b
|
|
361
|
-
function mod(a, b) {
|
|
362
|
-
const result = a % b;
|
|
363
|
-
return result >= modular_0n ? result : b + result;
|
|
364
|
-
}
|
|
365
|
-
/**
|
|
366
|
-
* Efficiently raise num to power and do modular division.
|
|
367
|
-
* Unsafe in some contexts: uses ladder, so can expose bigint bits.
|
|
368
|
-
* @example
|
|
369
|
-
* pow(2n, 6n, 11n) // 64n % 11n == 9n
|
|
370
|
-
*/
|
|
371
|
-
function pow(num, power, modulo) {
|
|
372
|
-
return FpPow(Field(modulo), num, power);
|
|
373
|
-
}
|
|
374
|
-
/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */
|
|
375
|
-
function pow2(x, power, modulo) {
|
|
376
|
-
let res = x;
|
|
377
|
-
while (power-- > modular_0n) {
|
|
378
|
-
res *= res;
|
|
379
|
-
res %= modulo;
|
|
380
|
-
}
|
|
381
|
-
return res;
|
|
382
|
-
}
|
|
383
|
-
/**
|
|
384
|
-
* Inverses number over modulo.
|
|
385
|
-
* Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/).
|
|
386
|
-
*/
|
|
387
|
-
function invert(number, modulo) {
|
|
388
|
-
if (number === modular_0n)
|
|
389
|
-
throw new Error('invert: expected non-zero number');
|
|
390
|
-
if (modulo <= modular_0n)
|
|
391
|
-
throw new Error('invert: expected positive modulus, got ' + modulo);
|
|
392
|
-
// Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower.
|
|
393
|
-
let a = mod(number, modulo);
|
|
394
|
-
let b = modulo;
|
|
395
|
-
// prettier-ignore
|
|
396
|
-
let x = modular_0n, y = modular_1n, u = modular_1n, v = modular_0n;
|
|
397
|
-
while (a !== modular_0n) {
|
|
398
|
-
// JIT applies optimization if those two lines follow each other
|
|
399
|
-
const q = b / a;
|
|
400
|
-
const r = b % a;
|
|
401
|
-
const m = x - u * q;
|
|
402
|
-
const n = y - v * q;
|
|
403
|
-
// prettier-ignore
|
|
404
|
-
b = a, a = r, x = u, y = v, u = m, v = n;
|
|
405
|
-
}
|
|
406
|
-
const gcd = b;
|
|
407
|
-
if (gcd !== modular_1n)
|
|
408
|
-
throw new Error('invert: does not exist');
|
|
409
|
-
return mod(x, modulo);
|
|
410
|
-
}
|
|
411
|
-
function assertIsSquare(Fp, root, n) {
|
|
412
|
-
if (!Fp.eql(Fp.sqr(root), n))
|
|
413
|
-
throw new Error('Cannot find square root');
|
|
414
|
-
}
|
|
415
|
-
// Not all roots are possible! Example which will throw:
|
|
416
|
-
// const NUM =
|
|
417
|
-
// n = 72057594037927816n;
|
|
418
|
-
// Fp = Field(BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab'));
|
|
419
|
-
function sqrt3mod4(Fp, n) {
|
|
420
|
-
const p1div4 = (Fp.ORDER + modular_1n) / _4n;
|
|
421
|
-
const root = Fp.pow(n, p1div4);
|
|
422
|
-
assertIsSquare(Fp, root, n);
|
|
423
|
-
return root;
|
|
424
|
-
}
|
|
425
|
-
function sqrt5mod8(Fp, n) {
|
|
426
|
-
const p5div8 = (Fp.ORDER - _5n) / _8n;
|
|
427
|
-
const n2 = Fp.mul(n, _2n);
|
|
428
|
-
const v = Fp.pow(n2, p5div8);
|
|
429
|
-
const nv = Fp.mul(n, v);
|
|
430
|
-
const i = Fp.mul(Fp.mul(nv, _2n), v);
|
|
431
|
-
const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));
|
|
432
|
-
assertIsSquare(Fp, root, n);
|
|
433
|
-
return root;
|
|
434
|
-
}
|
|
435
|
-
// Based on RFC9380, Kong algorithm
|
|
436
|
-
// prettier-ignore
|
|
437
|
-
function sqrt9mod16(P) {
|
|
438
|
-
const Fp_ = Field(P);
|
|
439
|
-
const tn = tonelliShanks(P);
|
|
440
|
-
const c1 = tn(Fp_, Fp_.neg(Fp_.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F
|
|
441
|
-
const c2 = tn(Fp_, c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F
|
|
442
|
-
const c3 = tn(Fp_, Fp_.neg(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F
|
|
443
|
-
const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic
|
|
444
|
-
return (Fp, n) => {
|
|
445
|
-
let tv1 = Fp.pow(n, c4); // 1. tv1 = x^c4
|
|
446
|
-
let tv2 = Fp.mul(tv1, c1); // 2. tv2 = c1 * tv1
|
|
447
|
-
const tv3 = Fp.mul(tv1, c2); // 3. tv3 = c2 * tv1
|
|
448
|
-
const tv4 = Fp.mul(tv1, c3); // 4. tv4 = c3 * tv1
|
|
449
|
-
const e1 = Fp.eql(Fp.sqr(tv2), n); // 5. e1 = (tv2^2) == x
|
|
450
|
-
const e2 = Fp.eql(Fp.sqr(tv3), n); // 6. e2 = (tv3^2) == x
|
|
451
|
-
tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x
|
|
452
|
-
tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x
|
|
453
|
-
const e3 = Fp.eql(Fp.sqr(tv2), n); // 9. e3 = (tv2^2) == x
|
|
454
|
-
const root = Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select sqrt from tv1 & tv2
|
|
455
|
-
assertIsSquare(Fp, root, n);
|
|
456
|
-
return root;
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
/**
|
|
460
|
-
* Tonelli-Shanks square root search algorithm.
|
|
461
|
-
* 1. https://eprint.iacr.org/2012/685.pdf (page 12)
|
|
462
|
-
* 2. Square Roots from 1; 24, 51, 10 to Dan Shanks
|
|
463
|
-
* @param P field order
|
|
464
|
-
* @returns function that takes field Fp (created from P) and number n
|
|
465
|
-
*/
|
|
466
|
-
function tonelliShanks(P) {
|
|
467
|
-
// Initialization (precomputation).
|
|
468
|
-
// Caching initialization could boost perf by 7%.
|
|
469
|
-
if (P < _3n)
|
|
470
|
-
throw new Error('sqrt is not defined for small field');
|
|
471
|
-
// Factor P - 1 = Q * 2^S, where Q is odd
|
|
472
|
-
let Q = P - modular_1n;
|
|
473
|
-
let S = 0;
|
|
474
|
-
while (Q % _2n === modular_0n) {
|
|
475
|
-
Q /= _2n;
|
|
476
|
-
S++;
|
|
477
|
-
}
|
|
478
|
-
// Find the first quadratic non-residue Z >= 2
|
|
479
|
-
let Z = _2n;
|
|
480
|
-
const _Fp = Field(P);
|
|
481
|
-
while (FpLegendre(_Fp, Z) === 1) {
|
|
482
|
-
// Basic primality test for P. After x iterations, chance of
|
|
483
|
-
// not finding quadratic non-residue is 2^x, so 2^1000.
|
|
484
|
-
if (Z++ > 1000)
|
|
485
|
-
throw new Error('Cannot find square root: probably non-prime P');
|
|
486
|
-
}
|
|
487
|
-
// Fast-path; usually done before Z, but we do "primality test".
|
|
488
|
-
if (S === 1)
|
|
489
|
-
return sqrt3mod4;
|
|
490
|
-
// Slow-path
|
|
491
|
-
// TODO: test on Fp2 and others
|
|
492
|
-
let cc = _Fp.pow(Z, Q); // c = z^Q
|
|
493
|
-
const Q1div2 = (Q + modular_1n) / _2n;
|
|
494
|
-
return function tonelliSlow(Fp, n) {
|
|
495
|
-
if (Fp.is0(n))
|
|
496
|
-
return n;
|
|
497
|
-
// Check if n is a quadratic residue using Legendre symbol
|
|
498
|
-
if (FpLegendre(Fp, n) !== 1)
|
|
499
|
-
throw new Error('Cannot find square root');
|
|
500
|
-
// Initialize variables for the main loop
|
|
501
|
-
let M = S;
|
|
502
|
-
let c = Fp.mul(Fp.ONE, cc); // c = z^Q, move cc from field _Fp into field Fp
|
|
503
|
-
let t = Fp.pow(n, Q); // t = n^Q, first guess at the fudge factor
|
|
504
|
-
let R = Fp.pow(n, Q1div2); // R = n^((Q+1)/2), first guess at the square root
|
|
505
|
-
// Main loop
|
|
506
|
-
// while t != 1
|
|
507
|
-
while (!Fp.eql(t, Fp.ONE)) {
|
|
508
|
-
if (Fp.is0(t))
|
|
509
|
-
return Fp.ZERO; // if t=0 return R=0
|
|
510
|
-
let i = 1;
|
|
511
|
-
// Find the smallest i >= 1 such that t^(2^i) ≡ 1 (mod P)
|
|
512
|
-
let t_tmp = Fp.sqr(t); // t^(2^1)
|
|
513
|
-
while (!Fp.eql(t_tmp, Fp.ONE)) {
|
|
514
|
-
i++;
|
|
515
|
-
t_tmp = Fp.sqr(t_tmp); // t^(2^2)...
|
|
516
|
-
if (i === M)
|
|
517
|
-
throw new Error('Cannot find square root');
|
|
518
|
-
}
|
|
519
|
-
// Calculate the exponent for b: 2^(M - i - 1)
|
|
520
|
-
const exponent = modular_1n << BigInt(M - i - 1); // bigint is important
|
|
521
|
-
const b = Fp.pow(c, exponent); // b = 2^(M - i - 1)
|
|
522
|
-
// Update variables
|
|
523
|
-
M = i;
|
|
524
|
-
c = Fp.sqr(b); // c = b^2
|
|
525
|
-
t = Fp.mul(t, c); // t = (t * b^2)
|
|
526
|
-
R = Fp.mul(R, b); // R = R*b
|
|
527
|
-
}
|
|
528
|
-
return R;
|
|
529
|
-
};
|
|
530
|
-
}
|
|
531
|
-
/**
|
|
532
|
-
* Square root for a finite field. Will try optimized versions first:
|
|
533
|
-
*
|
|
534
|
-
* 1. P ≡ 3 (mod 4)
|
|
535
|
-
* 2. P ≡ 5 (mod 8)
|
|
536
|
-
* 3. P ≡ 9 (mod 16)
|
|
537
|
-
* 4. Tonelli-Shanks algorithm
|
|
538
|
-
*
|
|
539
|
-
* Different algorithms can give different roots, it is up to user to decide which one they want.
|
|
540
|
-
* For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).
|
|
541
|
-
*/
|
|
542
|
-
function FpSqrt(P) {
|
|
543
|
-
// P ≡ 3 (mod 4) => √n = n^((P+1)/4)
|
|
544
|
-
if (P % _4n === _3n)
|
|
545
|
-
return sqrt3mod4;
|
|
546
|
-
// P ≡ 5 (mod 8) => Atkin algorithm, page 10 of https://eprint.iacr.org/2012/685.pdf
|
|
547
|
-
if (P % _8n === _5n)
|
|
548
|
-
return sqrt5mod8;
|
|
549
|
-
// P ≡ 9 (mod 16) => Kong algorithm, page 11 of https://eprint.iacr.org/2012/685.pdf (algorithm 4)
|
|
550
|
-
if (P % _16n === _9n)
|
|
551
|
-
return sqrt9mod16(P);
|
|
552
|
-
// Tonelli-Shanks algorithm
|
|
553
|
-
return tonelliShanks(P);
|
|
554
|
-
}
|
|
555
|
-
// Little-endian check for first LE bit (last BE bit);
|
|
556
|
-
const isNegativeLE = (num, modulo) => (mod(num, modulo) & modular_1n) === modular_1n;
|
|
557
|
-
// prettier-ignore
|
|
558
|
-
const FIELD_FIELDS = [
|
|
559
|
-
'create', 'isValid', 'is0', 'neg', 'inv', 'sqrt', 'sqr',
|
|
560
|
-
'eql', 'add', 'sub', 'mul', 'pow', 'div',
|
|
561
|
-
'addN', 'subN', 'mulN', 'sqrN'
|
|
562
|
-
];
|
|
563
|
-
function modular_validateField(field) {
|
|
564
|
-
const initial = {
|
|
565
|
-
ORDER: 'bigint',
|
|
566
|
-
MASK: 'bigint',
|
|
567
|
-
BYTES: 'number',
|
|
568
|
-
BITS: 'number',
|
|
569
|
-
};
|
|
570
|
-
const opts = FIELD_FIELDS.reduce((map, val) => {
|
|
571
|
-
map[val] = 'function';
|
|
572
|
-
return map;
|
|
573
|
-
}, initial);
|
|
574
|
-
_validateObject(field, opts);
|
|
575
|
-
// const max = 16384;
|
|
576
|
-
// if (field.BYTES < 1 || field.BYTES > max) throw new Error('invalid field');
|
|
577
|
-
// if (field.BITS < 1 || field.BITS > 8 * max) throw new Error('invalid field');
|
|
578
|
-
return field;
|
|
579
|
-
}
|
|
580
|
-
// Generic field functions
|
|
581
|
-
/**
|
|
582
|
-
* Same as `pow` but for Fp: non-constant-time.
|
|
583
|
-
* Unsafe in some contexts: uses ladder, so can expose bigint bits.
|
|
584
|
-
*/
|
|
585
|
-
function FpPow(Fp, num, power) {
|
|
586
|
-
if (power < modular_0n)
|
|
587
|
-
throw new Error('invalid exponent, negatives unsupported');
|
|
588
|
-
if (power === modular_0n)
|
|
589
|
-
return Fp.ONE;
|
|
590
|
-
if (power === modular_1n)
|
|
591
|
-
return num;
|
|
592
|
-
let p = Fp.ONE;
|
|
593
|
-
let d = num;
|
|
594
|
-
while (power > modular_0n) {
|
|
595
|
-
if (power & modular_1n)
|
|
596
|
-
p = Fp.mul(p, d);
|
|
597
|
-
d = Fp.sqr(d);
|
|
598
|
-
power >>= modular_1n;
|
|
599
|
-
}
|
|
600
|
-
return p;
|
|
601
|
-
}
|
|
602
|
-
/**
|
|
603
|
-
* Efficiently invert an array of Field elements.
|
|
604
|
-
* Exception-free. Will return `undefined` for 0 elements.
|
|
605
|
-
* @param passZero map 0 to 0 (instead of undefined)
|
|
606
|
-
*/
|
|
607
|
-
function modular_FpInvertBatch(Fp, nums, passZero = false) {
|
|
608
|
-
const inverted = new Array(nums.length).fill(passZero ? Fp.ZERO : undefined);
|
|
609
|
-
// Walk from first to last, multiply them by each other MOD p
|
|
610
|
-
const multipliedAcc = nums.reduce((acc, num, i) => {
|
|
611
|
-
if (Fp.is0(num))
|
|
612
|
-
return acc;
|
|
613
|
-
inverted[i] = acc;
|
|
614
|
-
return Fp.mul(acc, num);
|
|
615
|
-
}, Fp.ONE);
|
|
616
|
-
// Invert last element
|
|
617
|
-
const invertedAcc = Fp.inv(multipliedAcc);
|
|
618
|
-
// Walk from last to first, multiply them by inverted each other MOD p
|
|
619
|
-
nums.reduceRight((acc, num, i) => {
|
|
620
|
-
if (Fp.is0(num))
|
|
621
|
-
return acc;
|
|
622
|
-
inverted[i] = Fp.mul(acc, inverted[i]);
|
|
623
|
-
return Fp.mul(acc, num);
|
|
624
|
-
}, invertedAcc);
|
|
625
|
-
return inverted;
|
|
626
|
-
}
|
|
627
|
-
// TODO: remove
|
|
628
|
-
function FpDiv(Fp, lhs, rhs) {
|
|
629
|
-
return Fp.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, Fp.ORDER) : Fp.inv(rhs));
|
|
630
|
-
}
|
|
631
|
-
/**
|
|
632
|
-
* Legendre symbol.
|
|
633
|
-
* Legendre constant is used to calculate Legendre symbol (a | p)
|
|
634
|
-
* which denotes the value of a^((p-1)/2) (mod p).
|
|
635
|
-
*
|
|
636
|
-
* * (a | p) ≡ 1 if a is a square (mod p), quadratic residue
|
|
637
|
-
* * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue
|
|
638
|
-
* * (a | p) ≡ 0 if a ≡ 0 (mod p)
|
|
639
|
-
*/
|
|
640
|
-
function FpLegendre(Fp, n) {
|
|
641
|
-
// We can use 3rd argument as optional cache of this value
|
|
642
|
-
// but seems unneeded for now. The operation is very fast.
|
|
643
|
-
const p1mod2 = (Fp.ORDER - modular_1n) / _2n;
|
|
644
|
-
const powered = Fp.pow(n, p1mod2);
|
|
645
|
-
const yes = Fp.eql(powered, Fp.ONE);
|
|
646
|
-
const zero = Fp.eql(powered, Fp.ZERO);
|
|
647
|
-
const no = Fp.eql(powered, Fp.neg(Fp.ONE));
|
|
648
|
-
if (!yes && !zero && !no)
|
|
649
|
-
throw new Error('invalid Legendre symbol result');
|
|
650
|
-
return yes ? 1 : zero ? 0 : -1;
|
|
651
|
-
}
|
|
652
|
-
// This function returns True whenever the value x is a square in the field F.
|
|
653
|
-
function FpIsSquare(Fp, n) {
|
|
654
|
-
const l = FpLegendre(Fp, n);
|
|
655
|
-
return l === 1;
|
|
656
|
-
}
|
|
657
|
-
// CURVE.n lengths
|
|
658
|
-
function modular_nLength(n, nBitLength) {
|
|
659
|
-
// Bit size, byte size of CURVE.n
|
|
660
|
-
if (nBitLength !== undefined)
|
|
661
|
-
(0,esm_utils/* anumber */.Fe)(nBitLength);
|
|
662
|
-
const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length;
|
|
663
|
-
const nByteLength = Math.ceil(_nBitLength / 8);
|
|
664
|
-
return { nBitLength: _nBitLength, nByteLength };
|
|
665
|
-
}
|
|
666
|
-
/**
|
|
667
|
-
* Creates a finite field. Major performance optimizations:
|
|
668
|
-
* * 1. Denormalized operations like mulN instead of mul.
|
|
669
|
-
* * 2. Identical object shape: never add or remove keys.
|
|
670
|
-
* * 3. `Object.freeze`.
|
|
671
|
-
* Fragile: always run a benchmark on a change.
|
|
672
|
-
* Security note: operations don't check 'isValid' for all elements for performance reasons,
|
|
673
|
-
* it is caller responsibility to check this.
|
|
674
|
-
* This is low-level code, please make sure you know what you're doing.
|
|
675
|
-
*
|
|
676
|
-
* Note about field properties:
|
|
677
|
-
* * CHARACTERISTIC p = prime number, number of elements in main subgroup.
|
|
678
|
-
* * ORDER q = similar to cofactor in curves, may be composite `q = p^m`.
|
|
679
|
-
*
|
|
680
|
-
* @param ORDER field order, probably prime, or could be composite
|
|
681
|
-
* @param bitLen how many bits the field consumes
|
|
682
|
-
* @param isLE (default: false) if encoding / decoding should be in little-endian
|
|
683
|
-
* @param redef optional faster redefinitions of sqrt and other methods
|
|
684
|
-
*/
|
|
685
|
-
function Field(ORDER, bitLenOrOpts, // TODO: use opts only in v2?
|
|
686
|
-
isLE = false, opts = {}) {
|
|
687
|
-
if (ORDER <= modular_0n)
|
|
688
|
-
throw new Error('invalid field: expected ORDER > 0, got ' + ORDER);
|
|
689
|
-
let _nbitLength = undefined;
|
|
690
|
-
let _sqrt = undefined;
|
|
691
|
-
let modFromBytes = false;
|
|
692
|
-
let allowedLengths = undefined;
|
|
693
|
-
if (typeof bitLenOrOpts === 'object' && bitLenOrOpts != null) {
|
|
694
|
-
if (opts.sqrt || isLE)
|
|
695
|
-
throw new Error('cannot specify opts in two arguments');
|
|
696
|
-
const _opts = bitLenOrOpts;
|
|
697
|
-
if (_opts.BITS)
|
|
698
|
-
_nbitLength = _opts.BITS;
|
|
699
|
-
if (_opts.sqrt)
|
|
700
|
-
_sqrt = _opts.sqrt;
|
|
701
|
-
if (typeof _opts.isLE === 'boolean')
|
|
702
|
-
isLE = _opts.isLE;
|
|
703
|
-
if (typeof _opts.modFromBytes === 'boolean')
|
|
704
|
-
modFromBytes = _opts.modFromBytes;
|
|
705
|
-
allowedLengths = _opts.allowedLengths;
|
|
706
|
-
}
|
|
707
|
-
else {
|
|
708
|
-
if (typeof bitLenOrOpts === 'number')
|
|
709
|
-
_nbitLength = bitLenOrOpts;
|
|
710
|
-
if (opts.sqrt)
|
|
711
|
-
_sqrt = opts.sqrt;
|
|
712
|
-
}
|
|
713
|
-
const { nBitLength: BITS, nByteLength: BYTES } = modular_nLength(ORDER, _nbitLength);
|
|
714
|
-
if (BYTES > 2048)
|
|
715
|
-
throw new Error('invalid field: expected ORDER of <= 2048 bytes');
|
|
716
|
-
let sqrtP; // cached sqrtP
|
|
717
|
-
const f = Object.freeze({
|
|
718
|
-
ORDER,
|
|
719
|
-
isLE,
|
|
720
|
-
BITS,
|
|
721
|
-
BYTES,
|
|
722
|
-
MASK: utils_bitMask(BITS),
|
|
723
|
-
ZERO: modular_0n,
|
|
724
|
-
ONE: modular_1n,
|
|
725
|
-
allowedLengths: allowedLengths,
|
|
726
|
-
create: (num) => mod(num, ORDER),
|
|
727
|
-
isValid: (num) => {
|
|
728
|
-
if (typeof num !== 'bigint')
|
|
729
|
-
throw new Error('invalid field element: expected bigint, got ' + typeof num);
|
|
730
|
-
return modular_0n <= num && num < ORDER; // 0 is valid element, but it's not invertible
|
|
731
|
-
},
|
|
732
|
-
is0: (num) => num === modular_0n,
|
|
733
|
-
// is valid and invertible
|
|
734
|
-
isValidNot0: (num) => !f.is0(num) && f.isValid(num),
|
|
735
|
-
isOdd: (num) => (num & modular_1n) === modular_1n,
|
|
736
|
-
neg: (num) => mod(-num, ORDER),
|
|
737
|
-
eql: (lhs, rhs) => lhs === rhs,
|
|
738
|
-
sqr: (num) => mod(num * num, ORDER),
|
|
739
|
-
add: (lhs, rhs) => mod(lhs + rhs, ORDER),
|
|
740
|
-
sub: (lhs, rhs) => mod(lhs - rhs, ORDER),
|
|
741
|
-
mul: (lhs, rhs) => mod(lhs * rhs, ORDER),
|
|
742
|
-
pow: (num, power) => FpPow(f, num, power),
|
|
743
|
-
div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),
|
|
744
|
-
// Same as above, but doesn't normalize
|
|
745
|
-
sqrN: (num) => num * num,
|
|
746
|
-
addN: (lhs, rhs) => lhs + rhs,
|
|
747
|
-
subN: (lhs, rhs) => lhs - rhs,
|
|
748
|
-
mulN: (lhs, rhs) => lhs * rhs,
|
|
749
|
-
inv: (num) => invert(num, ORDER),
|
|
750
|
-
sqrt: _sqrt ||
|
|
751
|
-
((n) => {
|
|
752
|
-
if (!sqrtP)
|
|
753
|
-
sqrtP = FpSqrt(ORDER);
|
|
754
|
-
return sqrtP(f, n);
|
|
755
|
-
}),
|
|
756
|
-
toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)),
|
|
757
|
-
fromBytes: (bytes, skipValidation = true) => {
|
|
758
|
-
if (allowedLengths) {
|
|
759
|
-
if (!allowedLengths.includes(bytes.length) || bytes.length > BYTES) {
|
|
760
|
-
throw new Error('Field.fromBytes: expected ' + allowedLengths + ' bytes, got ' + bytes.length);
|
|
761
|
-
}
|
|
762
|
-
const padded = new Uint8Array(BYTES);
|
|
763
|
-
// isLE add 0 to right, !isLE to the left.
|
|
764
|
-
padded.set(bytes, isLE ? 0 : padded.length - bytes.length);
|
|
765
|
-
bytes = padded;
|
|
766
|
-
}
|
|
767
|
-
if (bytes.length !== BYTES)
|
|
768
|
-
throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length);
|
|
769
|
-
let scalar = isLE ? utils_bytesToNumberLE(bytes) : utils_bytesToNumberBE(bytes);
|
|
770
|
-
if (modFromBytes)
|
|
771
|
-
scalar = mod(scalar, ORDER);
|
|
772
|
-
if (!skipValidation)
|
|
773
|
-
if (!f.isValid(scalar))
|
|
774
|
-
throw new Error('invalid field element: outside of range 0..ORDER');
|
|
775
|
-
// NOTE: we don't validate scalar here, please use isValid. This done such way because some
|
|
776
|
-
// protocol may allow non-reduced scalar that reduced later or changed some other way.
|
|
777
|
-
return scalar;
|
|
778
|
-
},
|
|
779
|
-
// TODO: we don't need it here, move out to separate fn
|
|
780
|
-
invertBatch: (lst) => modular_FpInvertBatch(f, lst),
|
|
781
|
-
// We can't move this out because Fp6, Fp12 implement it
|
|
782
|
-
// and it's unclear what to return in there.
|
|
783
|
-
cmov: (a, b, c) => (c ? b : a),
|
|
784
|
-
});
|
|
785
|
-
return Object.freeze(f);
|
|
786
|
-
}
|
|
787
|
-
// Generic random scalar, we can do same for other fields if via Fp2.mul(Fp2.ONE, Fp2.random)?
|
|
788
|
-
// This allows unsafe methods like ignore bias or zero. These unsafe, but often used in different protocols (if deterministic RNG).
|
|
789
|
-
// which mean we cannot force this via opts.
|
|
790
|
-
// Not sure what to do with randomBytes, we can accept it inside opts if wanted.
|
|
791
|
-
// Probably need to export getMinHashLength somewhere?
|
|
792
|
-
// random(bytes?: Uint8Array, unsafeAllowZero = false, unsafeAllowBias = false) {
|
|
793
|
-
// const LEN = !unsafeAllowBias ? getMinHashLength(ORDER) : BYTES;
|
|
794
|
-
// if (bytes === undefined) bytes = randomBytes(LEN); // _opts.randomBytes?
|
|
795
|
-
// const num = isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
|
|
796
|
-
// // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0
|
|
797
|
-
// const reduced = unsafeAllowZero ? mod(num, ORDER) : mod(num, ORDER - _1n) + _1n;
|
|
798
|
-
// return reduced;
|
|
799
|
-
// },
|
|
800
|
-
function FpSqrtOdd(Fp, elm) {
|
|
801
|
-
if (!Fp.isOdd)
|
|
802
|
-
throw new Error("Field doesn't have isOdd");
|
|
803
|
-
const root = Fp.sqrt(elm);
|
|
804
|
-
return Fp.isOdd(root) ? root : Fp.neg(root);
|
|
805
|
-
}
|
|
806
|
-
function FpSqrtEven(Fp, elm) {
|
|
807
|
-
if (!Fp.isOdd)
|
|
808
|
-
throw new Error("Field doesn't have isOdd");
|
|
809
|
-
const root = Fp.sqrt(elm);
|
|
810
|
-
return Fp.isOdd(root) ? Fp.neg(root) : root;
|
|
811
|
-
}
|
|
812
|
-
/**
|
|
813
|
-
* "Constant-time" private key generation utility.
|
|
814
|
-
* Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field).
|
|
815
|
-
* Which makes it slightly more biased, less secure.
|
|
816
|
-
* @deprecated use `mapKeyToField` instead
|
|
817
|
-
*/
|
|
818
|
-
function hashToPrivateScalar(hash, groupOrder, isLE = false) {
|
|
819
|
-
hash = ensureBytes('privateHash', hash);
|
|
820
|
-
const hashLen = hash.length;
|
|
821
|
-
const minLen = modular_nLength(groupOrder).nByteLength + 8;
|
|
822
|
-
if (minLen < 24 || hashLen < minLen || hashLen > 1024)
|
|
823
|
-
throw new Error('hashToPrivateScalar: expected ' + minLen + '-1024 bytes of input, got ' + hashLen);
|
|
824
|
-
const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash);
|
|
825
|
-
return mod(num, groupOrder - modular_1n) + modular_1n;
|
|
826
|
-
}
|
|
827
|
-
/**
|
|
828
|
-
* Returns total number of bytes consumed by the field element.
|
|
829
|
-
* For example, 32 bytes for usual 256-bit weierstrass curve.
|
|
830
|
-
* @param fieldOrder number of field elements, usually CURVE.n
|
|
831
|
-
* @returns byte length of field
|
|
832
|
-
*/
|
|
833
|
-
function getFieldBytesLength(fieldOrder) {
|
|
834
|
-
if (typeof fieldOrder !== 'bigint')
|
|
835
|
-
throw new Error('field order must be bigint');
|
|
836
|
-
const bitLength = fieldOrder.toString(2).length;
|
|
837
|
-
return Math.ceil(bitLength / 8);
|
|
838
|
-
}
|
|
839
|
-
/**
|
|
840
|
-
* Returns minimal amount of bytes that can be safely reduced
|
|
841
|
-
* by field order.
|
|
842
|
-
* Should be 2^-128 for 128-bit curve such as P256.
|
|
843
|
-
* @param fieldOrder number of field elements, usually CURVE.n
|
|
844
|
-
* @returns byte length of target hash
|
|
845
|
-
*/
|
|
846
|
-
function getMinHashLength(fieldOrder) {
|
|
847
|
-
const length = getFieldBytesLength(fieldOrder);
|
|
848
|
-
return length + Math.ceil(length / 2);
|
|
849
|
-
}
|
|
850
|
-
/**
|
|
851
|
-
* "Constant-time" private key generation utility.
|
|
852
|
-
* Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF
|
|
853
|
-
* and convert them into private scalar, with the modulo bias being negligible.
|
|
854
|
-
* Needs at least 48 bytes of input for 32-byte private key.
|
|
855
|
-
* https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
|
|
856
|
-
* FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final
|
|
857
|
-
* RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5
|
|
858
|
-
* @param hash hash output from SHA3 or a similar function
|
|
859
|
-
* @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n)
|
|
860
|
-
* @param isLE interpret hash bytes as LE num
|
|
861
|
-
* @returns valid private scalar
|
|
862
|
-
*/
|
|
863
|
-
function mapHashToField(key, fieldOrder, isLE = false) {
|
|
864
|
-
const len = key.length;
|
|
865
|
-
const fieldLen = getFieldBytesLength(fieldOrder);
|
|
866
|
-
const minLen = getMinHashLength(fieldOrder);
|
|
867
|
-
// No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings.
|
|
868
|
-
if (len < 16 || len < minLen || len > 1024)
|
|
869
|
-
throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len);
|
|
870
|
-
const num = isLE ? utils_bytesToNumberLE(key) : utils_bytesToNumberBE(key);
|
|
871
|
-
// `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0
|
|
872
|
-
const reduced = mod(num, fieldOrder - modular_1n) + modular_1n;
|
|
873
|
-
return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);
|
|
874
|
-
}
|
|
875
|
-
//# sourceMappingURL=modular.js.map
|
|
876
|
-
;// CONCATENATED MODULE: ../../node_modules/.pnpm/@noble+curves@1.9.7/node_modules/@noble/curves/esm/abstract/curve.js
|
|
877
|
-
/**
|
|
878
|
-
* Methods for elliptic curve multiplication by scalars.
|
|
879
|
-
* Contains wNAF, pippenger.
|
|
880
|
-
* @module
|
|
881
|
-
*/
|
|
882
|
-
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
const curve_0n = BigInt(0);
|
|
886
|
-
const curve_1n = BigInt(1);
|
|
887
|
-
function negateCt(condition, item) {
|
|
888
|
-
const neg = item.negate();
|
|
889
|
-
return condition ? neg : item;
|
|
890
|
-
}
|
|
891
|
-
/**
|
|
892
|
-
* Takes a bunch of Projective Points but executes only one
|
|
893
|
-
* inversion on all of them. Inversion is very slow operation,
|
|
894
|
-
* so this improves performance massively.
|
|
895
|
-
* Optimization: converts a list of projective points to a list of identical points with Z=1.
|
|
896
|
-
*/
|
|
897
|
-
function normalizeZ(c, points) {
|
|
898
|
-
const invertedZs = modular_FpInvertBatch(c.Fp, points.map((p) => p.Z));
|
|
899
|
-
return points.map((p, i) => c.fromAffine(p.toAffine(invertedZs[i])));
|
|
900
|
-
}
|
|
901
|
-
function validateW(W, bits) {
|
|
902
|
-
if (!Number.isSafeInteger(W) || W <= 0 || W > bits)
|
|
903
|
-
throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W);
|
|
904
|
-
}
|
|
905
|
-
function calcWOpts(W, scalarBits) {
|
|
906
|
-
validateW(W, scalarBits);
|
|
907
|
-
const windows = Math.ceil(scalarBits / W) + 1; // W=8 33. Not 32, because we skip zero
|
|
908
|
-
const windowSize = 2 ** (W - 1); // W=8 128. Not 256, because we skip zero
|
|
909
|
-
const maxNumber = 2 ** W; // W=8 256
|
|
910
|
-
const mask = utils_bitMask(W); // W=8 255 == mask 0b11111111
|
|
911
|
-
const shiftBy = BigInt(W); // W=8 8
|
|
912
|
-
return { windows, windowSize, mask, maxNumber, shiftBy };
|
|
913
|
-
}
|
|
914
|
-
function calcOffsets(n, window, wOpts) {
|
|
915
|
-
const { windowSize, mask, maxNumber, shiftBy } = wOpts;
|
|
916
|
-
let wbits = Number(n & mask); // extract W bits.
|
|
917
|
-
let nextN = n >> shiftBy; // shift number by W bits.
|
|
918
|
-
// What actually happens here:
|
|
919
|
-
// const highestBit = Number(mask ^ (mask >> 1n));
|
|
920
|
-
// let wbits2 = wbits - 1; // skip zero
|
|
921
|
-
// if (wbits2 & highestBit) { wbits2 ^= Number(mask); // (~);
|
|
922
|
-
// split if bits > max: +224 => 256-32
|
|
923
|
-
if (wbits > windowSize) {
|
|
924
|
-
// we skip zero, which means instead of `>= size-1`, we do `> size`
|
|
925
|
-
wbits -= maxNumber; // -32, can be maxNumber - wbits, but then we need to set isNeg here.
|
|
926
|
-
nextN += curve_1n; // +256 (carry)
|
|
927
|
-
}
|
|
928
|
-
const offsetStart = window * windowSize;
|
|
929
|
-
const offset = offsetStart + Math.abs(wbits) - 1; // -1 because we skip zero
|
|
930
|
-
const isZero = wbits === 0; // is current window slice a 0?
|
|
931
|
-
const isNeg = wbits < 0; // is current window slice negative?
|
|
932
|
-
const isNegF = window % 2 !== 0; // fake random statement for noise
|
|
933
|
-
const offsetF = offsetStart; // fake offset for noise
|
|
934
|
-
return { nextN, offset, isZero, isNeg, isNegF, offsetF };
|
|
935
|
-
}
|
|
936
|
-
function validateMSMPoints(points, c) {
|
|
937
|
-
if (!Array.isArray(points))
|
|
938
|
-
throw new Error('array expected');
|
|
939
|
-
points.forEach((p, i) => {
|
|
940
|
-
if (!(p instanceof c))
|
|
941
|
-
throw new Error('invalid point at index ' + i);
|
|
942
|
-
});
|
|
943
|
-
}
|
|
944
|
-
function validateMSMScalars(scalars, field) {
|
|
945
|
-
if (!Array.isArray(scalars))
|
|
946
|
-
throw new Error('array of scalars expected');
|
|
947
|
-
scalars.forEach((s, i) => {
|
|
948
|
-
if (!field.isValid(s))
|
|
949
|
-
throw new Error('invalid scalar at index ' + i);
|
|
950
|
-
});
|
|
951
|
-
}
|
|
952
|
-
// Since points in different groups cannot be equal (different object constructor),
|
|
953
|
-
// we can have single place to store precomputes.
|
|
954
|
-
// Allows to make points frozen / immutable.
|
|
955
|
-
const pointPrecomputes = new WeakMap();
|
|
956
|
-
const pointWindowSizes = new WeakMap();
|
|
957
|
-
function getW(P) {
|
|
958
|
-
// To disable precomputes:
|
|
959
|
-
// return 1;
|
|
960
|
-
return pointWindowSizes.get(P) || 1;
|
|
961
|
-
}
|
|
962
|
-
function assert0(n) {
|
|
963
|
-
if (n !== curve_0n)
|
|
964
|
-
throw new Error('invalid wNAF');
|
|
965
|
-
}
|
|
966
|
-
/**
|
|
967
|
-
* Elliptic curve multiplication of Point by scalar. Fragile.
|
|
968
|
-
* Table generation takes **30MB of ram and 10ms on high-end CPU**,
|
|
969
|
-
* but may take much longer on slow devices. Actual generation will happen on
|
|
970
|
-
* first call of `multiply()`. By default, `BASE` point is precomputed.
|
|
971
|
-
*
|
|
972
|
-
* Scalars should always be less than curve order: this should be checked inside of a curve itself.
|
|
973
|
-
* Creates precomputation tables for fast multiplication:
|
|
974
|
-
* - private scalar is split by fixed size windows of W bits
|
|
975
|
-
* - every window point is collected from window's table & added to accumulator
|
|
976
|
-
* - since windows are different, same point inside tables won't be accessed more than once per calc
|
|
977
|
-
* - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar)
|
|
978
|
-
* - +1 window is neccessary for wNAF
|
|
979
|
-
* - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication
|
|
980
|
-
*
|
|
981
|
-
* @todo Research returning 2d JS array of windows, instead of a single window.
|
|
982
|
-
* This would allow windows to be in different memory locations
|
|
983
|
-
*/
|
|
984
|
-
class wNAF {
|
|
985
|
-
// Parametrized with a given Point class (not individual point)
|
|
986
|
-
constructor(Point, bits) {
|
|
987
|
-
this.BASE = Point.BASE;
|
|
988
|
-
this.ZERO = Point.ZERO;
|
|
989
|
-
this.Fn = Point.Fn;
|
|
990
|
-
this.bits = bits;
|
|
991
|
-
}
|
|
992
|
-
// non-const time multiplication ladder
|
|
993
|
-
_unsafeLadder(elm, n, p = this.ZERO) {
|
|
994
|
-
let d = elm;
|
|
995
|
-
while (n > curve_0n) {
|
|
996
|
-
if (n & curve_1n)
|
|
997
|
-
p = p.add(d);
|
|
998
|
-
d = d.double();
|
|
999
|
-
n >>= curve_1n;
|
|
1000
|
-
}
|
|
1001
|
-
return p;
|
|
1002
|
-
}
|
|
1003
|
-
/**
|
|
1004
|
-
* Creates a wNAF precomputation window. Used for caching.
|
|
1005
|
-
* Default window size is set by `utils.precompute()` and is equal to 8.
|
|
1006
|
-
* Number of precomputed points depends on the curve size:
|
|
1007
|
-
* 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
|
|
1008
|
-
* - 𝑊 is the window size
|
|
1009
|
-
* - 𝑛 is the bitlength of the curve order.
|
|
1010
|
-
* For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
|
|
1011
|
-
* @param point Point instance
|
|
1012
|
-
* @param W window size
|
|
1013
|
-
* @returns precomputed point tables flattened to a single array
|
|
1014
|
-
*/
|
|
1015
|
-
precomputeWindow(point, W) {
|
|
1016
|
-
const { windows, windowSize } = calcWOpts(W, this.bits);
|
|
1017
|
-
const points = [];
|
|
1018
|
-
let p = point;
|
|
1019
|
-
let base = p;
|
|
1020
|
-
for (let window = 0; window < windows; window++) {
|
|
1021
|
-
base = p;
|
|
1022
|
-
points.push(base);
|
|
1023
|
-
// i=1, bc we skip 0
|
|
1024
|
-
for (let i = 1; i < windowSize; i++) {
|
|
1025
|
-
base = base.add(p);
|
|
1026
|
-
points.push(base);
|
|
1027
|
-
}
|
|
1028
|
-
p = base.double();
|
|
1029
|
-
}
|
|
1030
|
-
return points;
|
|
1031
|
-
}
|
|
1032
|
-
/**
|
|
1033
|
-
* Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
|
|
1034
|
-
* More compact implementation:
|
|
1035
|
-
* https://github.com/paulmillr/noble-secp256k1/blob/47cb1669b6e506ad66b35fe7d76132ae97465da2/index.ts#L502-L541
|
|
1036
|
-
* @returns real and fake (for const-time) points
|
|
1037
|
-
*/
|
|
1038
|
-
wNAF(W, precomputes, n) {
|
|
1039
|
-
// Scalar should be smaller than field order
|
|
1040
|
-
if (!this.Fn.isValid(n))
|
|
1041
|
-
throw new Error('invalid scalar');
|
|
1042
|
-
// Accumulators
|
|
1043
|
-
let p = this.ZERO;
|
|
1044
|
-
let f = this.BASE;
|
|
1045
|
-
// This code was first written with assumption that 'f' and 'p' will never be infinity point:
|
|
1046
|
-
// since each addition is multiplied by 2 ** W, it cannot cancel each other. However,
|
|
1047
|
-
// there is negate now: it is possible that negated element from low value
|
|
1048
|
-
// would be the same as high element, which will create carry into next window.
|
|
1049
|
-
// It's not obvious how this can fail, but still worth investigating later.
|
|
1050
|
-
const wo = calcWOpts(W, this.bits);
|
|
1051
|
-
for (let window = 0; window < wo.windows; window++) {
|
|
1052
|
-
// (n === _0n) is handled and not early-exited. isEven and offsetF are used for noise
|
|
1053
|
-
const { nextN, offset, isZero, isNeg, isNegF, offsetF } = calcOffsets(n, window, wo);
|
|
1054
|
-
n = nextN;
|
|
1055
|
-
if (isZero) {
|
|
1056
|
-
// bits are 0: add garbage to fake point
|
|
1057
|
-
// Important part for const-time getPublicKey: add random "noise" point to f.
|
|
1058
|
-
f = f.add(negateCt(isNegF, precomputes[offsetF]));
|
|
1059
|
-
}
|
|
1060
|
-
else {
|
|
1061
|
-
// bits are 1: add to result point
|
|
1062
|
-
p = p.add(negateCt(isNeg, precomputes[offset]));
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
assert0(n);
|
|
1066
|
-
// Return both real and fake points: JIT won't eliminate f.
|
|
1067
|
-
// At this point there is a way to F be infinity-point even if p is not,
|
|
1068
|
-
// which makes it less const-time: around 1 bigint multiply.
|
|
1069
|
-
return { p, f };
|
|
1070
|
-
}
|
|
1071
|
-
/**
|
|
1072
|
-
* Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form.
|
|
1073
|
-
* @param acc accumulator point to add result of multiplication
|
|
1074
|
-
* @returns point
|
|
1075
|
-
*/
|
|
1076
|
-
wNAFUnsafe(W, precomputes, n, acc = this.ZERO) {
|
|
1077
|
-
const wo = calcWOpts(W, this.bits);
|
|
1078
|
-
for (let window = 0; window < wo.windows; window++) {
|
|
1079
|
-
if (n === curve_0n)
|
|
1080
|
-
break; // Early-exit, skip 0 value
|
|
1081
|
-
const { nextN, offset, isZero, isNeg } = calcOffsets(n, window, wo);
|
|
1082
|
-
n = nextN;
|
|
1083
|
-
if (isZero) {
|
|
1084
|
-
// Window bits are 0: skip processing.
|
|
1085
|
-
// Move to next window.
|
|
1086
|
-
continue;
|
|
1087
|
-
}
|
|
1088
|
-
else {
|
|
1089
|
-
const item = precomputes[offset];
|
|
1090
|
-
acc = acc.add(isNeg ? item.negate() : item); // Re-using acc allows to save adds in MSM
|
|
1091
|
-
}
|
|
1092
|
-
}
|
|
1093
|
-
assert0(n);
|
|
1094
|
-
return acc;
|
|
1095
|
-
}
|
|
1096
|
-
getPrecomputes(W, point, transform) {
|
|
1097
|
-
// Calculate precomputes on a first run, reuse them after
|
|
1098
|
-
let comp = pointPrecomputes.get(point);
|
|
1099
|
-
if (!comp) {
|
|
1100
|
-
comp = this.precomputeWindow(point, W);
|
|
1101
|
-
if (W !== 1) {
|
|
1102
|
-
// Doing transform outside of if brings 15% perf hit
|
|
1103
|
-
if (typeof transform === 'function')
|
|
1104
|
-
comp = transform(comp);
|
|
1105
|
-
pointPrecomputes.set(point, comp);
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
return comp;
|
|
1109
|
-
}
|
|
1110
|
-
cached(point, scalar, transform) {
|
|
1111
|
-
const W = getW(point);
|
|
1112
|
-
return this.wNAF(W, this.getPrecomputes(W, point, transform), scalar);
|
|
1113
|
-
}
|
|
1114
|
-
unsafe(point, scalar, transform, prev) {
|
|
1115
|
-
const W = getW(point);
|
|
1116
|
-
if (W === 1)
|
|
1117
|
-
return this._unsafeLadder(point, scalar, prev); // For W=1 ladder is ~x2 faster
|
|
1118
|
-
return this.wNAFUnsafe(W, this.getPrecomputes(W, point, transform), scalar, prev);
|
|
1119
|
-
}
|
|
1120
|
-
// We calculate precomputes for elliptic curve point multiplication
|
|
1121
|
-
// using windowed method. This specifies window size and
|
|
1122
|
-
// stores precomputed values. Usually only base point would be precomputed.
|
|
1123
|
-
createCache(P, W) {
|
|
1124
|
-
validateW(W, this.bits);
|
|
1125
|
-
pointWindowSizes.set(P, W);
|
|
1126
|
-
pointPrecomputes.delete(P);
|
|
1127
|
-
}
|
|
1128
|
-
hasCache(elm) {
|
|
1129
|
-
return getW(elm) !== 1;
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
/**
|
|
1133
|
-
* Endomorphism-specific multiplication for Koblitz curves.
|
|
1134
|
-
* Cost: 128 dbl, 0-256 adds.
|
|
1135
|
-
*/
|
|
1136
|
-
function mulEndoUnsafe(Point, point, k1, k2) {
|
|
1137
|
-
let acc = point;
|
|
1138
|
-
let p1 = Point.ZERO;
|
|
1139
|
-
let p2 = Point.ZERO;
|
|
1140
|
-
while (k1 > curve_0n || k2 > curve_0n) {
|
|
1141
|
-
if (k1 & curve_1n)
|
|
1142
|
-
p1 = p1.add(acc);
|
|
1143
|
-
if (k2 & curve_1n)
|
|
1144
|
-
p2 = p2.add(acc);
|
|
1145
|
-
acc = acc.double();
|
|
1146
|
-
k1 >>= curve_1n;
|
|
1147
|
-
k2 >>= curve_1n;
|
|
1148
|
-
}
|
|
1149
|
-
return { p1, p2 };
|
|
1150
|
-
}
|
|
1151
|
-
/**
|
|
1152
|
-
* Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
|
|
1153
|
-
* 30x faster vs naive addition on L=4096, 10x faster than precomputes.
|
|
1154
|
-
* For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL.
|
|
1155
|
-
* Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0.
|
|
1156
|
-
* @param c Curve Point constructor
|
|
1157
|
-
* @param fieldN field over CURVE.N - important that it's not over CURVE.P
|
|
1158
|
-
* @param points array of L curve points
|
|
1159
|
-
* @param scalars array of L scalars (aka secret keys / bigints)
|
|
1160
|
-
*/
|
|
1161
|
-
function pippenger(c, fieldN, points, scalars) {
|
|
1162
|
-
// If we split scalars by some window (let's say 8 bits), every chunk will only
|
|
1163
|
-
// take 256 buckets even if there are 4096 scalars, also re-uses double.
|
|
1164
|
-
// TODO:
|
|
1165
|
-
// - https://eprint.iacr.org/2024/750.pdf
|
|
1166
|
-
// - https://tches.iacr.org/index.php/TCHES/article/view/10287
|
|
1167
|
-
// 0 is accepted in scalars
|
|
1168
|
-
validateMSMPoints(points, c);
|
|
1169
|
-
validateMSMScalars(scalars, fieldN);
|
|
1170
|
-
const plength = points.length;
|
|
1171
|
-
const slength = scalars.length;
|
|
1172
|
-
if (plength !== slength)
|
|
1173
|
-
throw new Error('arrays of points and scalars must have equal length');
|
|
1174
|
-
// if (plength === 0) throw new Error('array must be of length >= 2');
|
|
1175
|
-
const zero = c.ZERO;
|
|
1176
|
-
const wbits = bitLen(BigInt(plength));
|
|
1177
|
-
let windowSize = 1; // bits
|
|
1178
|
-
if (wbits > 12)
|
|
1179
|
-
windowSize = wbits - 3;
|
|
1180
|
-
else if (wbits > 4)
|
|
1181
|
-
windowSize = wbits - 2;
|
|
1182
|
-
else if (wbits > 0)
|
|
1183
|
-
windowSize = 2;
|
|
1184
|
-
const MASK = utils_bitMask(windowSize);
|
|
1185
|
-
const buckets = new Array(Number(MASK) + 1).fill(zero); // +1 for zero array
|
|
1186
|
-
const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize;
|
|
1187
|
-
let sum = zero;
|
|
1188
|
-
for (let i = lastBits; i >= 0; i -= windowSize) {
|
|
1189
|
-
buckets.fill(zero);
|
|
1190
|
-
for (let j = 0; j < slength; j++) {
|
|
1191
|
-
const scalar = scalars[j];
|
|
1192
|
-
const wbits = Number((scalar >> BigInt(i)) & MASK);
|
|
1193
|
-
buckets[wbits] = buckets[wbits].add(points[j]);
|
|
1194
|
-
}
|
|
1195
|
-
let resI = zero; // not using this will do small speed-up, but will lose ct
|
|
1196
|
-
// Skip first bucket, because it is zero
|
|
1197
|
-
for (let j = buckets.length - 1, sumI = zero; j > 0; j--) {
|
|
1198
|
-
sumI = sumI.add(buckets[j]);
|
|
1199
|
-
resI = resI.add(sumI);
|
|
1200
|
-
}
|
|
1201
|
-
sum = sum.add(resI);
|
|
1202
|
-
if (i !== 0)
|
|
1203
|
-
for (let j = 0; j < windowSize; j++)
|
|
1204
|
-
sum = sum.double();
|
|
1205
|
-
}
|
|
1206
|
-
return sum;
|
|
1207
|
-
}
|
|
1208
|
-
/**
|
|
1209
|
-
* Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
|
|
1210
|
-
* @param c Curve Point constructor
|
|
1211
|
-
* @param fieldN field over CURVE.N - important that it's not over CURVE.P
|
|
1212
|
-
* @param points array of L curve points
|
|
1213
|
-
* @returns function which multiplies points with scaars
|
|
1214
|
-
*/
|
|
1215
|
-
function precomputeMSMUnsafe(c, fieldN, points, windowSize) {
|
|
1216
|
-
/**
|
|
1217
|
-
* Performance Analysis of Window-based Precomputation
|
|
1218
|
-
*
|
|
1219
|
-
* Base Case (256-bit scalar, 8-bit window):
|
|
1220
|
-
* - Standard precomputation requires:
|
|
1221
|
-
* - 31 additions per scalar × 256 scalars = 7,936 ops
|
|
1222
|
-
* - Plus 255 summary additions = 8,191 total ops
|
|
1223
|
-
* Note: Summary additions can be optimized via accumulator
|
|
1224
|
-
*
|
|
1225
|
-
* Chunked Precomputation Analysis:
|
|
1226
|
-
* - Using 32 chunks requires:
|
|
1227
|
-
* - 255 additions per chunk
|
|
1228
|
-
* - 256 doublings
|
|
1229
|
-
* - Total: (255 × 32) + 256 = 8,416 ops
|
|
1230
|
-
*
|
|
1231
|
-
* Memory Usage Comparison:
|
|
1232
|
-
* Window Size | Standard Points | Chunked Points
|
|
1233
|
-
* ------------|-----------------|---------------
|
|
1234
|
-
* 4-bit | 520 | 15
|
|
1235
|
-
* 8-bit | 4,224 | 255
|
|
1236
|
-
* 10-bit | 13,824 | 1,023
|
|
1237
|
-
* 16-bit | 557,056 | 65,535
|
|
1238
|
-
*
|
|
1239
|
-
* Key Advantages:
|
|
1240
|
-
* 1. Enables larger window sizes due to reduced memory overhead
|
|
1241
|
-
* 2. More efficient for smaller scalar counts:
|
|
1242
|
-
* - 16 chunks: (16 × 255) + 256 = 4,336 ops
|
|
1243
|
-
* - ~2x faster than standard 8,191 ops
|
|
1244
|
-
*
|
|
1245
|
-
* Limitations:
|
|
1246
|
-
* - Not suitable for plain precomputes (requires 256 constant doublings)
|
|
1247
|
-
* - Performance degrades with larger scalar counts:
|
|
1248
|
-
* - Optimal for ~256 scalars
|
|
1249
|
-
* - Less efficient for 4096+ scalars (Pippenger preferred)
|
|
1250
|
-
*/
|
|
1251
|
-
validateW(windowSize, fieldN.BITS);
|
|
1252
|
-
validateMSMPoints(points, c);
|
|
1253
|
-
const zero = c.ZERO;
|
|
1254
|
-
const tableSize = 2 ** windowSize - 1; // table size (without zero)
|
|
1255
|
-
const chunks = Math.ceil(fieldN.BITS / windowSize); // chunks of item
|
|
1256
|
-
const MASK = bitMask(windowSize);
|
|
1257
|
-
const tables = points.map((p) => {
|
|
1258
|
-
const res = [];
|
|
1259
|
-
for (let i = 0, acc = p; i < tableSize; i++) {
|
|
1260
|
-
res.push(acc);
|
|
1261
|
-
acc = acc.add(p);
|
|
1262
|
-
}
|
|
1263
|
-
return res;
|
|
1264
|
-
});
|
|
1265
|
-
return (scalars) => {
|
|
1266
|
-
validateMSMScalars(scalars, fieldN);
|
|
1267
|
-
if (scalars.length > points.length)
|
|
1268
|
-
throw new Error('array of scalars must be smaller than array of points');
|
|
1269
|
-
let res = zero;
|
|
1270
|
-
for (let i = 0; i < chunks; i++) {
|
|
1271
|
-
// No need to double if accumulator is still zero.
|
|
1272
|
-
if (res !== zero)
|
|
1273
|
-
for (let j = 0; j < windowSize; j++)
|
|
1274
|
-
res = res.double();
|
|
1275
|
-
const shiftBy = BigInt(chunks * windowSize - (i + 1) * windowSize);
|
|
1276
|
-
for (let j = 0; j < scalars.length; j++) {
|
|
1277
|
-
const n = scalars[j];
|
|
1278
|
-
const curr = Number((n >> shiftBy) & MASK);
|
|
1279
|
-
if (!curr)
|
|
1280
|
-
continue; // skip zero scalars chunks
|
|
1281
|
-
res = res.add(tables[j][curr - 1]);
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
return res;
|
|
1285
|
-
};
|
|
1286
|
-
}
|
|
1287
|
-
// TODO: remove
|
|
1288
|
-
/** @deprecated */
|
|
1289
|
-
function validateBasic(curve) {
|
|
1290
|
-
validateField(curve.Fp);
|
|
1291
|
-
validateObject(curve, {
|
|
1292
|
-
n: 'bigint',
|
|
1293
|
-
h: 'bigint',
|
|
1294
|
-
Gx: 'field',
|
|
1295
|
-
Gy: 'field',
|
|
1296
|
-
}, {
|
|
1297
|
-
nBitLength: 'isSafeInteger',
|
|
1298
|
-
nByteLength: 'isSafeInteger',
|
|
1299
|
-
});
|
|
1300
|
-
// Set defaults
|
|
1301
|
-
return Object.freeze({
|
|
1302
|
-
...nLength(curve.n, curve.nBitLength),
|
|
1303
|
-
...curve,
|
|
1304
|
-
...{ p: curve.Fp.ORDER },
|
|
1305
|
-
});
|
|
1306
|
-
}
|
|
1307
|
-
function createField(order, field, isLE) {
|
|
1308
|
-
if (field) {
|
|
1309
|
-
if (field.ORDER !== order)
|
|
1310
|
-
throw new Error('Field.ORDER must match order: Fp == p, Fn == n');
|
|
1311
|
-
modular_validateField(field);
|
|
1312
|
-
return field;
|
|
1313
|
-
}
|
|
1314
|
-
else {
|
|
1315
|
-
return Field(order, { isLE });
|
|
1316
|
-
}
|
|
1317
|
-
}
|
|
1318
|
-
/** Validates CURVE opts and creates fields */
|
|
1319
|
-
function _createCurveFields(type, CURVE, curveOpts = {}, FpFnLE) {
|
|
1320
|
-
if (FpFnLE === undefined)
|
|
1321
|
-
FpFnLE = type === 'edwards';
|
|
1322
|
-
if (!CURVE || typeof CURVE !== 'object')
|
|
1323
|
-
throw new Error(`expected valid ${type} CURVE object`);
|
|
1324
|
-
for (const p of ['p', 'n', 'h']) {
|
|
1325
|
-
const val = CURVE[p];
|
|
1326
|
-
if (!(typeof val === 'bigint' && val > curve_0n))
|
|
1327
|
-
throw new Error(`CURVE.${p} must be positive bigint`);
|
|
1328
|
-
}
|
|
1329
|
-
const Fp = createField(CURVE.p, curveOpts.Fp, FpFnLE);
|
|
1330
|
-
const Fn = createField(CURVE.n, curveOpts.Fn, FpFnLE);
|
|
1331
|
-
const _b = type === 'weierstrass' ? 'b' : 'd';
|
|
1332
|
-
const params = ['Gx', 'Gy', 'a', _b];
|
|
1333
|
-
for (const p of params) {
|
|
1334
|
-
// @ts-ignore
|
|
1335
|
-
if (!Fp.isValid(CURVE[p]))
|
|
1336
|
-
throw new Error(`CURVE.${p} must be valid field element of CURVE.Fp`);
|
|
1337
|
-
}
|
|
1338
|
-
CURVE = Object.freeze(Object.assign({}, CURVE));
|
|
1339
|
-
return { CURVE, Fp, Fn };
|
|
1340
|
-
}
|
|
1341
|
-
//# sourceMappingURL=curve.js.map
|
|
22
|
+
// EXTERNAL MODULE: ../../node_modules/.pnpm/@noble+curves@1.9.7/node_modules/@noble/curves/esm/utils.js
|
|
23
|
+
var curves_esm_utils = __webpack_require__(99284);
|
|
24
|
+
// EXTERNAL MODULE: ../../node_modules/.pnpm/@noble+curves@1.9.7/node_modules/@noble/curves/esm/abstract/curve.js
|
|
25
|
+
var curve = __webpack_require__(11267);
|
|
26
|
+
// EXTERNAL MODULE: ../../node_modules/.pnpm/@noble+curves@1.9.7/node_modules/@noble/curves/esm/abstract/modular.js
|
|
27
|
+
var modular = __webpack_require__(5194);
|
|
1342
28
|
;// CONCATENATED MODULE: ../../node_modules/.pnpm/@noble+curves@1.9.7/node_modules/@noble/curves/esm/abstract/weierstrass.js
|
|
1343
29
|
/**
|
|
1344
30
|
* Short Weierstrass curve methods. The formula is: y² = x³ + ax + b.
|
|
@@ -1373,7 +59,7 @@ function _createCurveFields(type, CURVE, curveOpts = {}, FpFnLE) {
|
|
|
1373
59
|
|
|
1374
60
|
|
|
1375
61
|
// We construct basis in such way that den is always positive and equals n, but num sign depends on basis (not on secret value)
|
|
1376
|
-
const divNearest = (num, den) => (num + (num >= 0 ? den : -den) /
|
|
62
|
+
const divNearest = (num, den) => (num + (num >= 0 ? den : -den) / _2n) / den;
|
|
1377
63
|
/**
|
|
1378
64
|
* Splits scalar for GLV endomorphism.
|
|
1379
65
|
*/
|
|
@@ -1388,16 +74,16 @@ function _splitEndoScalar(k, basis, n) {
|
|
|
1388
74
|
// If we do `k1 mod N`, we'll get big scalar (`> sqrt(N)`): so, we do cheaper negation instead.
|
|
1389
75
|
let k1 = k - c1 * a1 - c2 * a2;
|
|
1390
76
|
let k2 = -c1 * b1 - c2 * b2;
|
|
1391
|
-
const k1neg = k1 <
|
|
1392
|
-
const k2neg = k2 <
|
|
77
|
+
const k1neg = k1 < _0n;
|
|
78
|
+
const k2neg = k2 < _0n;
|
|
1393
79
|
if (k1neg)
|
|
1394
80
|
k1 = -k1;
|
|
1395
81
|
if (k2neg)
|
|
1396
82
|
k2 = -k2;
|
|
1397
83
|
// Double check that resulting scalar less than half bits of N: otherwise wNAF will fail.
|
|
1398
84
|
// This should only happen on wrong basises. Also, math inside is too complex and I don't trust it.
|
|
1399
|
-
const MAX_NUM =
|
|
1400
|
-
if (k1 <
|
|
85
|
+
const MAX_NUM = (0,curves_esm_utils/* bitMask */.OG)(Math.ceil((0,curves_esm_utils/* bitLen */.dJ)(n) / 2)) + _1n; // Half bits of N
|
|
86
|
+
if (k1 < _0n || k1 >= MAX_NUM || k2 < _0n || k2 >= MAX_NUM) {
|
|
1401
87
|
throw new Error('splitScalar (endomorphism): failed, k=' + k);
|
|
1402
88
|
}
|
|
1403
89
|
return { k1neg, k1, k2neg, k2 };
|
|
@@ -1413,8 +99,8 @@ function validateSigOpts(opts, def) {
|
|
|
1413
99
|
// @ts-ignore
|
|
1414
100
|
optsn[optName] = opts[optName] === undefined ? def[optName] : opts[optName];
|
|
1415
101
|
}
|
|
1416
|
-
_abool2(optsn.lowS, 'lowS');
|
|
1417
|
-
_abool2(optsn.prehash, 'prehash');
|
|
102
|
+
(0,curves_esm_utils/* _abool2 */.d6)(optsn.lowS, 'lowS');
|
|
103
|
+
(0,curves_esm_utils/* _abool2 */.d6)(optsn.prehash, 'prehash');
|
|
1418
104
|
if (optsn.format !== undefined)
|
|
1419
105
|
validateSigFormat(optsn.format);
|
|
1420
106
|
return optsn;
|
|
@@ -1443,12 +129,12 @@ const DER = {
|
|
|
1443
129
|
if (data.length & 1)
|
|
1444
130
|
throw new E('tlv.encode: unpadded data');
|
|
1445
131
|
const dataLen = data.length / 2;
|
|
1446
|
-
const len = numberToHexUnpadded(dataLen);
|
|
132
|
+
const len = (0,curves_esm_utils/* numberToHexUnpadded */.zW)(dataLen);
|
|
1447
133
|
if ((len.length / 2) & 128)
|
|
1448
134
|
throw new E('tlv.encode: long form length too big');
|
|
1449
135
|
// length of length with long form flag
|
|
1450
|
-
const lenLen = dataLen > 127 ? numberToHexUnpadded((len.length / 2) | 128) : '';
|
|
1451
|
-
const t = numberToHexUnpadded(tag);
|
|
136
|
+
const lenLen = dataLen > 127 ? (0,curves_esm_utils/* numberToHexUnpadded */.zW)((len.length / 2) | 128) : '';
|
|
137
|
+
const t = (0,curves_esm_utils/* numberToHexUnpadded */.zW)(tag);
|
|
1452
138
|
return t + lenLen + len + data;
|
|
1453
139
|
},
|
|
1454
140
|
// v - value, l - left bytes (unparsed)
|
|
@@ -1495,9 +181,9 @@ const DER = {
|
|
|
1495
181
|
_int: {
|
|
1496
182
|
encode(num) {
|
|
1497
183
|
const { Err: E } = DER;
|
|
1498
|
-
if (num <
|
|
184
|
+
if (num < _0n)
|
|
1499
185
|
throw new E('integer: negative integers are not allowed');
|
|
1500
|
-
let hex = numberToHexUnpadded(num);
|
|
186
|
+
let hex = (0,curves_esm_utils/* numberToHexUnpadded */.zW)(num);
|
|
1501
187
|
// Pad with zero byte if negative flag is present
|
|
1502
188
|
if (Number.parseInt(hex[0], 16) & 0b1000)
|
|
1503
189
|
hex = '00' + hex;
|
|
@@ -1511,13 +197,13 @@ const DER = {
|
|
|
1511
197
|
throw new E('invalid signature integer: negative');
|
|
1512
198
|
if (data[0] === 0x00 && !(data[1] & 128))
|
|
1513
199
|
throw new E('invalid signature integer: unnecessary leading zero');
|
|
1514
|
-
return
|
|
200
|
+
return (0,curves_esm_utils/* bytesToNumberBE */.Ph)(data);
|
|
1515
201
|
},
|
|
1516
202
|
},
|
|
1517
203
|
toSig(hex) {
|
|
1518
204
|
// parse DER signature
|
|
1519
205
|
const { Err: E, _int: int, _tlv: tlv } = DER;
|
|
1520
|
-
const data =
|
|
206
|
+
const data = (0,curves_esm_utils/* ensureBytes */.qj)('signature', hex);
|
|
1521
207
|
const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data);
|
|
1522
208
|
if (seqLeftBytes.length)
|
|
1523
209
|
throw new E('invalid signature: left bytes after parsing');
|
|
@@ -1537,7 +223,7 @@ const DER = {
|
|
|
1537
223
|
};
|
|
1538
224
|
// Be friendly to bad ECMAScript parsers by not using bigint literals
|
|
1539
225
|
// prettier-ignore
|
|
1540
|
-
const
|
|
226
|
+
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
|
|
1541
227
|
function _normFnElement(Fn, key) {
|
|
1542
228
|
const { BYTES: expected } = Fn;
|
|
1543
229
|
let num;
|
|
@@ -1545,7 +231,7 @@ function _normFnElement(Fn, key) {
|
|
|
1545
231
|
num = key;
|
|
1546
232
|
}
|
|
1547
233
|
else {
|
|
1548
|
-
let bytes =
|
|
234
|
+
let bytes = (0,curves_esm_utils/* ensureBytes */.qj)('private key', key);
|
|
1549
235
|
try {
|
|
1550
236
|
num = Fn.fromBytes(bytes);
|
|
1551
237
|
}
|
|
@@ -1575,11 +261,11 @@ const p256_Point = weierstrass(opts);
|
|
|
1575
261
|
```
|
|
1576
262
|
*/
|
|
1577
263
|
function weierstrassN(params, extraOpts = {}) {
|
|
1578
|
-
const validated = _createCurveFields('weierstrass', params, extraOpts);
|
|
264
|
+
const validated = (0,curve/* _createCurveFields */.UT)('weierstrass', params, extraOpts);
|
|
1579
265
|
const { Fp, Fn } = validated;
|
|
1580
266
|
let CURVE = validated.CURVE;
|
|
1581
267
|
const { h: cofactor, n: CURVE_ORDER } = CURVE;
|
|
1582
|
-
_validateObject(extraOpts, {}, {
|
|
268
|
+
(0,curves_esm_utils/* _validateObject */.DS)(extraOpts, {}, {
|
|
1583
269
|
allowInfinityPoint: 'boolean',
|
|
1584
270
|
clearCofactor: 'function',
|
|
1585
271
|
isTorsionFree: 'function',
|
|
@@ -1604,7 +290,7 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
1604
290
|
function pointToBytes(_c, point, isCompressed) {
|
|
1605
291
|
const { x, y } = point.toAffine();
|
|
1606
292
|
const bx = Fp.toBytes(x);
|
|
1607
|
-
_abool2(isCompressed, 'isCompressed');
|
|
293
|
+
(0,curves_esm_utils/* _abool2 */.d6)(isCompressed, 'isCompressed');
|
|
1608
294
|
if (isCompressed) {
|
|
1609
295
|
assertCompressionIsSupported();
|
|
1610
296
|
const hasEvenY = !Fp.isOdd(y);
|
|
@@ -1615,7 +301,7 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
1615
301
|
}
|
|
1616
302
|
}
|
|
1617
303
|
function pointFromBytes(bytes) {
|
|
1618
|
-
_abytes2(bytes, undefined, 'Point');
|
|
304
|
+
(0,curves_esm_utils/* _abytes2 */.eV)(bytes, undefined, 'Point');
|
|
1619
305
|
const { publicKey: comp, publicKeyUncompressed: uncomp } = lengths; // e.g. for 32-byte: 33, 65
|
|
1620
306
|
const length = bytes.length;
|
|
1621
307
|
const head = bytes[0];
|
|
@@ -1674,7 +360,7 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
1674
360
|
throw new Error('bad curve params: generator point');
|
|
1675
361
|
// Test 2: discriminant Δ part should be non-zero: 4a³ + 27b² != 0.
|
|
1676
362
|
// Guarantees curve is genus-1, smooth (non-singular).
|
|
1677
|
-
const _4a3 = Fp.mul(Fp.pow(CURVE.a,
|
|
363
|
+
const _4a3 = Fp.mul(Fp.pow(CURVE.a, _3n), _4n);
|
|
1678
364
|
const _27b2 = Fp.mul(Fp.sqr(CURVE.b), BigInt(27));
|
|
1679
365
|
if (Fp.is0(Fp.add(_4a3, _27b2)))
|
|
1680
366
|
throw new Error('bad curve params: a or b');
|
|
@@ -1697,7 +383,7 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
1697
383
|
// Converts Projective point to affine (x, y) coordinates.
|
|
1698
384
|
// Can accept precomputed Z^-1 - for example, from invertBatch.
|
|
1699
385
|
// (X, Y, Z) ∋ (x=X/Z, y=Y/Z)
|
|
1700
|
-
const toAffineMemo = memoized((p, iz) => {
|
|
386
|
+
const toAffineMemo = (0,curves_esm_utils/* memoized */.x)((p, iz) => {
|
|
1701
387
|
const { X, Y, Z } = p;
|
|
1702
388
|
// Fast-path for normalized points
|
|
1703
389
|
if (Fp.eql(Z, Fp.ONE))
|
|
@@ -1718,7 +404,7 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
1718
404
|
});
|
|
1719
405
|
// NOTE: on exception this will crash 'cached' and no value will be set.
|
|
1720
406
|
// Otherwise true will be return
|
|
1721
|
-
const assertValidMemo = memoized((p) => {
|
|
407
|
+
const assertValidMemo = (0,curves_esm_utils/* memoized */.x)((p) => {
|
|
1722
408
|
if (p.is0()) {
|
|
1723
409
|
// (0, 1, 0) aka ZERO is invalid in most contexts.
|
|
1724
410
|
// In BLS, ZERO can be serialized, so we allow it.
|
|
@@ -1739,8 +425,8 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
1739
425
|
});
|
|
1740
426
|
function finishEndo(endoBeta, k1p, k2p, k1neg, k2neg) {
|
|
1741
427
|
k2p = new Point(Fp.mul(k2p.X, endoBeta), k2p.Y, k2p.Z);
|
|
1742
|
-
k1p = negateCt(k1neg, k1p);
|
|
1743
|
-
k2p = negateCt(k2neg, k2p);
|
|
428
|
+
k1p = (0,curve/* negateCt */.u0)(k1neg, k1p);
|
|
429
|
+
k2p = (0,curve/* negateCt */.u0)(k2neg, k2p);
|
|
1744
430
|
return k1p.add(k2p);
|
|
1745
431
|
}
|
|
1746
432
|
/**
|
|
@@ -1772,12 +458,12 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
1772
458
|
return new Point(x, y, Fp.ONE);
|
|
1773
459
|
}
|
|
1774
460
|
static fromBytes(bytes) {
|
|
1775
|
-
const P = Point.fromAffine(decodePoint(_abytes2(bytes, undefined, 'point')));
|
|
461
|
+
const P = Point.fromAffine(decodePoint((0,curves_esm_utils/* _abytes2 */.eV)(bytes, undefined, 'point')));
|
|
1776
462
|
P.assertValidity();
|
|
1777
463
|
return P;
|
|
1778
464
|
}
|
|
1779
465
|
static fromHex(hex) {
|
|
1780
|
-
return Point.fromBytes(
|
|
466
|
+
return Point.fromBytes((0,curves_esm_utils/* ensureBytes */.qj)('pointHex', hex));
|
|
1781
467
|
}
|
|
1782
468
|
get x() {
|
|
1783
469
|
return this.toAffine().x;
|
|
@@ -1794,7 +480,7 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
1794
480
|
precompute(windowSize = 8, isLazy = true) {
|
|
1795
481
|
wnaf.createCache(this, windowSize);
|
|
1796
482
|
if (!isLazy)
|
|
1797
|
-
this.multiply(
|
|
483
|
+
this.multiply(_3n); // random number
|
|
1798
484
|
return this;
|
|
1799
485
|
}
|
|
1800
486
|
// TODO: return `this`
|
|
@@ -1827,7 +513,7 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
1827
513
|
// Cost: 8M + 3S + 3*a + 2*b3 + 15add.
|
|
1828
514
|
double() {
|
|
1829
515
|
const { a, b } = CURVE;
|
|
1830
|
-
const b3 = Fp.mul(b,
|
|
516
|
+
const b3 = Fp.mul(b, _3n);
|
|
1831
517
|
const { X: X1, Y: Y1, Z: Z1 } = this;
|
|
1832
518
|
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
|
|
1833
519
|
let t0 = Fp.mul(X1, X1); // step 1
|
|
@@ -1873,7 +559,7 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
1873
559
|
const { X: X2, Y: Y2, Z: Z2 } = other;
|
|
1874
560
|
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
|
|
1875
561
|
const a = CURVE.a;
|
|
1876
|
-
const b3 = Fp.mul(CURVE.b,
|
|
562
|
+
const b3 = Fp.mul(CURVE.b, _3n);
|
|
1877
563
|
let t0 = Fp.mul(X1, X2); // step 1
|
|
1878
564
|
let t1 = Fp.mul(Y1, Y2);
|
|
1879
565
|
let t2 = Fp.mul(Z1, Z2);
|
|
@@ -1936,7 +622,7 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
1936
622
|
if (!Fn.isValidNot0(scalar))
|
|
1937
623
|
throw new Error('invalid scalar: out of range'); // 0 is invalid
|
|
1938
624
|
let point, fake; // Fake point is used to const-time mult
|
|
1939
|
-
const mul = (n) => wnaf.cached(this, n, (p) => normalizeZ(Point, p));
|
|
625
|
+
const mul = (n) => wnaf.cached(this, n, (p) => (0,curve/* normalizeZ */.Ak)(Point, p));
|
|
1940
626
|
/** See docs for {@link EndomorphismOpts} */
|
|
1941
627
|
if (endo) {
|
|
1942
628
|
const { k1neg, k1, k2neg, k2 } = splitEndoScalarN(scalar);
|
|
@@ -1951,7 +637,7 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
1951
637
|
fake = f;
|
|
1952
638
|
}
|
|
1953
639
|
// Normalize `z` for both points, but return only real one
|
|
1954
|
-
return normalizeZ(Point, [point, fake])[0];
|
|
640
|
+
return (0,curve/* normalizeZ */.Ak)(Point, [point, fake])[0];
|
|
1955
641
|
}
|
|
1956
642
|
/**
|
|
1957
643
|
* Non-constant-time multiplication. Uses double-and-add algorithm.
|
|
@@ -1963,15 +649,15 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
1963
649
|
const p = this;
|
|
1964
650
|
if (!Fn.isValid(sc))
|
|
1965
651
|
throw new Error('invalid scalar: out of range'); // 0 is valid
|
|
1966
|
-
if (sc ===
|
|
652
|
+
if (sc === _0n || p.is0())
|
|
1967
653
|
return Point.ZERO;
|
|
1968
|
-
if (sc ===
|
|
654
|
+
if (sc === _1n)
|
|
1969
655
|
return p; // fast-path
|
|
1970
656
|
if (wnaf.hasCache(this))
|
|
1971
657
|
return this.multiply(sc);
|
|
1972
658
|
if (endo) {
|
|
1973
659
|
const { k1neg, k1, k2neg, k2 } = splitEndoScalarN(sc);
|
|
1974
|
-
const { p1, p2 } = mulEndoUnsafe(Point, p, k1, k2); // 30% faster vs wnaf.unsafe
|
|
660
|
+
const { p1, p2 } = (0,curve/* mulEndoUnsafe */.fH)(Point, p, k1, k2); // 30% faster vs wnaf.unsafe
|
|
1975
661
|
return finishEndo(endo.beta, p1, p2, k1neg, k2neg);
|
|
1976
662
|
}
|
|
1977
663
|
else {
|
|
@@ -1995,7 +681,7 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
1995
681
|
*/
|
|
1996
682
|
isTorsionFree() {
|
|
1997
683
|
const { isTorsionFree } = extraOpts;
|
|
1998
|
-
if (cofactor ===
|
|
684
|
+
if (cofactor === _1n)
|
|
1999
685
|
return true;
|
|
2000
686
|
if (isTorsionFree)
|
|
2001
687
|
return isTorsionFree(Point, this);
|
|
@@ -2003,7 +689,7 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
2003
689
|
}
|
|
2004
690
|
clearCofactor() {
|
|
2005
691
|
const { clearCofactor } = extraOpts;
|
|
2006
|
-
if (cofactor ===
|
|
692
|
+
if (cofactor === _1n)
|
|
2007
693
|
return this; // Fast-path
|
|
2008
694
|
if (clearCofactor)
|
|
2009
695
|
return clearCofactor(Point, this);
|
|
@@ -2014,7 +700,7 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
2014
700
|
return this.multiplyUnsafe(cofactor).is0();
|
|
2015
701
|
}
|
|
2016
702
|
toBytes(isCompressed = true) {
|
|
2017
|
-
_abool2(isCompressed, 'isCompressed');
|
|
703
|
+
(0,curves_esm_utils/* _abool2 */.d6)(isCompressed, 'isCompressed');
|
|
2018
704
|
this.assertValidity();
|
|
2019
705
|
return encodePoint(Point, this, isCompressed);
|
|
2020
706
|
}
|
|
@@ -2041,10 +727,10 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
2041
727
|
this.precompute(windowSize);
|
|
2042
728
|
}
|
|
2043
729
|
static normalizeZ(points) {
|
|
2044
|
-
return normalizeZ(Point, points);
|
|
730
|
+
return (0,curve/* normalizeZ */.Ak)(Point, points);
|
|
2045
731
|
}
|
|
2046
732
|
static msm(points, scalars) {
|
|
2047
|
-
return pippenger(Point, Fn, points, scalars);
|
|
733
|
+
return (0,curve/* pippenger */.Xf)(Point, Fn, points, scalars);
|
|
2048
734
|
}
|
|
2049
735
|
static fromPrivateKey(privateKey) {
|
|
2050
736
|
return Point.BASE.multiply(_normFnElement(Fn, privateKey));
|
|
@@ -2059,7 +745,7 @@ function weierstrassN(params, extraOpts = {}) {
|
|
|
2059
745
|
// scalar field
|
|
2060
746
|
Point.Fn = Fn;
|
|
2061
747
|
const bits = Fn.BITS;
|
|
2062
|
-
const wnaf = new wNAF(Point, extraOpts.endo ? Math.ceil(bits / 2) : bits);
|
|
748
|
+
const wnaf = new curve/* wNAF */.hT(Point, extraOpts.endo ? Math.ceil(bits / 2) : bits);
|
|
2063
749
|
Point.BASE.precompute(8); // Enable precomputes. Slows down first publicKey computation by 20ms.
|
|
2064
750
|
return Point;
|
|
2065
751
|
}
|
|
@@ -2079,20 +765,20 @@ function pprefix(hasEvenY) {
|
|
|
2079
765
|
function SWUFpSqrtRatio(Fp, Z) {
|
|
2080
766
|
// Generic implementation
|
|
2081
767
|
const q = Fp.ORDER;
|
|
2082
|
-
let l =
|
|
2083
|
-
for (let o = q -
|
|
2084
|
-
l +=
|
|
768
|
+
let l = _0n;
|
|
769
|
+
for (let o = q - _1n; o % _2n === _0n; o /= _2n)
|
|
770
|
+
l += _1n;
|
|
2085
771
|
const c1 = l; // 1. c1, the largest integer such that 2^c1 divides q - 1.
|
|
2086
772
|
// We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<.
|
|
2087
773
|
// 2n ** c1 == 2n << (c1-1)
|
|
2088
|
-
const _2n_pow_c1_1 =
|
|
2089
|
-
const _2n_pow_c1 = _2n_pow_c1_1 *
|
|
2090
|
-
const c2 = (q -
|
|
2091
|
-
const c3 = (c2 -
|
|
2092
|
-
const c4 = _2n_pow_c1 -
|
|
774
|
+
const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n);
|
|
775
|
+
const _2n_pow_c1 = _2n_pow_c1_1 * _2n;
|
|
776
|
+
const c2 = (q - _1n) / _2n_pow_c1; // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic
|
|
777
|
+
const c3 = (c2 - _1n) / _2n; // 3. c3 = (c2 - 1) / 2 # Integer arithmetic
|
|
778
|
+
const c4 = _2n_pow_c1 - _1n; // 4. c4 = 2^c1 - 1 # Integer arithmetic
|
|
2093
779
|
const c5 = _2n_pow_c1_1; // 5. c5 = 2^(c1 - 1) # Integer arithmetic
|
|
2094
780
|
const c6 = Fp.pow(Z, c2); // 6. c6 = Z^c2
|
|
2095
|
-
const c7 = Fp.pow(Z, (c2 +
|
|
781
|
+
const c7 = Fp.pow(Z, (c2 + _1n) / _2n); // 7. c7 = Z^((c2 + 1) / 2)
|
|
2096
782
|
let sqrtRatio = (u, v) => {
|
|
2097
783
|
let tv1 = c6; // 1. tv1 = c6
|
|
2098
784
|
let tv2 = Fp.pow(v, c4); // 2. tv2 = v^c4
|
|
@@ -2111,9 +797,9 @@ function SWUFpSqrtRatio(Fp, Z) {
|
|
|
2111
797
|
tv3 = Fp.cmov(tv2, tv3, isQR); // 15. tv3 = CMOV(tv2, tv3, isQR)
|
|
2112
798
|
tv4 = Fp.cmov(tv5, tv4, isQR); // 16. tv4 = CMOV(tv5, tv4, isQR)
|
|
2113
799
|
// 17. for i in (c1, c1 - 1, ..., 2):
|
|
2114
|
-
for (let i = c1; i >
|
|
2115
|
-
let tv5 = i -
|
|
2116
|
-
tv5 =
|
|
800
|
+
for (let i = c1; i > _1n; i--) {
|
|
801
|
+
let tv5 = i - _2n; // 18. tv5 = i - 2
|
|
802
|
+
tv5 = _2n << (tv5 - _1n); // 19. tv5 = 2^tv5
|
|
2117
803
|
let tvv5 = Fp.pow(tv4, tv5); // 20. tv5 = tv4^tv5
|
|
2118
804
|
const e1 = Fp.eql(tvv5, Fp.ONE); // 21. e1 = tv5 == 1
|
|
2119
805
|
tv2 = Fp.mul(tv3, tv1); // 22. tv2 = tv3 * tv1
|
|
@@ -2124,9 +810,9 @@ function SWUFpSqrtRatio(Fp, Z) {
|
|
|
2124
810
|
}
|
|
2125
811
|
return { isValid: isQR, value: tv3 };
|
|
2126
812
|
};
|
|
2127
|
-
if (Fp.ORDER %
|
|
813
|
+
if (Fp.ORDER % _4n === _3n) {
|
|
2128
814
|
// sqrt_ratio_3mod4(u, v)
|
|
2129
|
-
const c1 = (Fp.ORDER -
|
|
815
|
+
const c1 = (Fp.ORDER - _3n) / _4n; // 1. c1 = (q - 3) / 4 # Integer arithmetic
|
|
2130
816
|
const c2 = Fp.sqrt(Fp.neg(Z)); // 2. c2 = sqrt(-Z)
|
|
2131
817
|
sqrtRatio = (u, v) => {
|
|
2132
818
|
let tv1 = Fp.sqr(v); // 1. tv1 = v^2
|
|
@@ -2207,7 +893,7 @@ function getWLengths(Fp, Fn) {
|
|
|
2207
893
|
function ecdh(Point, ecdhOpts = {}) {
|
|
2208
894
|
const { Fn } = Point;
|
|
2209
895
|
const randomBytes_ = ecdhOpts.randomBytes || esm_utils/* randomBytes */.po;
|
|
2210
|
-
const lengths = Object.assign(getWLengths(Point.Fp, Fn), { seed: getMinHashLength(Fn.ORDER) });
|
|
896
|
+
const lengths = Object.assign(getWLengths(Point.Fp, Fn), { seed: (0,modular/* getMinHashLength */.Tp)(Fn.ORDER) });
|
|
2211
897
|
function isValidSecretKey(secretKey) {
|
|
2212
898
|
try {
|
|
2213
899
|
return !!_normFnElement(Fn, secretKey);
|
|
@@ -2235,7 +921,7 @@ function ecdh(Point, ecdhOpts = {}) {
|
|
|
2235
921
|
* (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.
|
|
2236
922
|
*/
|
|
2237
923
|
function randomSecretKey(seed = randomBytes_(lengths.seed)) {
|
|
2238
|
-
return mapHashToField(_abytes2(seed, lengths.seed, 'seed'), Fn.ORDER);
|
|
924
|
+
return (0,modular/* mapHashToField */.qy)((0,curves_esm_utils/* _abytes2 */.eV)(seed, lengths.seed, 'seed'), Fn.ORDER);
|
|
2239
925
|
}
|
|
2240
926
|
/**
|
|
2241
927
|
* Computes public key for a secret key. Checks for validity of the secret key.
|
|
@@ -2260,7 +946,7 @@ function ecdh(Point, ecdhOpts = {}) {
|
|
|
2260
946
|
const { secretKey, publicKey, publicKeyUncompressed } = lengths;
|
|
2261
947
|
if (Fn.allowedLengths || secretKey === publicKey)
|
|
2262
948
|
return undefined;
|
|
2263
|
-
const l =
|
|
949
|
+
const l = (0,curves_esm_utils/* ensureBytes */.qj)('key', item).length;
|
|
2264
950
|
return l === publicKey || l === publicKeyUncompressed;
|
|
2265
951
|
}
|
|
2266
952
|
/**
|
|
@@ -2312,7 +998,7 @@ function ecdh(Point, ecdhOpts = {}) {
|
|
|
2312
998
|
*/
|
|
2313
999
|
function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
2314
1000
|
(0,esm_utils/* ahash */.sd)(hash);
|
|
2315
|
-
_validateObject(ecdsaOpts, {}, {
|
|
1001
|
+
(0,curves_esm_utils/* _validateObject */.DS)(ecdsaOpts, {}, {
|
|
2316
1002
|
hmac: 'function',
|
|
2317
1003
|
lowS: 'boolean',
|
|
2318
1004
|
randomBytes: 'function',
|
|
@@ -2333,7 +1019,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
2333
1019
|
};
|
|
2334
1020
|
const defaultSigOpts_format = 'compact';
|
|
2335
1021
|
function isBiggerThanHalfOrder(number) {
|
|
2336
|
-
const HALF = CURVE_ORDER >>
|
|
1022
|
+
const HALF = CURVE_ORDER >> _1n;
|
|
2337
1023
|
return number > HALF;
|
|
2338
1024
|
}
|
|
2339
1025
|
function validateRS(title, num) {
|
|
@@ -2345,7 +1031,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
2345
1031
|
validateSigFormat(format);
|
|
2346
1032
|
const size = lengths.signature;
|
|
2347
1033
|
const sizer = format === 'compact' ? size : format === 'recovered' ? size + 1 : undefined;
|
|
2348
|
-
return _abytes2(bytes, sizer, `${format} signature`);
|
|
1034
|
+
return (0,curves_esm_utils/* _abytes2 */.eV)(bytes, sizer, `${format} signature`);
|
|
2349
1035
|
}
|
|
2350
1036
|
/**
|
|
2351
1037
|
* ECDSA signature with its (r, s) properties. Supports compact, recovered & DER representations.
|
|
@@ -2362,7 +1048,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
2362
1048
|
validateSigLength(bytes, format);
|
|
2363
1049
|
let recid;
|
|
2364
1050
|
if (format === 'der') {
|
|
2365
|
-
const { r, s } = DER.toSig(_abytes2(bytes));
|
|
1051
|
+
const { r, s } = DER.toSig((0,curves_esm_utils/* _abytes2 */.eV)(bytes));
|
|
2366
1052
|
return new Signature(r, s);
|
|
2367
1053
|
}
|
|
2368
1054
|
if (format === 'recovered') {
|
|
@@ -2394,7 +1080,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
2394
1080
|
// To easily get i, we either need to:
|
|
2395
1081
|
// a. increase amount of valid recid values (4, 5...); OR
|
|
2396
1082
|
// b. prohibit non-prime-order signatures (recid > 1).
|
|
2397
|
-
const hasCofactor = CURVE_ORDER *
|
|
1083
|
+
const hasCofactor = CURVE_ORDER * _2n < FIELD_ORDER;
|
|
2398
1084
|
if (hasCofactor && rec > 1)
|
|
2399
1085
|
throw new Error('recovery id is ambiguous for h>1 curve');
|
|
2400
1086
|
const radj = rec === 2 || rec === 3 ? r + CURVE_ORDER : r;
|
|
@@ -2403,7 +1089,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
2403
1089
|
const x = Fp.toBytes(radj);
|
|
2404
1090
|
const R = Point.fromBytes((0,esm_utils/* concatBytes */.Id)(pprefix((rec & 1) === 0), x));
|
|
2405
1091
|
const ir = Fn.inv(radj); // r^-1
|
|
2406
|
-
const h = bits2int_modN(
|
|
1092
|
+
const h = bits2int_modN((0,curves_esm_utils/* ensureBytes */.qj)('msgHash', messageHash)); // Truncate hash
|
|
2407
1093
|
const u1 = Fn.create(-h * ir); // -hr^-1
|
|
2408
1094
|
const u2 = Fn.create(s * ir); // sr^-1
|
|
2409
1095
|
// (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1). unsafe is fine: there is no private data.
|
|
@@ -2436,10 +1122,10 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
2436
1122
|
// TODO: remove
|
|
2437
1123
|
assertValidity() { }
|
|
2438
1124
|
static fromCompact(hex) {
|
|
2439
|
-
return Signature.fromBytes(
|
|
1125
|
+
return Signature.fromBytes((0,curves_esm_utils/* ensureBytes */.qj)('sig', hex), 'compact');
|
|
2440
1126
|
}
|
|
2441
1127
|
static fromDER(hex) {
|
|
2442
|
-
return Signature.fromBytes(
|
|
1128
|
+
return Signature.fromBytes((0,curves_esm_utils/* ensureBytes */.qj)('sig', hex), 'der');
|
|
2443
1129
|
}
|
|
2444
1130
|
normalizeS() {
|
|
2445
1131
|
return this.hasHighS() ? new Signature(this.r, Fn.neg(this.s), this.recovery) : this;
|
|
@@ -2468,7 +1154,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
2468
1154
|
throw new Error('input is too large');
|
|
2469
1155
|
// For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)
|
|
2470
1156
|
// for some cases, since bytes.length * 8 is not actual bitLength.
|
|
2471
|
-
const num =
|
|
1157
|
+
const num = (0,curves_esm_utils/* bytesToNumberBE */.Ph)(bytes); // check for == u8 done here
|
|
2472
1158
|
const delta = bytes.length * 8 - fnBits; // truncate to nBitLength leftmost bits
|
|
2473
1159
|
return delta > 0 ? num >> BigInt(delta) : num;
|
|
2474
1160
|
};
|
|
@@ -2477,16 +1163,16 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
2477
1163
|
return Fn.create(bits2int(bytes)); // can't use bytesToNumberBE here
|
|
2478
1164
|
};
|
|
2479
1165
|
// Pads output with zero as per spec
|
|
2480
|
-
const ORDER_MASK =
|
|
1166
|
+
const ORDER_MASK = (0,curves_esm_utils/* bitMask */.OG)(fnBits);
|
|
2481
1167
|
/** Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`. */
|
|
2482
1168
|
function int2octets(num) {
|
|
2483
1169
|
// IMPORTANT: the check ensures working for case `Fn.BYTES != Fn.BITS * 8`
|
|
2484
|
-
aInRange('num < 2^' + fnBits, num,
|
|
1170
|
+
(0,curves_esm_utils/* aInRange */.aK)('num < 2^' + fnBits, num, _0n, ORDER_MASK);
|
|
2485
1171
|
return Fn.toBytes(num);
|
|
2486
1172
|
}
|
|
2487
1173
|
function validateMsgAndHash(message, prehash) {
|
|
2488
|
-
_abytes2(message, undefined, 'message');
|
|
2489
|
-
return prehash ? _abytes2(hash(message), undefined, 'prehashed message') : message;
|
|
1174
|
+
(0,curves_esm_utils/* _abytes2 */.eV)(message, undefined, 'message');
|
|
1175
|
+
return prehash ? (0,curves_esm_utils/* _abytes2 */.eV)(hash(message), undefined, 'prehashed message') : message;
|
|
2490
1176
|
}
|
|
2491
1177
|
/**
|
|
2492
1178
|
* Steps A, D of RFC6979 3.2.
|
|
@@ -2512,7 +1198,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
2512
1198
|
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
|
|
2513
1199
|
// gen random bytes OR pass as-is
|
|
2514
1200
|
const e = extraEntropy === true ? randomBytes(lengths.secretKey) : extraEntropy;
|
|
2515
|
-
seedArgs.push(
|
|
1201
|
+
seedArgs.push((0,curves_esm_utils/* ensureBytes */.qj)('extraEntropy', e)); // check for being bytes
|
|
2516
1202
|
}
|
|
2517
1203
|
const seed = (0,esm_utils/* concatBytes */.Id)(...seedArgs); // Step D of RFC6979 3.2
|
|
2518
1204
|
const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!
|
|
@@ -2533,12 +1219,12 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
2533
1219
|
const ik = Fn.inv(k); // k^-1 mod n
|
|
2534
1220
|
const q = Point.BASE.multiply(k).toAffine(); // q = k⋅G
|
|
2535
1221
|
const r = Fn.create(q.x); // r = q.x mod n
|
|
2536
|
-
if (r ===
|
|
1222
|
+
if (r === _0n)
|
|
2537
1223
|
return;
|
|
2538
1224
|
const s = Fn.create(ik * Fn.create(m + r * d)); // Not using blinding here, see comment above
|
|
2539
|
-
if (s ===
|
|
1225
|
+
if (s === _0n)
|
|
2540
1226
|
return;
|
|
2541
|
-
let recovery = (q.x === r ? 0 : 2) | Number(q.y &
|
|
1227
|
+
let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n); // recovery bit (2 or 3, when q.x > n)
|
|
2542
1228
|
let normS = s;
|
|
2543
1229
|
if (lowS && isBiggerThanHalfOrder(s)) {
|
|
2544
1230
|
normS = Fn.neg(s); // if lowS was passed, ensure s is always
|
|
@@ -2560,9 +1246,9 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
2560
1246
|
* ```
|
|
2561
1247
|
*/
|
|
2562
1248
|
function sign(message, secretKey, opts = {}) {
|
|
2563
|
-
message =
|
|
1249
|
+
message = (0,curves_esm_utils/* ensureBytes */.qj)('message', message);
|
|
2564
1250
|
const { seed, k2sig } = prepSig(message, secretKey, opts); // Steps A, D of RFC6979 3.2.
|
|
2565
|
-
const drbg = createHmacDrbg(hash.outputLen, Fn.BYTES, hmac);
|
|
1251
|
+
const drbg = (0,curves_esm_utils/* createHmacDrbg */.fg)(hash.outputLen, Fn.BYTES, hmac);
|
|
2566
1252
|
const sig = drbg(seed, k2sig); // Steps B, C, D, E, F, G
|
|
2567
1253
|
return sig;
|
|
2568
1254
|
}
|
|
@@ -2582,7 +1268,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
2582
1268
|
}
|
|
2583
1269
|
else if (isHex) {
|
|
2584
1270
|
try {
|
|
2585
|
-
sig = Signature.fromBytes(
|
|
1271
|
+
sig = Signature.fromBytes((0,curves_esm_utils/* ensureBytes */.qj)('sig', sg), 'der');
|
|
2586
1272
|
}
|
|
2587
1273
|
catch (derError) {
|
|
2588
1274
|
if (!(derError instanceof DER.Err))
|
|
@@ -2590,7 +1276,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
2590
1276
|
}
|
|
2591
1277
|
if (!sig) {
|
|
2592
1278
|
try {
|
|
2593
|
-
sig = Signature.fromBytes(
|
|
1279
|
+
sig = Signature.fromBytes((0,curves_esm_utils/* ensureBytes */.qj)('sig', sg), 'compact');
|
|
2594
1280
|
}
|
|
2595
1281
|
catch (error) {
|
|
2596
1282
|
return false;
|
|
@@ -2616,13 +1302,13 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
2616
1302
|
*/
|
|
2617
1303
|
function verify(signature, message, publicKey, opts = {}) {
|
|
2618
1304
|
const { lowS, prehash, format } = validateSigOpts(opts, defaultSigOpts);
|
|
2619
|
-
publicKey =
|
|
2620
|
-
message = validateMsgAndHash(
|
|
1305
|
+
publicKey = (0,curves_esm_utils/* ensureBytes */.qj)('publicKey', publicKey);
|
|
1306
|
+
message = validateMsgAndHash((0,curves_esm_utils/* ensureBytes */.qj)('message', message), prehash);
|
|
2621
1307
|
if ('strict' in opts)
|
|
2622
1308
|
throw new Error('options.strict was renamed to lowS');
|
|
2623
1309
|
const sig = format === undefined
|
|
2624
1310
|
? tryParsingSig(signature)
|
|
2625
|
-
: Signature.fromBytes(
|
|
1311
|
+
: Signature.fromBytes((0,curves_esm_utils/* ensureBytes */.qj)('sig', signature), format);
|
|
2626
1312
|
if (sig === false)
|
|
2627
1313
|
return false;
|
|
2628
1314
|
try {
|
|
@@ -2683,7 +1369,7 @@ function _weierstrass_legacy_opts_to_new(c) {
|
|
|
2683
1369
|
let allowedLengths = c.allowedPrivateKeyLengths
|
|
2684
1370
|
? Array.from(new Set(c.allowedPrivateKeyLengths.map((l) => Math.ceil(l / 2))))
|
|
2685
1371
|
: undefined;
|
|
2686
|
-
const Fn = Field(CURVE.n, {
|
|
1372
|
+
const Fn = (0,modular/* Field */.D0)(CURVE.n, {
|
|
2687
1373
|
BITS: c.nBitLength,
|
|
2688
1374
|
allowedLengths: allowedLengths,
|
|
2689
1375
|
modFromBytes: c.wrapPrivateKey,
|
|
@@ -2726,7 +1412,7 @@ function _legacyHelperEquat(Fp, a, b) {
|
|
|
2726
1412
|
function _weierstrass_new_output_to_legacy(c, Point) {
|
|
2727
1413
|
const { Fp, Fn } = Point;
|
|
2728
1414
|
function isWithinCurveOrder(num) {
|
|
2729
|
-
return inRange(num,
|
|
1415
|
+
return inRange(num, _1n, Fn.ORDER);
|
|
2730
1416
|
}
|
|
2731
1417
|
const weierstrassEquation = _legacyHelperEquat(Fp, c.a, c.b);
|
|
2732
1418
|
return Object.assign({}, {
|
|
@@ -2742,7 +1428,7 @@ function _ecdsa_new_output_to_legacy(c, _ecdsa) {
|
|
|
2742
1428
|
const Point = _ecdsa.Point;
|
|
2743
1429
|
return Object.assign({}, _ecdsa, {
|
|
2744
1430
|
ProjectivePoint: Point,
|
|
2745
|
-
CURVE: Object.assign({}, c,
|
|
1431
|
+
CURVE: Object.assign({}, c, (0,modular/* nLength */.LH)(Point.Fn.ORDER, Point.Fn.BITS)),
|
|
2746
1432
|
});
|
|
2747
1433
|
}
|
|
2748
1434
|
// _ecdsa_legacy
|
|
@@ -2813,9 +1499,9 @@ const p521_CURVE = {
|
|
|
2813
1499
|
Gx: BigInt('0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66'),
|
|
2814
1500
|
Gy: BigInt('0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'),
|
|
2815
1501
|
};
|
|
2816
|
-
const Fp256 = Field(p256_CURVE.p);
|
|
2817
|
-
const Fp384 = Field(p384_CURVE.p);
|
|
2818
|
-
const Fp521 = Field(p521_CURVE.p);
|
|
1502
|
+
const Fp256 = (0,modular/* Field */.D0)(p256_CURVE.p);
|
|
1503
|
+
const Fp384 = (0,modular/* Field */.D0)(p384_CURVE.p);
|
|
1504
|
+
const Fp521 = (0,modular/* Field */.D0)(p521_CURVE.p);
|
|
2819
1505
|
function createSWU(Point, opts) {
|
|
2820
1506
|
const map = mapToCurveSimpleSWU(Point.Fp, opts);
|
|
2821
1507
|
return (scalars) => map(scalars[0]);
|