@xchainjs/xchain-radix 2.0.7 → 2.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/lib/index.esm.js +12 -3372
  2. package/lib/index.js +16 -3372
  3. package/package.json +7 -7
package/lib/index.esm.js CHANGED
@@ -2,8 +2,9 @@ import { NetworkId, generateRandomNonce, RadixEngineToolkit, Convert, ManifestBu
2
2
  import { Network, BaseXChainClient, singleFee, FeeType, TxType } from '@xchainjs/xchain-client';
3
3
  import { getSeed } from '@xchainjs/xchain-crypto';
4
4
  import { AssetType, assetToBase, assetAmount, eqAsset, baseAmount } from '@xchainjs/xchain-util';
5
- import { createBase58check, bech32m } from '@scure/base';
6
- import { derivePath } from 'ed25519-hd-key';
5
+ import { bech32m } from '@scure/base';
6
+ import { HDKey } from '@scure/bip32';
7
+ import slip10 from 'micro-key-producer/slip10.js';
7
8
  import { GatewayApiClient } from '@radixdlt/babylon-gateway-api-sdk';
8
9
 
9
10
  /******************************************************************************
@@ -38,3369 +39,6 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
38
39
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
39
40
  };
40
41
 
41
- const crypto = typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined;
42
-
43
- /**
44
- * Utilities for hex, bytes, CSPRNG.
45
- * @module
46
- */
47
- /*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
48
- // We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.
49
- // node.js versions earlier than v19 don't declare it in global scope.
50
- // For node.js, package.json#exports field mapping rewrites import
51
- // from `crypto` to `cryptoNode`, which imports native module.
52
- // Makes the utils un-importable in browsers without a bundler.
53
- // Once node.js 18 is deprecated (2025-04-30), we can just drop the import.
54
- /** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */
55
- function isBytes(a) {
56
- return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
57
- }
58
- /** Asserts something is positive integer. */
59
- function anumber(n) {
60
- if (!Number.isSafeInteger(n) || n < 0)
61
- throw new Error('positive integer expected, got ' + n);
62
- }
63
- /** Asserts something is Uint8Array. */
64
- function abytes(b, ...lengths) {
65
- if (!isBytes(b))
66
- throw new Error('Uint8Array expected');
67
- if (lengths.length > 0 && !lengths.includes(b.length))
68
- throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length);
69
- }
70
- /** Asserts something is hash */
71
- function ahash(h) {
72
- if (typeof h !== 'function' || typeof h.create !== 'function')
73
- throw new Error('Hash should be wrapped by utils.createHasher');
74
- anumber(h.outputLen);
75
- anumber(h.blockLen);
76
- }
77
- /** Asserts a hash instance has not been destroyed / finished */
78
- function aexists(instance, checkFinished = true) {
79
- if (instance.destroyed)
80
- throw new Error('Hash instance has been destroyed');
81
- if (checkFinished && instance.finished)
82
- throw new Error('Hash#digest() has already been called');
83
- }
84
- /** Asserts output is properly-sized byte array */
85
- function aoutput(out, instance) {
86
- abytes(out);
87
- const min = instance.outputLen;
88
- if (out.length < min) {
89
- throw new Error('digestInto() expects output buffer of length at least ' + min);
90
- }
91
- }
92
- /** Zeroize a byte array. Warning: JS provides no guarantees. */
93
- function clean(...arrays) {
94
- for (let i = 0; i < arrays.length; i++) {
95
- arrays[i].fill(0);
96
- }
97
- }
98
- /** Create DataView of an array for easy byte-level manipulation. */
99
- function createView(arr) {
100
- return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
101
- }
102
- /** The rotate right (circular right shift) operation for uint32 */
103
- function rotr(word, shift) {
104
- return (word << (32 - shift)) | (word >>> shift);
105
- }
106
- /** The rotate left (circular left shift) operation for uint32 */
107
- function rotl(word, shift) {
108
- return (word << shift) | ((word >>> (32 - shift)) >>> 0);
109
- }
110
- // Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex
111
- const hasHexBuiltin = /* @__PURE__ */ (() =>
112
- // @ts-ignore
113
- typeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function')();
114
- // Array where index 0xf0 (240) is mapped to string 'f0'
115
- const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));
116
- /**
117
- * Convert byte array to hex string. Uses built-in function, when available.
118
- * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'
119
- */
120
- function bytesToHex(bytes) {
121
- abytes(bytes);
122
- // @ts-ignore
123
- if (hasHexBuiltin)
124
- return bytes.toHex();
125
- // pre-caching improves the speed 6x
126
- let hex = '';
127
- for (let i = 0; i < bytes.length; i++) {
128
- hex += hexes[bytes[i]];
129
- }
130
- return hex;
131
- }
132
- // We use optimized technique to convert hex string to byte array
133
- const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
134
- function asciiToBase16(ch) {
135
- if (ch >= asciis._0 && ch <= asciis._9)
136
- return ch - asciis._0; // '2' => 50-48
137
- if (ch >= asciis.A && ch <= asciis.F)
138
- return ch - (asciis.A - 10); // 'B' => 66-(65-10)
139
- if (ch >= asciis.a && ch <= asciis.f)
140
- return ch - (asciis.a - 10); // 'b' => 98-(97-10)
141
- return;
142
- }
143
- /**
144
- * Convert hex string to byte array. Uses built-in function, when available.
145
- * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])
146
- */
147
- function hexToBytes(hex) {
148
- if (typeof hex !== 'string')
149
- throw new Error('hex string expected, got ' + typeof hex);
150
- // @ts-ignore
151
- if (hasHexBuiltin)
152
- return Uint8Array.fromHex(hex);
153
- const hl = hex.length;
154
- const al = hl / 2;
155
- if (hl % 2)
156
- throw new Error('hex string expected, got unpadded hex of length ' + hl);
157
- const array = new Uint8Array(al);
158
- for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
159
- const n1 = asciiToBase16(hex.charCodeAt(hi));
160
- const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
161
- if (n1 === undefined || n2 === undefined) {
162
- const char = hex[hi] + hex[hi + 1];
163
- throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
164
- }
165
- array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163
166
- }
167
- return array;
168
- }
169
- /**
170
- * Converts string to bytes using UTF8 encoding.
171
- * @example utf8ToBytes('abc') // Uint8Array.from([97, 98, 99])
172
- */
173
- function utf8ToBytes(str) {
174
- if (typeof str !== 'string')
175
- throw new Error('string expected');
176
- return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
177
- }
178
- /**
179
- * Normalizes (non-hex) string or Uint8Array to Uint8Array.
180
- * Warning: when Uint8Array is passed, it would NOT get copied.
181
- * Keep in mind for future mutable operations.
182
- */
183
- function toBytes(data) {
184
- if (typeof data === 'string')
185
- data = utf8ToBytes(data);
186
- abytes(data);
187
- return data;
188
- }
189
- /** Copies several Uint8Arrays into one. */
190
- function concatBytes(...arrays) {
191
- let sum = 0;
192
- for (let i = 0; i < arrays.length; i++) {
193
- const a = arrays[i];
194
- abytes(a);
195
- sum += a.length;
196
- }
197
- const res = new Uint8Array(sum);
198
- for (let i = 0, pad = 0; i < arrays.length; i++) {
199
- const a = arrays[i];
200
- res.set(a, pad);
201
- pad += a.length;
202
- }
203
- return res;
204
- }
205
- /** For runtime check if class implements interface */
206
- class Hash {
207
- }
208
- /** Wraps hash function, creating an interface on top of it */
209
- function createHasher(hashCons) {
210
- const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
211
- const tmp = hashCons();
212
- hashC.outputLen = tmp.outputLen;
213
- hashC.blockLen = tmp.blockLen;
214
- hashC.create = () => hashCons();
215
- return hashC;
216
- }
217
- /** Cryptographically secure PRNG. Uses internal OS-level `crypto.getRandomValues`. */
218
- function randomBytes(bytesLength = 32) {
219
- if (crypto && typeof crypto.getRandomValues === 'function') {
220
- return crypto.getRandomValues(new Uint8Array(bytesLength));
221
- }
222
- // Legacy Node.js compatibility
223
- if (crypto && typeof crypto.randomBytes === 'function') {
224
- return Uint8Array.from(crypto.randomBytes(bytesLength));
225
- }
226
- throw new Error('crypto.getRandomValues must be defined');
227
- }
228
-
229
- /**
230
- * Hex, bytes and number utilities.
231
- * @module
232
- */
233
- /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
234
- const _0n$3 = /* @__PURE__ */ BigInt(0);
235
- const _1n$4 = /* @__PURE__ */ BigInt(1);
236
- function abool(title, value) {
237
- if (typeof value !== 'boolean')
238
- throw new Error(title + ' boolean expected, got ' + value);
239
- }
240
- // Used in weierstrass, der
241
- function numberToHexUnpadded(num) {
242
- const hex = num.toString(16);
243
- return hex.length & 1 ? '0' + hex : hex;
244
- }
245
- function hexToNumber(hex) {
246
- if (typeof hex !== 'string')
247
- throw new Error('hex string expected, got ' + typeof hex);
248
- return hex === '' ? _0n$3 : BigInt('0x' + hex); // Big Endian
249
- }
250
- // BE: Big Endian, LE: Little Endian
251
- function bytesToNumberBE(bytes) {
252
- return hexToNumber(bytesToHex(bytes));
253
- }
254
- function bytesToNumberLE(bytes) {
255
- abytes(bytes);
256
- return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
257
- }
258
- function numberToBytesBE(n, len) {
259
- return hexToBytes(n.toString(16).padStart(len * 2, '0'));
260
- }
261
- function numberToBytesLE(n, len) {
262
- return numberToBytesBE(n, len).reverse();
263
- }
264
- /**
265
- * Takes hex string or Uint8Array, converts to Uint8Array.
266
- * Validates output length.
267
- * Will throw error for other types.
268
- * @param title descriptive title for an error e.g. 'private key'
269
- * @param hex hex string or Uint8Array
270
- * @param expectedLength optional, will compare to result array's length
271
- * @returns
272
- */
273
- function ensureBytes(title, hex, expectedLength) {
274
- let res;
275
- if (typeof hex === 'string') {
276
- try {
277
- res = hexToBytes(hex);
278
- }
279
- catch (e) {
280
- throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e);
281
- }
282
- }
283
- else if (isBytes(hex)) {
284
- // Uint8Array.from() instead of hash.slice() because node.js Buffer
285
- // is instance of Uint8Array, and its slice() creates **mutable** copy
286
- res = Uint8Array.from(hex);
287
- }
288
- else {
289
- throw new Error(title + ' must be hex string or Uint8Array');
290
- }
291
- const len = res.length;
292
- if (typeof expectedLength === 'number' && len !== expectedLength)
293
- throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len);
294
- return res;
295
- }
296
- /**
297
- * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
298
- */
299
- // export const utf8ToBytes: typeof utf8ToBytes_ = utf8ToBytes_;
300
- /**
301
- * Converts bytes to string using UTF8 encoding.
302
- * @example bytesToUtf8(Uint8Array.from([97, 98, 99])) // 'abc'
303
- */
304
- // export const bytesToUtf8: typeof bytesToUtf8_ = bytesToUtf8_;
305
- // Is positive bigint
306
- const isPosBig = (n) => typeof n === 'bigint' && _0n$3 <= n;
307
- function inRange(n, min, max) {
308
- return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;
309
- }
310
- /**
311
- * Asserts min <= n < max. NOTE: It's < max and not <= max.
312
- * @example
313
- * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n)
314
- */
315
- function aInRange(title, n, min, max) {
316
- // Why min <= n < max and not a (min < n < max) OR b (min <= n <= max)?
317
- // consider P=256n, min=0n, max=P
318
- // - a for min=0 would require -1: `inRange('x', x, -1n, P)`
319
- // - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)`
320
- // - our way is the cleanest: `inRange('x', x, 0n, P)
321
- if (!inRange(n, min, max))
322
- throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n);
323
- }
324
- // Bit operations
325
- /**
326
- * Calculates amount of bits in a bigint.
327
- * Same as `n.toString(2).length`
328
- * TODO: merge with nLength in modular
329
- */
330
- function bitLen(n) {
331
- let len;
332
- for (len = 0; n > _0n$3; n >>= _1n$4, len += 1)
333
- ;
334
- return len;
335
- }
336
- /**
337
- * Calculate mask for N bits. Not using ** operator with bigints because of old engines.
338
- * Same as BigInt(`0b${Array(i).fill('1').join('')}`)
339
- */
340
- const bitMask = (n) => (_1n$4 << BigInt(n)) - _1n$4;
341
- /**
342
- * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
343
- * @returns function that will call DRBG until 2nd arg returns something meaningful
344
- * @example
345
- * const drbg = createHmacDRBG<Key>(32, 32, hmac);
346
- * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined
347
- */
348
- function createHmacDrbg(hashLen, qByteLen, hmacFn) {
349
- if (typeof hashLen !== 'number' || hashLen < 2)
350
- throw new Error('hashLen must be a number');
351
- if (typeof qByteLen !== 'number' || qByteLen < 2)
352
- throw new Error('qByteLen must be a number');
353
- if (typeof hmacFn !== 'function')
354
- throw new Error('hmacFn must be a function');
355
- // Step B, Step C: set hashLen to 8*ceil(hlen/8)
356
- const u8n = (len) => new Uint8Array(len); // creates Uint8Array
357
- const u8of = (byte) => Uint8Array.of(byte); // another shortcut
358
- let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
359
- let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same
360
- let i = 0; // Iterations counter, will throw when over 1000
361
- const reset = () => {
362
- v.fill(1);
363
- k.fill(0);
364
- i = 0;
365
- };
366
- const h = (...b) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)
367
- const reseed = (seed = u8n(0)) => {
368
- // HMAC-DRBG reseed() function. Steps D-G
369
- k = h(u8of(0x00), seed); // k = hmac(k || v || 0x00 || seed)
370
- v = h(); // v = hmac(k || v)
371
- if (seed.length === 0)
372
- return;
373
- k = h(u8of(0x01), seed); // k = hmac(k || v || 0x01 || seed)
374
- v = h(); // v = hmac(k || v)
375
- };
376
- const gen = () => {
377
- // HMAC-DRBG generate() function
378
- if (i++ >= 1000)
379
- throw new Error('drbg: tried 1000 values');
380
- let len = 0;
381
- const out = [];
382
- while (len < qByteLen) {
383
- v = h();
384
- const sl = v.slice();
385
- out.push(sl);
386
- len += v.length;
387
- }
388
- return concatBytes(...out);
389
- };
390
- const genUntil = (seed, pred) => {
391
- reset();
392
- reseed(seed); // Steps D-G
393
- let res = undefined; // Step H: grind until k is in [1..n-1]
394
- while (!(res = pred(gen())))
395
- reseed();
396
- reset();
397
- return res;
398
- };
399
- return genUntil;
400
- }
401
- function _validateObject(object, fields, optFields = {}) {
402
- if (!object || typeof object !== 'object')
403
- throw new Error('expected valid options object');
404
- function checkField(fieldName, expectedType, isOpt) {
405
- const val = object[fieldName];
406
- if (isOpt && val === undefined)
407
- return;
408
- const current = typeof val;
409
- if (current !== expectedType || val === null)
410
- throw new Error(`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`);
411
- }
412
- Object.entries(fields).forEach(([k, v]) => checkField(k, v, false));
413
- Object.entries(optFields).forEach(([k, v]) => checkField(k, v, true));
414
- }
415
- /**
416
- * Memoizes (caches) computation result.
417
- * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed.
418
- */
419
- function memoized(fn) {
420
- const map = new WeakMap();
421
- return (arg, ...args) => {
422
- const val = map.get(arg);
423
- if (val !== undefined)
424
- return val;
425
- const computed = fn(arg, ...args);
426
- map.set(arg, computed);
427
- return computed;
428
- };
429
- }
430
-
431
- /**
432
- * Utils for modular division and fields.
433
- * Field over 11 is a finite (Galois) field is integer number operations `mod 11`.
434
- * There is no division: it is replaced by modular multiplicative inverse.
435
- * @module
436
- */
437
- /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
438
- // prettier-ignore
439
- const _0n$2 = BigInt(0), _1n$3 = BigInt(1), _2n$2 = /* @__PURE__ */ BigInt(2), _3n$1 = /* @__PURE__ */ BigInt(3);
440
- // prettier-ignore
441
- const _4n$1 = /* @__PURE__ */ BigInt(4), _5n = /* @__PURE__ */ BigInt(5);
442
- const _8n = /* @__PURE__ */ BigInt(8);
443
- // Calculates a modulo b
444
- function mod(a, b) {
445
- const result = a % b;
446
- return result >= _0n$2 ? result : b + result;
447
- }
448
- /** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */
449
- function pow2(x, power, modulo) {
450
- let res = x;
451
- while (power-- > _0n$2) {
452
- res *= res;
453
- res %= modulo;
454
- }
455
- return res;
456
- }
457
- /**
458
- * Inverses number over modulo.
459
- * Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/).
460
- */
461
- function invert(number, modulo) {
462
- if (number === _0n$2)
463
- throw new Error('invert: expected non-zero number');
464
- if (modulo <= _0n$2)
465
- throw new Error('invert: expected positive modulus, got ' + modulo);
466
- // Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower.
467
- let a = mod(number, modulo);
468
- let b = modulo;
469
- // prettier-ignore
470
- let x = _0n$2, u = _1n$3;
471
- while (a !== _0n$2) {
472
- // JIT applies optimization if those two lines follow each other
473
- const q = b / a;
474
- const r = b % a;
475
- const m = x - u * q;
476
- // prettier-ignore
477
- b = a, a = r, x = u, u = m;
478
- }
479
- const gcd = b;
480
- if (gcd !== _1n$3)
481
- throw new Error('invert: does not exist');
482
- return mod(x, modulo);
483
- }
484
- // Not all roots are possible! Example which will throw:
485
- // const NUM =
486
- // n = 72057594037927816n;
487
- // Fp = Field(BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab'));
488
- function sqrt3mod4(Fp, n) {
489
- const p1div4 = (Fp.ORDER + _1n$3) / _4n$1;
490
- const root = Fp.pow(n, p1div4);
491
- // Throw if root^2 != n
492
- if (!Fp.eql(Fp.sqr(root), n))
493
- throw new Error('Cannot find square root');
494
- return root;
495
- }
496
- function sqrt5mod8(Fp, n) {
497
- const p5div8 = (Fp.ORDER - _5n) / _8n;
498
- const n2 = Fp.mul(n, _2n$2);
499
- const v = Fp.pow(n2, p5div8);
500
- const nv = Fp.mul(n, v);
501
- const i = Fp.mul(Fp.mul(nv, _2n$2), v);
502
- const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));
503
- if (!Fp.eql(Fp.sqr(root), n))
504
- throw new Error('Cannot find square root');
505
- return root;
506
- }
507
- // TODO: Commented-out for now. Provide test vectors.
508
- // Tonelli is too slow for extension fields Fp2.
509
- // That means we can't use sqrt (c1, c2...) even for initialization constants.
510
- // if (P % _16n === _9n) return sqrt9mod16;
511
- // // prettier-ignore
512
- // function sqrt9mod16<T>(Fp: IField<T>, n: T, p7div16?: bigint) {
513
- // if (p7div16 === undefined) p7div16 = (Fp.ORDER + BigInt(7)) / _16n;
514
- // const c1 = Fp.sqrt(Fp.neg(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F
515
- // const c2 = Fp.sqrt(c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F
516
- // const c3 = Fp.sqrt(Fp.neg(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F
517
- // const c4 = p7div16; // 4. c4 = (q + 7) / 16 # Integer arithmetic
518
- // let tv1 = Fp.pow(n, c4); // 1. tv1 = x^c4
519
- // let tv2 = Fp.mul(c1, tv1); // 2. tv2 = c1 * tv1
520
- // const tv3 = Fp.mul(c2, tv1); // 3. tv3 = c2 * tv1
521
- // let tv4 = Fp.mul(c3, tv1); // 4. tv4 = c3 * tv1
522
- // const e1 = Fp.eql(Fp.sqr(tv2), n); // 5. e1 = (tv2^2) == x
523
- // const e2 = Fp.eql(Fp.sqr(tv3), n); // 6. e2 = (tv3^2) == x
524
- // tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x
525
- // tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x
526
- // const e3 = Fp.eql(Fp.sqr(tv2), n); // 9. e3 = (tv2^2) == x
527
- // return Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select the sqrt from tv1 and tv2
528
- // }
529
- /**
530
- * Tonelli-Shanks square root search algorithm.
531
- * 1. https://eprint.iacr.org/2012/685.pdf (page 12)
532
- * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks
533
- * @param P field order
534
- * @returns function that takes field Fp (created from P) and number n
535
- */
536
- function tonelliShanks(P) {
537
- // Initialization (precomputation).
538
- // Caching initialization could boost perf by 7%.
539
- if (P < BigInt(3))
540
- throw new Error('sqrt is not defined for small field');
541
- // Factor P - 1 = Q * 2^S, where Q is odd
542
- let Q = P - _1n$3;
543
- let S = 0;
544
- while (Q % _2n$2 === _0n$2) {
545
- Q /= _2n$2;
546
- S++;
547
- }
548
- // Find the first quadratic non-residue Z >= 2
549
- let Z = _2n$2;
550
- const _Fp = Field(P);
551
- while (FpLegendre(_Fp, Z) === 1) {
552
- // Basic primality test for P. After x iterations, chance of
553
- // not finding quadratic non-residue is 2^x, so 2^1000.
554
- if (Z++ > 1000)
555
- throw new Error('Cannot find square root: probably non-prime P');
556
- }
557
- // Fast-path; usually done before Z, but we do "primality test".
558
- if (S === 1)
559
- return sqrt3mod4;
560
- // Slow-path
561
- // TODO: test on Fp2 and others
562
- let cc = _Fp.pow(Z, Q); // c = z^Q
563
- const Q1div2 = (Q + _1n$3) / _2n$2;
564
- return function tonelliSlow(Fp, n) {
565
- if (Fp.is0(n))
566
- return n;
567
- // Check if n is a quadratic residue using Legendre symbol
568
- if (FpLegendre(Fp, n) !== 1)
569
- throw new Error('Cannot find square root');
570
- // Initialize variables for the main loop
571
- let M = S;
572
- let c = Fp.mul(Fp.ONE, cc); // c = z^Q, move cc from field _Fp into field Fp
573
- let t = Fp.pow(n, Q); // t = n^Q, first guess at the fudge factor
574
- let R = Fp.pow(n, Q1div2); // R = n^((Q+1)/2), first guess at the square root
575
- // Main loop
576
- // while t != 1
577
- while (!Fp.eql(t, Fp.ONE)) {
578
- if (Fp.is0(t))
579
- return Fp.ZERO; // if t=0 return R=0
580
- let i = 1;
581
- // Find the smallest i >= 1 such that t^(2^i) ≡ 1 (mod P)
582
- let t_tmp = Fp.sqr(t); // t^(2^1)
583
- while (!Fp.eql(t_tmp, Fp.ONE)) {
584
- i++;
585
- t_tmp = Fp.sqr(t_tmp); // t^(2^2)...
586
- if (i === M)
587
- throw new Error('Cannot find square root');
588
- }
589
- // Calculate the exponent for b: 2^(M - i - 1)
590
- const exponent = _1n$3 << BigInt(M - i - 1); // bigint is important
591
- const b = Fp.pow(c, exponent); // b = 2^(M - i - 1)
592
- // Update variables
593
- M = i;
594
- c = Fp.sqr(b); // c = b^2
595
- t = Fp.mul(t, c); // t = (t * b^2)
596
- R = Fp.mul(R, b); // R = R*b
597
- }
598
- return R;
599
- };
600
- }
601
- /**
602
- * Square root for a finite field. Will try optimized versions first:
603
- *
604
- * 1. P ≡ 3 (mod 4)
605
- * 2. P ≡ 5 (mod 8)
606
- * 3. Tonelli-Shanks algorithm
607
- *
608
- * Different algorithms can give different roots, it is up to user to decide which one they want.
609
- * For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).
610
- */
611
- function FpSqrt(P) {
612
- // P ≡ 3 (mod 4) => √n = n^((P+1)/4)
613
- if (P % _4n$1 === _3n$1)
614
- return sqrt3mod4;
615
- // P ≡ 5 (mod 8) => Atkin algorithm, page 10 of https://eprint.iacr.org/2012/685.pdf
616
- if (P % _8n === _5n)
617
- return sqrt5mod8;
618
- // P ≡ 9 (mod 16) not implemented, see above
619
- // Tonelli-Shanks algorithm
620
- return tonelliShanks(P);
621
- }
622
- // prettier-ignore
623
- const FIELD_FIELDS = [
624
- 'create', 'isValid', 'is0', 'neg', 'inv', 'sqrt', 'sqr',
625
- 'eql', 'add', 'sub', 'mul', 'pow', 'div',
626
- 'addN', 'subN', 'mulN', 'sqrN'
627
- ];
628
- function validateField(field) {
629
- const initial = {
630
- ORDER: 'bigint',
631
- MASK: 'bigint',
632
- BYTES: 'number',
633
- BITS: 'number',
634
- };
635
- const opts = FIELD_FIELDS.reduce((map, val) => {
636
- map[val] = 'function';
637
- return map;
638
- }, initial);
639
- _validateObject(field, opts);
640
- // const max = 16384;
641
- // if (field.BYTES < 1 || field.BYTES > max) throw new Error('invalid field');
642
- // if (field.BITS < 1 || field.BITS > 8 * max) throw new Error('invalid field');
643
- return field;
644
- }
645
- // Generic field functions
646
- /**
647
- * Same as `pow` but for Fp: non-constant-time.
648
- * Unsafe in some contexts: uses ladder, so can expose bigint bits.
649
- */
650
- function FpPow(Fp, num, power) {
651
- if (power < _0n$2)
652
- throw new Error('invalid exponent, negatives unsupported');
653
- if (power === _0n$2)
654
- return Fp.ONE;
655
- if (power === _1n$3)
656
- return num;
657
- let p = Fp.ONE;
658
- let d = num;
659
- while (power > _0n$2) {
660
- if (power & _1n$3)
661
- p = Fp.mul(p, d);
662
- d = Fp.sqr(d);
663
- power >>= _1n$3;
664
- }
665
- return p;
666
- }
667
- /**
668
- * Efficiently invert an array of Field elements.
669
- * Exception-free. Will return `undefined` for 0 elements.
670
- * @param passZero map 0 to 0 (instead of undefined)
671
- */
672
- function FpInvertBatch(Fp, nums, passZero = false) {
673
- const inverted = new Array(nums.length).fill(passZero ? Fp.ZERO : undefined);
674
- // Walk from first to last, multiply them by each other MOD p
675
- const multipliedAcc = nums.reduce((acc, num, i) => {
676
- if (Fp.is0(num))
677
- return acc;
678
- inverted[i] = acc;
679
- return Fp.mul(acc, num);
680
- }, Fp.ONE);
681
- // Invert last element
682
- const invertedAcc = Fp.inv(multipliedAcc);
683
- // Walk from last to first, multiply them by inverted each other MOD p
684
- nums.reduceRight((acc, num, i) => {
685
- if (Fp.is0(num))
686
- return acc;
687
- inverted[i] = Fp.mul(acc, inverted[i]);
688
- return Fp.mul(acc, num);
689
- }, invertedAcc);
690
- return inverted;
691
- }
692
- /**
693
- * Legendre symbol.
694
- * Legendre constant is used to calculate Legendre symbol (a | p)
695
- * which denotes the value of a^((p-1)/2) (mod p).
696
- *
697
- * * (a | p) ≡ 1 if a is a square (mod p), quadratic residue
698
- * * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue
699
- * * (a | p) ≡ 0 if a ≡ 0 (mod p)
700
- */
701
- function FpLegendre(Fp, n) {
702
- // We can use 3rd argument as optional cache of this value
703
- // but seems unneeded for now. The operation is very fast.
704
- const p1mod2 = (Fp.ORDER - _1n$3) / _2n$2;
705
- const powered = Fp.pow(n, p1mod2);
706
- const yes = Fp.eql(powered, Fp.ONE);
707
- const zero = Fp.eql(powered, Fp.ZERO);
708
- const no = Fp.eql(powered, Fp.neg(Fp.ONE));
709
- if (!yes && !zero && !no)
710
- throw new Error('invalid Legendre symbol result');
711
- return yes ? 1 : zero ? 0 : -1;
712
- }
713
- // CURVE.n lengths
714
- function nLength(n, nBitLength) {
715
- // Bit size, byte size of CURVE.n
716
- if (nBitLength !== undefined)
717
- anumber(nBitLength);
718
- const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length;
719
- const nByteLength = Math.ceil(_nBitLength / 8);
720
- return { nBitLength: _nBitLength, nByteLength };
721
- }
722
- /**
723
- * Creates a finite field. Major performance optimizations:
724
- * * 1. Denormalized operations like mulN instead of mul.
725
- * * 2. Identical object shape: never add or remove keys.
726
- * * 3. `Object.freeze`.
727
- * Fragile: always run a benchmark on a change.
728
- * Security note: operations don't check 'isValid' for all elements for performance reasons,
729
- * it is caller responsibility to check this.
730
- * This is low-level code, please make sure you know what you're doing.
731
- *
732
- * Note about field properties:
733
- * * CHARACTERISTIC p = prime number, number of elements in main subgroup.
734
- * * ORDER q = similar to cofactor in curves, may be composite `q = p^m`.
735
- *
736
- * @param ORDER field order, probably prime, or could be composite
737
- * @param bitLen how many bits the field consumes
738
- * @param isLE (default: false) if encoding / decoding should be in little-endian
739
- * @param redef optional faster redefinitions of sqrt and other methods
740
- */
741
- function Field(ORDER, bitLenOrOpts, isLE = false, opts = {}) {
742
- if (ORDER <= _0n$2)
743
- throw new Error('invalid field: expected ORDER > 0, got ' + ORDER);
744
- let _nbitLength = undefined;
745
- let _sqrt = undefined;
746
- if (typeof bitLenOrOpts === 'object' && bitLenOrOpts != null) {
747
- if (opts.sqrt || isLE)
748
- throw new Error('cannot specify opts in two arguments');
749
- const _opts = bitLenOrOpts;
750
- if (_opts.BITS)
751
- _nbitLength = _opts.BITS;
752
- if (_opts.sqrt)
753
- _sqrt = _opts.sqrt;
754
- if (typeof _opts.isLE === 'boolean')
755
- isLE = _opts.isLE;
756
- }
757
- else {
758
- if (typeof bitLenOrOpts === 'number')
759
- _nbitLength = bitLenOrOpts;
760
- if (opts.sqrt)
761
- _sqrt = opts.sqrt;
762
- }
763
- const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, _nbitLength);
764
- if (BYTES > 2048)
765
- throw new Error('invalid field: expected ORDER of <= 2048 bytes');
766
- let sqrtP; // cached sqrtP
767
- const f = Object.freeze({
768
- ORDER,
769
- isLE,
770
- BITS,
771
- BYTES,
772
- MASK: bitMask(BITS),
773
- ZERO: _0n$2,
774
- ONE: _1n$3,
775
- create: (num) => mod(num, ORDER),
776
- isValid: (num) => {
777
- if (typeof num !== 'bigint')
778
- throw new Error('invalid field element: expected bigint, got ' + typeof num);
779
- return _0n$2 <= num && num < ORDER; // 0 is valid element, but it's not invertible
780
- },
781
- is0: (num) => num === _0n$2,
782
- // is valid and invertible
783
- isValidNot0: (num) => !f.is0(num) && f.isValid(num),
784
- isOdd: (num) => (num & _1n$3) === _1n$3,
785
- neg: (num) => mod(-num, ORDER),
786
- eql: (lhs, rhs) => lhs === rhs,
787
- sqr: (num) => mod(num * num, ORDER),
788
- add: (lhs, rhs) => mod(lhs + rhs, ORDER),
789
- sub: (lhs, rhs) => mod(lhs - rhs, ORDER),
790
- mul: (lhs, rhs) => mod(lhs * rhs, ORDER),
791
- pow: (num, power) => FpPow(f, num, power),
792
- div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),
793
- // Same as above, but doesn't normalize
794
- sqrN: (num) => num * num,
795
- addN: (lhs, rhs) => lhs + rhs,
796
- subN: (lhs, rhs) => lhs - rhs,
797
- mulN: (lhs, rhs) => lhs * rhs,
798
- inv: (num) => invert(num, ORDER),
799
- sqrt: _sqrt ||
800
- ((n) => {
801
- if (!sqrtP)
802
- sqrtP = FpSqrt(ORDER);
803
- return sqrtP(f, n);
804
- }),
805
- toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)),
806
- fromBytes: (bytes) => {
807
- if (bytes.length !== BYTES)
808
- throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length);
809
- return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
810
- },
811
- // TODO: we don't need it here, move out to separate fn
812
- invertBatch: (lst) => FpInvertBatch(f, lst),
813
- // We can't move this out because Fp6, Fp12 implement it
814
- // and it's unclear what to return in there.
815
- cmov: (a, b, c) => (c ? b : a),
816
- });
817
- return Object.freeze(f);
818
- }
819
- /**
820
- * Returns total number of bytes consumed by the field element.
821
- * For example, 32 bytes for usual 256-bit weierstrass curve.
822
- * @param fieldOrder number of field elements, usually CURVE.n
823
- * @returns byte length of field
824
- */
825
- function getFieldBytesLength(fieldOrder) {
826
- if (typeof fieldOrder !== 'bigint')
827
- throw new Error('field order must be bigint');
828
- const bitLength = fieldOrder.toString(2).length;
829
- return Math.ceil(bitLength / 8);
830
- }
831
- /**
832
- * Returns minimal amount of bytes that can be safely reduced
833
- * by field order.
834
- * Should be 2^-128 for 128-bit curve such as P256.
835
- * @param fieldOrder number of field elements, usually CURVE.n
836
- * @returns byte length of target hash
837
- */
838
- function getMinHashLength(fieldOrder) {
839
- const length = getFieldBytesLength(fieldOrder);
840
- return length + Math.ceil(length / 2);
841
- }
842
- /**
843
- * "Constant-time" private key generation utility.
844
- * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF
845
- * and convert them into private scalar, with the modulo bias being negligible.
846
- * Needs at least 48 bytes of input for 32-byte private key.
847
- * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
848
- * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final
849
- * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5
850
- * @param hash hash output from SHA3 or a similar function
851
- * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n)
852
- * @param isLE interpret hash bytes as LE num
853
- * @returns valid private scalar
854
- */
855
- function mapHashToField(key, fieldOrder, isLE = false) {
856
- const len = key.length;
857
- const fieldLen = getFieldBytesLength(fieldOrder);
858
- const minLen = getMinHashLength(fieldOrder);
859
- // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings.
860
- if (len < 16 || len < minLen || len > 1024)
861
- throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len);
862
- const num = isLE ? bytesToNumberLE(key) : bytesToNumberBE(key);
863
- // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0
864
- const reduced = mod(num, fieldOrder - _1n$3) + _1n$3;
865
- return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);
866
- }
867
-
868
- /**
869
- * Internal Merkle-Damgard hash utils.
870
- * @module
871
- */
872
- /** Polyfill for Safari 14. https://caniuse.com/mdn-javascript_builtins_dataview_setbiguint64 */
873
- function setBigUint64(view, byteOffset, value, isLE) {
874
- if (typeof view.setBigUint64 === 'function')
875
- return view.setBigUint64(byteOffset, value, isLE);
876
- const _32n = BigInt(32);
877
- const _u32_max = BigInt(0xffffffff);
878
- const wh = Number((value >> _32n) & _u32_max);
879
- const wl = Number(value & _u32_max);
880
- const h = isLE ? 4 : 0;
881
- const l = isLE ? 0 : 4;
882
- view.setUint32(byteOffset + h, wh, isLE);
883
- view.setUint32(byteOffset + l, wl, isLE);
884
- }
885
- /** Choice: a ? b : c */
886
- function Chi(a, b, c) {
887
- return (a & b) ^ (~a & c);
888
- }
889
- /** Majority function, true if any two inputs is true. */
890
- function Maj(a, b, c) {
891
- return (a & b) ^ (a & c) ^ (b & c);
892
- }
893
- /**
894
- * Merkle-Damgard hash construction base class.
895
- * Could be used to create MD5, RIPEMD, SHA1, SHA2.
896
- */
897
- class HashMD extends Hash {
898
- constructor(blockLen, outputLen, padOffset, isLE) {
899
- super();
900
- this.finished = false;
901
- this.length = 0;
902
- this.pos = 0;
903
- this.destroyed = false;
904
- this.blockLen = blockLen;
905
- this.outputLen = outputLen;
906
- this.padOffset = padOffset;
907
- this.isLE = isLE;
908
- this.buffer = new Uint8Array(blockLen);
909
- this.view = createView(this.buffer);
910
- }
911
- update(data) {
912
- aexists(this);
913
- data = toBytes(data);
914
- abytes(data);
915
- const { view, buffer, blockLen } = this;
916
- const len = data.length;
917
- for (let pos = 0; pos < len;) {
918
- const take = Math.min(blockLen - this.pos, len - pos);
919
- // Fast path: we have at least one block in input, cast it to view and process
920
- if (take === blockLen) {
921
- const dataView = createView(data);
922
- for (; blockLen <= len - pos; pos += blockLen)
923
- this.process(dataView, pos);
924
- continue;
925
- }
926
- buffer.set(data.subarray(pos, pos + take), this.pos);
927
- this.pos += take;
928
- pos += take;
929
- if (this.pos === blockLen) {
930
- this.process(view, 0);
931
- this.pos = 0;
932
- }
933
- }
934
- this.length += data.length;
935
- this.roundClean();
936
- return this;
937
- }
938
- digestInto(out) {
939
- aexists(this);
940
- aoutput(out, this);
941
- this.finished = true;
942
- // Padding
943
- // We can avoid allocation of buffer for padding completely if it
944
- // was previously not allocated here. But it won't change performance.
945
- const { buffer, view, blockLen, isLE } = this;
946
- let { pos } = this;
947
- // append the bit '1' to the message
948
- buffer[pos++] = 0b10000000;
949
- clean(this.buffer.subarray(pos));
950
- // we have less than padOffset left in buffer, so we cannot put length in
951
- // current block, need process it and pad again
952
- if (this.padOffset > blockLen - pos) {
953
- this.process(view, 0);
954
- pos = 0;
955
- }
956
- // Pad until full block byte with zeros
957
- for (let i = pos; i < blockLen; i++)
958
- buffer[i] = 0;
959
- // Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that
960
- // You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.
961
- // So we just write lowest 64 bits of that value.
962
- setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
963
- this.process(view, 0);
964
- const oview = createView(out);
965
- const len = this.outputLen;
966
- // NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT
967
- if (len % 4)
968
- throw new Error('_sha2: outputLen should be aligned to 32bit');
969
- const outLen = len / 4;
970
- const state = this.get();
971
- if (outLen > state.length)
972
- throw new Error('_sha2: outputLen bigger than state');
973
- for (let i = 0; i < outLen; i++)
974
- oview.setUint32(4 * i, state[i], isLE);
975
- }
976
- digest() {
977
- const { buffer, outputLen } = this;
978
- this.digestInto(buffer);
979
- const res = buffer.slice(0, outputLen);
980
- this.destroy();
981
- return res;
982
- }
983
- _cloneInto(to) {
984
- to || (to = new this.constructor());
985
- to.set(...this.get());
986
- const { blockLen, buffer, length, finished, destroyed, pos } = this;
987
- to.destroyed = destroyed;
988
- to.finished = finished;
989
- to.length = length;
990
- to.pos = pos;
991
- if (length % blockLen)
992
- to.buffer.set(buffer);
993
- return to;
994
- }
995
- clone() {
996
- return this._cloneInto();
997
- }
998
- }
999
- /**
1000
- * Initial SHA-2 state: fractional parts of square roots of first 16 primes 2..53.
1001
- * Check out `test/misc/sha2-gen-iv.js` for recomputation guide.
1002
- */
1003
- /** Initial SHA256 state. Bits 0..32 of frac part of sqrt of primes 2..19 */
1004
- const SHA256_IV = /* @__PURE__ */ Uint32Array.from([
1005
- 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
1006
- ]);
1007
- /** Initial SHA512 state. Bits 0..64 of frac part of sqrt of primes 2..19 */
1008
- const SHA512_IV = /* @__PURE__ */ Uint32Array.from([
1009
- 0x6a09e667, 0xf3bcc908, 0xbb67ae85, 0x84caa73b, 0x3c6ef372, 0xfe94f82b, 0xa54ff53a, 0x5f1d36f1,
1010
- 0x510e527f, 0xade682d1, 0x9b05688c, 0x2b3e6c1f, 0x1f83d9ab, 0xfb41bd6b, 0x5be0cd19, 0x137e2179,
1011
- ]);
1012
-
1013
- /**
1014
- * Internal helpers for u64. BigUint64Array is too slow as per 2025, so we implement it using Uint32Array.
1015
- * @todo re-check https://issues.chromium.org/issues/42212588
1016
- * @module
1017
- */
1018
- const U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);
1019
- const _32n = /* @__PURE__ */ BigInt(32);
1020
- function fromBig(n, le = false) {
1021
- if (le)
1022
- return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };
1023
- return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };
1024
- }
1025
- function split(lst, le = false) {
1026
- const len = lst.length;
1027
- let Ah = new Uint32Array(len);
1028
- let Al = new Uint32Array(len);
1029
- for (let i = 0; i < len; i++) {
1030
- const { h, l } = fromBig(lst[i], le);
1031
- [Ah[i], Al[i]] = [h, l];
1032
- }
1033
- return [Ah, Al];
1034
- }
1035
- // for Shift in [0, 32)
1036
- const shrSH = (h, _l, s) => h >>> s;
1037
- const shrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);
1038
- // Right rotate for Shift in [1, 32)
1039
- const rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s));
1040
- const rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);
1041
- // Right rotate for Shift in (32, 64), NOTE: 32 is special case.
1042
- const rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32));
1043
- const rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s));
1044
- // JS uses 32-bit signed integers for bitwise operations which means we cannot
1045
- // simple take carry out of low bit sum by shift, we need to use division.
1046
- function add(Ah, Al, Bh, Bl) {
1047
- const l = (Al >>> 0) + (Bl >>> 0);
1048
- return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 };
1049
- }
1050
- // Addition with more than 2 elements
1051
- const add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);
1052
- const add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0;
1053
- const add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);
1054
- const add4H = (low, Ah, Bh, Ch, Dh) => (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0;
1055
- const add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);
1056
- const add5H = (low, Ah, Bh, Ch, Dh, Eh) => (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0;
1057
-
1058
- /**
1059
- * SHA2 hash function. A.k.a. sha256, sha384, sha512, sha512_224, sha512_256.
1060
- * SHA256 is the fastest hash implementable in JS, even faster than Blake3.
1061
- * Check out [RFC 4634](https://datatracker.ietf.org/doc/html/rfc4634) and
1062
- * [FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf).
1063
- * @module
1064
- */
1065
- /**
1066
- * Round constants:
1067
- * First 32 bits of fractional parts of the cube roots of the first 64 primes 2..311)
1068
- */
1069
- // prettier-ignore
1070
- const SHA256_K = /* @__PURE__ */ Uint32Array.from([
1071
- 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
1072
- 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
1073
- 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
1074
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
1075
- 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
1076
- 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
1077
- 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
1078
- 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
1079
- ]);
1080
- /** Reusable temporary buffer. "W" comes straight from spec. */
1081
- const SHA256_W = /* @__PURE__ */ new Uint32Array(64);
1082
- class SHA256 extends HashMD {
1083
- constructor(outputLen = 32) {
1084
- super(64, outputLen, 8, false);
1085
- // We cannot use array here since array allows indexing by variable
1086
- // which means optimizer/compiler cannot use registers.
1087
- this.A = SHA256_IV[0] | 0;
1088
- this.B = SHA256_IV[1] | 0;
1089
- this.C = SHA256_IV[2] | 0;
1090
- this.D = SHA256_IV[3] | 0;
1091
- this.E = SHA256_IV[4] | 0;
1092
- this.F = SHA256_IV[5] | 0;
1093
- this.G = SHA256_IV[6] | 0;
1094
- this.H = SHA256_IV[7] | 0;
1095
- }
1096
- get() {
1097
- const { A, B, C, D, E, F, G, H } = this;
1098
- return [A, B, C, D, E, F, G, H];
1099
- }
1100
- // prettier-ignore
1101
- set(A, B, C, D, E, F, G, H) {
1102
- this.A = A | 0;
1103
- this.B = B | 0;
1104
- this.C = C | 0;
1105
- this.D = D | 0;
1106
- this.E = E | 0;
1107
- this.F = F | 0;
1108
- this.G = G | 0;
1109
- this.H = H | 0;
1110
- }
1111
- process(view, offset) {
1112
- // Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array
1113
- for (let i = 0; i < 16; i++, offset += 4)
1114
- SHA256_W[i] = view.getUint32(offset, false);
1115
- for (let i = 16; i < 64; i++) {
1116
- const W15 = SHA256_W[i - 15];
1117
- const W2 = SHA256_W[i - 2];
1118
- const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ (W15 >>> 3);
1119
- const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ (W2 >>> 10);
1120
- SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0;
1121
- }
1122
- // Compression function main loop, 64 rounds
1123
- let { A, B, C, D, E, F, G, H } = this;
1124
- for (let i = 0; i < 64; i++) {
1125
- const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
1126
- const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;
1127
- const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
1128
- const T2 = (sigma0 + Maj(A, B, C)) | 0;
1129
- H = G;
1130
- G = F;
1131
- F = E;
1132
- E = (D + T1) | 0;
1133
- D = C;
1134
- C = B;
1135
- B = A;
1136
- A = (T1 + T2) | 0;
1137
- }
1138
- // Add the compressed chunk to the current hash value
1139
- A = (A + this.A) | 0;
1140
- B = (B + this.B) | 0;
1141
- C = (C + this.C) | 0;
1142
- D = (D + this.D) | 0;
1143
- E = (E + this.E) | 0;
1144
- F = (F + this.F) | 0;
1145
- G = (G + this.G) | 0;
1146
- H = (H + this.H) | 0;
1147
- this.set(A, B, C, D, E, F, G, H);
1148
- }
1149
- roundClean() {
1150
- clean(SHA256_W);
1151
- }
1152
- destroy() {
1153
- this.set(0, 0, 0, 0, 0, 0, 0, 0);
1154
- clean(this.buffer);
1155
- }
1156
- }
1157
- // SHA2-512 is slower than sha256 in js because u64 operations are slow.
1158
- // Round contants
1159
- // First 32 bits of the fractional parts of the cube roots of the first 80 primes 2..409
1160
- // prettier-ignore
1161
- const K512 = /* @__PURE__ */ (() => split([
1162
- '0x428a2f98d728ae22', '0x7137449123ef65cd', '0xb5c0fbcfec4d3b2f', '0xe9b5dba58189dbbc',
1163
- '0x3956c25bf348b538', '0x59f111f1b605d019', '0x923f82a4af194f9b', '0xab1c5ed5da6d8118',
1164
- '0xd807aa98a3030242', '0x12835b0145706fbe', '0x243185be4ee4b28c', '0x550c7dc3d5ffb4e2',
1165
- '0x72be5d74f27b896f', '0x80deb1fe3b1696b1', '0x9bdc06a725c71235', '0xc19bf174cf692694',
1166
- '0xe49b69c19ef14ad2', '0xefbe4786384f25e3', '0x0fc19dc68b8cd5b5', '0x240ca1cc77ac9c65',
1167
- '0x2de92c6f592b0275', '0x4a7484aa6ea6e483', '0x5cb0a9dcbd41fbd4', '0x76f988da831153b5',
1168
- '0x983e5152ee66dfab', '0xa831c66d2db43210', '0xb00327c898fb213f', '0xbf597fc7beef0ee4',
1169
- '0xc6e00bf33da88fc2', '0xd5a79147930aa725', '0x06ca6351e003826f', '0x142929670a0e6e70',
1170
- '0x27b70a8546d22ffc', '0x2e1b21385c26c926', '0x4d2c6dfc5ac42aed', '0x53380d139d95b3df',
1171
- '0x650a73548baf63de', '0x766a0abb3c77b2a8', '0x81c2c92e47edaee6', '0x92722c851482353b',
1172
- '0xa2bfe8a14cf10364', '0xa81a664bbc423001', '0xc24b8b70d0f89791', '0xc76c51a30654be30',
1173
- '0xd192e819d6ef5218', '0xd69906245565a910', '0xf40e35855771202a', '0x106aa07032bbd1b8',
1174
- '0x19a4c116b8d2d0c8', '0x1e376c085141ab53', '0x2748774cdf8eeb99', '0x34b0bcb5e19b48a8',
1175
- '0x391c0cb3c5c95a63', '0x4ed8aa4ae3418acb', '0x5b9cca4f7763e373', '0x682e6ff3d6b2b8a3',
1176
- '0x748f82ee5defb2fc', '0x78a5636f43172f60', '0x84c87814a1f0ab72', '0x8cc702081a6439ec',
1177
- '0x90befffa23631e28', '0xa4506cebde82bde9', '0xbef9a3f7b2c67915', '0xc67178f2e372532b',
1178
- '0xca273eceea26619c', '0xd186b8c721c0c207', '0xeada7dd6cde0eb1e', '0xf57d4f7fee6ed178',
1179
- '0x06f067aa72176fba', '0x0a637dc5a2c898a6', '0x113f9804bef90dae', '0x1b710b35131c471b',
1180
- '0x28db77f523047d84', '0x32caab7b40c72493', '0x3c9ebe0a15c9bebc', '0x431d67c49c100d4c',
1181
- '0x4cc5d4becb3e42b6', '0x597f299cfc657e2a', '0x5fcb6fab3ad6faec', '0x6c44198c4a475817'
1182
- ].map(n => BigInt(n))))();
1183
- const SHA512_Kh = /* @__PURE__ */ (() => K512[0])();
1184
- const SHA512_Kl = /* @__PURE__ */ (() => K512[1])();
1185
- // Reusable temporary buffers
1186
- const SHA512_W_H = /* @__PURE__ */ new Uint32Array(80);
1187
- const SHA512_W_L = /* @__PURE__ */ new Uint32Array(80);
1188
- class SHA512 extends HashMD {
1189
- constructor(outputLen = 64) {
1190
- super(128, outputLen, 16, false);
1191
- // We cannot use array here since array allows indexing by variable
1192
- // which means optimizer/compiler cannot use registers.
1193
- // h -- high 32 bits, l -- low 32 bits
1194
- this.Ah = SHA512_IV[0] | 0;
1195
- this.Al = SHA512_IV[1] | 0;
1196
- this.Bh = SHA512_IV[2] | 0;
1197
- this.Bl = SHA512_IV[3] | 0;
1198
- this.Ch = SHA512_IV[4] | 0;
1199
- this.Cl = SHA512_IV[5] | 0;
1200
- this.Dh = SHA512_IV[6] | 0;
1201
- this.Dl = SHA512_IV[7] | 0;
1202
- this.Eh = SHA512_IV[8] | 0;
1203
- this.El = SHA512_IV[9] | 0;
1204
- this.Fh = SHA512_IV[10] | 0;
1205
- this.Fl = SHA512_IV[11] | 0;
1206
- this.Gh = SHA512_IV[12] | 0;
1207
- this.Gl = SHA512_IV[13] | 0;
1208
- this.Hh = SHA512_IV[14] | 0;
1209
- this.Hl = SHA512_IV[15] | 0;
1210
- }
1211
- // prettier-ignore
1212
- get() {
1213
- const { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;
1214
- return [Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl];
1215
- }
1216
- // prettier-ignore
1217
- set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl) {
1218
- this.Ah = Ah | 0;
1219
- this.Al = Al | 0;
1220
- this.Bh = Bh | 0;
1221
- this.Bl = Bl | 0;
1222
- this.Ch = Ch | 0;
1223
- this.Cl = Cl | 0;
1224
- this.Dh = Dh | 0;
1225
- this.Dl = Dl | 0;
1226
- this.Eh = Eh | 0;
1227
- this.El = El | 0;
1228
- this.Fh = Fh | 0;
1229
- this.Fl = Fl | 0;
1230
- this.Gh = Gh | 0;
1231
- this.Gl = Gl | 0;
1232
- this.Hh = Hh | 0;
1233
- this.Hl = Hl | 0;
1234
- }
1235
- process(view, offset) {
1236
- // Extend the first 16 words into the remaining 64 words w[16..79] of the message schedule array
1237
- for (let i = 0; i < 16; i++, offset += 4) {
1238
- SHA512_W_H[i] = view.getUint32(offset);
1239
- SHA512_W_L[i] = view.getUint32((offset += 4));
1240
- }
1241
- for (let i = 16; i < 80; i++) {
1242
- // s0 := (w[i-15] rightrotate 1) xor (w[i-15] rightrotate 8) xor (w[i-15] rightshift 7)
1243
- const W15h = SHA512_W_H[i - 15] | 0;
1244
- const W15l = SHA512_W_L[i - 15] | 0;
1245
- const s0h = rotrSH(W15h, W15l, 1) ^ rotrSH(W15h, W15l, 8) ^ shrSH(W15h, W15l, 7);
1246
- const s0l = rotrSL(W15h, W15l, 1) ^ rotrSL(W15h, W15l, 8) ^ shrSL(W15h, W15l, 7);
1247
- // s1 := (w[i-2] rightrotate 19) xor (w[i-2] rightrotate 61) xor (w[i-2] rightshift 6)
1248
- const W2h = SHA512_W_H[i - 2] | 0;
1249
- const W2l = SHA512_W_L[i - 2] | 0;
1250
- const s1h = rotrSH(W2h, W2l, 19) ^ rotrBH(W2h, W2l, 61) ^ shrSH(W2h, W2l, 6);
1251
- const s1l = rotrSL(W2h, W2l, 19) ^ rotrBL(W2h, W2l, 61) ^ shrSL(W2h, W2l, 6);
1252
- // SHA256_W[i] = s0 + s1 + SHA256_W[i - 7] + SHA256_W[i - 16];
1253
- const SUMl = add4L(s0l, s1l, SHA512_W_L[i - 7], SHA512_W_L[i - 16]);
1254
- const SUMh = add4H(SUMl, s0h, s1h, SHA512_W_H[i - 7], SHA512_W_H[i - 16]);
1255
- SHA512_W_H[i] = SUMh | 0;
1256
- SHA512_W_L[i] = SUMl | 0;
1257
- }
1258
- let { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;
1259
- // Compression function main loop, 80 rounds
1260
- for (let i = 0; i < 80; i++) {
1261
- // S1 := (e rightrotate 14) xor (e rightrotate 18) xor (e rightrotate 41)
1262
- const sigma1h = rotrSH(Eh, El, 14) ^ rotrSH(Eh, El, 18) ^ rotrBH(Eh, El, 41);
1263
- const sigma1l = rotrSL(Eh, El, 14) ^ rotrSL(Eh, El, 18) ^ rotrBL(Eh, El, 41);
1264
- //const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;
1265
- const CHIh = (Eh & Fh) ^ (~Eh & Gh);
1266
- const CHIl = (El & Fl) ^ (~El & Gl);
1267
- // T1 = H + sigma1 + Chi(E, F, G) + SHA512_K[i] + SHA512_W[i]
1268
- // prettier-ignore
1269
- const T1ll = add5L(Hl, sigma1l, CHIl, SHA512_Kl[i], SHA512_W_L[i]);
1270
- const T1h = add5H(T1ll, Hh, sigma1h, CHIh, SHA512_Kh[i], SHA512_W_H[i]);
1271
- const T1l = T1ll | 0;
1272
- // S0 := (a rightrotate 28) xor (a rightrotate 34) xor (a rightrotate 39)
1273
- const sigma0h = rotrSH(Ah, Al, 28) ^ rotrBH(Ah, Al, 34) ^ rotrBH(Ah, Al, 39);
1274
- const sigma0l = rotrSL(Ah, Al, 28) ^ rotrBL(Ah, Al, 34) ^ rotrBL(Ah, Al, 39);
1275
- const MAJh = (Ah & Bh) ^ (Ah & Ch) ^ (Bh & Ch);
1276
- const MAJl = (Al & Bl) ^ (Al & Cl) ^ (Bl & Cl);
1277
- Hh = Gh | 0;
1278
- Hl = Gl | 0;
1279
- Gh = Fh | 0;
1280
- Gl = Fl | 0;
1281
- Fh = Eh | 0;
1282
- Fl = El | 0;
1283
- ({ h: Eh, l: El } = add(Dh | 0, Dl | 0, T1h | 0, T1l | 0));
1284
- Dh = Ch | 0;
1285
- Dl = Cl | 0;
1286
- Ch = Bh | 0;
1287
- Cl = Bl | 0;
1288
- Bh = Ah | 0;
1289
- Bl = Al | 0;
1290
- const All = add3L(T1l, sigma0l, MAJl);
1291
- Ah = add3H(All, T1h, sigma0h, MAJh);
1292
- Al = All | 0;
1293
- }
1294
- // Add the compressed chunk to the current hash value
1295
- ({ h: Ah, l: Al } = add(this.Ah | 0, this.Al | 0, Ah | 0, Al | 0));
1296
- ({ h: Bh, l: Bl } = add(this.Bh | 0, this.Bl | 0, Bh | 0, Bl | 0));
1297
- ({ h: Ch, l: Cl } = add(this.Ch | 0, this.Cl | 0, Ch | 0, Cl | 0));
1298
- ({ h: Dh, l: Dl } = add(this.Dh | 0, this.Dl | 0, Dh | 0, Dl | 0));
1299
- ({ h: Eh, l: El } = add(this.Eh | 0, this.El | 0, Eh | 0, El | 0));
1300
- ({ h: Fh, l: Fl } = add(this.Fh | 0, this.Fl | 0, Fh | 0, Fl | 0));
1301
- ({ h: Gh, l: Gl } = add(this.Gh | 0, this.Gl | 0, Gh | 0, Gl | 0));
1302
- ({ h: Hh, l: Hl } = add(this.Hh | 0, this.Hl | 0, Hh | 0, Hl | 0));
1303
- this.set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl);
1304
- }
1305
- roundClean() {
1306
- clean(SHA512_W_H, SHA512_W_L);
1307
- }
1308
- destroy() {
1309
- clean(this.buffer);
1310
- this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1311
- }
1312
- }
1313
- /**
1314
- * SHA2-256 hash function from RFC 4634.
1315
- *
1316
- * It is the fastest JS hash, even faster than Blake3.
1317
- * To break sha256 using birthday attack, attackers need to try 2^128 hashes.
1318
- * BTC network is doing 2^70 hashes/sec (2^95 hashes/year) as per 2025.
1319
- */
1320
- const sha256 = /* @__PURE__ */ createHasher(() => new SHA256());
1321
- /** SHA2-512 hash function from RFC 4634. */
1322
- const sha512 = /* @__PURE__ */ createHasher(() => new SHA512());
1323
-
1324
- /**
1325
- * HMAC: RFC2104 message authentication code.
1326
- * @module
1327
- */
1328
- class HMAC extends Hash {
1329
- constructor(hash, _key) {
1330
- super();
1331
- this.finished = false;
1332
- this.destroyed = false;
1333
- ahash(hash);
1334
- const key = toBytes(_key);
1335
- this.iHash = hash.create();
1336
- if (typeof this.iHash.update !== 'function')
1337
- throw new Error('Expected instance of class which extends utils.Hash');
1338
- this.blockLen = this.iHash.blockLen;
1339
- this.outputLen = this.iHash.outputLen;
1340
- const blockLen = this.blockLen;
1341
- const pad = new Uint8Array(blockLen);
1342
- // blockLen can be bigger than outputLen
1343
- pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
1344
- for (let i = 0; i < pad.length; i++)
1345
- pad[i] ^= 0x36;
1346
- this.iHash.update(pad);
1347
- // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone
1348
- this.oHash = hash.create();
1349
- // Undo internal XOR && apply outer XOR
1350
- for (let i = 0; i < pad.length; i++)
1351
- pad[i] ^= 0x36 ^ 0x5c;
1352
- this.oHash.update(pad);
1353
- clean(pad);
1354
- }
1355
- update(buf) {
1356
- aexists(this);
1357
- this.iHash.update(buf);
1358
- return this;
1359
- }
1360
- digestInto(out) {
1361
- aexists(this);
1362
- abytes(out, this.outputLen);
1363
- this.finished = true;
1364
- this.iHash.digestInto(out);
1365
- this.oHash.update(out);
1366
- this.oHash.digestInto(out);
1367
- this.destroy();
1368
- }
1369
- digest() {
1370
- const out = new Uint8Array(this.oHash.outputLen);
1371
- this.digestInto(out);
1372
- return out;
1373
- }
1374
- _cloneInto(to) {
1375
- // Create new instance without calling constructor since key already in state and we don't know it.
1376
- to || (to = Object.create(Object.getPrototypeOf(this), {}));
1377
- const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
1378
- to = to;
1379
- to.finished = finished;
1380
- to.destroyed = destroyed;
1381
- to.blockLen = blockLen;
1382
- to.outputLen = outputLen;
1383
- to.oHash = oHash._cloneInto(to.oHash);
1384
- to.iHash = iHash._cloneInto(to.iHash);
1385
- return to;
1386
- }
1387
- clone() {
1388
- return this._cloneInto();
1389
- }
1390
- destroy() {
1391
- this.destroyed = true;
1392
- this.oHash.destroy();
1393
- this.iHash.destroy();
1394
- }
1395
- }
1396
- /**
1397
- * HMAC: RFC2104 message authentication code.
1398
- * @param hash - function that would be used e.g. sha256
1399
- * @param key - message key
1400
- * @param message - message data
1401
- * @example
1402
- * import { hmac } from '@noble/hashes/hmac';
1403
- * import { sha256 } from '@noble/hashes/sha2';
1404
- * const mac1 = hmac(sha256, 'key', 'message');
1405
- */
1406
- const hmac = (hash, key, message) => new HMAC(hash, key).update(message).digest();
1407
- hmac.create = (hash, key) => new HMAC(hash, key);
1408
-
1409
- /**
1410
- * Methods for elliptic curve multiplication by scalars.
1411
- * Contains wNAF, pippenger
1412
- * @module
1413
- */
1414
- /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
1415
- const _0n$1 = BigInt(0);
1416
- const _1n$2 = BigInt(1);
1417
- function negateCt(condition, item) {
1418
- const neg = item.negate();
1419
- return condition ? neg : item;
1420
- }
1421
- /**
1422
- * Takes a bunch of Projective Points but executes only one
1423
- * inversion on all of them. Inversion is very slow operation,
1424
- * so this improves performance massively.
1425
- * Optimization: converts a list of projective points to a list of identical points with Z=1.
1426
- */
1427
- function normalizeZ(c, property, points) {
1428
- const getz = (p) => p.pz ;
1429
- const toInv = FpInvertBatch(c.Fp, points.map(getz));
1430
- // @ts-ignore
1431
- const affined = points.map((p, i) => p.toAffine(toInv[i]));
1432
- return affined.map(c.fromAffine);
1433
- }
1434
- function validateW(W, bits) {
1435
- if (!Number.isSafeInteger(W) || W <= 0 || W > bits)
1436
- throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W);
1437
- }
1438
- function calcWOpts(W, scalarBits) {
1439
- validateW(W, scalarBits);
1440
- const windows = Math.ceil(scalarBits / W) + 1; // W=8 33. Not 32, because we skip zero
1441
- const windowSize = 2 ** (W - 1); // W=8 128. Not 256, because we skip zero
1442
- const maxNumber = 2 ** W; // W=8 256
1443
- const mask = bitMask(W); // W=8 255 == mask 0b11111111
1444
- const shiftBy = BigInt(W); // W=8 8
1445
- return { windows, windowSize, mask, maxNumber, shiftBy };
1446
- }
1447
- function calcOffsets(n, window, wOpts) {
1448
- const { windowSize, mask, maxNumber, shiftBy } = wOpts;
1449
- let wbits = Number(n & mask); // extract W bits.
1450
- let nextN = n >> shiftBy; // shift number by W bits.
1451
- // What actually happens here:
1452
- // const highestBit = Number(mask ^ (mask >> 1n));
1453
- // let wbits2 = wbits - 1; // skip zero
1454
- // if (wbits2 & highestBit) { wbits2 ^= Number(mask); // (~);
1455
- // split if bits > max: +224 => 256-32
1456
- if (wbits > windowSize) {
1457
- // we skip zero, which means instead of `>= size-1`, we do `> size`
1458
- wbits -= maxNumber; // -32, can be maxNumber - wbits, but then we need to set isNeg here.
1459
- nextN += _1n$2; // +256 (carry)
1460
- }
1461
- const offsetStart = window * windowSize;
1462
- const offset = offsetStart + Math.abs(wbits) - 1; // -1 because we skip zero
1463
- const isZero = wbits === 0; // is current window slice a 0?
1464
- const isNeg = wbits < 0; // is current window slice negative?
1465
- const isNegF = window % 2 !== 0; // fake random statement for noise
1466
- const offsetF = offsetStart; // fake offset for noise
1467
- return { nextN, offset, isZero, isNeg, isNegF, offsetF };
1468
- }
1469
- function validateMSMPoints(points, c) {
1470
- if (!Array.isArray(points))
1471
- throw new Error('array expected');
1472
- points.forEach((p, i) => {
1473
- if (!(p instanceof c))
1474
- throw new Error('invalid point at index ' + i);
1475
- });
1476
- }
1477
- function validateMSMScalars(scalars, field) {
1478
- if (!Array.isArray(scalars))
1479
- throw new Error('array of scalars expected');
1480
- scalars.forEach((s, i) => {
1481
- if (!field.isValid(s))
1482
- throw new Error('invalid scalar at index ' + i);
1483
- });
1484
- }
1485
- // Since points in different groups cannot be equal (different object constructor),
1486
- // we can have single place to store precomputes.
1487
- // Allows to make points frozen / immutable.
1488
- const pointPrecomputes = new WeakMap();
1489
- const pointWindowSizes = new WeakMap();
1490
- function getW(P) {
1491
- return pointWindowSizes.get(P) || 1;
1492
- }
1493
- function assert0(n) {
1494
- if (n !== _0n$1)
1495
- throw new Error('invalid wNAF');
1496
- }
1497
- /**
1498
- * Elliptic curve multiplication of Point by scalar. Fragile.
1499
- * Scalars should always be less than curve order: this should be checked inside of a curve itself.
1500
- * Creates precomputation tables for fast multiplication:
1501
- * - private scalar is split by fixed size windows of W bits
1502
- * - every window point is collected from window's table & added to accumulator
1503
- * - since windows are different, same point inside tables won't be accessed more than once per calc
1504
- * - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar)
1505
- * - +1 window is neccessary for wNAF
1506
- * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication
1507
- *
1508
- * @todo Research returning 2d JS array of windows, instead of a single window.
1509
- * This would allow windows to be in different memory locations
1510
- */
1511
- function wNAF(c, bits) {
1512
- return {
1513
- constTimeNegate: negateCt,
1514
- hasPrecomputes(elm) {
1515
- return getW(elm) !== 1;
1516
- },
1517
- // non-const time multiplication ladder
1518
- unsafeLadder(elm, n, p = c.ZERO) {
1519
- let d = elm;
1520
- while (n > _0n$1) {
1521
- if (n & _1n$2)
1522
- p = p.add(d);
1523
- d = d.double();
1524
- n >>= _1n$2;
1525
- }
1526
- return p;
1527
- },
1528
- /**
1529
- * Creates a wNAF precomputation window. Used for caching.
1530
- * Default window size is set by `utils.precompute()` and is equal to 8.
1531
- * Number of precomputed points depends on the curve size:
1532
- * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
1533
- * - 𝑊 is the window size
1534
- * - 𝑛 is the bitlength of the curve order.
1535
- * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
1536
- * @param elm Point instance
1537
- * @param W window size
1538
- * @returns precomputed point tables flattened to a single array
1539
- */
1540
- precomputeWindow(elm, W) {
1541
- const { windows, windowSize } = calcWOpts(W, bits);
1542
- const points = [];
1543
- let p = elm;
1544
- let base = p;
1545
- for (let window = 0; window < windows; window++) {
1546
- base = p;
1547
- points.push(base);
1548
- // i=1, bc we skip 0
1549
- for (let i = 1; i < windowSize; i++) {
1550
- base = base.add(p);
1551
- points.push(base);
1552
- }
1553
- p = base.double();
1554
- }
1555
- return points;
1556
- },
1557
- /**
1558
- * Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
1559
- * @param W window size
1560
- * @param precomputes precomputed tables
1561
- * @param n scalar (we don't check here, but should be less than curve order)
1562
- * @returns real and fake (for const-time) points
1563
- */
1564
- wNAF(W, precomputes, n) {
1565
- // Smaller version:
1566
- // https://github.com/paulmillr/noble-secp256k1/blob/47cb1669b6e506ad66b35fe7d76132ae97465da2/index.ts#L502-L541
1567
- // TODO: check the scalar is less than group order?
1568
- // wNAF behavior is undefined otherwise. But have to carefully remove
1569
- // other checks before wNAF. ORDER == bits here.
1570
- // Accumulators
1571
- let p = c.ZERO;
1572
- let f = c.BASE;
1573
- // This code was first written with assumption that 'f' and 'p' will never be infinity point:
1574
- // since each addition is multiplied by 2 ** W, it cannot cancel each other. However,
1575
- // there is negate now: it is possible that negated element from low value
1576
- // would be the same as high element, which will create carry into next window.
1577
- // It's not obvious how this can fail, but still worth investigating later.
1578
- const wo = calcWOpts(W, bits);
1579
- for (let window = 0; window < wo.windows; window++) {
1580
- // (n === _0n) is handled and not early-exited. isEven and offsetF are used for noise
1581
- const { nextN, offset, isZero, isNeg, isNegF, offsetF } = calcOffsets(n, window, wo);
1582
- n = nextN;
1583
- if (isZero) {
1584
- // bits are 0: add garbage to fake point
1585
- // Important part for const-time getPublicKey: add random "noise" point to f.
1586
- f = f.add(negateCt(isNegF, precomputes[offsetF]));
1587
- }
1588
- else {
1589
- // bits are 1: add to result point
1590
- p = p.add(negateCt(isNeg, precomputes[offset]));
1591
- }
1592
- }
1593
- assert0(n);
1594
- // Return both real and fake points: JIT won't eliminate f.
1595
- // At this point there is a way to F be infinity-point even if p is not,
1596
- // which makes it less const-time: around 1 bigint multiply.
1597
- return { p, f };
1598
- },
1599
- /**
1600
- * Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form.
1601
- * @param W window size
1602
- * @param precomputes precomputed tables
1603
- * @param n scalar (we don't check here, but should be less than curve order)
1604
- * @param acc accumulator point to add result of multiplication
1605
- * @returns point
1606
- */
1607
- wNAFUnsafe(W, precomputes, n, acc = c.ZERO) {
1608
- const wo = calcWOpts(W, bits);
1609
- for (let window = 0; window < wo.windows; window++) {
1610
- if (n === _0n$1)
1611
- break; // Early-exit, skip 0 value
1612
- const { nextN, offset, isZero, isNeg } = calcOffsets(n, window, wo);
1613
- n = nextN;
1614
- if (isZero) {
1615
- // Window bits are 0: skip processing.
1616
- // Move to next window.
1617
- continue;
1618
- }
1619
- else {
1620
- const item = precomputes[offset];
1621
- acc = acc.add(isNeg ? item.negate() : item); // Re-using acc allows to save adds in MSM
1622
- }
1623
- }
1624
- assert0(n);
1625
- return acc;
1626
- },
1627
- getPrecomputes(W, P, transform) {
1628
- // Calculate precomputes on a first run, reuse them after
1629
- let comp = pointPrecomputes.get(P);
1630
- if (!comp) {
1631
- comp = this.precomputeWindow(P, W);
1632
- if (W !== 1) {
1633
- // Doing transform outside of if brings 15% perf hit
1634
- if (typeof transform === 'function')
1635
- comp = transform(comp);
1636
- pointPrecomputes.set(P, comp);
1637
- }
1638
- }
1639
- return comp;
1640
- },
1641
- wNAFCached(P, n, transform) {
1642
- const W = getW(P);
1643
- return this.wNAF(W, this.getPrecomputes(W, P, transform), n);
1644
- },
1645
- wNAFCachedUnsafe(P, n, transform, prev) {
1646
- const W = getW(P);
1647
- if (W === 1)
1648
- return this.unsafeLadder(P, n, prev); // For W=1 ladder is ~x2 faster
1649
- return this.wNAFUnsafe(W, this.getPrecomputes(W, P, transform), n, prev);
1650
- },
1651
- // We calculate precomputes for elliptic curve point multiplication
1652
- // using windowed method. This specifies window size and
1653
- // stores precomputed values. Usually only base point would be precomputed.
1654
- setWindowSize(P, W) {
1655
- validateW(W, bits);
1656
- pointWindowSizes.set(P, W);
1657
- pointPrecomputes.delete(P);
1658
- },
1659
- };
1660
- }
1661
- /**
1662
- * Endomorphism-specific multiplication for Koblitz curves.
1663
- * Cost: 128 dbl, 0-256 adds.
1664
- */
1665
- function mulEndoUnsafe(c, point, k1, k2) {
1666
- let acc = point;
1667
- let p1 = c.ZERO;
1668
- let p2 = c.ZERO;
1669
- while (k1 > _0n$1 || k2 > _0n$1) {
1670
- if (k1 & _1n$2)
1671
- p1 = p1.add(acc);
1672
- if (k2 & _1n$2)
1673
- p2 = p2.add(acc);
1674
- acc = acc.double();
1675
- k1 >>= _1n$2;
1676
- k2 >>= _1n$2;
1677
- }
1678
- return { p1, p2 };
1679
- }
1680
- /**
1681
- * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
1682
- * 30x faster vs naive addition on L=4096, 10x faster than precomputes.
1683
- * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL.
1684
- * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0.
1685
- * @param c Curve Point constructor
1686
- * @param fieldN field over CURVE.N - important that it's not over CURVE.P
1687
- * @param points array of L curve points
1688
- * @param scalars array of L scalars (aka private keys / bigints)
1689
- */
1690
- function pippenger(c, fieldN, points, scalars) {
1691
- // If we split scalars by some window (let's say 8 bits), every chunk will only
1692
- // take 256 buckets even if there are 4096 scalars, also re-uses double.
1693
- // TODO:
1694
- // - https://eprint.iacr.org/2024/750.pdf
1695
- // - https://tches.iacr.org/index.php/TCHES/article/view/10287
1696
- // 0 is accepted in scalars
1697
- validateMSMPoints(points, c);
1698
- validateMSMScalars(scalars, fieldN);
1699
- const plength = points.length;
1700
- const slength = scalars.length;
1701
- if (plength !== slength)
1702
- throw new Error('arrays of points and scalars must have equal length');
1703
- // if (plength === 0) throw new Error('array must be of length >= 2');
1704
- const zero = c.ZERO;
1705
- const wbits = bitLen(BigInt(plength));
1706
- let windowSize = 1; // bits
1707
- if (wbits > 12)
1708
- windowSize = wbits - 3;
1709
- else if (wbits > 4)
1710
- windowSize = wbits - 2;
1711
- else if (wbits > 0)
1712
- windowSize = 2;
1713
- const MASK = bitMask(windowSize);
1714
- const buckets = new Array(Number(MASK) + 1).fill(zero); // +1 for zero array
1715
- const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize;
1716
- let sum = zero;
1717
- for (let i = lastBits; i >= 0; i -= windowSize) {
1718
- buckets.fill(zero);
1719
- for (let j = 0; j < slength; j++) {
1720
- const scalar = scalars[j];
1721
- const wbits = Number((scalar >> BigInt(i)) & MASK);
1722
- buckets[wbits] = buckets[wbits].add(points[j]);
1723
- }
1724
- let resI = zero; // not using this will do small speed-up, but will lose ct
1725
- // Skip first bucket, because it is zero
1726
- for (let j = buckets.length - 1, sumI = zero; j > 0; j--) {
1727
- sumI = sumI.add(buckets[j]);
1728
- resI = resI.add(sumI);
1729
- }
1730
- sum = sum.add(resI);
1731
- if (i !== 0)
1732
- for (let j = 0; j < windowSize; j++)
1733
- sum = sum.double();
1734
- }
1735
- return sum;
1736
- }
1737
- function createField(order, field) {
1738
- if (field) {
1739
- if (field.ORDER !== order)
1740
- throw new Error('Field.ORDER must match order: Fp == p, Fn == n');
1741
- validateField(field);
1742
- return field;
1743
- }
1744
- else {
1745
- return Field(order);
1746
- }
1747
- }
1748
- /** Validates CURVE opts and creates fields */
1749
- function _createCurveFields(type, CURVE, curveOpts = {}) {
1750
- if (!CURVE || typeof CURVE !== 'object')
1751
- throw new Error(`expected valid ${type} CURVE object`);
1752
- for (const p of ['p', 'n', 'h']) {
1753
- const val = CURVE[p];
1754
- if (!(typeof val === 'bigint' && val > _0n$1))
1755
- throw new Error(`CURVE.${p} must be positive bigint`);
1756
- }
1757
- const Fp = createField(CURVE.p, curveOpts.Fp);
1758
- const Fn = createField(CURVE.n, curveOpts.Fn);
1759
- const _b = 'b' ;
1760
- const params = ['Gx', 'Gy', 'a', _b];
1761
- for (const p of params) {
1762
- // @ts-ignore
1763
- if (!Fp.isValid(CURVE[p]))
1764
- throw new Error(`CURVE.${p} must be valid field element of CURVE.Fp`);
1765
- }
1766
- return { Fp, Fn };
1767
- }
1768
-
1769
- /**
1770
- * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b.
1771
- *
1772
- * ### Design rationale for types
1773
- *
1774
- * * Interaction between classes from different curves should fail:
1775
- * `k256.Point.BASE.add(p256.Point.BASE)`
1776
- * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime
1777
- * * Different calls of `curve()` would return different classes -
1778
- * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve,
1779
- * it won't affect others
1780
- *
1781
- * TypeScript can't infer types for classes created inside a function. Classes is one instance
1782
- * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create
1783
- * unique type for every function call.
1784
- *
1785
- * We can use generic types via some param, like curve opts, but that would:
1786
- * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params)
1787
- * which is hard to debug.
1788
- * 2. Params can be generic and we can't enforce them to be constant value:
1789
- * if somebody creates curve from non-constant params,
1790
- * it would be allowed to interact with other curves with non-constant params
1791
- *
1792
- * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol
1793
- * @module
1794
- */
1795
- /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
1796
- function validateSigVerOpts(opts) {
1797
- if (opts.lowS !== undefined)
1798
- abool('lowS', opts.lowS);
1799
- if (opts.prehash !== undefined)
1800
- abool('prehash', opts.prehash);
1801
- }
1802
- class DERErr extends Error {
1803
- constructor(m = '') {
1804
- super(m);
1805
- }
1806
- }
1807
- /**
1808
- * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format:
1809
- *
1810
- * [0x30 (SEQUENCE), bytelength, 0x02 (INTEGER), intLength, R, 0x02 (INTEGER), intLength, S]
1811
- *
1812
- * Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html
1813
- */
1814
- const DER = {
1815
- // asn.1 DER encoding utils
1816
- Err: DERErr,
1817
- // Basic building block is TLV (Tag-Length-Value)
1818
- _tlv: {
1819
- encode: (tag, data) => {
1820
- const { Err: E } = DER;
1821
- if (tag < 0 || tag > 256)
1822
- throw new E('tlv.encode: wrong tag');
1823
- if (data.length & 1)
1824
- throw new E('tlv.encode: unpadded data');
1825
- const dataLen = data.length / 2;
1826
- const len = numberToHexUnpadded(dataLen);
1827
- if ((len.length / 2) & 128)
1828
- throw new E('tlv.encode: long form length too big');
1829
- // length of length with long form flag
1830
- const lenLen = dataLen > 127 ? numberToHexUnpadded((len.length / 2) | 128) : '';
1831
- const t = numberToHexUnpadded(tag);
1832
- return t + lenLen + len + data;
1833
- },
1834
- // v - value, l - left bytes (unparsed)
1835
- decode(tag, data) {
1836
- const { Err: E } = DER;
1837
- let pos = 0;
1838
- if (tag < 0 || tag > 256)
1839
- throw new E('tlv.encode: wrong tag');
1840
- if (data.length < 2 || data[pos++] !== tag)
1841
- throw new E('tlv.decode: wrong tlv');
1842
- const first = data[pos++];
1843
- const isLong = !!(first & 128); // First bit of first length byte is flag for short/long form
1844
- let length = 0;
1845
- if (!isLong)
1846
- length = first;
1847
- else {
1848
- // Long form: [longFlag(1bit), lengthLength(7bit), length (BE)]
1849
- const lenLen = first & 127;
1850
- if (!lenLen)
1851
- throw new E('tlv.decode(long): indefinite length not supported');
1852
- if (lenLen > 4)
1853
- throw new E('tlv.decode(long): byte length is too big'); // this will overflow u32 in js
1854
- const lengthBytes = data.subarray(pos, pos + lenLen);
1855
- if (lengthBytes.length !== lenLen)
1856
- throw new E('tlv.decode: length bytes not complete');
1857
- if (lengthBytes[0] === 0)
1858
- throw new E('tlv.decode(long): zero leftmost byte');
1859
- for (const b of lengthBytes)
1860
- length = (length << 8) | b;
1861
- pos += lenLen;
1862
- if (length < 128)
1863
- throw new E('tlv.decode(long): not minimal encoding');
1864
- }
1865
- const v = data.subarray(pos, pos + length);
1866
- if (v.length !== length)
1867
- throw new E('tlv.decode: wrong value length');
1868
- return { v, l: data.subarray(pos + length) };
1869
- },
1870
- },
1871
- // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,
1872
- // since we always use positive integers here. It must always be empty:
1873
- // - add zero byte if exists
1874
- // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)
1875
- _int: {
1876
- encode(num) {
1877
- const { Err: E } = DER;
1878
- if (num < _0n)
1879
- throw new E('integer: negative integers are not allowed');
1880
- let hex = numberToHexUnpadded(num);
1881
- // Pad with zero byte if negative flag is present
1882
- if (Number.parseInt(hex[0], 16) & 0b1000)
1883
- hex = '00' + hex;
1884
- if (hex.length & 1)
1885
- throw new E('unexpected DER parsing assertion: unpadded hex');
1886
- return hex;
1887
- },
1888
- decode(data) {
1889
- const { Err: E } = DER;
1890
- if (data[0] & 128)
1891
- throw new E('invalid signature integer: negative');
1892
- if (data[0] === 0x00 && !(data[1] & 128))
1893
- throw new E('invalid signature integer: unnecessary leading zero');
1894
- return bytesToNumberBE(data);
1895
- },
1896
- },
1897
- toSig(hex) {
1898
- // parse DER signature
1899
- const { Err: E, _int: int, _tlv: tlv } = DER;
1900
- const data = ensureBytes('signature', hex);
1901
- const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data);
1902
- if (seqLeftBytes.length)
1903
- throw new E('invalid signature: left bytes after parsing');
1904
- const { v: rBytes, l: rLeftBytes } = tlv.decode(0x02, seqBytes);
1905
- const { v: sBytes, l: sLeftBytes } = tlv.decode(0x02, rLeftBytes);
1906
- if (sLeftBytes.length)
1907
- throw new E('invalid signature: left bytes after parsing');
1908
- return { r: int.decode(rBytes), s: int.decode(sBytes) };
1909
- },
1910
- hexFromSig(sig) {
1911
- const { _tlv: tlv, _int: int } = DER;
1912
- const rs = tlv.encode(0x02, int.encode(sig.r));
1913
- const ss = tlv.encode(0x02, int.encode(sig.s));
1914
- const seq = rs + ss;
1915
- return tlv.encode(0x30, seq);
1916
- },
1917
- };
1918
- // Be friendly to bad ECMAScript parsers by not using bigint literals
1919
- // prettier-ignore
1920
- const _0n = BigInt(0), _1n$1 = BigInt(1), _2n$1 = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
1921
- // TODO: remove
1922
- function _legacyHelperEquat(Fp, a, b) {
1923
- /**
1924
- * y² = x³ + ax + b: Short weierstrass curve formula. Takes x, returns y².
1925
- * @returns y²
1926
- */
1927
- function weierstrassEquation(x) {
1928
- const x2 = Fp.sqr(x); // x * x
1929
- const x3 = Fp.mul(x2, x); // x² * x
1930
- return Fp.add(Fp.add(x3, Fp.mul(x, a)), b); // x³ + a * x + b
1931
- }
1932
- return weierstrassEquation;
1933
- }
1934
- function _legacyHelperNormPriv(Fn, allowedPrivateKeyLengths, wrapPrivateKey) {
1935
- const { BYTES: expected } = Fn;
1936
- // Validates if priv key is valid and converts it to bigint.
1937
- function normPrivateKeyToScalar(key) {
1938
- let num;
1939
- if (typeof key === 'bigint') {
1940
- num = key;
1941
- }
1942
- else {
1943
- let bytes = ensureBytes('private key', key);
1944
- if (allowedPrivateKeyLengths) {
1945
- if (!allowedPrivateKeyLengths.includes(bytes.length * 2))
1946
- throw new Error('invalid private key');
1947
- const padded = new Uint8Array(expected);
1948
- padded.set(bytes, padded.length - bytes.length);
1949
- bytes = padded;
1950
- }
1951
- try {
1952
- num = Fn.fromBytes(bytes);
1953
- }
1954
- catch (error) {
1955
- throw new Error(`invalid private key: expected ui8a of size ${expected}, got ${typeof key}`);
1956
- }
1957
- }
1958
- if (wrapPrivateKey)
1959
- num = Fn.create(num); // disabled by default, enabled for BLS
1960
- if (!Fn.isValidNot0(num))
1961
- throw new Error('invalid private key: out of range [1..N-1]');
1962
- return num;
1963
- }
1964
- return normPrivateKeyToScalar;
1965
- }
1966
- function weierstrassN(CURVE, curveOpts = {}) {
1967
- const { Fp, Fn } = _createCurveFields('weierstrass', CURVE, curveOpts);
1968
- const { h: cofactor, n: CURVE_ORDER } = CURVE;
1969
- _validateObject(curveOpts, {}, {
1970
- allowInfinityPoint: 'boolean',
1971
- clearCofactor: 'function',
1972
- isTorsionFree: 'function',
1973
- fromBytes: 'function',
1974
- toBytes: 'function',
1975
- endo: 'object',
1976
- wrapPrivateKey: 'boolean',
1977
- });
1978
- const { endo } = curveOpts;
1979
- if (endo) {
1980
- // validateObject(endo, { beta: 'bigint', splitScalar: 'function' });
1981
- if (!Fp.is0(CURVE.a) ||
1982
- typeof endo.beta !== 'bigint' ||
1983
- typeof endo.splitScalar !== 'function') {
1984
- throw new Error('invalid endo: expected "beta": bigint and "splitScalar": function');
1985
- }
1986
- }
1987
- function assertCompressionIsSupported() {
1988
- if (!Fp.isOdd)
1989
- throw new Error('compression is not supported: Field does not have .isOdd()');
1990
- }
1991
- // Implements IEEE P1363 point encoding
1992
- function pointToBytes(_c, point, isCompressed) {
1993
- const { x, y } = point.toAffine();
1994
- const bx = Fp.toBytes(x);
1995
- abool('isCompressed', isCompressed);
1996
- if (isCompressed) {
1997
- assertCompressionIsSupported();
1998
- const hasEvenY = !Fp.isOdd(y);
1999
- return concatBytes(pprefix(hasEvenY), bx);
2000
- }
2001
- else {
2002
- return concatBytes(Uint8Array.of(0x04), bx, Fp.toBytes(y));
2003
- }
2004
- }
2005
- function pointFromBytes(bytes) {
2006
- abytes(bytes);
2007
- const L = Fp.BYTES;
2008
- const LC = L + 1; // length compressed, e.g. 33 for 32-byte field
2009
- const LU = 2 * L + 1; // length uncompressed, e.g. 65 for 32-byte field
2010
- const length = bytes.length;
2011
- const head = bytes[0];
2012
- const tail = bytes.subarray(1);
2013
- // No actual validation is done here: use .assertValidity()
2014
- if (length === LC && (head === 0x02 || head === 0x03)) {
2015
- const x = Fp.fromBytes(tail);
2016
- if (!Fp.isValid(x))
2017
- throw new Error('bad point: is not on curve, wrong x');
2018
- const y2 = weierstrassEquation(x); // y² = x³ + ax + b
2019
- let y;
2020
- try {
2021
- y = Fp.sqrt(y2); // y = y² ^ (p+1)/4
2022
- }
2023
- catch (sqrtError) {
2024
- const err = sqrtError instanceof Error ? ': ' + sqrtError.message : '';
2025
- throw new Error('bad point: is not on curve, sqrt error' + err);
2026
- }
2027
- assertCompressionIsSupported();
2028
- const isYOdd = Fp.isOdd(y); // (y & _1n) === _1n;
2029
- const isHeadOdd = (head & 1) === 1; // ECDSA-specific
2030
- if (isHeadOdd !== isYOdd)
2031
- y = Fp.neg(y);
2032
- return { x, y };
2033
- }
2034
- else if (length === LU && head === 0x04) {
2035
- // TODO: more checks
2036
- const x = Fp.fromBytes(tail.subarray(L * 0, L * 1));
2037
- const y = Fp.fromBytes(tail.subarray(L * 1, L * 2));
2038
- if (!isValidXY(x, y))
2039
- throw new Error('bad point: is not on curve');
2040
- return { x, y };
2041
- }
2042
- else {
2043
- throw new Error(`bad point: got length ${length}, expected compressed=${LC} or uncompressed=${LU}`);
2044
- }
2045
- }
2046
- const toBytes = curveOpts.toBytes || pointToBytes;
2047
- const fromBytes = curveOpts.fromBytes || pointFromBytes;
2048
- const weierstrassEquation = _legacyHelperEquat(Fp, CURVE.a, CURVE.b);
2049
- // TODO: move top-level
2050
- /** Checks whether equation holds for given x, y: y² == x³ + ax + b */
2051
- function isValidXY(x, y) {
2052
- const left = Fp.sqr(y); // y²
2053
- const right = weierstrassEquation(x); // x³ + ax + b
2054
- return Fp.eql(left, right);
2055
- }
2056
- // Validate whether the passed curve params are valid.
2057
- // Test 1: equation y² = x³ + ax + b should work for generator point.
2058
- if (!isValidXY(CURVE.Gx, CURVE.Gy))
2059
- throw new Error('bad curve params: generator point');
2060
- // Test 2: discriminant Δ part should be non-zero: 4a³ + 27b² != 0.
2061
- // Guarantees curve is genus-1, smooth (non-singular).
2062
- const _4a3 = Fp.mul(Fp.pow(CURVE.a, _3n), _4n);
2063
- const _27b2 = Fp.mul(Fp.sqr(CURVE.b), BigInt(27));
2064
- if (Fp.is0(Fp.add(_4a3, _27b2)))
2065
- throw new Error('bad curve params: a or b');
2066
- /** Asserts coordinate is valid: 0 <= n < Fp.ORDER. */
2067
- function acoord(title, n, banZero = false) {
2068
- if (!Fp.isValid(n) || (banZero && Fp.is0(n)))
2069
- throw new Error(`bad point coordinate ${title}`);
2070
- return n;
2071
- }
2072
- function aprjpoint(other) {
2073
- if (!(other instanceof Point))
2074
- throw new Error('ProjectivePoint expected');
2075
- }
2076
- // Memoized toAffine / validity check. They are heavy. Points are immutable.
2077
- // Converts Projective point to affine (x, y) coordinates.
2078
- // Can accept precomputed Z^-1 - for example, from invertBatch.
2079
- // (X, Y, Z) ∋ (x=X/Z, y=Y/Z)
2080
- const toAffineMemo = memoized((p, iz) => {
2081
- const { px: x, py: y, pz: z } = p;
2082
- // Fast-path for normalized points
2083
- if (Fp.eql(z, Fp.ONE))
2084
- return { x, y };
2085
- const is0 = p.is0();
2086
- // If invZ was 0, we return zero point. However we still want to execute
2087
- // all operations, so we replace invZ with a random number, 1.
2088
- if (iz == null)
2089
- iz = is0 ? Fp.ONE : Fp.inv(z);
2090
- const ax = Fp.mul(x, iz);
2091
- const ay = Fp.mul(y, iz);
2092
- const zz = Fp.mul(z, iz);
2093
- if (is0)
2094
- return { x: Fp.ZERO, y: Fp.ZERO };
2095
- if (!Fp.eql(zz, Fp.ONE))
2096
- throw new Error('invZ was invalid');
2097
- return { x: ax, y: ay };
2098
- });
2099
- // NOTE: on exception this will crash 'cached' and no value will be set.
2100
- // Otherwise true will be return
2101
- const assertValidMemo = memoized((p) => {
2102
- if (p.is0()) {
2103
- // (0, 1, 0) aka ZERO is invalid in most contexts.
2104
- // In BLS, ZERO can be serialized, so we allow it.
2105
- // (0, 0, 0) is invalid representation of ZERO.
2106
- if (curveOpts.allowInfinityPoint && !Fp.is0(p.py))
2107
- return;
2108
- throw new Error('bad point: ZERO');
2109
- }
2110
- // Some 3rd-party test vectors require different wording between here & `fromCompressedHex`
2111
- const { x, y } = p.toAffine();
2112
- if (!Fp.isValid(x) || !Fp.isValid(y))
2113
- throw new Error('bad point: x or y not field elements');
2114
- if (!isValidXY(x, y))
2115
- throw new Error('bad point: equation left != right');
2116
- if (!p.isTorsionFree())
2117
- throw new Error('bad point: not in prime-order subgroup');
2118
- return true;
2119
- });
2120
- function finishEndo(endoBeta, k1p, k2p, k1neg, k2neg) {
2121
- k2p = new Point(Fp.mul(k2p.px, endoBeta), k2p.py, k2p.pz);
2122
- k1p = negateCt(k1neg, k1p);
2123
- k2p = negateCt(k2neg, k2p);
2124
- return k1p.add(k2p);
2125
- }
2126
- /**
2127
- * Projective Point works in 3d / projective (homogeneous) coordinates:(X, Y, Z) ∋ (x=X/Z, y=Y/Z).
2128
- * Default Point works in 2d / affine coordinates: (x, y).
2129
- * We're doing calculations in projective, because its operations don't require costly inversion.
2130
- */
2131
- class Point {
2132
- /** Does NOT validate if the point is valid. Use `.assertValidity()`. */
2133
- constructor(px, py, pz) {
2134
- this.px = acoord('x', px);
2135
- this.py = acoord('y', py, true);
2136
- this.pz = acoord('z', pz);
2137
- Object.freeze(this);
2138
- }
2139
- /** Does NOT validate if the point is valid. Use `.assertValidity()`. */
2140
- static fromAffine(p) {
2141
- const { x, y } = p || {};
2142
- if (!p || !Fp.isValid(x) || !Fp.isValid(y))
2143
- throw new Error('invalid affine point');
2144
- if (p instanceof Point)
2145
- throw new Error('projective point not allowed');
2146
- // (0, 0) would've produced (0, 0, 1) - instead, we need (0, 1, 0)
2147
- if (Fp.is0(x) && Fp.is0(y))
2148
- return Point.ZERO;
2149
- return new Point(x, y, Fp.ONE);
2150
- }
2151
- get x() {
2152
- return this.toAffine().x;
2153
- }
2154
- get y() {
2155
- return this.toAffine().y;
2156
- }
2157
- static normalizeZ(points) {
2158
- return normalizeZ(Point, 'pz', points);
2159
- }
2160
- static fromBytes(bytes) {
2161
- abytes(bytes);
2162
- return Point.fromHex(bytes);
2163
- }
2164
- /** Converts hash string or Uint8Array to Point. */
2165
- static fromHex(hex) {
2166
- const P = Point.fromAffine(fromBytes(ensureBytes('pointHex', hex)));
2167
- P.assertValidity();
2168
- return P;
2169
- }
2170
- /** Multiplies generator point by privateKey. */
2171
- static fromPrivateKey(privateKey) {
2172
- const normPrivateKeyToScalar = _legacyHelperNormPriv(Fn, curveOpts.allowedPrivateKeyLengths, curveOpts.wrapPrivateKey);
2173
- return Point.BASE.multiply(normPrivateKeyToScalar(privateKey));
2174
- }
2175
- /** Multiscalar Multiplication */
2176
- static msm(points, scalars) {
2177
- return pippenger(Point, Fn, points, scalars);
2178
- }
2179
- /**
2180
- *
2181
- * @param windowSize
2182
- * @param isLazy true will defer table computation until the first multiplication
2183
- * @returns
2184
- */
2185
- precompute(windowSize = 8, isLazy = true) {
2186
- wnaf.setWindowSize(this, windowSize);
2187
- if (!isLazy)
2188
- this.multiply(_3n); // random number
2189
- return this;
2190
- }
2191
- /** "Private method", don't use it directly */
2192
- _setWindowSize(windowSize) {
2193
- this.precompute(windowSize);
2194
- }
2195
- // TODO: return `this`
2196
- /** A point on curve is valid if it conforms to equation. */
2197
- assertValidity() {
2198
- assertValidMemo(this);
2199
- }
2200
- hasEvenY() {
2201
- const { y } = this.toAffine();
2202
- if (!Fp.isOdd)
2203
- throw new Error("Field doesn't support isOdd");
2204
- return !Fp.isOdd(y);
2205
- }
2206
- /** Compare one point to another. */
2207
- equals(other) {
2208
- aprjpoint(other);
2209
- const { px: X1, py: Y1, pz: Z1 } = this;
2210
- const { px: X2, py: Y2, pz: Z2 } = other;
2211
- const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1));
2212
- const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1));
2213
- return U1 && U2;
2214
- }
2215
- /** Flips point to one corresponding to (x, -y) in Affine coordinates. */
2216
- negate() {
2217
- return new Point(this.px, Fp.neg(this.py), this.pz);
2218
- }
2219
- // Renes-Costello-Batina exception-free doubling formula.
2220
- // There is 30% faster Jacobian formula, but it is not complete.
2221
- // https://eprint.iacr.org/2015/1060, algorithm 3
2222
- // Cost: 8M + 3S + 3*a + 2*b3 + 15add.
2223
- double() {
2224
- const { a, b } = CURVE;
2225
- const b3 = Fp.mul(b, _3n);
2226
- const { px: X1, py: Y1, pz: Z1 } = this;
2227
- let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
2228
- let t0 = Fp.mul(X1, X1); // step 1
2229
- let t1 = Fp.mul(Y1, Y1);
2230
- let t2 = Fp.mul(Z1, Z1);
2231
- let t3 = Fp.mul(X1, Y1);
2232
- t3 = Fp.add(t3, t3); // step 5
2233
- Z3 = Fp.mul(X1, Z1);
2234
- Z3 = Fp.add(Z3, Z3);
2235
- X3 = Fp.mul(a, Z3);
2236
- Y3 = Fp.mul(b3, t2);
2237
- Y3 = Fp.add(X3, Y3); // step 10
2238
- X3 = Fp.sub(t1, Y3);
2239
- Y3 = Fp.add(t1, Y3);
2240
- Y3 = Fp.mul(X3, Y3);
2241
- X3 = Fp.mul(t3, X3);
2242
- Z3 = Fp.mul(b3, Z3); // step 15
2243
- t2 = Fp.mul(a, t2);
2244
- t3 = Fp.sub(t0, t2);
2245
- t3 = Fp.mul(a, t3);
2246
- t3 = Fp.add(t3, Z3);
2247
- Z3 = Fp.add(t0, t0); // step 20
2248
- t0 = Fp.add(Z3, t0);
2249
- t0 = Fp.add(t0, t2);
2250
- t0 = Fp.mul(t0, t3);
2251
- Y3 = Fp.add(Y3, t0);
2252
- t2 = Fp.mul(Y1, Z1); // step 25
2253
- t2 = Fp.add(t2, t2);
2254
- t0 = Fp.mul(t2, t3);
2255
- X3 = Fp.sub(X3, t0);
2256
- Z3 = Fp.mul(t2, t1);
2257
- Z3 = Fp.add(Z3, Z3); // step 30
2258
- Z3 = Fp.add(Z3, Z3);
2259
- return new Point(X3, Y3, Z3);
2260
- }
2261
- // Renes-Costello-Batina exception-free addition formula.
2262
- // There is 30% faster Jacobian formula, but it is not complete.
2263
- // https://eprint.iacr.org/2015/1060, algorithm 1
2264
- // Cost: 12M + 0S + 3*a + 3*b3 + 23add.
2265
- add(other) {
2266
- aprjpoint(other);
2267
- const { px: X1, py: Y1, pz: Z1 } = this;
2268
- const { px: X2, py: Y2, pz: Z2 } = other;
2269
- let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
2270
- const a = CURVE.a;
2271
- const b3 = Fp.mul(CURVE.b, _3n);
2272
- let t0 = Fp.mul(X1, X2); // step 1
2273
- let t1 = Fp.mul(Y1, Y2);
2274
- let t2 = Fp.mul(Z1, Z2);
2275
- let t3 = Fp.add(X1, Y1);
2276
- let t4 = Fp.add(X2, Y2); // step 5
2277
- t3 = Fp.mul(t3, t4);
2278
- t4 = Fp.add(t0, t1);
2279
- t3 = Fp.sub(t3, t4);
2280
- t4 = Fp.add(X1, Z1);
2281
- let t5 = Fp.add(X2, Z2); // step 10
2282
- t4 = Fp.mul(t4, t5);
2283
- t5 = Fp.add(t0, t2);
2284
- t4 = Fp.sub(t4, t5);
2285
- t5 = Fp.add(Y1, Z1);
2286
- X3 = Fp.add(Y2, Z2); // step 15
2287
- t5 = Fp.mul(t5, X3);
2288
- X3 = Fp.add(t1, t2);
2289
- t5 = Fp.sub(t5, X3);
2290
- Z3 = Fp.mul(a, t4);
2291
- X3 = Fp.mul(b3, t2); // step 20
2292
- Z3 = Fp.add(X3, Z3);
2293
- X3 = Fp.sub(t1, Z3);
2294
- Z3 = Fp.add(t1, Z3);
2295
- Y3 = Fp.mul(X3, Z3);
2296
- t1 = Fp.add(t0, t0); // step 25
2297
- t1 = Fp.add(t1, t0);
2298
- t2 = Fp.mul(a, t2);
2299
- t4 = Fp.mul(b3, t4);
2300
- t1 = Fp.add(t1, t2);
2301
- t2 = Fp.sub(t0, t2); // step 30
2302
- t2 = Fp.mul(a, t2);
2303
- t4 = Fp.add(t4, t2);
2304
- t0 = Fp.mul(t1, t4);
2305
- Y3 = Fp.add(Y3, t0);
2306
- t0 = Fp.mul(t5, t4); // step 35
2307
- X3 = Fp.mul(t3, X3);
2308
- X3 = Fp.sub(X3, t0);
2309
- t0 = Fp.mul(t3, t1);
2310
- Z3 = Fp.mul(t5, Z3);
2311
- Z3 = Fp.add(Z3, t0); // step 40
2312
- return new Point(X3, Y3, Z3);
2313
- }
2314
- subtract(other) {
2315
- return this.add(other.negate());
2316
- }
2317
- is0() {
2318
- return this.equals(Point.ZERO);
2319
- }
2320
- /**
2321
- * Constant time multiplication.
2322
- * Uses wNAF method. Windowed method may be 10% faster,
2323
- * but takes 2x longer to generate and consumes 2x memory.
2324
- * Uses precomputes when available.
2325
- * Uses endomorphism for Koblitz curves.
2326
- * @param scalar by which the point would be multiplied
2327
- * @returns New point
2328
- */
2329
- multiply(scalar) {
2330
- const { endo } = curveOpts;
2331
- if (!Fn.isValidNot0(scalar))
2332
- throw new Error('invalid scalar: out of range'); // 0 is invalid
2333
- let point, fake; // Fake point is used to const-time mult
2334
- const mul = (n) => wnaf.wNAFCached(this, n, Point.normalizeZ);
2335
- /** See docs for {@link EndomorphismOpts} */
2336
- if (endo) {
2337
- const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar);
2338
- const { p: k1p, f: k1f } = mul(k1);
2339
- const { p: k2p, f: k2f } = mul(k2);
2340
- fake = k1f.add(k2f);
2341
- point = finishEndo(endo.beta, k1p, k2p, k1neg, k2neg);
2342
- }
2343
- else {
2344
- const { p, f } = mul(scalar);
2345
- point = p;
2346
- fake = f;
2347
- }
2348
- // Normalize `z` for both points, but return only real one
2349
- return Point.normalizeZ([point, fake])[0];
2350
- }
2351
- /**
2352
- * Non-constant-time multiplication. Uses double-and-add algorithm.
2353
- * It's faster, but should only be used when you don't care about
2354
- * an exposed private key e.g. sig verification, which works over *public* keys.
2355
- */
2356
- multiplyUnsafe(sc) {
2357
- const { endo } = curveOpts;
2358
- const p = this;
2359
- if (!Fn.isValid(sc))
2360
- throw new Error('invalid scalar: out of range'); // 0 is valid
2361
- if (sc === _0n || p.is0())
2362
- return Point.ZERO;
2363
- if (sc === _1n$1)
2364
- return p; // fast-path
2365
- if (wnaf.hasPrecomputes(this))
2366
- return this.multiply(sc);
2367
- if (endo) {
2368
- const { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc);
2369
- // `wNAFCachedUnsafe` is 30% slower
2370
- const { p1, p2 } = mulEndoUnsafe(Point, p, k1, k2);
2371
- return finishEndo(endo.beta, p1, p2, k1neg, k2neg);
2372
- }
2373
- else {
2374
- return wnaf.wNAFCachedUnsafe(p, sc);
2375
- }
2376
- }
2377
- multiplyAndAddUnsafe(Q, a, b) {
2378
- const sum = this.multiplyUnsafe(a).add(Q.multiplyUnsafe(b));
2379
- return sum.is0() ? undefined : sum;
2380
- }
2381
- /**
2382
- * Converts Projective point to affine (x, y) coordinates.
2383
- * @param invertedZ Z^-1 (inverted zero) - optional, precomputation is useful for invertBatch
2384
- */
2385
- toAffine(invertedZ) {
2386
- return toAffineMemo(this, invertedZ);
2387
- }
2388
- /**
2389
- * Checks whether Point is free of torsion elements (is in prime subgroup).
2390
- * Always torsion-free for cofactor=1 curves.
2391
- */
2392
- isTorsionFree() {
2393
- const { isTorsionFree } = curveOpts;
2394
- if (cofactor === _1n$1)
2395
- return true;
2396
- if (isTorsionFree)
2397
- return isTorsionFree(Point, this);
2398
- return wnaf.wNAFCachedUnsafe(this, CURVE_ORDER).is0();
2399
- }
2400
- clearCofactor() {
2401
- const { clearCofactor } = curveOpts;
2402
- if (cofactor === _1n$1)
2403
- return this; // Fast-path
2404
- if (clearCofactor)
2405
- return clearCofactor(Point, this);
2406
- return this.multiplyUnsafe(cofactor);
2407
- }
2408
- toBytes(isCompressed = true) {
2409
- abool('isCompressed', isCompressed);
2410
- this.assertValidity();
2411
- return toBytes(Point, this, isCompressed);
2412
- }
2413
- /** @deprecated use `toBytes` */
2414
- toRawBytes(isCompressed = true) {
2415
- return this.toBytes(isCompressed);
2416
- }
2417
- toHex(isCompressed = true) {
2418
- return bytesToHex(this.toBytes(isCompressed));
2419
- }
2420
- toString() {
2421
- return `<Point ${this.is0() ? 'ZERO' : this.toHex()}>`;
2422
- }
2423
- }
2424
- // base / generator point
2425
- Point.BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE);
2426
- // zero / infinity / identity point
2427
- Point.ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO); // 0, 1, 0
2428
- // fields
2429
- Point.Fp = Fp;
2430
- Point.Fn = Fn;
2431
- const bits = Fn.BITS;
2432
- const wnaf = wNAF(Point, curveOpts.endo ? Math.ceil(bits / 2) : bits);
2433
- return Point;
2434
- }
2435
- // Points start with byte 0x02 when y is even; otherwise 0x03
2436
- function pprefix(hasEvenY) {
2437
- return Uint8Array.of(hasEvenY ? 0x02 : 0x03);
2438
- }
2439
- function ecdsa(Point, ecdsaOpts, curveOpts = {}) {
2440
- _validateObject(ecdsaOpts, { hash: 'function' }, {
2441
- hmac: 'function',
2442
- lowS: 'boolean',
2443
- randomBytes: 'function',
2444
- bits2int: 'function',
2445
- bits2int_modN: 'function',
2446
- });
2447
- const randomBytes_ = ecdsaOpts.randomBytes || randomBytes;
2448
- const hmac_ = ecdsaOpts.hmac ||
2449
- ((key, ...msgs) => hmac(ecdsaOpts.hash, key, concatBytes(...msgs)));
2450
- const { Fp, Fn } = Point;
2451
- const { ORDER: CURVE_ORDER, BITS: fnBits } = Fn;
2452
- function isBiggerThanHalfOrder(number) {
2453
- const HALF = CURVE_ORDER >> _1n$1;
2454
- return number > HALF;
2455
- }
2456
- function normalizeS(s) {
2457
- return isBiggerThanHalfOrder(s) ? Fn.neg(s) : s;
2458
- }
2459
- function aValidRS(title, num) {
2460
- if (!Fn.isValidNot0(num))
2461
- throw new Error(`invalid signature ${title}: out of range 1..CURVE.n`);
2462
- }
2463
- /**
2464
- * ECDSA signature with its (r, s) properties. Supports DER & compact representations.
2465
- */
2466
- class Signature {
2467
- constructor(r, s, recovery) {
2468
- aValidRS('r', r); // r in [1..N-1]
2469
- aValidRS('s', s); // s in [1..N-1]
2470
- this.r = r;
2471
- this.s = s;
2472
- if (recovery != null)
2473
- this.recovery = recovery;
2474
- Object.freeze(this);
2475
- }
2476
- // pair (bytes of r, bytes of s)
2477
- static fromCompact(hex) {
2478
- const L = Fn.BYTES;
2479
- const b = ensureBytes('compactSignature', hex, L * 2);
2480
- return new Signature(Fn.fromBytes(b.subarray(0, L)), Fn.fromBytes(b.subarray(L, L * 2)));
2481
- }
2482
- // DER encoded ECDSA signature
2483
- // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script
2484
- static fromDER(hex) {
2485
- const { r, s } = DER.toSig(ensureBytes('DER', hex));
2486
- return new Signature(r, s);
2487
- }
2488
- /**
2489
- * @todo remove
2490
- * @deprecated
2491
- */
2492
- assertValidity() { }
2493
- addRecoveryBit(recovery) {
2494
- return new Signature(this.r, this.s, recovery);
2495
- }
2496
- // ProjPointType<bigint>
2497
- recoverPublicKey(msgHash) {
2498
- const FIELD_ORDER = Fp.ORDER;
2499
- const { r, s, recovery: rec } = this;
2500
- if (rec == null || ![0, 1, 2, 3].includes(rec))
2501
- throw new Error('recovery id invalid');
2502
- // ECDSA recovery is hard for cofactor > 1 curves.
2503
- // In sign, `r = q.x mod n`, and here we recover q.x from r.
2504
- // While recovering q.x >= n, we need to add r+n for cofactor=1 curves.
2505
- // However, for cofactor>1, r+n may not get q.x:
2506
- // r+n*i would need to be done instead where i is unknown.
2507
- // To easily get i, we either need to:
2508
- // a. increase amount of valid recid values (4, 5...); OR
2509
- // b. prohibit non-prime-order signatures (recid > 1).
2510
- const hasCofactor = CURVE_ORDER * _2n$1 < FIELD_ORDER;
2511
- if (hasCofactor && rec > 1)
2512
- throw new Error('recovery id is ambiguous for h>1 curve');
2513
- const radj = rec === 2 || rec === 3 ? r + CURVE_ORDER : r;
2514
- if (!Fp.isValid(radj))
2515
- throw new Error('recovery id 2 or 3 invalid');
2516
- const x = Fp.toBytes(radj);
2517
- const R = Point.fromHex(concatBytes(pprefix((rec & 1) === 0), x));
2518
- const ir = Fn.inv(radj); // r^-1
2519
- const h = bits2int_modN(ensureBytes('msgHash', msgHash)); // Truncate hash
2520
- const u1 = Fn.create(-h * ir); // -hr^-1
2521
- const u2 = Fn.create(s * ir); // sr^-1
2522
- // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1). unsafe is fine: there is no private data.
2523
- const Q = Point.BASE.multiplyUnsafe(u1).add(R.multiplyUnsafe(u2));
2524
- if (Q.is0())
2525
- throw new Error('point at infinify');
2526
- Q.assertValidity();
2527
- return Q;
2528
- }
2529
- // Signatures should be low-s, to prevent malleability.
2530
- hasHighS() {
2531
- return isBiggerThanHalfOrder(this.s);
2532
- }
2533
- normalizeS() {
2534
- return this.hasHighS() ? new Signature(this.r, Fn.neg(this.s), this.recovery) : this;
2535
- }
2536
- toBytes(format) {
2537
- if (format === 'compact')
2538
- return concatBytes(Fn.toBytes(this.r), Fn.toBytes(this.s));
2539
- if (format === 'der')
2540
- return hexToBytes(DER.hexFromSig(this));
2541
- throw new Error('invalid format');
2542
- }
2543
- // DER-encoded
2544
- toDERRawBytes() {
2545
- return this.toBytes('der');
2546
- }
2547
- toDERHex() {
2548
- return bytesToHex(this.toBytes('der'));
2549
- }
2550
- // padded bytes of r, then padded bytes of s
2551
- toCompactRawBytes() {
2552
- return this.toBytes('compact');
2553
- }
2554
- toCompactHex() {
2555
- return bytesToHex(this.toBytes('compact'));
2556
- }
2557
- }
2558
- const normPrivateKeyToScalar = _legacyHelperNormPriv(Fn, curveOpts.allowedPrivateKeyLengths, curveOpts.wrapPrivateKey);
2559
- const utils = {
2560
- isValidPrivateKey(privateKey) {
2561
- try {
2562
- normPrivateKeyToScalar(privateKey);
2563
- return true;
2564
- }
2565
- catch (error) {
2566
- return false;
2567
- }
2568
- },
2569
- normPrivateKeyToScalar: normPrivateKeyToScalar,
2570
- /**
2571
- * Produces cryptographically secure private key from random of size
2572
- * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.
2573
- */
2574
- randomPrivateKey: () => {
2575
- const n = CURVE_ORDER;
2576
- return mapHashToField(randomBytes_(getMinHashLength(n)), n);
2577
- },
2578
- precompute(windowSize = 8, point = Point.BASE) {
2579
- return point.precompute(windowSize, false);
2580
- },
2581
- };
2582
- /**
2583
- * Computes public key for a private key. Checks for validity of the private key.
2584
- * @param privateKey private key
2585
- * @param isCompressed whether to return compact (default), or full key
2586
- * @returns Public key, full when isCompressed=false; short when isCompressed=true
2587
- */
2588
- function getPublicKey(privateKey, isCompressed = true) {
2589
- return Point.fromPrivateKey(privateKey).toBytes(isCompressed);
2590
- }
2591
- /**
2592
- * Quick and dirty check for item being public key. Does not validate hex, or being on-curve.
2593
- */
2594
- function isProbPub(item) {
2595
- if (typeof item === 'bigint')
2596
- return false;
2597
- if (item instanceof Point)
2598
- return true;
2599
- const arr = ensureBytes('key', item);
2600
- const length = arr.length;
2601
- const L = Fp.BYTES;
2602
- const LC = L + 1; // e.g. 33 for 32
2603
- const LU = 2 * L + 1; // e.g. 65 for 32
2604
- if (curveOpts.allowedPrivateKeyLengths || Fn.BYTES === LC) {
2605
- return undefined;
2606
- }
2607
- else {
2608
- return length === LC || length === LU;
2609
- }
2610
- }
2611
- /**
2612
- * ECDH (Elliptic Curve Diffie Hellman).
2613
- * Computes shared public key from private key and public key.
2614
- * Checks: 1) private key validity 2) shared key is on-curve.
2615
- * Does NOT hash the result.
2616
- * @param privateA private key
2617
- * @param publicB different public key
2618
- * @param isCompressed whether to return compact (default), or full key
2619
- * @returns shared public key
2620
- */
2621
- function getSharedSecret(privateA, publicB, isCompressed = true) {
2622
- if (isProbPub(privateA) === true)
2623
- throw new Error('first arg must be private key');
2624
- if (isProbPub(publicB) === false)
2625
- throw new Error('second arg must be public key');
2626
- const b = Point.fromHex(publicB); // check for being on-curve
2627
- return b.multiply(normPrivateKeyToScalar(privateA)).toBytes(isCompressed);
2628
- }
2629
- // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets.
2630
- // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int.
2631
- // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same.
2632
- // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors
2633
- const bits2int = ecdsaOpts.bits2int ||
2634
- function (bytes) {
2635
- // Our custom check "just in case", for protection against DoS
2636
- if (bytes.length > 8192)
2637
- throw new Error('input is too large');
2638
- // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)
2639
- // for some cases, since bytes.length * 8 is not actual bitLength.
2640
- const num = bytesToNumberBE(bytes); // check for == u8 done here
2641
- const delta = bytes.length * 8 - fnBits; // truncate to nBitLength leftmost bits
2642
- return delta > 0 ? num >> BigInt(delta) : num;
2643
- };
2644
- const bits2int_modN = ecdsaOpts.bits2int_modN ||
2645
- function (bytes) {
2646
- return Fn.create(bits2int(bytes)); // can't use bytesToNumberBE here
2647
- };
2648
- // NOTE: pads output with zero as per spec
2649
- const ORDER_MASK = bitMask(fnBits);
2650
- /**
2651
- * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.
2652
- */
2653
- function int2octets(num) {
2654
- // IMPORTANT: the check ensures working for case `Fn.BYTES != Fn.BITS * 8`
2655
- aInRange('num < 2^' + fnBits, num, _0n, ORDER_MASK);
2656
- return Fn.toBytes(num);
2657
- }
2658
- // Steps A, D of RFC6979 3.2
2659
- // Creates RFC6979 seed; converts msg/privKey to numbers.
2660
- // Used only in sign, not in verify.
2661
- // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order,
2662
- // this will be invalid at least for P521. Also it can be bigger for P224 + SHA256
2663
- function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
2664
- if (['recovered', 'canonical'].some((k) => k in opts))
2665
- throw new Error('sign() legacy options not supported');
2666
- const { hash } = ecdsaOpts;
2667
- let { lowS, prehash, extraEntropy: ent } = opts; // generates low-s sigs by default
2668
- if (lowS == null)
2669
- lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash
2670
- msgHash = ensureBytes('msgHash', msgHash);
2671
- validateSigVerOpts(opts);
2672
- if (prehash)
2673
- msgHash = ensureBytes('prehashed msgHash', hash(msgHash));
2674
- // We can't later call bits2octets, since nested bits2int is broken for curves
2675
- // with fnBits % 8 !== 0. Because of that, we unwrap it here as int2octets call.
2676
- // const bits2octets = (bits) => int2octets(bits2int_modN(bits))
2677
- const h1int = bits2int_modN(msgHash);
2678
- const d = normPrivateKeyToScalar(privateKey); // validate private key, convert to bigint
2679
- const seedArgs = [int2octets(d), int2octets(h1int)];
2680
- // extraEntropy. RFC6979 3.6: additional k' (optional).
2681
- if (ent != null && ent !== false) {
2682
- // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
2683
- const e = ent === true ? randomBytes_(Fp.BYTES) : ent; // generate random bytes OR pass as-is
2684
- seedArgs.push(ensureBytes('extraEntropy', e)); // check for being bytes
2685
- }
2686
- const seed = concatBytes(...seedArgs); // Step D of RFC6979 3.2
2687
- const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!
2688
- // Converts signature params into point w r/s, checks result for validity.
2689
- // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to
2690
- // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it:
2691
- // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT
2692
- function k2sig(kBytes) {
2693
- // RFC 6979 Section 3.2, step 3: k = bits2int(T)
2694
- // Important: all mod() calls here must be done over N
2695
- const k = bits2int(kBytes); // Cannot use fields methods, since it is group element
2696
- if (!Fn.isValidNot0(k))
2697
- return; // Valid scalars (including k) must be in 1..N-1
2698
- const ik = Fn.inv(k); // k^-1 mod n
2699
- const q = Point.BASE.multiply(k).toAffine(); // q = Gk
2700
- const r = Fn.create(q.x); // r = q.x mod n
2701
- if (r === _0n)
2702
- return;
2703
- const s = Fn.create(ik * Fn.create(m + r * d)); // Not using blinding here, see comment above
2704
- if (s === _0n)
2705
- return;
2706
- let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n$1); // recovery bit (2 or 3, when q.x > n)
2707
- let normS = s;
2708
- if (lowS && isBiggerThanHalfOrder(s)) {
2709
- normS = normalizeS(s); // if lowS was passed, ensure s is always
2710
- recovery ^= 1; // // in the bottom half of N
2711
- }
2712
- return new Signature(r, normS, recovery); // use normS, not s
2713
- }
2714
- return { seed, k2sig };
2715
- }
2716
- const defaultSigOpts = { lowS: ecdsaOpts.lowS, prehash: false };
2717
- const defaultVerOpts = { lowS: ecdsaOpts.lowS, prehash: false };
2718
- /**
2719
- * Signs message hash with a private key.
2720
- * ```
2721
- * sign(m, d, k) where
2722
- * (x, y) = G × k
2723
- * r = x mod n
2724
- * s = (m + dr)/k mod n
2725
- * ```
2726
- * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`.
2727
- * @param privKey private key
2728
- * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg.
2729
- * @returns signature with recovery param
2730
- */
2731
- function sign(msgHash, privKey, opts = defaultSigOpts) {
2732
- const { seed, k2sig } = prepSig(msgHash, privKey, opts); // Steps A, D of RFC6979 3.2.
2733
- const drbg = createHmacDrbg(ecdsaOpts.hash.outputLen, Fn.BYTES, hmac_);
2734
- return drbg(seed, k2sig); // Steps B, C, D, E, F, G
2735
- }
2736
- // Enable precomputes. Slows down first publicKey computation by 20ms.
2737
- Point.BASE.precompute(8);
2738
- /**
2739
- * Verifies a signature against message hash and public key.
2740
- * Rejects lowS signatures by default: to override,
2741
- * specify option `{lowS: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf:
2742
- *
2743
- * ```
2744
- * verify(r, s, h, P) where
2745
- * U1 = hs^-1 mod n
2746
- * U2 = rs^-1 mod n
2747
- * R = U1⋅G - U2⋅P
2748
- * mod(R.x, n) == r
2749
- * ```
2750
- */
2751
- function verify(signature, msgHash, publicKey, opts = defaultVerOpts) {
2752
- const sg = signature;
2753
- msgHash = ensureBytes('msgHash', msgHash);
2754
- publicKey = ensureBytes('publicKey', publicKey);
2755
- // Verify opts
2756
- validateSigVerOpts(opts);
2757
- const { lowS, prehash, format } = opts;
2758
- // TODO: remove
2759
- if ('strict' in opts)
2760
- throw new Error('options.strict was renamed to lowS');
2761
- if (format !== undefined && !['compact', 'der', 'js'].includes(format))
2762
- throw new Error('format must be "compact", "der" or "js"');
2763
- const isHex = typeof sg === 'string' || isBytes(sg);
2764
- const isObj = !isHex &&
2765
- !format &&
2766
- typeof sg === 'object' &&
2767
- sg !== null &&
2768
- typeof sg.r === 'bigint' &&
2769
- typeof sg.s === 'bigint';
2770
- if (!isHex && !isObj)
2771
- throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance');
2772
- let _sig = undefined;
2773
- let P;
2774
- // deduce signature format
2775
- try {
2776
- // if (format === 'js') {
2777
- // if (sg != null && !isBytes(sg)) _sig = new Signature(sg.r, sg.s);
2778
- // } else if (format === 'compact') {
2779
- // _sig = Signature.fromCompact(sg);
2780
- // } else if (format === 'der') {
2781
- // _sig = Signature.fromDER(sg);
2782
- // } else {
2783
- // throw new Error('invalid format');
2784
- // }
2785
- if (isObj) {
2786
- if (format === undefined || format === 'js') {
2787
- _sig = new Signature(sg.r, sg.s);
2788
- }
2789
- else {
2790
- throw new Error('invalid format');
2791
- }
2792
- }
2793
- if (isHex) {
2794
- // TODO: remove this malleable check
2795
- // Signature can be represented in 2 ways: compact (2*Fn.BYTES) & DER (variable-length).
2796
- // Since DER can also be 2*Fn.BYTES bytes, we check for it first.
2797
- try {
2798
- if (format !== 'compact')
2799
- _sig = Signature.fromDER(sg);
2800
- }
2801
- catch (derError) {
2802
- if (!(derError instanceof DER.Err))
2803
- throw derError;
2804
- }
2805
- if (!_sig && format !== 'der')
2806
- _sig = Signature.fromCompact(sg);
2807
- }
2808
- P = Point.fromHex(publicKey);
2809
- }
2810
- catch (error) {
2811
- return false;
2812
- }
2813
- if (!_sig)
2814
- return false;
2815
- if (lowS && _sig.hasHighS())
2816
- return false;
2817
- // todo: optional.hash => hash
2818
- if (prehash)
2819
- msgHash = ecdsaOpts.hash(msgHash);
2820
- const { r, s } = _sig;
2821
- const h = bits2int_modN(msgHash); // Cannot use fields methods, since it is group element
2822
- const is = Fn.inv(s); // s^-1
2823
- const u1 = Fn.create(h * is); // u1 = hs^-1 mod n
2824
- const u2 = Fn.create(r * is); // u2 = rs^-1 mod n
2825
- const R = Point.BASE.multiplyUnsafe(u1).add(P.multiplyUnsafe(u2));
2826
- if (R.is0())
2827
- return false;
2828
- const v = Fn.create(R.x); // v = r.x mod n
2829
- return v === r;
2830
- }
2831
- // TODO: clarify API for cloning .clone({hash: sha512}) ? .createWith({hash: sha512})?
2832
- // const clone = (hash: CHash): ECDSA => ecdsa(Point, { ...ecdsaOpts, ...getHash(hash) }, curveOpts);
2833
- return Object.freeze({
2834
- getPublicKey,
2835
- getSharedSecret,
2836
- sign,
2837
- verify,
2838
- utils,
2839
- Point,
2840
- Signature,
2841
- });
2842
- }
2843
- function _weierstrass_legacy_opts_to_new(c) {
2844
- const CURVE = {
2845
- a: c.a,
2846
- b: c.b,
2847
- p: c.Fp.ORDER,
2848
- n: c.n,
2849
- h: c.h,
2850
- Gx: c.Gx,
2851
- Gy: c.Gy,
2852
- };
2853
- const Fp = c.Fp;
2854
- const Fn = Field(CURVE.n, c.nBitLength);
2855
- const curveOpts = {
2856
- Fp,
2857
- Fn,
2858
- allowedPrivateKeyLengths: c.allowedPrivateKeyLengths,
2859
- allowInfinityPoint: c.allowInfinityPoint,
2860
- endo: c.endo,
2861
- wrapPrivateKey: c.wrapPrivateKey,
2862
- isTorsionFree: c.isTorsionFree,
2863
- clearCofactor: c.clearCofactor,
2864
- fromBytes: c.fromBytes,
2865
- toBytes: c.toBytes,
2866
- };
2867
- return { CURVE, curveOpts };
2868
- }
2869
- function _ecdsa_legacy_opts_to_new(c) {
2870
- const { CURVE, curveOpts } = _weierstrass_legacy_opts_to_new(c);
2871
- const ecdsaOpts = {
2872
- hash: c.hash,
2873
- hmac: c.hmac,
2874
- randomBytes: c.randomBytes,
2875
- lowS: c.lowS,
2876
- bits2int: c.bits2int,
2877
- bits2int_modN: c.bits2int_modN,
2878
- };
2879
- return { CURVE, curveOpts, ecdsaOpts };
2880
- }
2881
- function _ecdsa_new_output_to_legacy(c, ecdsa) {
2882
- return Object.assign({}, ecdsa, {
2883
- ProjectivePoint: ecdsa.Point,
2884
- CURVE: c,
2885
- });
2886
- }
2887
- // _ecdsa_legacy
2888
- function weierstrass(c) {
2889
- const { CURVE, curveOpts, ecdsaOpts } = _ecdsa_legacy_opts_to_new(c);
2890
- const Point = weierstrassN(CURVE, curveOpts);
2891
- const signs = ecdsa(Point, ecdsaOpts, curveOpts);
2892
- return _ecdsa_new_output_to_legacy(c, signs);
2893
- }
2894
-
2895
- /**
2896
- * Utilities for short weierstrass curves, combined with noble-hashes.
2897
- * @module
2898
- */
2899
- /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2900
- function createCurve(curveDef, defHash) {
2901
- const create = (hash) => weierstrass({ ...curveDef, hash: hash });
2902
- return { ...create(defHash), create };
2903
- }
2904
-
2905
- /**
2906
- * SECG secp256k1. See [pdf](https://www.secg.org/sec2-v2.pdf).
2907
- *
2908
- * Belongs to Koblitz curves: it has efficiently-computable GLV endomorphism ψ,
2909
- * check out {@link EndomorphismOpts}. Seems to be rigid (not backdoored).
2910
- * @module
2911
- */
2912
- /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2913
- // Seems like generator was produced from some seed:
2914
- // `Point.BASE.multiply(Point.Fn.inv(2n, N)).toAffine().x`
2915
- // // gives short x 0x3b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63n
2916
- const secp256k1_CURVE = {
2917
- p: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'),
2918
- n: BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'),
2919
- h: BigInt(1),
2920
- a: BigInt(0),
2921
- b: BigInt(7),
2922
- Gx: BigInt('0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'),
2923
- Gy: BigInt('0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'),
2924
- };
2925
- BigInt(0);
2926
- const _1n = BigInt(1);
2927
- const _2n = BigInt(2);
2928
- const divNearest = (a, b) => (a + b / _2n) / b;
2929
- /**
2930
- * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit.
2931
- * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00]
2932
- */
2933
- function sqrtMod(y) {
2934
- const P = secp256k1_CURVE.p;
2935
- // prettier-ignore
2936
- const _3n = BigInt(3), _6n = BigInt(6), _11n = BigInt(11), _22n = BigInt(22);
2937
- // prettier-ignore
2938
- const _23n = BigInt(23), _44n = BigInt(44), _88n = BigInt(88);
2939
- const b2 = (y * y * y) % P; // x^3, 11
2940
- const b3 = (b2 * b2 * y) % P; // x^7
2941
- const b6 = (pow2(b3, _3n, P) * b3) % P;
2942
- const b9 = (pow2(b6, _3n, P) * b3) % P;
2943
- const b11 = (pow2(b9, _2n, P) * b2) % P;
2944
- const b22 = (pow2(b11, _11n, P) * b11) % P;
2945
- const b44 = (pow2(b22, _22n, P) * b22) % P;
2946
- const b88 = (pow2(b44, _44n, P) * b44) % P;
2947
- const b176 = (pow2(b88, _88n, P) * b88) % P;
2948
- const b220 = (pow2(b176, _44n, P) * b44) % P;
2949
- const b223 = (pow2(b220, _3n, P) * b3) % P;
2950
- const t1 = (pow2(b223, _23n, P) * b22) % P;
2951
- const t2 = (pow2(t1, _6n, P) * b2) % P;
2952
- const root = pow2(t2, _2n, P);
2953
- if (!Fpk1.eql(Fpk1.sqr(root), y))
2954
- throw new Error('Cannot find square root');
2955
- return root;
2956
- }
2957
- const Fpk1 = Field(secp256k1_CURVE.p, undefined, undefined, { sqrt: sqrtMod });
2958
- /**
2959
- * secp256k1 curve, ECDSA and ECDH methods.
2960
- *
2961
- * Field: `2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n`
2962
- *
2963
- * @example
2964
- * ```js
2965
- * import { secp256k1 } from '@noble/curves/secp256k1';
2966
- * const priv = secp256k1.utils.randomPrivateKey();
2967
- * const pub = secp256k1.getPublicKey(priv);
2968
- * const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa
2969
- * const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available
2970
- * const isValid = secp256k1.verify(sig, msg, pub) === true;
2971
- * ```
2972
- */
2973
- const secp256k1 = createCurve({
2974
- ...secp256k1_CURVE,
2975
- Fp: Fpk1,
2976
- lowS: true, // Allow only low-S signatures by default in sign() and verify()
2977
- endo: {
2978
- // Endomorphism, see above
2979
- beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
2980
- splitScalar: (k) => {
2981
- const n = secp256k1_CURVE.n;
2982
- const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15');
2983
- const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3');
2984
- const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8');
2985
- const b2 = a1;
2986
- const POW_2_128 = BigInt('0x100000000000000000000000000000000'); // (2n**128n).toString(16)
2987
- const c1 = divNearest(b2 * k, n);
2988
- const c2 = divNearest(-b1 * k, n);
2989
- let k1 = mod(k - c1 * a1 - c2 * a2, n);
2990
- let k2 = mod(-c1 * b1 - c2 * b2, n);
2991
- const k1neg = k1 > POW_2_128;
2992
- const k2neg = k2 > POW_2_128;
2993
- if (k1neg)
2994
- k1 = n - k1;
2995
- if (k2neg)
2996
- k2 = n - k2;
2997
- if (k1 > POW_2_128 || k2 > POW_2_128) {
2998
- throw new Error('splitScalar: Endomorphism failed, k=' + k);
2999
- }
3000
- return { k1neg, k1, k2neg, k2 };
3001
- },
3002
- },
3003
- }, sha256);
3004
-
3005
- /**
3006
-
3007
- SHA1 (RFC 3174), MD5 (RFC 1321) and RIPEMD160 (RFC 2286) legacy, weak hash functions.
3008
- Don't use them in a new protocol. What "weak" means:
3009
-
3010
- - Collisions can be made with 2^18 effort in MD5, 2^60 in SHA1, 2^80 in RIPEMD160.
3011
- - No practical pre-image attacks (only theoretical, 2^123.4)
3012
- - HMAC seems kinda ok: https://datatracker.ietf.org/doc/html/rfc6151
3013
- * @module
3014
- */
3015
- // RIPEMD-160
3016
- const Rho160 = /* @__PURE__ */ Uint8Array.from([
3017
- 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
3018
- ]);
3019
- const Id160 = /* @__PURE__ */ (() => Uint8Array.from(new Array(16).fill(0).map((_, i) => i)))();
3020
- const Pi160 = /* @__PURE__ */ (() => Id160.map((i) => (9 * i + 5) % 16))();
3021
- const idxLR = /* @__PURE__ */ (() => {
3022
- const L = [Id160];
3023
- const R = [Pi160];
3024
- const res = [L, R];
3025
- for (let i = 0; i < 4; i++)
3026
- for (let j of res)
3027
- j.push(j[i].map((k) => Rho160[k]));
3028
- return res;
3029
- })();
3030
- const idxL = /* @__PURE__ */ (() => idxLR[0])();
3031
- const idxR = /* @__PURE__ */ (() => idxLR[1])();
3032
- // const [idxL, idxR] = idxLR;
3033
- const shifts160 = /* @__PURE__ */ [
3034
- [11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8],
3035
- [12, 13, 11, 15, 6, 9, 9, 7, 12, 15, 11, 13, 7, 8, 7, 7],
3036
- [13, 15, 14, 11, 7, 7, 6, 8, 13, 14, 13, 12, 5, 5, 6, 9],
3037
- [14, 11, 12, 14, 8, 6, 5, 5, 15, 12, 15, 14, 9, 9, 8, 6],
3038
- [15, 12, 13, 13, 9, 5, 8, 6, 14, 11, 12, 11, 8, 6, 5, 5],
3039
- ].map((i) => Uint8Array.from(i));
3040
- const shiftsL160 = /* @__PURE__ */ idxL.map((idx, i) => idx.map((j) => shifts160[i][j]));
3041
- const shiftsR160 = /* @__PURE__ */ idxR.map((idx, i) => idx.map((j) => shifts160[i][j]));
3042
- const Kl160 = /* @__PURE__ */ Uint32Array.from([
3043
- 0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e,
3044
- ]);
3045
- const Kr160 = /* @__PURE__ */ Uint32Array.from([
3046
- 0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000,
3047
- ]);
3048
- // It's called f() in spec.
3049
- function ripemd_f(group, x, y, z) {
3050
- if (group === 0)
3051
- return x ^ y ^ z;
3052
- if (group === 1)
3053
- return (x & y) | (~x & z);
3054
- if (group === 2)
3055
- return (x | ~y) ^ z;
3056
- if (group === 3)
3057
- return (x & z) | (y & ~z);
3058
- return x ^ (y | ~z);
3059
- }
3060
- // Reusable temporary buffer
3061
- const BUF_160 = /* @__PURE__ */ new Uint32Array(16);
3062
- class RIPEMD160 extends HashMD {
3063
- constructor() {
3064
- super(64, 20, 8, true);
3065
- this.h0 = 0x67452301 | 0;
3066
- this.h1 = 0xefcdab89 | 0;
3067
- this.h2 = 0x98badcfe | 0;
3068
- this.h3 = 0x10325476 | 0;
3069
- this.h4 = 0xc3d2e1f0 | 0;
3070
- }
3071
- get() {
3072
- const { h0, h1, h2, h3, h4 } = this;
3073
- return [h0, h1, h2, h3, h4];
3074
- }
3075
- set(h0, h1, h2, h3, h4) {
3076
- this.h0 = h0 | 0;
3077
- this.h1 = h1 | 0;
3078
- this.h2 = h2 | 0;
3079
- this.h3 = h3 | 0;
3080
- this.h4 = h4 | 0;
3081
- }
3082
- process(view, offset) {
3083
- for (let i = 0; i < 16; i++, offset += 4)
3084
- BUF_160[i] = view.getUint32(offset, true);
3085
- // prettier-ignore
3086
- let al = this.h0 | 0, ar = al, bl = this.h1 | 0, br = bl, cl = this.h2 | 0, cr = cl, dl = this.h3 | 0, dr = dl, el = this.h4 | 0, er = el;
3087
- // Instead of iterating 0 to 80, we split it into 5 groups
3088
- // And use the groups in constants, functions, etc. Much simpler
3089
- for (let group = 0; group < 5; group++) {
3090
- const rGroup = 4 - group;
3091
- const hbl = Kl160[group], hbr = Kr160[group]; // prettier-ignore
3092
- const rl = idxL[group], rr = idxR[group]; // prettier-ignore
3093
- const sl = shiftsL160[group], sr = shiftsR160[group]; // prettier-ignore
3094
- for (let i = 0; i < 16; i++) {
3095
- const tl = (rotl(al + ripemd_f(group, bl, cl, dl) + BUF_160[rl[i]] + hbl, sl[i]) + el) | 0;
3096
- al = el, el = dl, dl = rotl(cl, 10) | 0, cl = bl, bl = tl; // prettier-ignore
3097
- }
3098
- // 2 loops are 10% faster
3099
- for (let i = 0; i < 16; i++) {
3100
- const tr = (rotl(ar + ripemd_f(rGroup, br, cr, dr) + BUF_160[rr[i]] + hbr, sr[i]) + er) | 0;
3101
- ar = er, er = dr, dr = rotl(cr, 10) | 0, cr = br, br = tr; // prettier-ignore
3102
- }
3103
- }
3104
- // Add the compressed chunk to the current hash value
3105
- this.set((this.h1 + cl + dr) | 0, (this.h2 + dl + er) | 0, (this.h3 + el + ar) | 0, (this.h4 + al + br) | 0, (this.h0 + bl + cr) | 0);
3106
- }
3107
- roundClean() {
3108
- clean(BUF_160);
3109
- }
3110
- destroy() {
3111
- this.destroyed = true;
3112
- clean(this.buffer);
3113
- this.set(0, 0, 0, 0, 0);
3114
- }
3115
- }
3116
- /**
3117
- * RIPEMD-160 - a legacy hash function from 1990s.
3118
- * * https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
3119
- * * https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf
3120
- */
3121
- const ripemd160 = /* @__PURE__ */ createHasher(() => new RIPEMD160());
3122
-
3123
- /**
3124
- * @module BIP32 hierarchical deterministic (HD) wallets over secp256k1.
3125
- * @example
3126
- * ```js
3127
- * import { HDKey } from "@scure/bip32";
3128
- * const hdkey1 = HDKey.fromMasterSeed(seed);
3129
- * const hdkey2 = HDKey.fromExtendedKey(base58key);
3130
- * const hdkey3 = HDKey.fromJSON({ xpriv: string });
3131
- *
3132
- * // props
3133
- * [hdkey1.depth, hdkey1.index, hdkey1.chainCode];
3134
- * console.log(hdkey2.privateKey, hdkey2.publicKey);
3135
- * console.log(hdkey3.derive("m/0/2147483647'/1"));
3136
- * const sig = hdkey3.sign(hash);
3137
- * hdkey3.verify(hash, sig);
3138
- * ```
3139
- */
3140
- /*! scure-bip32 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) */
3141
- const Point = secp256k1.ProjectivePoint;
3142
- const base58check = createBase58check(sha256);
3143
- function bytesToNumber(bytes) {
3144
- abytes(bytes);
3145
- const h = bytes.length === 0 ? '0' : bytesToHex(bytes);
3146
- return BigInt('0x' + h);
3147
- }
3148
- function numberToBytes(num) {
3149
- if (typeof num !== 'bigint')
3150
- throw new Error('bigint expected');
3151
- return hexToBytes(num.toString(16).padStart(64, '0'));
3152
- }
3153
- const MASTER_SECRET = utf8ToBytes('Bitcoin seed');
3154
- // Bitcoin hardcoded by default
3155
- const BITCOIN_VERSIONS = { private: 0x0488ade4, public: 0x0488b21e };
3156
- const HARDENED_OFFSET = 0x80000000;
3157
- const hash160 = (data) => ripemd160(sha256(data));
3158
- const fromU32 = (data) => createView(data).getUint32(0, false);
3159
- const toU32 = (n) => {
3160
- if (!Number.isSafeInteger(n) || n < 0 || n > 2 ** 32 - 1) {
3161
- throw new Error('invalid number, should be from 0 to 2**32-1, got ' + n);
3162
- }
3163
- const buf = new Uint8Array(4);
3164
- createView(buf).setUint32(0, n, false);
3165
- return buf;
3166
- };
3167
- class HDKey {
3168
- get fingerprint() {
3169
- if (!this.pubHash) {
3170
- throw new Error('No publicKey set!');
3171
- }
3172
- return fromU32(this.pubHash);
3173
- }
3174
- get identifier() {
3175
- return this.pubHash;
3176
- }
3177
- get pubKeyHash() {
3178
- return this.pubHash;
3179
- }
3180
- get privateKey() {
3181
- return this.privKeyBytes || null;
3182
- }
3183
- get publicKey() {
3184
- return this.pubKey || null;
3185
- }
3186
- get privateExtendedKey() {
3187
- const priv = this.privateKey;
3188
- if (!priv) {
3189
- throw new Error('No private key');
3190
- }
3191
- return base58check.encode(this.serialize(this.versions.private, concatBytes(new Uint8Array([0]), priv)));
3192
- }
3193
- get publicExtendedKey() {
3194
- if (!this.pubKey) {
3195
- throw new Error('No public key');
3196
- }
3197
- return base58check.encode(this.serialize(this.versions.public, this.pubKey));
3198
- }
3199
- static fromMasterSeed(seed, versions = BITCOIN_VERSIONS) {
3200
- abytes(seed);
3201
- if (8 * seed.length < 128 || 8 * seed.length > 512) {
3202
- throw new Error('HDKey: seed length must be between 128 and 512 bits; 256 bits is advised, got ' +
3203
- seed.length);
3204
- }
3205
- const I = hmac(sha512, MASTER_SECRET, seed);
3206
- return new HDKey({
3207
- versions,
3208
- chainCode: I.slice(32),
3209
- privateKey: I.slice(0, 32),
3210
- });
3211
- }
3212
- static fromExtendedKey(base58key, versions = BITCOIN_VERSIONS) {
3213
- // => version(4) || depth(1) || fingerprint(4) || index(4) || chain(32) || key(33)
3214
- const keyBuffer = base58check.decode(base58key);
3215
- const keyView = createView(keyBuffer);
3216
- const version = keyView.getUint32(0, false);
3217
- const opt = {
3218
- versions,
3219
- depth: keyBuffer[4],
3220
- parentFingerprint: keyView.getUint32(5, false),
3221
- index: keyView.getUint32(9, false),
3222
- chainCode: keyBuffer.slice(13, 45),
3223
- };
3224
- const key = keyBuffer.slice(45);
3225
- const isPriv = key[0] === 0;
3226
- if (version !== versions[isPriv ? 'private' : 'public']) {
3227
- throw new Error('Version mismatch');
3228
- }
3229
- if (isPriv) {
3230
- return new HDKey({ ...opt, privateKey: key.slice(1) });
3231
- }
3232
- else {
3233
- return new HDKey({ ...opt, publicKey: key });
3234
- }
3235
- }
3236
- static fromJSON(json) {
3237
- return HDKey.fromExtendedKey(json.xpriv);
3238
- }
3239
- constructor(opt) {
3240
- this.depth = 0;
3241
- this.index = 0;
3242
- this.chainCode = null;
3243
- this.parentFingerprint = 0;
3244
- if (!opt || typeof opt !== 'object') {
3245
- throw new Error('HDKey.constructor must not be called directly');
3246
- }
3247
- this.versions = opt.versions || BITCOIN_VERSIONS;
3248
- this.depth = opt.depth || 0;
3249
- this.chainCode = opt.chainCode || null;
3250
- this.index = opt.index || 0;
3251
- this.parentFingerprint = opt.parentFingerprint || 0;
3252
- if (!this.depth) {
3253
- if (this.parentFingerprint || this.index) {
3254
- throw new Error('HDKey: zero depth with non-zero index/parent fingerprint');
3255
- }
3256
- }
3257
- if (opt.publicKey && opt.privateKey) {
3258
- throw new Error('HDKey: publicKey and privateKey at same time.');
3259
- }
3260
- if (opt.privateKey) {
3261
- if (!secp256k1.utils.isValidPrivateKey(opt.privateKey)) {
3262
- throw new Error('Invalid private key');
3263
- }
3264
- this.privKey =
3265
- typeof opt.privateKey === 'bigint' ? opt.privateKey : bytesToNumber(opt.privateKey);
3266
- this.privKeyBytes = numberToBytes(this.privKey);
3267
- this.pubKey = secp256k1.getPublicKey(opt.privateKey, true);
3268
- }
3269
- else if (opt.publicKey) {
3270
- this.pubKey = Point.fromHex(opt.publicKey).toRawBytes(true); // force compressed point
3271
- }
3272
- else {
3273
- throw new Error('HDKey: no public or private key provided');
3274
- }
3275
- this.pubHash = hash160(this.pubKey);
3276
- }
3277
- derive(path) {
3278
- if (!/^[mM]'?/.test(path)) {
3279
- throw new Error('Path must start with "m" or "M"');
3280
- }
3281
- if (/^[mM]'?$/.test(path)) {
3282
- return this;
3283
- }
3284
- const parts = path.replace(/^[mM]'?\//, '').split('/');
3285
- // tslint:disable-next-line
3286
- let child = this;
3287
- for (const c of parts) {
3288
- const m = /^(\d+)('?)$/.exec(c);
3289
- const m1 = m && m[1];
3290
- if (!m || m.length !== 3 || typeof m1 !== 'string')
3291
- throw new Error('invalid child index: ' + c);
3292
- let idx = +m1;
3293
- if (!Number.isSafeInteger(idx) || idx >= HARDENED_OFFSET) {
3294
- throw new Error('Invalid index');
3295
- }
3296
- // hardened key
3297
- if (m[2] === "'") {
3298
- idx += HARDENED_OFFSET;
3299
- }
3300
- child = child.deriveChild(idx);
3301
- }
3302
- return child;
3303
- }
3304
- deriveChild(index) {
3305
- if (!this.pubKey || !this.chainCode) {
3306
- throw new Error('No publicKey or chainCode set');
3307
- }
3308
- let data = toU32(index);
3309
- if (index >= HARDENED_OFFSET) {
3310
- // Hardened
3311
- const priv = this.privateKey;
3312
- if (!priv) {
3313
- throw new Error('Could not derive hardened child key');
3314
- }
3315
- // Hardened child: 0x00 || ser256(kpar) || ser32(index)
3316
- data = concatBytes(new Uint8Array([0]), priv, data);
3317
- }
3318
- else {
3319
- // Normal child: serP(point(kpar)) || ser32(index)
3320
- data = concatBytes(this.pubKey, data);
3321
- }
3322
- const I = hmac(sha512, this.chainCode, data);
3323
- const childTweak = bytesToNumber(I.slice(0, 32));
3324
- const chainCode = I.slice(32);
3325
- if (!secp256k1.utils.isValidPrivateKey(childTweak)) {
3326
- throw new Error('Tweak bigger than curve order');
3327
- }
3328
- const opt = {
3329
- versions: this.versions,
3330
- chainCode,
3331
- depth: this.depth + 1,
3332
- parentFingerprint: this.fingerprint,
3333
- index,
3334
- };
3335
- try {
3336
- // Private parent key -> private child key
3337
- if (this.privateKey) {
3338
- const added = mod(this.privKey + childTweak, secp256k1.CURVE.n);
3339
- if (!secp256k1.utils.isValidPrivateKey(added)) {
3340
- throw new Error('The tweak was out of range or the resulted private key is invalid');
3341
- }
3342
- opt.privateKey = added;
3343
- }
3344
- else {
3345
- const added = Point.fromHex(this.pubKey).add(Point.fromPrivateKey(childTweak));
3346
- // Cryptographically impossible: hmac-sha512 preimage would need to be found
3347
- if (added.equals(Point.ZERO)) {
3348
- throw new Error('The tweak was equal to negative P, which made the result key invalid');
3349
- }
3350
- opt.publicKey = added.toRawBytes(true);
3351
- }
3352
- return new HDKey(opt);
3353
- }
3354
- catch (err) {
3355
- return this.deriveChild(index + 1);
3356
- }
3357
- }
3358
- sign(hash) {
3359
- if (!this.privateKey) {
3360
- throw new Error('No privateKey set!');
3361
- }
3362
- abytes(hash, 32);
3363
- return secp256k1.sign(hash, this.privKey).toCompactRawBytes();
3364
- }
3365
- verify(hash, signature) {
3366
- abytes(hash, 32);
3367
- abytes(signature, 64);
3368
- if (!this.publicKey) {
3369
- throw new Error('No publicKey set!');
3370
- }
3371
- let sig;
3372
- try {
3373
- sig = secp256k1.Signature.fromCompact(signature);
3374
- }
3375
- catch (error) {
3376
- return false;
3377
- }
3378
- return secp256k1.verify(sig, hash, this.publicKey);
3379
- }
3380
- wipePrivateData() {
3381
- this.privKey = undefined;
3382
- if (this.privKeyBytes) {
3383
- this.privKeyBytes.fill(0);
3384
- this.privKeyBytes = undefined;
3385
- }
3386
- return this;
3387
- }
3388
- toJSON() {
3389
- return {
3390
- xpriv: this.privateExtendedKey,
3391
- xpub: this.publicExtendedKey,
3392
- };
3393
- }
3394
- serialize(version, key) {
3395
- if (!this.chainCode) {
3396
- throw new Error('No chainCode set');
3397
- }
3398
- abytes(key, 33);
3399
- // version(4) || depth(1) || fingerprint(4) || index(4) || chain(32) || key(33)
3400
- return concatBytes(toU32(version), new Uint8Array([this.depth]), toU32(this.parentFingerprint), toU32(this.index), this.chainCode, key);
3401
- }
3402
- }
3403
-
3404
42
  /**
3405
43
  * Chain identifier for Radix.
3406
44
  * This constant represents the identifier for the Radix Chain.
@@ -3837,9 +475,11 @@ class Client extends BaseXChainClient {
3837
475
  }
3838
476
  const updatedDerivationPath = derivationPath.replace(/\/$/, '') + `/${index}'`;
3839
477
  if (this.curve === 'Ed25519') {
3840
- const seedHex = seed.toString('hex');
3841
- const keys = derivePath(updatedDerivationPath, seedHex);
3842
- return keys.key;
478
+ const masterKey = slip10.fromMasterSeed(seed);
479
+ const childKey = masterKey.derive(updatedDerivationPath);
480
+ if (!childKey.privateKey)
481
+ throw new Error('child does not have a privateKey');
482
+ return Buffer.from(childKey.privateKey);
3843
483
  }
3844
484
  else {
3845
485
  const node = HDKey.fromMasterSeed(seed);
@@ -3941,7 +581,7 @@ class Client extends BaseXChainClient {
3941
581
  }
3942
582
  return true;
3943
583
  }
3944
- catch (error) {
584
+ catch (_error) {
3945
585
  return false;
3946
586
  }
3947
587
  }
@@ -4015,7 +655,7 @@ class Client extends BaseXChainClient {
4015
655
  txList.txs.push(transaction);
4016
656
  }
4017
657
  }
4018
- catch (error) { }
658
+ catch (_error) { }
4019
659
  }
4020
660
  txList.total = txList.txs.length;
4021
661
  return txList;
@@ -4052,7 +692,7 @@ class Client extends BaseXChainClient {
4052
692
  throw new Error('Incomplete transaction data received');
4053
693
  }
4054
694
  }
4055
- catch (error) {
695
+ catch (_error) {
4056
696
  throw new Error('Failed to fetch transaction data');
4057
697
  }
4058
698
  });
@@ -4103,7 +743,7 @@ class Client extends BaseXChainClient {
4103
743
  };
4104
744
  return transaction;
4105
745
  }
4106
- catch (error) {
746
+ catch (_error) {
4107
747
  return {
4108
748
  from: [],
4109
749
  to: [],