@frequency-chain/ethereum-utils 1.17.0-rc5 → 1.17.0-rc7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/address.d.ts +1 -1
- package/browser/frequency-ethereum-utils.esm.min.js +902 -656
- package/browser/frequency-ethereum-utils.umd.min.js +882 -644
- package/cjs/index.js +8 -8
- package/cjs/signature.definitions.js +53 -3
- package/cjs/signature.js +184 -64
- package/esm/index.js +8 -8
- package/esm/signature.definitions.js +52 -2
- package/esm/signature.js +137 -22
- package/index.d.ts +33 -15
- package/package.json +7 -4
- package/payloads.d.ts +20 -1
- package/signature.d.ts +45 -5
- package/signature.definitions.d.ts +67 -2
- package/utils.d.ts +1 -1
|
@@ -137,7 +137,11 @@ function getAugmentedNamespace(n) {
|
|
|
137
137
|
var f = n.default;
|
|
138
138
|
if (typeof f == "function") {
|
|
139
139
|
var a = function a () {
|
|
140
|
-
|
|
140
|
+
var isInstance = false;
|
|
141
|
+
try {
|
|
142
|
+
isInstance = this instanceof a;
|
|
143
|
+
} catch {}
|
|
144
|
+
if (isInstance) {
|
|
141
145
|
return Reflect.construct(f, arguments, this.constructor);
|
|
142
146
|
}
|
|
143
147
|
return f.apply(this, arguments);
|
|
@@ -4553,7 +4557,7 @@ const keccak512 = /*#__PURE__*/ withWasm((wasm, data) => {
|
|
|
4553
4557
|
function isReady() {
|
|
4554
4558
|
return !!bridge.wasm;
|
|
4555
4559
|
}/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
4556
|
-
function isBytes$
|
|
4560
|
+
function isBytes$1(a) {
|
|
4557
4561
|
return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
|
|
4558
4562
|
}
|
|
4559
4563
|
function isArrayOf(isString, arr) {
|
|
@@ -4713,7 +4717,7 @@ function radix(num) {
|
|
|
4713
4717
|
const _256 = 2 ** 8;
|
|
4714
4718
|
return {
|
|
4715
4719
|
encode: (bytes) => {
|
|
4716
|
-
if (!isBytes$
|
|
4720
|
+
if (!isBytes$1(bytes))
|
|
4717
4721
|
throw new Error('radix.encode input should be Uint8Array');
|
|
4718
4722
|
return convertRadix(Array.from(bytes), _256, num);
|
|
4719
4723
|
},
|
|
@@ -4815,7 +4819,7 @@ const base58Encode = /*#__PURE__*/ createEncode(config);const crypto$2 = typeof
|
|
|
4815
4819
|
// Makes the utils un-importable in browsers without a bundler.
|
|
4816
4820
|
// Once node.js 18 is deprecated (2025-04-30), we can just drop the import.
|
|
4817
4821
|
/** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */
|
|
4818
|
-
function isBytes
|
|
4822
|
+
function isBytes(a) {
|
|
4819
4823
|
return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
|
|
4820
4824
|
}
|
|
4821
4825
|
/** Asserts something is positive integer. */
|
|
@@ -4824,8 +4828,8 @@ function anumber(n) {
|
|
|
4824
4828
|
throw new Error('positive integer expected, got ' + n);
|
|
4825
4829
|
}
|
|
4826
4830
|
/** Asserts something is Uint8Array. */
|
|
4827
|
-
function abytes
|
|
4828
|
-
if (!isBytes
|
|
4831
|
+
function abytes(b, ...lengths) {
|
|
4832
|
+
if (!isBytes(b))
|
|
4829
4833
|
throw new Error('Uint8Array expected');
|
|
4830
4834
|
if (lengths.length > 0 && !lengths.includes(b.length))
|
|
4831
4835
|
throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length);
|
|
@@ -4846,7 +4850,7 @@ function aexists(instance, checkFinished = true) {
|
|
|
4846
4850
|
}
|
|
4847
4851
|
/** Asserts output is properly-sized byte array */
|
|
4848
4852
|
function aoutput(out, instance) {
|
|
4849
|
-
abytes
|
|
4853
|
+
abytes(out);
|
|
4850
4854
|
const min = instance.outputLen;
|
|
4851
4855
|
if (out.length < min) {
|
|
4852
4856
|
throw new Error('digestInto() expects output buffer of length at least ' + min);
|
|
@@ -4893,6 +4897,65 @@ function byteSwap32(arr) {
|
|
|
4893
4897
|
const swap32IfBE = isLE$1
|
|
4894
4898
|
? (u) => u
|
|
4895
4899
|
: byteSwap32;
|
|
4900
|
+
// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex
|
|
4901
|
+
const hasHexBuiltin = /* @__PURE__ */ (() =>
|
|
4902
|
+
// @ts-ignore
|
|
4903
|
+
typeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function')();
|
|
4904
|
+
// Array where index 0xf0 (240) is mapped to string 'f0'
|
|
4905
|
+
const hexes$1 = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));
|
|
4906
|
+
/**
|
|
4907
|
+
* Convert byte array to hex string. Uses built-in function, when available.
|
|
4908
|
+
* @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'
|
|
4909
|
+
*/
|
|
4910
|
+
function bytesToHex$1(bytes) {
|
|
4911
|
+
abytes(bytes);
|
|
4912
|
+
// @ts-ignore
|
|
4913
|
+
if (hasHexBuiltin)
|
|
4914
|
+
return bytes.toHex();
|
|
4915
|
+
// pre-caching improves the speed 6x
|
|
4916
|
+
let hex = '';
|
|
4917
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
4918
|
+
hex += hexes$1[bytes[i]];
|
|
4919
|
+
}
|
|
4920
|
+
return hex;
|
|
4921
|
+
}
|
|
4922
|
+
// We use optimized technique to convert hex string to byte array
|
|
4923
|
+
const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
|
|
4924
|
+
function asciiToBase16(ch) {
|
|
4925
|
+
if (ch >= asciis._0 && ch <= asciis._9)
|
|
4926
|
+
return ch - asciis._0; // '2' => 50-48
|
|
4927
|
+
if (ch >= asciis.A && ch <= asciis.F)
|
|
4928
|
+
return ch - (asciis.A - 10); // 'B' => 66-(65-10)
|
|
4929
|
+
if (ch >= asciis.a && ch <= asciis.f)
|
|
4930
|
+
return ch - (asciis.a - 10); // 'b' => 98-(97-10)
|
|
4931
|
+
return;
|
|
4932
|
+
}
|
|
4933
|
+
/**
|
|
4934
|
+
* Convert hex string to byte array. Uses built-in function, when available.
|
|
4935
|
+
* @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])
|
|
4936
|
+
*/
|
|
4937
|
+
function hexToBytes$1(hex) {
|
|
4938
|
+
if (typeof hex !== 'string')
|
|
4939
|
+
throw new Error('hex string expected, got ' + typeof hex);
|
|
4940
|
+
// @ts-ignore
|
|
4941
|
+
if (hasHexBuiltin)
|
|
4942
|
+
return Uint8Array.fromHex(hex);
|
|
4943
|
+
const hl = hex.length;
|
|
4944
|
+
const al = hl / 2;
|
|
4945
|
+
if (hl % 2)
|
|
4946
|
+
throw new Error('hex string expected, got unpadded hex of length ' + hl);
|
|
4947
|
+
const array = new Uint8Array(al);
|
|
4948
|
+
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
|
|
4949
|
+
const n1 = asciiToBase16(hex.charCodeAt(hi));
|
|
4950
|
+
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
|
|
4951
|
+
if (n1 === undefined || n2 === undefined) {
|
|
4952
|
+
const char = hex[hi] + hex[hi + 1];
|
|
4953
|
+
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
|
|
4954
|
+
}
|
|
4955
|
+
array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163
|
|
4956
|
+
}
|
|
4957
|
+
return array;
|
|
4958
|
+
}
|
|
4896
4959
|
/**
|
|
4897
4960
|
* Converts string to bytes using UTF8 encoding.
|
|
4898
4961
|
* @example utf8ToBytes('abc') // Uint8Array.from([97, 98, 99])
|
|
@@ -4910,15 +4973,15 @@ function utf8ToBytes$2(str) {
|
|
|
4910
4973
|
function toBytes$1(data) {
|
|
4911
4974
|
if (typeof data === 'string')
|
|
4912
4975
|
data = utf8ToBytes$2(data);
|
|
4913
|
-
abytes
|
|
4976
|
+
abytes(data);
|
|
4914
4977
|
return data;
|
|
4915
4978
|
}
|
|
4916
4979
|
/** Copies several Uint8Arrays into one. */
|
|
4917
|
-
function concatBytes$
|
|
4980
|
+
function concatBytes$2(...arrays) {
|
|
4918
4981
|
let sum = 0;
|
|
4919
4982
|
for (let i = 0; i < arrays.length; i++) {
|
|
4920
4983
|
const a = arrays[i];
|
|
4921
|
-
abytes
|
|
4984
|
+
abytes(a);
|
|
4922
4985
|
sum += a.length;
|
|
4923
4986
|
}
|
|
4924
4987
|
const res = new Uint8Array(sum);
|
|
@@ -5032,7 +5095,7 @@ class HashMD extends Hash$1 {
|
|
|
5032
5095
|
update(data) {
|
|
5033
5096
|
aexists(this);
|
|
5034
5097
|
data = toBytes$1(data);
|
|
5035
|
-
abytes
|
|
5098
|
+
abytes(data);
|
|
5036
5099
|
const { view, buffer, blockLen } = this;
|
|
5037
5100
|
const len = data.length;
|
|
5038
5101
|
for (let pos = 0; pos < len;) {
|
|
@@ -5260,7 +5323,7 @@ class BLAKE2 extends Hash$1 {
|
|
|
5260
5323
|
update(data) {
|
|
5261
5324
|
aexists(this);
|
|
5262
5325
|
data = toBytes$1(data);
|
|
5263
|
-
abytes
|
|
5326
|
+
abytes(data);
|
|
5264
5327
|
// Main difference with other hashes: there is flag for last block,
|
|
5265
5328
|
// so we cannot process current block before we know that there
|
|
5266
5329
|
// is the next one. This significantly complicates logic and reduces ability
|
|
@@ -7530,6 +7593,9 @@ var knownSubstrate = [
|
|
|
7530
7593
|
'0xe3777fa922cafbff200cadeaea1a76bd7898ad5b89f7848999058b50e715f636', // Kusama CC2
|
|
7531
7594
|
'0x3fd7b9eb6a00376e5be61f01abb429ffb0b104be05eaff4d458da48fcd425baf' // Kusama CC1
|
|
7532
7595
|
],
|
|
7596
|
+
liberland: [
|
|
7597
|
+
'0x6bd89e052d67a45bb60a9a23e8581053d5e0d619f15cb9865946937e690c42d6'
|
|
7598
|
+
],
|
|
7533
7599
|
matrixchain: [
|
|
7534
7600
|
'0x3af4ff48ec76d2efc8476730f423ac07e25ad48f5f4c9dc39c778b164d808615'
|
|
7535
7601
|
],
|
|
@@ -7656,6 +7722,7 @@ var knownSubstrate = [
|
|
|
7656
7722
|
karura: 0x000002ae,
|
|
7657
7723
|
khala: 0x000001b2,
|
|
7658
7724
|
kusama: 0x000001b2,
|
|
7725
|
+
liberland: 0x000002ff,
|
|
7659
7726
|
matrixchain: 0x00000483,
|
|
7660
7727
|
nodle: 0x000003eb,
|
|
7661
7728
|
origintrail: 0x00000162,
|
|
@@ -7901,7 +7968,7 @@ let HMAC$1=class HMAC extends Hash$1 {
|
|
|
7901
7968
|
}
|
|
7902
7969
|
digestInto(out) {
|
|
7903
7970
|
aexists(this);
|
|
7904
|
-
abytes
|
|
7971
|
+
abytes(out, this.outputLen);
|
|
7905
7972
|
this.finished = true;
|
|
7906
7973
|
this.iHash.digestInto(out);
|
|
7907
7974
|
this.oHash.update(out);
|
|
@@ -7951,19 +8018,8 @@ hmac$1.create = (hash, key) => new HMAC$1(hash, key);/**
|
|
|
7951
8018
|
* @module
|
|
7952
8019
|
*/
|
|
7953
8020
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
7954
|
-
|
|
7955
|
-
// This is OK: `abstract` directory does not use noble-hashes.
|
|
7956
|
-
// User may opt-in into using different hashing library. This way, noble-hashes
|
|
7957
|
-
// won't be included into their bundle.
|
|
7958
|
-
const _0n$a = /* @__PURE__ */ BigInt(0);
|
|
8021
|
+
const _0n$9 = /* @__PURE__ */ BigInt(0);
|
|
7959
8022
|
const _1n$b = /* @__PURE__ */ BigInt(1);
|
|
7960
|
-
function isBytes(a) {
|
|
7961
|
-
return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
|
|
7962
|
-
}
|
|
7963
|
-
function abytes(item) {
|
|
7964
|
-
if (!isBytes(item))
|
|
7965
|
-
throw new Error('Uint8Array expected');
|
|
7966
|
-
}
|
|
7967
8023
|
function abool(title, value) {
|
|
7968
8024
|
if (typeof value !== 'boolean')
|
|
7969
8025
|
throw new Error(title + ' boolean expected, got ' + value);
|
|
@@ -7976,66 +8032,7 @@ function numberToHexUnpadded$1(num) {
|
|
|
7976
8032
|
function hexToNumber$1(hex) {
|
|
7977
8033
|
if (typeof hex !== 'string')
|
|
7978
8034
|
throw new Error('hex string expected, got ' + typeof hex);
|
|
7979
|
-
return hex === '' ? _0n$
|
|
7980
|
-
}
|
|
7981
|
-
// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex
|
|
7982
|
-
const hasHexBuiltin =
|
|
7983
|
-
// @ts-ignore
|
|
7984
|
-
typeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function';
|
|
7985
|
-
// Array where index 0xf0 (240) is mapped to string 'f0'
|
|
7986
|
-
const hexes$1 = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));
|
|
7987
|
-
/**
|
|
7988
|
-
* Convert byte array to hex string. Uses built-in function, when available.
|
|
7989
|
-
* @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'
|
|
7990
|
-
*/
|
|
7991
|
-
function bytesToHex$1(bytes) {
|
|
7992
|
-
abytes(bytes);
|
|
7993
|
-
// @ts-ignore
|
|
7994
|
-
if (hasHexBuiltin)
|
|
7995
|
-
return bytes.toHex();
|
|
7996
|
-
// pre-caching improves the speed 6x
|
|
7997
|
-
let hex = '';
|
|
7998
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
7999
|
-
hex += hexes$1[bytes[i]];
|
|
8000
|
-
}
|
|
8001
|
-
return hex;
|
|
8002
|
-
}
|
|
8003
|
-
// We use optimized technique to convert hex string to byte array
|
|
8004
|
-
const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
|
|
8005
|
-
function asciiToBase16(ch) {
|
|
8006
|
-
if (ch >= asciis._0 && ch <= asciis._9)
|
|
8007
|
-
return ch - asciis._0; // '2' => 50-48
|
|
8008
|
-
if (ch >= asciis.A && ch <= asciis.F)
|
|
8009
|
-
return ch - (asciis.A - 10); // 'B' => 66-(65-10)
|
|
8010
|
-
if (ch >= asciis.a && ch <= asciis.f)
|
|
8011
|
-
return ch - (asciis.a - 10); // 'b' => 98-(97-10)
|
|
8012
|
-
return;
|
|
8013
|
-
}
|
|
8014
|
-
/**
|
|
8015
|
-
* Convert hex string to byte array. Uses built-in function, when available.
|
|
8016
|
-
* @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])
|
|
8017
|
-
*/
|
|
8018
|
-
function hexToBytes$1(hex) {
|
|
8019
|
-
if (typeof hex !== 'string')
|
|
8020
|
-
throw new Error('hex string expected, got ' + typeof hex);
|
|
8021
|
-
// @ts-ignore
|
|
8022
|
-
if (hasHexBuiltin)
|
|
8023
|
-
return Uint8Array.fromHex(hex);
|
|
8024
|
-
const hl = hex.length;
|
|
8025
|
-
const al = hl / 2;
|
|
8026
|
-
if (hl % 2)
|
|
8027
|
-
throw new Error('hex string expected, got unpadded hex of length ' + hl);
|
|
8028
|
-
const array = new Uint8Array(al);
|
|
8029
|
-
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
|
|
8030
|
-
const n1 = asciiToBase16(hex.charCodeAt(hi));
|
|
8031
|
-
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
|
|
8032
|
-
if (n1 === undefined || n2 === undefined) {
|
|
8033
|
-
const char = hex[hi] + hex[hi + 1];
|
|
8034
|
-
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
|
|
8035
|
-
}
|
|
8036
|
-
array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163
|
|
8037
|
-
}
|
|
8038
|
-
return array;
|
|
8035
|
+
return hex === '' ? _0n$9 : BigInt('0x' + hex); // Big Endian
|
|
8039
8036
|
}
|
|
8040
8037
|
// BE: Big Endian, LE: Little Endian
|
|
8041
8038
|
function bytesToNumberBE$1(bytes) {
|
|
@@ -8084,25 +8081,16 @@ function ensureBytes$1(title, hex, expectedLength) {
|
|
|
8084
8081
|
return res;
|
|
8085
8082
|
}
|
|
8086
8083
|
/**
|
|
8087
|
-
*
|
|
8084
|
+
* @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
|
|
8088
8085
|
*/
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
|
|
8094
|
-
|
|
8095
|
-
}
|
|
8096
|
-
const res = new Uint8Array(sum);
|
|
8097
|
-
for (let i = 0, pad = 0; i < arrays.length; i++) {
|
|
8098
|
-
const a = arrays[i];
|
|
8099
|
-
res.set(a, pad);
|
|
8100
|
-
pad += a.length;
|
|
8101
|
-
}
|
|
8102
|
-
return res;
|
|
8103
|
-
}
|
|
8086
|
+
// export const utf8ToBytes: typeof utf8ToBytes_ = utf8ToBytes_;
|
|
8087
|
+
/**
|
|
8088
|
+
* Converts bytes to string using UTF8 encoding.
|
|
8089
|
+
* @example bytesToUtf8(Uint8Array.from([97, 98, 99])) // 'abc'
|
|
8090
|
+
*/
|
|
8091
|
+
// export const bytesToUtf8: typeof bytesToUtf8_ = bytesToUtf8_;
|
|
8104
8092
|
// Is positive bigint
|
|
8105
|
-
const isPosBig = (n) => typeof n === 'bigint' && _0n$
|
|
8093
|
+
const isPosBig = (n) => typeof n === 'bigint' && _0n$9 <= n;
|
|
8106
8094
|
function inRange(n, min, max) {
|
|
8107
8095
|
return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;
|
|
8108
8096
|
}
|
|
@@ -8128,7 +8116,7 @@ function aInRange(title, n, min, max) {
|
|
|
8128
8116
|
*/
|
|
8129
8117
|
function bitLen$1(n) {
|
|
8130
8118
|
let len;
|
|
8131
|
-
for (len = 0; n > _0n$
|
|
8119
|
+
for (len = 0; n > _0n$9; n >>= _1n$b, len += 1)
|
|
8132
8120
|
;
|
|
8133
8121
|
return len;
|
|
8134
8122
|
}
|
|
@@ -8137,9 +8125,6 @@ function bitLen$1(n) {
|
|
|
8137
8125
|
* Same as BigInt(`0b${Array(i).fill('1').join('')}`)
|
|
8138
8126
|
*/
|
|
8139
8127
|
const bitMask$1 = (n) => (_1n$b << BigInt(n)) - _1n$b;
|
|
8140
|
-
// DRBG
|
|
8141
|
-
const u8n$1 = (len) => new Uint8Array(len); // creates Uint8Array
|
|
8142
|
-
const u8fr$1 = (arr) => Uint8Array.from(arr); // another shortcut
|
|
8143
8128
|
/**
|
|
8144
8129
|
* Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
|
|
8145
8130
|
* @returns function that will call DRBG until 2nd arg returns something meaningful
|
|
@@ -8155,8 +8140,10 @@ function createHmacDrbg$1(hashLen, qByteLen, hmacFn) {
|
|
|
8155
8140
|
if (typeof hmacFn !== 'function')
|
|
8156
8141
|
throw new Error('hmacFn must be a function');
|
|
8157
8142
|
// Step B, Step C: set hashLen to 8*ceil(hlen/8)
|
|
8158
|
-
|
|
8159
|
-
|
|
8143
|
+
const u8n = (len) => new Uint8Array(len); // creates Uint8Array
|
|
8144
|
+
const u8of = (byte) => Uint8Array.of(byte); // another shortcut
|
|
8145
|
+
let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
|
|
8146
|
+
let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same
|
|
8160
8147
|
let i = 0; // Iterations counter, will throw when over 1000
|
|
8161
8148
|
const reset = () => {
|
|
8162
8149
|
v.fill(1);
|
|
@@ -8164,13 +8151,13 @@ function createHmacDrbg$1(hashLen, qByteLen, hmacFn) {
|
|
|
8164
8151
|
i = 0;
|
|
8165
8152
|
};
|
|
8166
8153
|
const h = (...b) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)
|
|
8167
|
-
const reseed = (seed = u8n
|
|
8154
|
+
const reseed = (seed = u8n(0)) => {
|
|
8168
8155
|
// HMAC-DRBG reseed() function. Steps D-G
|
|
8169
|
-
k = h(
|
|
8156
|
+
k = h(u8of(0x00), seed); // k = hmac(k || v || 0x00 || seed)
|
|
8170
8157
|
v = h(); // v = hmac(k || v)
|
|
8171
8158
|
if (seed.length === 0)
|
|
8172
8159
|
return;
|
|
8173
|
-
k = h(
|
|
8160
|
+
k = h(u8of(0x01), seed); // k = hmac(k || v || 0x01 || seed)
|
|
8174
8161
|
v = h(); // v = hmac(k || v)
|
|
8175
8162
|
};
|
|
8176
8163
|
const gen = () => {
|
|
@@ -8198,36 +8185,19 @@ function createHmacDrbg$1(hashLen, qByteLen, hmacFn) {
|
|
|
8198
8185
|
};
|
|
8199
8186
|
return genUntil;
|
|
8200
8187
|
}
|
|
8201
|
-
|
|
8202
|
-
|
|
8203
|
-
|
|
8204
|
-
function
|
|
8205
|
-
boolean: (val) => typeof val === 'boolean',
|
|
8206
|
-
string: (val) => typeof val === 'string',
|
|
8207
|
-
stringOrUint8Array: (val) => typeof val === 'string' || isBytes(val),
|
|
8208
|
-
isSafeInteger: (val) => Number.isSafeInteger(val),
|
|
8209
|
-
array: (val) => Array.isArray(val),
|
|
8210
|
-
field: (val, object) => object.Fp.isValid(val),
|
|
8211
|
-
hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
|
|
8212
|
-
};
|
|
8213
|
-
// type Record<K extends string | number | symbol, T> = { [P in K]: T; }
|
|
8214
|
-
function validateObject$1(object, validators, optValidators = {}) {
|
|
8215
|
-
const checkField = (fieldName, type, isOptional) => {
|
|
8216
|
-
const checkVal = validatorFns$1[type];
|
|
8217
|
-
if (typeof checkVal !== 'function')
|
|
8218
|
-
throw new Error('invalid validator function');
|
|
8188
|
+
function _validateObject(object, fields, optFields = {}) {
|
|
8189
|
+
if (!object || typeof object !== 'object')
|
|
8190
|
+
throw new Error('expected valid options object');
|
|
8191
|
+
function checkField(fieldName, expectedType, isOpt) {
|
|
8219
8192
|
const val = object[fieldName];
|
|
8220
|
-
if (
|
|
8193
|
+
if (isOpt && val === undefined)
|
|
8221
8194
|
return;
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
}
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
for (const [fieldName, type] of Object.entries(optValidators))
|
|
8229
|
-
checkField(fieldName, type, true);
|
|
8230
|
-
return object;
|
|
8195
|
+
const current = typeof val;
|
|
8196
|
+
if (current !== expectedType || val === null)
|
|
8197
|
+
throw new Error(`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`);
|
|
8198
|
+
}
|
|
8199
|
+
Object.entries(fields).forEach(([k, v]) => checkField(k, v, false));
|
|
8200
|
+
Object.entries(optFields).forEach(([k, v]) => checkField(k, v, true));
|
|
8231
8201
|
}
|
|
8232
8202
|
/**
|
|
8233
8203
|
* Memoizes (caches) computation result.
|
|
@@ -8244,25 +8214,26 @@ function memoized(fn) {
|
|
|
8244
8214
|
return computed;
|
|
8245
8215
|
};
|
|
8246
8216
|
}/**
|
|
8247
|
-
* Utils for modular division and
|
|
8248
|
-
*
|
|
8217
|
+
* Utils for modular division and fields.
|
|
8218
|
+
* Field over 11 is a finite (Galois) field is integer number operations `mod 11`.
|
|
8249
8219
|
* There is no division: it is replaced by modular multiplicative inverse.
|
|
8250
8220
|
* @module
|
|
8251
8221
|
*/
|
|
8252
8222
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
8253
8223
|
// prettier-ignore
|
|
8254
|
-
const _0n$
|
|
8224
|
+
const _0n$8 = BigInt(0), _1n$a = BigInt(1), _2n$7 = /* @__PURE__ */ BigInt(2), _3n$3 = /* @__PURE__ */ BigInt(3);
|
|
8255
8225
|
// prettier-ignore
|
|
8256
|
-
const _4n$2 = /* @__PURE__ */ BigInt(4), _5n$1 = /* @__PURE__ */ BigInt(5)
|
|
8226
|
+
const _4n$2 = /* @__PURE__ */ BigInt(4), _5n$1 = /* @__PURE__ */ BigInt(5);
|
|
8227
|
+
const _8n$1 = /* @__PURE__ */ BigInt(8);
|
|
8257
8228
|
// Calculates a modulo b
|
|
8258
8229
|
function mod$1(a, b) {
|
|
8259
8230
|
const result = a % b;
|
|
8260
|
-
return result >= _0n$
|
|
8231
|
+
return result >= _0n$8 ? result : b + result;
|
|
8261
8232
|
}
|
|
8262
8233
|
/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */
|
|
8263
8234
|
function pow2$1(x, power, modulo) {
|
|
8264
8235
|
let res = x;
|
|
8265
|
-
while (power-- > _0n$
|
|
8236
|
+
while (power-- > _0n$8) {
|
|
8266
8237
|
res *= res;
|
|
8267
8238
|
res %= modulo;
|
|
8268
8239
|
}
|
|
@@ -8273,16 +8244,16 @@ function pow2$1(x, power, modulo) {
|
|
|
8273
8244
|
* Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/).
|
|
8274
8245
|
*/
|
|
8275
8246
|
function invert$1(number, modulo) {
|
|
8276
|
-
if (number === _0n$
|
|
8247
|
+
if (number === _0n$8)
|
|
8277
8248
|
throw new Error('invert: expected non-zero number');
|
|
8278
|
-
if (modulo <= _0n$
|
|
8249
|
+
if (modulo <= _0n$8)
|
|
8279
8250
|
throw new Error('invert: expected positive modulus, got ' + modulo);
|
|
8280
8251
|
// Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower.
|
|
8281
8252
|
let a = mod$1(number, modulo);
|
|
8282
8253
|
let b = modulo;
|
|
8283
8254
|
// prettier-ignore
|
|
8284
|
-
let x = _0n$
|
|
8285
|
-
while (a !== _0n$
|
|
8255
|
+
let x = _0n$8, u = _1n$a;
|
|
8256
|
+
while (a !== _0n$8) {
|
|
8286
8257
|
// JIT applies optimization if those two lines follow each other
|
|
8287
8258
|
const q = b / a;
|
|
8288
8259
|
const r = b % a;
|
|
@@ -8309,10 +8280,10 @@ function sqrt3mod4(Fp, n) {
|
|
|
8309
8280
|
}
|
|
8310
8281
|
function sqrt5mod8(Fp, n) {
|
|
8311
8282
|
const p5div8 = (Fp.ORDER - _5n$1) / _8n$1;
|
|
8312
|
-
const n2 = Fp.mul(n, _2n$
|
|
8283
|
+
const n2 = Fp.mul(n, _2n$7);
|
|
8313
8284
|
const v = Fp.pow(n2, p5div8);
|
|
8314
8285
|
const nv = Fp.mul(n, v);
|
|
8315
|
-
const i = Fp.mul(Fp.mul(nv, _2n$
|
|
8286
|
+
const i = Fp.mul(Fp.mul(nv, _2n$7), v);
|
|
8316
8287
|
const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));
|
|
8317
8288
|
if (!Fp.eql(Fp.sqr(root), n))
|
|
8318
8289
|
throw new Error('Cannot find square root');
|
|
@@ -8349,17 +8320,18 @@ function sqrt5mod8(Fp, n) {
|
|
|
8349
8320
|
*/
|
|
8350
8321
|
function tonelliShanks$1(P) {
|
|
8351
8322
|
// Initialization (precomputation).
|
|
8323
|
+
// Caching initialization could boost perf by 7%.
|
|
8352
8324
|
if (P < BigInt(3))
|
|
8353
8325
|
throw new Error('sqrt is not defined for small field');
|
|
8354
8326
|
// Factor P - 1 = Q * 2^S, where Q is odd
|
|
8355
8327
|
let Q = P - _1n$a;
|
|
8356
8328
|
let S = 0;
|
|
8357
|
-
while (Q % _2n$
|
|
8358
|
-
Q /= _2n$
|
|
8329
|
+
while (Q % _2n$7 === _0n$8) {
|
|
8330
|
+
Q /= _2n$7;
|
|
8359
8331
|
S++;
|
|
8360
8332
|
}
|
|
8361
8333
|
// Find the first quadratic non-residue Z >= 2
|
|
8362
|
-
let Z = _2n$
|
|
8334
|
+
let Z = _2n$7;
|
|
8363
8335
|
const _Fp = Field$1(P);
|
|
8364
8336
|
while (FpLegendre(_Fp, Z) === 1) {
|
|
8365
8337
|
// Basic primality test for P. After x iterations, chance of
|
|
@@ -8373,7 +8345,7 @@ function tonelliShanks$1(P) {
|
|
|
8373
8345
|
// Slow-path
|
|
8374
8346
|
// TODO: test on Fp2 and others
|
|
8375
8347
|
let cc = _Fp.pow(Z, Q); // c = z^Q
|
|
8376
|
-
const Q1div2 = (Q + _1n$a) / _2n$
|
|
8348
|
+
const Q1div2 = (Q + _1n$a) / _2n$7;
|
|
8377
8349
|
return function tonelliSlow(Fp, n) {
|
|
8378
8350
|
if (Fp.is0(n))
|
|
8379
8351
|
return n;
|
|
@@ -8442,14 +8414,18 @@ function validateField$1(field) {
|
|
|
8442
8414
|
const initial = {
|
|
8443
8415
|
ORDER: 'bigint',
|
|
8444
8416
|
MASK: 'bigint',
|
|
8445
|
-
BYTES: '
|
|
8446
|
-
BITS: '
|
|
8417
|
+
BYTES: 'number',
|
|
8418
|
+
BITS: 'number',
|
|
8447
8419
|
};
|
|
8448
8420
|
const opts = FIELD_FIELDS$1.reduce((map, val) => {
|
|
8449
8421
|
map[val] = 'function';
|
|
8450
8422
|
return map;
|
|
8451
8423
|
}, initial);
|
|
8452
|
-
|
|
8424
|
+
_validateObject(field, opts);
|
|
8425
|
+
// const max = 16384;
|
|
8426
|
+
// if (field.BYTES < 1 || field.BYTES > max) throw new Error('invalid field');
|
|
8427
|
+
// if (field.BITS < 1 || field.BITS > 8 * max) throw new Error('invalid field');
|
|
8428
|
+
return field;
|
|
8453
8429
|
}
|
|
8454
8430
|
// Generic field functions
|
|
8455
8431
|
/**
|
|
@@ -8457,15 +8433,15 @@ function validateField$1(field) {
|
|
|
8457
8433
|
* Unsafe in some contexts: uses ladder, so can expose bigint bits.
|
|
8458
8434
|
*/
|
|
8459
8435
|
function FpPow$1(Fp, num, power) {
|
|
8460
|
-
if (power < _0n$
|
|
8436
|
+
if (power < _0n$8)
|
|
8461
8437
|
throw new Error('invalid exponent, negatives unsupported');
|
|
8462
|
-
if (power === _0n$
|
|
8438
|
+
if (power === _0n$8)
|
|
8463
8439
|
return Fp.ONE;
|
|
8464
8440
|
if (power === _1n$a)
|
|
8465
8441
|
return num;
|
|
8466
8442
|
let p = Fp.ONE;
|
|
8467
8443
|
let d = num;
|
|
8468
|
-
while (power > _0n$
|
|
8444
|
+
while (power > _0n$8) {
|
|
8469
8445
|
if (power & _1n$a)
|
|
8470
8446
|
p = Fp.mul(p, d);
|
|
8471
8447
|
d = Fp.sqr(d);
|
|
@@ -8510,7 +8486,7 @@ function FpInvertBatch$1(Fp, nums, passZero = false) {
|
|
|
8510
8486
|
function FpLegendre(Fp, n) {
|
|
8511
8487
|
// We can use 3rd argument as optional cache of this value
|
|
8512
8488
|
// but seems unneeded for now. The operation is very fast.
|
|
8513
|
-
const p1mod2 = (Fp.ORDER - _1n$a) / _2n$
|
|
8489
|
+
const p1mod2 = (Fp.ORDER - _1n$a) / _2n$7;
|
|
8514
8490
|
const powered = Fp.pow(n, p1mod2);
|
|
8515
8491
|
const yes = Fp.eql(powered, Fp.ONE);
|
|
8516
8492
|
const zero = Fp.eql(powered, Fp.ZERO);
|
|
@@ -8529,24 +8505,47 @@ function nLength$1(n, nBitLength) {
|
|
|
8529
8505
|
return { nBitLength: _nBitLength, nByteLength };
|
|
8530
8506
|
}
|
|
8531
8507
|
/**
|
|
8532
|
-
*
|
|
8533
|
-
*
|
|
8534
|
-
* *
|
|
8535
|
-
* *
|
|
8536
|
-
* * c) Object.freeze
|
|
8508
|
+
* Creates a finite field. Major performance optimizations:
|
|
8509
|
+
* * 1. Denormalized operations like mulN instead of mul.
|
|
8510
|
+
* * 2. Identical object shape: never add or remove keys.
|
|
8511
|
+
* * 3. `Object.freeze`.
|
|
8537
8512
|
* Fragile: always run a benchmark on a change.
|
|
8538
8513
|
* Security note: operations don't check 'isValid' for all elements for performance reasons,
|
|
8539
8514
|
* it is caller responsibility to check this.
|
|
8540
8515
|
* This is low-level code, please make sure you know what you're doing.
|
|
8541
|
-
*
|
|
8516
|
+
*
|
|
8517
|
+
* Note about field properties:
|
|
8518
|
+
* * CHARACTERISTIC p = prime number, number of elements in main subgroup.
|
|
8519
|
+
* * ORDER q = similar to cofactor in curves, may be composite `q = p^m`.
|
|
8520
|
+
*
|
|
8521
|
+
* @param ORDER field order, probably prime, or could be composite
|
|
8542
8522
|
* @param bitLen how many bits the field consumes
|
|
8543
|
-
* @param isLE (
|
|
8523
|
+
* @param isLE (default: false) if encoding / decoding should be in little-endian
|
|
8544
8524
|
* @param redef optional faster redefinitions of sqrt and other methods
|
|
8545
8525
|
*/
|
|
8546
|
-
function Field$1(ORDER,
|
|
8547
|
-
if (ORDER <= _0n$
|
|
8526
|
+
function Field$1(ORDER, bitLenOrOpts, isLE = false, opts = {}) {
|
|
8527
|
+
if (ORDER <= _0n$8)
|
|
8548
8528
|
throw new Error('invalid field: expected ORDER > 0, got ' + ORDER);
|
|
8549
|
-
|
|
8529
|
+
let _nbitLength = undefined;
|
|
8530
|
+
let _sqrt = undefined;
|
|
8531
|
+
if (typeof bitLenOrOpts === 'object' && bitLenOrOpts != null) {
|
|
8532
|
+
if (opts.sqrt || isLE)
|
|
8533
|
+
throw new Error('cannot specify opts in two arguments');
|
|
8534
|
+
const _opts = bitLenOrOpts;
|
|
8535
|
+
if (_opts.BITS)
|
|
8536
|
+
_nbitLength = _opts.BITS;
|
|
8537
|
+
if (_opts.sqrt)
|
|
8538
|
+
_sqrt = _opts.sqrt;
|
|
8539
|
+
if (typeof _opts.isLE === 'boolean')
|
|
8540
|
+
isLE = _opts.isLE;
|
|
8541
|
+
}
|
|
8542
|
+
else {
|
|
8543
|
+
if (typeof bitLenOrOpts === 'number')
|
|
8544
|
+
_nbitLength = bitLenOrOpts;
|
|
8545
|
+
if (opts.sqrt)
|
|
8546
|
+
_sqrt = opts.sqrt;
|
|
8547
|
+
}
|
|
8548
|
+
const { nBitLength: BITS, nByteLength: BYTES } = nLength$1(ORDER, _nbitLength);
|
|
8550
8549
|
if (BYTES > 2048)
|
|
8551
8550
|
throw new Error('invalid field: expected ORDER of <= 2048 bytes');
|
|
8552
8551
|
let sqrtP; // cached sqrtP
|
|
@@ -8556,15 +8555,17 @@ function Field$1(ORDER, bitLen, isLE = false, redef = {}) {
|
|
|
8556
8555
|
BITS,
|
|
8557
8556
|
BYTES,
|
|
8558
8557
|
MASK: bitMask$1(BITS),
|
|
8559
|
-
ZERO: _0n$
|
|
8558
|
+
ZERO: _0n$8,
|
|
8560
8559
|
ONE: _1n$a,
|
|
8561
8560
|
create: (num) => mod$1(num, ORDER),
|
|
8562
8561
|
isValid: (num) => {
|
|
8563
8562
|
if (typeof num !== 'bigint')
|
|
8564
8563
|
throw new Error('invalid field element: expected bigint, got ' + typeof num);
|
|
8565
|
-
return _0n$
|
|
8564
|
+
return _0n$8 <= num && num < ORDER; // 0 is valid element, but it's not invertible
|
|
8566
8565
|
},
|
|
8567
|
-
is0: (num) => num === _0n$
|
|
8566
|
+
is0: (num) => num === _0n$8,
|
|
8567
|
+
// is valid and invertible
|
|
8568
|
+
isValidNot0: (num) => !f.is0(num) && f.isValid(num),
|
|
8568
8569
|
isOdd: (num) => (num & _1n$a) === _1n$a,
|
|
8569
8570
|
neg: (num) => mod$1(-num, ORDER),
|
|
8570
8571
|
eql: (lhs, rhs) => lhs === rhs,
|
|
@@ -8580,7 +8581,7 @@ function Field$1(ORDER, bitLen, isLE = false, redef = {}) {
|
|
|
8580
8581
|
subN: (lhs, rhs) => lhs - rhs,
|
|
8581
8582
|
mulN: (lhs, rhs) => lhs * rhs,
|
|
8582
8583
|
inv: (num) => invert$1(num, ORDER),
|
|
8583
|
-
sqrt:
|
|
8584
|
+
sqrt: _sqrt ||
|
|
8584
8585
|
((n) => {
|
|
8585
8586
|
if (!sqrtP)
|
|
8586
8587
|
sqrtP = FpSqrt$1(ORDER);
|
|
@@ -8653,12 +8654,25 @@ function mapHashToField$1(key, fieldOrder, isLE = false) {
|
|
|
8653
8654
|
* @module
|
|
8654
8655
|
*/
|
|
8655
8656
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
8656
|
-
const _0n$
|
|
8657
|
+
const _0n$7 = BigInt(0);
|
|
8657
8658
|
const _1n$9 = BigInt(1);
|
|
8658
|
-
function
|
|
8659
|
+
function negateCt(condition, item) {
|
|
8659
8660
|
const neg = item.negate();
|
|
8660
8661
|
return condition ? neg : item;
|
|
8661
8662
|
}
|
|
8663
|
+
/**
|
|
8664
|
+
* Takes a bunch of Projective Points but executes only one
|
|
8665
|
+
* inversion on all of them. Inversion is very slow operation,
|
|
8666
|
+
* so this improves performance massively.
|
|
8667
|
+
* Optimization: converts a list of projective points to a list of identical points with Z=1.
|
|
8668
|
+
*/
|
|
8669
|
+
function normalizeZ(c, property, points) {
|
|
8670
|
+
const getz = (p) => p.pz ;
|
|
8671
|
+
const toInv = FpInvertBatch$1(c.Fp, points.map(getz));
|
|
8672
|
+
// @ts-ignore
|
|
8673
|
+
const affined = points.map((p, i) => p.toAffine(toInv[i]));
|
|
8674
|
+
return affined.map(c.fromAffine);
|
|
8675
|
+
}
|
|
8662
8676
|
function validateW(W, bits) {
|
|
8663
8677
|
if (!Number.isSafeInteger(W) || W <= 0 || W > bits)
|
|
8664
8678
|
throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W);
|
|
@@ -8718,6 +8732,10 @@ const pointWindowSizes = new WeakMap();
|
|
|
8718
8732
|
function getW(P) {
|
|
8719
8733
|
return pointWindowSizes.get(P) || 1;
|
|
8720
8734
|
}
|
|
8735
|
+
function assert0(n) {
|
|
8736
|
+
if (n !== _0n$7)
|
|
8737
|
+
throw new Error('invalid wNAF');
|
|
8738
|
+
}
|
|
8721
8739
|
/**
|
|
8722
8740
|
* Elliptic curve multiplication of Point by scalar. Fragile.
|
|
8723
8741
|
* Scalars should always be less than curve order: this should be checked inside of a curve itself.
|
|
@@ -8734,14 +8752,14 @@ function getW(P) {
|
|
|
8734
8752
|
*/
|
|
8735
8753
|
function wNAF$1(c, bits) {
|
|
8736
8754
|
return {
|
|
8737
|
-
constTimeNegate,
|
|
8755
|
+
constTimeNegate: negateCt,
|
|
8738
8756
|
hasPrecomputes(elm) {
|
|
8739
8757
|
return getW(elm) !== 1;
|
|
8740
8758
|
},
|
|
8741
8759
|
// non-const time multiplication ladder
|
|
8742
8760
|
unsafeLadder(elm, n, p = c.ZERO) {
|
|
8743
8761
|
let d = elm;
|
|
8744
|
-
while (n > _0n$
|
|
8762
|
+
while (n > _0n$7) {
|
|
8745
8763
|
if (n & _1n$9)
|
|
8746
8764
|
p = p.add(d);
|
|
8747
8765
|
d = d.double();
|
|
@@ -8807,13 +8825,14 @@ function wNAF$1(c, bits) {
|
|
|
8807
8825
|
if (isZero) {
|
|
8808
8826
|
// bits are 0: add garbage to fake point
|
|
8809
8827
|
// Important part for const-time getPublicKey: add random "noise" point to f.
|
|
8810
|
-
f = f.add(
|
|
8828
|
+
f = f.add(negateCt(isNegF, precomputes[offsetF]));
|
|
8811
8829
|
}
|
|
8812
8830
|
else {
|
|
8813
8831
|
// bits are 1: add to result point
|
|
8814
|
-
p = p.add(
|
|
8832
|
+
p = p.add(negateCt(isNeg, precomputes[offset]));
|
|
8815
8833
|
}
|
|
8816
8834
|
}
|
|
8835
|
+
assert0(n);
|
|
8817
8836
|
// Return both real and fake points: JIT won't eliminate f.
|
|
8818
8837
|
// At this point there is a way to F be infinity-point even if p is not,
|
|
8819
8838
|
// which makes it less const-time: around 1 bigint multiply.
|
|
@@ -8830,7 +8849,7 @@ function wNAF$1(c, bits) {
|
|
|
8830
8849
|
wNAFUnsafe(W, precomputes, n, acc = c.ZERO) {
|
|
8831
8850
|
const wo = calcWOpts(W, bits);
|
|
8832
8851
|
for (let window = 0; window < wo.windows; window++) {
|
|
8833
|
-
if (n === _0n$
|
|
8852
|
+
if (n === _0n$7)
|
|
8834
8853
|
break; // Early-exit, skip 0 value
|
|
8835
8854
|
const { nextN, offset, isZero, isNeg } = calcOffsets(n, window, wo);
|
|
8836
8855
|
n = nextN;
|
|
@@ -8844,6 +8863,7 @@ function wNAF$1(c, bits) {
|
|
|
8844
8863
|
acc = acc.add(isNeg ? item.negate() : item); // Re-using acc allows to save adds in MSM
|
|
8845
8864
|
}
|
|
8846
8865
|
}
|
|
8866
|
+
assert0(n);
|
|
8847
8867
|
return acc;
|
|
8848
8868
|
},
|
|
8849
8869
|
getPrecomputes(W, P, transform) {
|
|
@@ -8851,8 +8871,12 @@ function wNAF$1(c, bits) {
|
|
|
8851
8871
|
let comp = pointPrecomputes.get(P);
|
|
8852
8872
|
if (!comp) {
|
|
8853
8873
|
comp = this.precomputeWindow(P, W);
|
|
8854
|
-
if (W !== 1)
|
|
8855
|
-
|
|
8874
|
+
if (W !== 1) {
|
|
8875
|
+
// Doing transform outside of if brings 15% perf hit
|
|
8876
|
+
if (typeof transform === 'function')
|
|
8877
|
+
comp = transform(comp);
|
|
8878
|
+
pointPrecomputes.set(P, comp);
|
|
8879
|
+
}
|
|
8856
8880
|
}
|
|
8857
8881
|
return comp;
|
|
8858
8882
|
},
|
|
@@ -8876,6 +8900,25 @@ function wNAF$1(c, bits) {
|
|
|
8876
8900
|
},
|
|
8877
8901
|
};
|
|
8878
8902
|
}
|
|
8903
|
+
/**
|
|
8904
|
+
* Endomorphism-specific multiplication for Koblitz curves.
|
|
8905
|
+
* Cost: 128 dbl, 0-256 adds.
|
|
8906
|
+
*/
|
|
8907
|
+
function mulEndoUnsafe(c, point, k1, k2) {
|
|
8908
|
+
let acc = point;
|
|
8909
|
+
let p1 = c.ZERO;
|
|
8910
|
+
let p2 = c.ZERO;
|
|
8911
|
+
while (k1 > _0n$7 || k2 > _0n$7) {
|
|
8912
|
+
if (k1 & _1n$9)
|
|
8913
|
+
p1 = p1.add(acc);
|
|
8914
|
+
if (k2 & _1n$9)
|
|
8915
|
+
p2 = p2.add(acc);
|
|
8916
|
+
acc = acc.double();
|
|
8917
|
+
k1 >>= _1n$9;
|
|
8918
|
+
k2 >>= _1n$9;
|
|
8919
|
+
}
|
|
8920
|
+
return { p1, p2 };
|
|
8921
|
+
}
|
|
8879
8922
|
/**
|
|
8880
8923
|
* Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
|
|
8881
8924
|
* 30x faster vs naive addition on L=4096, 10x faster than precomputes.
|
|
@@ -8933,39 +8976,39 @@ function pippenger(c, fieldN, points, scalars) {
|
|
|
8933
8976
|
}
|
|
8934
8977
|
return sum;
|
|
8935
8978
|
}
|
|
8936
|
-
function
|
|
8937
|
-
|
|
8938
|
-
|
|
8939
|
-
|
|
8940
|
-
|
|
8941
|
-
|
|
8942
|
-
|
|
8943
|
-
|
|
8944
|
-
|
|
8945
|
-
|
|
8946
|
-
|
|
8947
|
-
|
|
8948
|
-
|
|
8949
|
-
|
|
8950
|
-
|
|
8951
|
-
|
|
8952
|
-
|
|
8979
|
+
function createField(order, field) {
|
|
8980
|
+
if (field) {
|
|
8981
|
+
if (field.ORDER !== order)
|
|
8982
|
+
throw new Error('Field.ORDER must match order: Fp == p, Fn == n');
|
|
8983
|
+
validateField$1(field);
|
|
8984
|
+
return field;
|
|
8985
|
+
}
|
|
8986
|
+
else {
|
|
8987
|
+
return Field$1(order);
|
|
8988
|
+
}
|
|
8989
|
+
}
|
|
8990
|
+
/** Validates CURVE opts and creates fields */
|
|
8991
|
+
function _createCurveFields(type, CURVE, curveOpts = {}) {
|
|
8992
|
+
if (!CURVE || typeof CURVE !== 'object')
|
|
8993
|
+
throw new Error(`expected valid ${type} CURVE object`);
|
|
8994
|
+
for (const p of ['p', 'n', 'h']) {
|
|
8995
|
+
const val = CURVE[p];
|
|
8996
|
+
if (!(typeof val === 'bigint' && val > _0n$7))
|
|
8997
|
+
throw new Error(`CURVE.${p} must be positive bigint`);
|
|
8998
|
+
}
|
|
8999
|
+
const Fp = createField(CURVE.p, curveOpts.Fp);
|
|
9000
|
+
const Fn = createField(CURVE.n, curveOpts.Fn);
|
|
9001
|
+
const _b = 'b' ;
|
|
9002
|
+
const params = ['Gx', 'Gy', 'a', _b];
|
|
9003
|
+
for (const p of params) {
|
|
9004
|
+
// @ts-ignore
|
|
9005
|
+
if (!Fp.isValid(CURVE[p]))
|
|
9006
|
+
throw new Error(`CURVE.${p} must be valid field element of CURVE.Fp`);
|
|
9007
|
+
}
|
|
9008
|
+
return { Fp, Fn };
|
|
8953
9009
|
}/**
|
|
8954
9010
|
* Short Weierstrass curve methods. The formula is: y² = x³ + ax + b.
|
|
8955
9011
|
*
|
|
8956
|
-
* ### Parameters
|
|
8957
|
-
*
|
|
8958
|
-
* To initialize a weierstrass curve, one needs to pass following params:
|
|
8959
|
-
*
|
|
8960
|
-
* * a: formula param
|
|
8961
|
-
* * b: formula param
|
|
8962
|
-
* * Fp: finite field of prime characteristic P; may be complex (Fp2). Arithmetics is done in field
|
|
8963
|
-
* * n: order of prime subgroup a.k.a total amount of valid curve points
|
|
8964
|
-
* * Gx: Base point (x, y) aka generator point. Gx = x coordinate
|
|
8965
|
-
* * Gy: ...y coordinate
|
|
8966
|
-
* * h: cofactor, usually 1. h*n = curve group order (n is only subgroup order)
|
|
8967
|
-
* * lowS: whether to enable (default) or disable "low-s" non-malleable signatures
|
|
8968
|
-
*
|
|
8969
9012
|
* ### Design rationale for types
|
|
8970
9013
|
*
|
|
8971
9014
|
* * Interaction between classes from different curves should fail:
|
|
@@ -8990,40 +9033,12 @@ function validateBasic$1(curve) {
|
|
|
8990
9033
|
* @module
|
|
8991
9034
|
*/
|
|
8992
9035
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
8993
|
-
// prettier-ignore
|
|
8994
9036
|
function validateSigVerOpts(opts) {
|
|
8995
9037
|
if (opts.lowS !== undefined)
|
|
8996
9038
|
abool('lowS', opts.lowS);
|
|
8997
9039
|
if (opts.prehash !== undefined)
|
|
8998
9040
|
abool('prehash', opts.prehash);
|
|
8999
9041
|
}
|
|
9000
|
-
function validatePointOpts$1(curve) {
|
|
9001
|
-
const opts = validateBasic$1(curve);
|
|
9002
|
-
validateObject$1(opts, {
|
|
9003
|
-
a: 'field',
|
|
9004
|
-
b: 'field',
|
|
9005
|
-
}, {
|
|
9006
|
-
allowInfinityPoint: 'boolean',
|
|
9007
|
-
allowedPrivateKeyLengths: 'array',
|
|
9008
|
-
clearCofactor: 'function',
|
|
9009
|
-
fromBytes: 'function',
|
|
9010
|
-
isTorsionFree: 'function',
|
|
9011
|
-
toBytes: 'function',
|
|
9012
|
-
wrapPrivateKey: 'boolean',
|
|
9013
|
-
});
|
|
9014
|
-
const { endo, Fp, a } = opts;
|
|
9015
|
-
if (endo) {
|
|
9016
|
-
if (!Fp.eql(a, Fp.ZERO)) {
|
|
9017
|
-
throw new Error('invalid endo: CURVE.a must be 0');
|
|
9018
|
-
}
|
|
9019
|
-
if (typeof endo !== 'object' ||
|
|
9020
|
-
typeof endo.beta !== 'bigint' ||
|
|
9021
|
-
typeof endo.splitScalar !== 'function') {
|
|
9022
|
-
throw new Error('invalid endo: expected "beta": bigint and "splitScalar": function');
|
|
9023
|
-
}
|
|
9024
|
-
}
|
|
9025
|
-
return Object.freeze({ ...opts });
|
|
9026
|
-
}
|
|
9027
9042
|
class DERErr extends Error {
|
|
9028
9043
|
constructor(m = '') {
|
|
9029
9044
|
super(m);
|
|
@@ -9100,7 +9115,7 @@ const DER$1 = {
|
|
|
9100
9115
|
_int: {
|
|
9101
9116
|
encode(num) {
|
|
9102
9117
|
const { Err: E } = DER$1;
|
|
9103
|
-
if (num < _0n$
|
|
9118
|
+
if (num < _0n$6)
|
|
9104
9119
|
throw new E('integer: negative integers are not allowed');
|
|
9105
9120
|
let hex = numberToHexUnpadded$1(num);
|
|
9106
9121
|
// Pad with zero byte if negative flag is present
|
|
@@ -9140,40 +9155,139 @@ const DER$1 = {
|
|
|
9140
9155
|
return tlv.encode(0x30, seq);
|
|
9141
9156
|
},
|
|
9142
9157
|
};
|
|
9143
|
-
function numToSizedHex(num, size) {
|
|
9144
|
-
return bytesToHex$1(numberToBytesBE$1(num, size));
|
|
9145
|
-
}
|
|
9146
9158
|
// Be friendly to bad ECMAScript parsers by not using bigint literals
|
|
9147
9159
|
// prettier-ignore
|
|
9148
|
-
const _0n$
|
|
9149
|
-
|
|
9150
|
-
|
|
9151
|
-
const { Fp } = CURVE; // All curves has same field / group length as for now, but they can differ
|
|
9152
|
-
const Fn = Field$1(CURVE.n, CURVE.nBitLength);
|
|
9153
|
-
const toBytes = CURVE.toBytes ||
|
|
9154
|
-
((_c, point, _isCompressed) => {
|
|
9155
|
-
const a = point.toAffine();
|
|
9156
|
-
return concatBytes$2(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y));
|
|
9157
|
-
});
|
|
9158
|
-
const fromBytes = CURVE.fromBytes ||
|
|
9159
|
-
((bytes) => {
|
|
9160
|
-
// const head = bytes[0];
|
|
9161
|
-
const tail = bytes.subarray(1);
|
|
9162
|
-
// if (head !== 0x04) throw new Error('Only non-compressed encoding is supported');
|
|
9163
|
-
const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));
|
|
9164
|
-
const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));
|
|
9165
|
-
return { x, y };
|
|
9166
|
-
});
|
|
9160
|
+
const _0n$6 = BigInt(0), _1n$8 = BigInt(1), _2n$6 = BigInt(2), _3n$2 = BigInt(3), _4n$1 = BigInt(4);
|
|
9161
|
+
// TODO: remove
|
|
9162
|
+
function _legacyHelperEquat(Fp, a, b) {
|
|
9167
9163
|
/**
|
|
9168
9164
|
* y² = x³ + ax + b: Short weierstrass curve formula. Takes x, returns y².
|
|
9169
9165
|
* @returns y²
|
|
9170
9166
|
*/
|
|
9171
9167
|
function weierstrassEquation(x) {
|
|
9172
|
-
const { a, b } = CURVE;
|
|
9173
9168
|
const x2 = Fp.sqr(x); // x * x
|
|
9174
9169
|
const x3 = Fp.mul(x2, x); // x² * x
|
|
9175
9170
|
return Fp.add(Fp.add(x3, Fp.mul(x, a)), b); // x³ + a * x + b
|
|
9176
9171
|
}
|
|
9172
|
+
return weierstrassEquation;
|
|
9173
|
+
}
|
|
9174
|
+
function _legacyHelperNormPriv(Fn, allowedPrivateKeyLengths, wrapPrivateKey) {
|
|
9175
|
+
const { BYTES: expected } = Fn;
|
|
9176
|
+
// Validates if priv key is valid and converts it to bigint.
|
|
9177
|
+
function normPrivateKeyToScalar(key) {
|
|
9178
|
+
let num;
|
|
9179
|
+
if (typeof key === 'bigint') {
|
|
9180
|
+
num = key;
|
|
9181
|
+
}
|
|
9182
|
+
else {
|
|
9183
|
+
let bytes = ensureBytes$1('private key', key);
|
|
9184
|
+
if (allowedPrivateKeyLengths) {
|
|
9185
|
+
if (!allowedPrivateKeyLengths.includes(bytes.length * 2))
|
|
9186
|
+
throw new Error('invalid private key');
|
|
9187
|
+
const padded = new Uint8Array(expected);
|
|
9188
|
+
padded.set(bytes, padded.length - bytes.length);
|
|
9189
|
+
bytes = padded;
|
|
9190
|
+
}
|
|
9191
|
+
try {
|
|
9192
|
+
num = Fn.fromBytes(bytes);
|
|
9193
|
+
}
|
|
9194
|
+
catch (error) {
|
|
9195
|
+
throw new Error(`invalid private key: expected ui8a of size ${expected}, got ${typeof key}`);
|
|
9196
|
+
}
|
|
9197
|
+
}
|
|
9198
|
+
if (wrapPrivateKey)
|
|
9199
|
+
num = Fn.create(num); // disabled by default, enabled for BLS
|
|
9200
|
+
if (!Fn.isValidNot0(num))
|
|
9201
|
+
throw new Error('invalid private key: out of range [1..N-1]');
|
|
9202
|
+
return num;
|
|
9203
|
+
}
|
|
9204
|
+
return normPrivateKeyToScalar;
|
|
9205
|
+
}
|
|
9206
|
+
function weierstrassN(CURVE, curveOpts = {}) {
|
|
9207
|
+
const { Fp, Fn } = _createCurveFields('weierstrass', CURVE, curveOpts);
|
|
9208
|
+
const { h: cofactor, n: CURVE_ORDER } = CURVE;
|
|
9209
|
+
_validateObject(curveOpts, {}, {
|
|
9210
|
+
allowInfinityPoint: 'boolean',
|
|
9211
|
+
clearCofactor: 'function',
|
|
9212
|
+
isTorsionFree: 'function',
|
|
9213
|
+
fromBytes: 'function',
|
|
9214
|
+
toBytes: 'function',
|
|
9215
|
+
endo: 'object',
|
|
9216
|
+
wrapPrivateKey: 'boolean',
|
|
9217
|
+
});
|
|
9218
|
+
const { endo } = curveOpts;
|
|
9219
|
+
if (endo) {
|
|
9220
|
+
// validateObject(endo, { beta: 'bigint', splitScalar: 'function' });
|
|
9221
|
+
if (!Fp.is0(CURVE.a) ||
|
|
9222
|
+
typeof endo.beta !== 'bigint' ||
|
|
9223
|
+
typeof endo.splitScalar !== 'function') {
|
|
9224
|
+
throw new Error('invalid endo: expected "beta": bigint and "splitScalar": function');
|
|
9225
|
+
}
|
|
9226
|
+
}
|
|
9227
|
+
function assertCompressionIsSupported() {
|
|
9228
|
+
if (!Fp.isOdd)
|
|
9229
|
+
throw new Error('compression is not supported: Field does not have .isOdd()');
|
|
9230
|
+
}
|
|
9231
|
+
// Implements IEEE P1363 point encoding
|
|
9232
|
+
function pointToBytes(_c, point, isCompressed) {
|
|
9233
|
+
const { x, y } = point.toAffine();
|
|
9234
|
+
const bx = Fp.toBytes(x);
|
|
9235
|
+
abool('isCompressed', isCompressed);
|
|
9236
|
+
if (isCompressed) {
|
|
9237
|
+
assertCompressionIsSupported();
|
|
9238
|
+
const hasEvenY = !Fp.isOdd(y);
|
|
9239
|
+
return concatBytes$2(pprefix(hasEvenY), bx);
|
|
9240
|
+
}
|
|
9241
|
+
else {
|
|
9242
|
+
return concatBytes$2(Uint8Array.of(0x04), bx, Fp.toBytes(y));
|
|
9243
|
+
}
|
|
9244
|
+
}
|
|
9245
|
+
function pointFromBytes(bytes) {
|
|
9246
|
+
abytes(bytes);
|
|
9247
|
+
const L = Fp.BYTES;
|
|
9248
|
+
const LC = L + 1; // length compressed, e.g. 33 for 32-byte field
|
|
9249
|
+
const LU = 2 * L + 1; // length uncompressed, e.g. 65 for 32-byte field
|
|
9250
|
+
const length = bytes.length;
|
|
9251
|
+
const head = bytes[0];
|
|
9252
|
+
const tail = bytes.subarray(1);
|
|
9253
|
+
// No actual validation is done here: use .assertValidity()
|
|
9254
|
+
if (length === LC && (head === 0x02 || head === 0x03)) {
|
|
9255
|
+
const x = Fp.fromBytes(tail);
|
|
9256
|
+
if (!Fp.isValid(x))
|
|
9257
|
+
throw new Error('bad point: is not on curve, wrong x');
|
|
9258
|
+
const y2 = weierstrassEquation(x); // y² = x³ + ax + b
|
|
9259
|
+
let y;
|
|
9260
|
+
try {
|
|
9261
|
+
y = Fp.sqrt(y2); // y = y² ^ (p+1)/4
|
|
9262
|
+
}
|
|
9263
|
+
catch (sqrtError) {
|
|
9264
|
+
const err = sqrtError instanceof Error ? ': ' + sqrtError.message : '';
|
|
9265
|
+
throw new Error('bad point: is not on curve, sqrt error' + err);
|
|
9266
|
+
}
|
|
9267
|
+
assertCompressionIsSupported();
|
|
9268
|
+
const isYOdd = Fp.isOdd(y); // (y & _1n) === _1n;
|
|
9269
|
+
const isHeadOdd = (head & 1) === 1; // ECDSA-specific
|
|
9270
|
+
if (isHeadOdd !== isYOdd)
|
|
9271
|
+
y = Fp.neg(y);
|
|
9272
|
+
return { x, y };
|
|
9273
|
+
}
|
|
9274
|
+
else if (length === LU && head === 0x04) {
|
|
9275
|
+
// TODO: more checks
|
|
9276
|
+
const x = Fp.fromBytes(tail.subarray(L * 0, L * 1));
|
|
9277
|
+
const y = Fp.fromBytes(tail.subarray(L * 1, L * 2));
|
|
9278
|
+
if (!isValidXY(x, y))
|
|
9279
|
+
throw new Error('bad point: is not on curve');
|
|
9280
|
+
return { x, y };
|
|
9281
|
+
}
|
|
9282
|
+
else {
|
|
9283
|
+
throw new Error(`bad point: got length ${length}, expected compressed=${LC} or uncompressed=${LU}`);
|
|
9284
|
+
}
|
|
9285
|
+
}
|
|
9286
|
+
const toBytes = curveOpts.toBytes || pointToBytes;
|
|
9287
|
+
const fromBytes = curveOpts.fromBytes || pointFromBytes;
|
|
9288
|
+
const weierstrassEquation = _legacyHelperEquat(Fp, CURVE.a, CURVE.b);
|
|
9289
|
+
// TODO: move top-level
|
|
9290
|
+
/** Checks whether equation holds for given x, y: y² == x³ + ax + b */
|
|
9177
9291
|
function isValidXY(x, y) {
|
|
9178
9292
|
const left = Fp.sqr(y); // y²
|
|
9179
9293
|
const right = weierstrassEquation(x); // x³ + ax + b
|
|
@@ -9189,36 +9303,11 @@ function weierstrassPoints$1(opts) {
|
|
|
9189
9303
|
const _27b2 = Fp.mul(Fp.sqr(CURVE.b), BigInt(27));
|
|
9190
9304
|
if (Fp.is0(Fp.add(_4a3, _27b2)))
|
|
9191
9305
|
throw new Error('bad curve params: a or b');
|
|
9192
|
-
|
|
9193
|
-
function
|
|
9194
|
-
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
// Supports options allowedPrivateKeyLengths and wrapPrivateKey.
|
|
9198
|
-
function normPrivateKeyToScalar(key) {
|
|
9199
|
-
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n: N } = CURVE;
|
|
9200
|
-
if (lengths && typeof key !== 'bigint') {
|
|
9201
|
-
if (isBytes(key))
|
|
9202
|
-
key = bytesToHex$1(key);
|
|
9203
|
-
// Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes
|
|
9204
|
-
if (typeof key !== 'string' || !lengths.includes(key.length))
|
|
9205
|
-
throw new Error('invalid private key');
|
|
9206
|
-
key = key.padStart(nByteLength * 2, '0');
|
|
9207
|
-
}
|
|
9208
|
-
let num;
|
|
9209
|
-
try {
|
|
9210
|
-
num =
|
|
9211
|
-
typeof key === 'bigint'
|
|
9212
|
-
? key
|
|
9213
|
-
: bytesToNumberBE$1(ensureBytes$1('private key', key, nByteLength));
|
|
9214
|
-
}
|
|
9215
|
-
catch (error) {
|
|
9216
|
-
throw new Error('invalid private key, expected hex or ' + nByteLength + ' bytes, got ' + typeof key);
|
|
9217
|
-
}
|
|
9218
|
-
if (wrapPrivateKey)
|
|
9219
|
-
num = mod$1(num, N); // disabled by default, enabled for BLS
|
|
9220
|
-
aInRange('private key', num, _1n$8, N); // num in range [1..N-1]
|
|
9221
|
-
return num;
|
|
9306
|
+
/** Asserts coordinate is valid: 0 <= n < Fp.ORDER. */
|
|
9307
|
+
function acoord(title, n, banZero = false) {
|
|
9308
|
+
if (!Fp.isValid(n) || (banZero && Fp.is0(n)))
|
|
9309
|
+
throw new Error(`bad point coordinate ${title}`);
|
|
9310
|
+
return n;
|
|
9222
9311
|
}
|
|
9223
9312
|
function aprjpoint(other) {
|
|
9224
9313
|
if (!(other instanceof Point))
|
|
@@ -9254,50 +9343,48 @@ function weierstrassPoints$1(opts) {
|
|
|
9254
9343
|
// (0, 1, 0) aka ZERO is invalid in most contexts.
|
|
9255
9344
|
// In BLS, ZERO can be serialized, so we allow it.
|
|
9256
9345
|
// (0, 0, 0) is invalid representation of ZERO.
|
|
9257
|
-
if (
|
|
9346
|
+
if (curveOpts.allowInfinityPoint && !Fp.is0(p.py))
|
|
9258
9347
|
return;
|
|
9259
9348
|
throw new Error('bad point: ZERO');
|
|
9260
9349
|
}
|
|
9261
9350
|
// Some 3rd-party test vectors require different wording between here & `fromCompressedHex`
|
|
9262
9351
|
const { x, y } = p.toAffine();
|
|
9263
|
-
// Check if x, y are valid field elements
|
|
9264
9352
|
if (!Fp.isValid(x) || !Fp.isValid(y))
|
|
9265
|
-
throw new Error('bad point: x or y not
|
|
9353
|
+
throw new Error('bad point: x or y not field elements');
|
|
9266
9354
|
if (!isValidXY(x, y))
|
|
9267
9355
|
throw new Error('bad point: equation left != right');
|
|
9268
9356
|
if (!p.isTorsionFree())
|
|
9269
9357
|
throw new Error('bad point: not in prime-order subgroup');
|
|
9270
9358
|
return true;
|
|
9271
9359
|
});
|
|
9360
|
+
function finishEndo(endoBeta, k1p, k2p, k1neg, k2neg) {
|
|
9361
|
+
k2p = new Point(Fp.mul(k2p.px, endoBeta), k2p.py, k2p.pz);
|
|
9362
|
+
k1p = negateCt(k1neg, k1p);
|
|
9363
|
+
k2p = negateCt(k2neg, k2p);
|
|
9364
|
+
return k1p.add(k2p);
|
|
9365
|
+
}
|
|
9272
9366
|
/**
|
|
9273
|
-
* Projective Point works in 3d / projective (homogeneous) coordinates:
|
|
9274
|
-
* Default Point works in 2d / affine coordinates: (x, y)
|
|
9367
|
+
* Projective Point works in 3d / projective (homogeneous) coordinates:(X, Y, Z) ∋ (x=X/Z, y=Y/Z).
|
|
9368
|
+
* Default Point works in 2d / affine coordinates: (x, y).
|
|
9275
9369
|
* We're doing calculations in projective, because its operations don't require costly inversion.
|
|
9276
9370
|
*/
|
|
9277
9371
|
class Point {
|
|
9372
|
+
/** Does NOT validate if the point is valid. Use `.assertValidity()`. */
|
|
9278
9373
|
constructor(px, py, pz) {
|
|
9279
|
-
|
|
9280
|
-
|
|
9281
|
-
|
|
9282
|
-
throw new Error('y required');
|
|
9283
|
-
if (pz == null || !Fp.isValid(pz))
|
|
9284
|
-
throw new Error('z required');
|
|
9285
|
-
this.px = px;
|
|
9286
|
-
this.py = py;
|
|
9287
|
-
this.pz = pz;
|
|
9374
|
+
this.px = acoord('x', px);
|
|
9375
|
+
this.py = acoord('y', py, true);
|
|
9376
|
+
this.pz = acoord('z', pz);
|
|
9288
9377
|
Object.freeze(this);
|
|
9289
9378
|
}
|
|
9290
|
-
|
|
9291
|
-
// Use fromHex instead, or call assertValidity() later.
|
|
9379
|
+
/** Does NOT validate if the point is valid. Use `.assertValidity()`. */
|
|
9292
9380
|
static fromAffine(p) {
|
|
9293
9381
|
const { x, y } = p || {};
|
|
9294
9382
|
if (!p || !Fp.isValid(x) || !Fp.isValid(y))
|
|
9295
9383
|
throw new Error('invalid affine point');
|
|
9296
9384
|
if (p instanceof Point)
|
|
9297
9385
|
throw new Error('projective point not allowed');
|
|
9298
|
-
|
|
9299
|
-
|
|
9300
|
-
if (is0(x) && is0(y))
|
|
9386
|
+
// (0, 0) would've produced (0, 0, 1) - instead, we need (0, 1, 0)
|
|
9387
|
+
if (Fp.is0(x) && Fp.is0(y))
|
|
9301
9388
|
return Point.ZERO;
|
|
9302
9389
|
return new Point(x, y, Fp.ONE);
|
|
9303
9390
|
}
|
|
@@ -9307,50 +9394,56 @@ function weierstrassPoints$1(opts) {
|
|
|
9307
9394
|
get y() {
|
|
9308
9395
|
return this.toAffine().y;
|
|
9309
9396
|
}
|
|
9310
|
-
/**
|
|
9311
|
-
* Takes a bunch of Projective Points but executes only one
|
|
9312
|
-
* inversion on all of them. Inversion is very slow operation,
|
|
9313
|
-
* so this improves performance massively.
|
|
9314
|
-
* Optimization: converts a list of projective points to a list of identical points with Z=1.
|
|
9315
|
-
*/
|
|
9316
9397
|
static normalizeZ(points) {
|
|
9317
|
-
|
|
9318
|
-
return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);
|
|
9398
|
+
return normalizeZ(Point, 'pz', points);
|
|
9319
9399
|
}
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
|
|
9323
|
-
|
|
9400
|
+
static fromBytes(bytes) {
|
|
9401
|
+
abytes(bytes);
|
|
9402
|
+
return Point.fromHex(bytes);
|
|
9403
|
+
}
|
|
9404
|
+
/** Converts hash string or Uint8Array to Point. */
|
|
9324
9405
|
static fromHex(hex) {
|
|
9325
9406
|
const P = Point.fromAffine(fromBytes(ensureBytes$1('pointHex', hex)));
|
|
9326
9407
|
P.assertValidity();
|
|
9327
9408
|
return P;
|
|
9328
9409
|
}
|
|
9329
|
-
|
|
9410
|
+
/** Multiplies generator point by privateKey. */
|
|
9330
9411
|
static fromPrivateKey(privateKey) {
|
|
9412
|
+
const normPrivateKeyToScalar = _legacyHelperNormPriv(Fn, curveOpts.allowedPrivateKeyLengths, curveOpts.wrapPrivateKey);
|
|
9331
9413
|
return Point.BASE.multiply(normPrivateKeyToScalar(privateKey));
|
|
9332
9414
|
}
|
|
9333
|
-
|
|
9415
|
+
/** Multiscalar Multiplication */
|
|
9334
9416
|
static msm(points, scalars) {
|
|
9335
9417
|
return pippenger(Point, Fn, points, scalars);
|
|
9336
9418
|
}
|
|
9337
|
-
|
|
9338
|
-
|
|
9419
|
+
/**
|
|
9420
|
+
*
|
|
9421
|
+
* @param windowSize
|
|
9422
|
+
* @param isLazy true will defer table computation until the first multiplication
|
|
9423
|
+
* @returns
|
|
9424
|
+
*/
|
|
9425
|
+
precompute(windowSize = 8, isLazy = true) {
|
|
9339
9426
|
wnaf.setWindowSize(this, windowSize);
|
|
9427
|
+
if (!isLazy)
|
|
9428
|
+
this.multiply(_3n$2); // random number
|
|
9429
|
+
return this;
|
|
9340
9430
|
}
|
|
9341
|
-
|
|
9431
|
+
/** "Private method", don't use it directly */
|
|
9432
|
+
_setWindowSize(windowSize) {
|
|
9433
|
+
this.precompute(windowSize);
|
|
9434
|
+
}
|
|
9435
|
+
// TODO: return `this`
|
|
9436
|
+
/** A point on curve is valid if it conforms to equation. */
|
|
9342
9437
|
assertValidity() {
|
|
9343
9438
|
assertValidMemo(this);
|
|
9344
9439
|
}
|
|
9345
9440
|
hasEvenY() {
|
|
9346
9441
|
const { y } = this.toAffine();
|
|
9347
|
-
if (Fp.isOdd)
|
|
9348
|
-
|
|
9349
|
-
|
|
9442
|
+
if (!Fp.isOdd)
|
|
9443
|
+
throw new Error("Field doesn't support isOdd");
|
|
9444
|
+
return !Fp.isOdd(y);
|
|
9350
9445
|
}
|
|
9351
|
-
/**
|
|
9352
|
-
* Compare one point to another.
|
|
9353
|
-
*/
|
|
9446
|
+
/** Compare one point to another. */
|
|
9354
9447
|
equals(other) {
|
|
9355
9448
|
aprjpoint(other);
|
|
9356
9449
|
const { px: X1, py: Y1, pz: Z1 } = this;
|
|
@@ -9359,9 +9452,7 @@ function weierstrassPoints$1(opts) {
|
|
|
9359
9452
|
const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1));
|
|
9360
9453
|
return U1 && U2;
|
|
9361
9454
|
}
|
|
9362
|
-
/**
|
|
9363
|
-
* Flips point to one corresponding to (x, -y) in Affine coordinates.
|
|
9364
|
-
*/
|
|
9455
|
+
/** Flips point to one corresponding to (x, -y) in Affine coordinates. */
|
|
9365
9456
|
negate() {
|
|
9366
9457
|
return new Point(this.px, Fp.neg(this.py), this.pz);
|
|
9367
9458
|
}
|
|
@@ -9466,47 +9557,6 @@ function weierstrassPoints$1(opts) {
|
|
|
9466
9557
|
is0() {
|
|
9467
9558
|
return this.equals(Point.ZERO);
|
|
9468
9559
|
}
|
|
9469
|
-
wNAF(n) {
|
|
9470
|
-
return wnaf.wNAFCached(this, n, Point.normalizeZ);
|
|
9471
|
-
}
|
|
9472
|
-
/**
|
|
9473
|
-
* Non-constant-time multiplication. Uses double-and-add algorithm.
|
|
9474
|
-
* It's faster, but should only be used when you don't care about
|
|
9475
|
-
* an exposed private key e.g. sig verification, which works over *public* keys.
|
|
9476
|
-
*/
|
|
9477
|
-
multiplyUnsafe(sc) {
|
|
9478
|
-
const { endo, n: N } = CURVE;
|
|
9479
|
-
aInRange('scalar', sc, _0n$7, N);
|
|
9480
|
-
const I = Point.ZERO;
|
|
9481
|
-
if (sc === _0n$7)
|
|
9482
|
-
return I;
|
|
9483
|
-
if (this.is0() || sc === _1n$8)
|
|
9484
|
-
return this;
|
|
9485
|
-
// Case a: no endomorphism. Case b: has precomputes.
|
|
9486
|
-
if (!endo || wnaf.hasPrecomputes(this))
|
|
9487
|
-
return wnaf.wNAFCachedUnsafe(this, sc, Point.normalizeZ);
|
|
9488
|
-
// Case c: endomorphism
|
|
9489
|
-
/** See docs for {@link EndomorphismOpts} */
|
|
9490
|
-
let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc);
|
|
9491
|
-
let k1p = I;
|
|
9492
|
-
let k2p = I;
|
|
9493
|
-
let d = this;
|
|
9494
|
-
while (k1 > _0n$7 || k2 > _0n$7) {
|
|
9495
|
-
if (k1 & _1n$8)
|
|
9496
|
-
k1p = k1p.add(d);
|
|
9497
|
-
if (k2 & _1n$8)
|
|
9498
|
-
k2p = k2p.add(d);
|
|
9499
|
-
d = d.double();
|
|
9500
|
-
k1 >>= _1n$8;
|
|
9501
|
-
k2 >>= _1n$8;
|
|
9502
|
-
}
|
|
9503
|
-
if (k1neg)
|
|
9504
|
-
k1p = k1p.negate();
|
|
9505
|
-
if (k2neg)
|
|
9506
|
-
k2p = k2p.negate();
|
|
9507
|
-
k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
|
|
9508
|
-
return k1p.add(k2p);
|
|
9509
|
-
}
|
|
9510
9560
|
/**
|
|
9511
9561
|
* Constant time multiplication.
|
|
9512
9562
|
* Uses wNAF method. Windowed method may be 10% faster,
|
|
@@ -9517,22 +9567,21 @@ function weierstrassPoints$1(opts) {
|
|
|
9517
9567
|
* @returns New point
|
|
9518
9568
|
*/
|
|
9519
9569
|
multiply(scalar) {
|
|
9520
|
-
const { endo
|
|
9521
|
-
|
|
9570
|
+
const { endo } = curveOpts;
|
|
9571
|
+
if (!Fn.isValidNot0(scalar))
|
|
9572
|
+
throw new Error('invalid scalar: out of range'); // 0 is invalid
|
|
9522
9573
|
let point, fake; // Fake point is used to const-time mult
|
|
9574
|
+
const mul = (n) => wnaf.wNAFCached(this, n, Point.normalizeZ);
|
|
9523
9575
|
/** See docs for {@link EndomorphismOpts} */
|
|
9524
9576
|
if (endo) {
|
|
9525
9577
|
const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar);
|
|
9526
|
-
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9530
|
-
k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
|
|
9531
|
-
point = k1p.add(k2p);
|
|
9532
|
-
fake = f1p.add(f2p);
|
|
9578
|
+
const { p: k1p, f: k1f } = mul(k1);
|
|
9579
|
+
const { p: k2p, f: k2f } = mul(k2);
|
|
9580
|
+
fake = k1f.add(k2f);
|
|
9581
|
+
point = finishEndo(endo.beta, k1p, k2p, k1neg, k2neg);
|
|
9533
9582
|
}
|
|
9534
9583
|
else {
|
|
9535
|
-
const { p, f } =
|
|
9584
|
+
const { p, f } = mul(scalar);
|
|
9536
9585
|
point = p;
|
|
9537
9586
|
fake = f;
|
|
9538
9587
|
}
|
|
@@ -9540,162 +9589,124 @@ function weierstrassPoints$1(opts) {
|
|
|
9540
9589
|
return Point.normalizeZ([point, fake])[0];
|
|
9541
9590
|
}
|
|
9542
9591
|
/**
|
|
9543
|
-
*
|
|
9544
|
-
*
|
|
9545
|
-
*
|
|
9546
|
-
* @returns non-zero affine point
|
|
9592
|
+
* Non-constant-time multiplication. Uses double-and-add algorithm.
|
|
9593
|
+
* It's faster, but should only be used when you don't care about
|
|
9594
|
+
* an exposed private key e.g. sig verification, which works over *public* keys.
|
|
9547
9595
|
*/
|
|
9596
|
+
multiplyUnsafe(sc) {
|
|
9597
|
+
const { endo } = curveOpts;
|
|
9598
|
+
const p = this;
|
|
9599
|
+
if (!Fn.isValid(sc))
|
|
9600
|
+
throw new Error('invalid scalar: out of range'); // 0 is valid
|
|
9601
|
+
if (sc === _0n$6 || p.is0())
|
|
9602
|
+
return Point.ZERO;
|
|
9603
|
+
if (sc === _1n$8)
|
|
9604
|
+
return p; // fast-path
|
|
9605
|
+
if (wnaf.hasPrecomputes(this))
|
|
9606
|
+
return this.multiply(sc);
|
|
9607
|
+
if (endo) {
|
|
9608
|
+
const { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc);
|
|
9609
|
+
// `wNAFCachedUnsafe` is 30% slower
|
|
9610
|
+
const { p1, p2 } = mulEndoUnsafe(Point, p, k1, k2);
|
|
9611
|
+
return finishEndo(endo.beta, p1, p2, k1neg, k2neg);
|
|
9612
|
+
}
|
|
9613
|
+
else {
|
|
9614
|
+
return wnaf.wNAFCachedUnsafe(p, sc);
|
|
9615
|
+
}
|
|
9616
|
+
}
|
|
9548
9617
|
multiplyAndAddUnsafe(Q, a, b) {
|
|
9549
|
-
const
|
|
9550
|
-
const mul = (P, a // Select faster multiply() method
|
|
9551
|
-
) => (a === _0n$7 || a === _1n$8 || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a));
|
|
9552
|
-
const sum = mul(this, a).add(mul(Q, b));
|
|
9618
|
+
const sum = this.multiplyUnsafe(a).add(Q.multiplyUnsafe(b));
|
|
9553
9619
|
return sum.is0() ? undefined : sum;
|
|
9554
9620
|
}
|
|
9555
|
-
|
|
9556
|
-
|
|
9557
|
-
|
|
9558
|
-
|
|
9559
|
-
|
|
9560
|
-
|
|
9621
|
+
/**
|
|
9622
|
+
* Converts Projective point to affine (x, y) coordinates.
|
|
9623
|
+
* @param invertedZ Z^-1 (inverted zero) - optional, precomputation is useful for invertBatch
|
|
9624
|
+
*/
|
|
9625
|
+
toAffine(invertedZ) {
|
|
9626
|
+
return toAffineMemo(this, invertedZ);
|
|
9627
|
+
}
|
|
9628
|
+
/**
|
|
9629
|
+
* Checks whether Point is free of torsion elements (is in prime subgroup).
|
|
9630
|
+
* Always torsion-free for cofactor=1 curves.
|
|
9631
|
+
*/
|
|
9561
9632
|
isTorsionFree() {
|
|
9562
|
-
const {
|
|
9633
|
+
const { isTorsionFree } = curveOpts;
|
|
9563
9634
|
if (cofactor === _1n$8)
|
|
9564
|
-
return true;
|
|
9635
|
+
return true;
|
|
9565
9636
|
if (isTorsionFree)
|
|
9566
9637
|
return isTorsionFree(Point, this);
|
|
9567
|
-
|
|
9638
|
+
return wnaf.wNAFCachedUnsafe(this, CURVE_ORDER).is0();
|
|
9568
9639
|
}
|
|
9569
9640
|
clearCofactor() {
|
|
9570
|
-
const {
|
|
9641
|
+
const { clearCofactor } = curveOpts;
|
|
9571
9642
|
if (cofactor === _1n$8)
|
|
9572
9643
|
return this; // Fast-path
|
|
9573
9644
|
if (clearCofactor)
|
|
9574
9645
|
return clearCofactor(Point, this);
|
|
9575
|
-
return this.multiplyUnsafe(
|
|
9646
|
+
return this.multiplyUnsafe(cofactor);
|
|
9576
9647
|
}
|
|
9577
|
-
|
|
9648
|
+
toBytes(isCompressed = true) {
|
|
9578
9649
|
abool('isCompressed', isCompressed);
|
|
9579
9650
|
this.assertValidity();
|
|
9580
9651
|
return toBytes(Point, this, isCompressed);
|
|
9581
9652
|
}
|
|
9653
|
+
/** @deprecated use `toBytes` */
|
|
9654
|
+
toRawBytes(isCompressed = true) {
|
|
9655
|
+
return this.toBytes(isCompressed);
|
|
9656
|
+
}
|
|
9582
9657
|
toHex(isCompressed = true) {
|
|
9583
|
-
|
|
9584
|
-
|
|
9658
|
+
return bytesToHex$1(this.toBytes(isCompressed));
|
|
9659
|
+
}
|
|
9660
|
+
toString() {
|
|
9661
|
+
return `<Point ${this.is0() ? 'ZERO' : this.toHex()}>`;
|
|
9585
9662
|
}
|
|
9586
9663
|
}
|
|
9587
9664
|
// base / generator point
|
|
9588
9665
|
Point.BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE);
|
|
9589
9666
|
// zero / infinity / identity point
|
|
9590
9667
|
Point.ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO); // 0, 1, 0
|
|
9591
|
-
|
|
9592
|
-
|
|
9593
|
-
|
|
9594
|
-
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
9599
|
-
|
|
9600
|
-
|
|
9601
|
-
|
|
9602
|
-
|
|
9603
|
-
|
|
9604
|
-
hash: 'hash',
|
|
9668
|
+
// fields
|
|
9669
|
+
Point.Fp = Fp;
|
|
9670
|
+
Point.Fn = Fn;
|
|
9671
|
+
const bits = Fn.BITS;
|
|
9672
|
+
const wnaf = wNAF$1(Point, curveOpts.endo ? Math.ceil(bits / 2) : bits);
|
|
9673
|
+
return Point;
|
|
9674
|
+
}
|
|
9675
|
+
// Points start with byte 0x02 when y is even; otherwise 0x03
|
|
9676
|
+
function pprefix(hasEvenY) {
|
|
9677
|
+
return Uint8Array.of(hasEvenY ? 0x02 : 0x03);
|
|
9678
|
+
}
|
|
9679
|
+
function ecdsa(Point, ecdsaOpts, curveOpts = {}) {
|
|
9680
|
+
_validateObject(ecdsaOpts, { hash: 'function' }, {
|
|
9605
9681
|
hmac: 'function',
|
|
9682
|
+
lowS: 'boolean',
|
|
9606
9683
|
randomBytes: 'function',
|
|
9607
|
-
}, {
|
|
9608
9684
|
bits2int: 'function',
|
|
9609
9685
|
bits2int_modN: 'function',
|
|
9610
|
-
lowS: 'boolean',
|
|
9611
|
-
});
|
|
9612
|
-
return Object.freeze({ lowS: true, ...opts });
|
|
9613
|
-
}
|
|
9614
|
-
/**
|
|
9615
|
-
* Creates short weierstrass curve and ECDSA signature methods for it.
|
|
9616
|
-
* @example
|
|
9617
|
-
* import { Field } from '@noble/curves/abstract/modular';
|
|
9618
|
-
* // Before that, define BigInt-s: a, b, p, n, Gx, Gy
|
|
9619
|
-
* const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n })
|
|
9620
|
-
*/
|
|
9621
|
-
function weierstrass$1(curveDef) {
|
|
9622
|
-
const CURVE = validateOpts$1(curveDef);
|
|
9623
|
-
const { Fp, n: CURVE_ORDER, nByteLength, nBitLength } = CURVE;
|
|
9624
|
-
const compressedLen = Fp.BYTES + 1; // e.g. 33 for 32
|
|
9625
|
-
const uncompressedLen = 2 * Fp.BYTES + 1; // e.g. 65 for 32
|
|
9626
|
-
function modN(a) {
|
|
9627
|
-
return mod$1(a, CURVE_ORDER);
|
|
9628
|
-
}
|
|
9629
|
-
function invN(a) {
|
|
9630
|
-
return invert$1(a, CURVE_ORDER);
|
|
9631
|
-
}
|
|
9632
|
-
const { ProjectivePoint: Point, normPrivateKeyToScalar, weierstrassEquation, isWithinCurveOrder, } = weierstrassPoints$1({
|
|
9633
|
-
...CURVE,
|
|
9634
|
-
toBytes(_c, point, isCompressed) {
|
|
9635
|
-
const a = point.toAffine();
|
|
9636
|
-
const x = Fp.toBytes(a.x);
|
|
9637
|
-
const cat = concatBytes$2;
|
|
9638
|
-
abool('isCompressed', isCompressed);
|
|
9639
|
-
if (isCompressed) {
|
|
9640
|
-
return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x);
|
|
9641
|
-
}
|
|
9642
|
-
else {
|
|
9643
|
-
return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y));
|
|
9644
|
-
}
|
|
9645
|
-
},
|
|
9646
|
-
fromBytes(bytes) {
|
|
9647
|
-
const len = bytes.length;
|
|
9648
|
-
const head = bytes[0];
|
|
9649
|
-
const tail = bytes.subarray(1);
|
|
9650
|
-
// this.assertValidity() is done inside of fromHex
|
|
9651
|
-
if (len === compressedLen && (head === 0x02 || head === 0x03)) {
|
|
9652
|
-
const x = bytesToNumberBE$1(tail);
|
|
9653
|
-
if (!inRange(x, _1n$8, Fp.ORDER))
|
|
9654
|
-
throw new Error('Point is not on curve');
|
|
9655
|
-
const y2 = weierstrassEquation(x); // y² = x³ + ax + b
|
|
9656
|
-
let y;
|
|
9657
|
-
try {
|
|
9658
|
-
y = Fp.sqrt(y2); // y = y² ^ (p+1)/4
|
|
9659
|
-
}
|
|
9660
|
-
catch (sqrtError) {
|
|
9661
|
-
const suffix = sqrtError instanceof Error ? ': ' + sqrtError.message : '';
|
|
9662
|
-
throw new Error('Point is not on curve' + suffix);
|
|
9663
|
-
}
|
|
9664
|
-
const isYOdd = (y & _1n$8) === _1n$8;
|
|
9665
|
-
// ECDSA
|
|
9666
|
-
const isHeadOdd = (head & 1) === 1;
|
|
9667
|
-
if (isHeadOdd !== isYOdd)
|
|
9668
|
-
y = Fp.neg(y);
|
|
9669
|
-
return { x, y };
|
|
9670
|
-
}
|
|
9671
|
-
else if (len === uncompressedLen && head === 0x04) {
|
|
9672
|
-
const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));
|
|
9673
|
-
const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));
|
|
9674
|
-
return { x, y };
|
|
9675
|
-
}
|
|
9676
|
-
else {
|
|
9677
|
-
const cl = compressedLen;
|
|
9678
|
-
const ul = uncompressedLen;
|
|
9679
|
-
throw new Error('invalid Point, expected length of ' + cl + ', or uncompressed ' + ul + ', got ' + len);
|
|
9680
|
-
}
|
|
9681
|
-
},
|
|
9682
9686
|
});
|
|
9687
|
+
const randomBytes_ = ecdsaOpts.randomBytes || randomBytes$3;
|
|
9688
|
+
const hmac_ = ecdsaOpts.hmac ||
|
|
9689
|
+
((key, ...msgs) => hmac$1(ecdsaOpts.hash, key, concatBytes$2(...msgs)));
|
|
9690
|
+
const { Fp, Fn } = Point;
|
|
9691
|
+
const { ORDER: CURVE_ORDER, BITS: fnBits } = Fn;
|
|
9683
9692
|
function isBiggerThanHalfOrder(number) {
|
|
9684
9693
|
const HALF = CURVE_ORDER >> _1n$8;
|
|
9685
9694
|
return number > HALF;
|
|
9686
9695
|
}
|
|
9687
9696
|
function normalizeS(s) {
|
|
9688
|
-
return isBiggerThanHalfOrder(s) ?
|
|
9697
|
+
return isBiggerThanHalfOrder(s) ? Fn.neg(s) : s;
|
|
9698
|
+
}
|
|
9699
|
+
function aValidRS(title, num) {
|
|
9700
|
+
if (!Fn.isValidNot0(num))
|
|
9701
|
+
throw new Error(`invalid signature ${title}: out of range 1..CURVE.n`);
|
|
9689
9702
|
}
|
|
9690
|
-
// slice bytes num
|
|
9691
|
-
const slcNum = (b, from, to) => bytesToNumberBE$1(b.slice(from, to));
|
|
9692
9703
|
/**
|
|
9693
9704
|
* ECDSA signature with its (r, s) properties. Supports DER & compact representations.
|
|
9694
9705
|
*/
|
|
9695
9706
|
class Signature {
|
|
9696
9707
|
constructor(r, s, recovery) {
|
|
9697
|
-
|
|
9698
|
-
|
|
9708
|
+
aValidRS('r', r); // r in [1..N-1]
|
|
9709
|
+
aValidRS('s', s); // s in [1..N-1]
|
|
9699
9710
|
this.r = r;
|
|
9700
9711
|
this.s = s;
|
|
9701
9712
|
if (recovery != null)
|
|
@@ -9704,9 +9715,9 @@ function weierstrass$1(curveDef) {
|
|
|
9704
9715
|
}
|
|
9705
9716
|
// pair (bytes of r, bytes of s)
|
|
9706
9717
|
static fromCompact(hex) {
|
|
9707
|
-
const
|
|
9708
|
-
|
|
9709
|
-
return new Signature(
|
|
9718
|
+
const L = Fn.BYTES;
|
|
9719
|
+
const b = ensureBytes$1('compactSignature', hex, L * 2);
|
|
9720
|
+
return new Signature(Fn.fromBytes(b.subarray(0, L)), Fn.fromBytes(b.subarray(L, L * 2)));
|
|
9710
9721
|
}
|
|
9711
9722
|
// DER encoded ECDSA signature
|
|
9712
9723
|
// https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script
|
|
@@ -9722,22 +9733,36 @@ function weierstrass$1(curveDef) {
|
|
|
9722
9733
|
addRecoveryBit(recovery) {
|
|
9723
9734
|
return new Signature(this.r, this.s, recovery);
|
|
9724
9735
|
}
|
|
9736
|
+
// ProjPointType<bigint>
|
|
9725
9737
|
recoverPublicKey(msgHash) {
|
|
9738
|
+
const FIELD_ORDER = Fp.ORDER;
|
|
9726
9739
|
const { r, s, recovery: rec } = this;
|
|
9727
|
-
const h = bits2int_modN(ensureBytes$1('msgHash', msgHash)); // Truncate hash
|
|
9728
9740
|
if (rec == null || ![0, 1, 2, 3].includes(rec))
|
|
9729
9741
|
throw new Error('recovery id invalid');
|
|
9730
|
-
|
|
9731
|
-
|
|
9742
|
+
// ECDSA recovery is hard for cofactor > 1 curves.
|
|
9743
|
+
// In sign, `r = q.x mod n`, and here we recover q.x from r.
|
|
9744
|
+
// While recovering q.x >= n, we need to add r+n for cofactor=1 curves.
|
|
9745
|
+
// However, for cofactor>1, r+n may not get q.x:
|
|
9746
|
+
// r+n*i would need to be done instead where i is unknown.
|
|
9747
|
+
// To easily get i, we either need to:
|
|
9748
|
+
// a. increase amount of valid recid values (4, 5...); OR
|
|
9749
|
+
// b. prohibit non-prime-order signatures (recid > 1).
|
|
9750
|
+
const hasCofactor = CURVE_ORDER * _2n$6 < FIELD_ORDER;
|
|
9751
|
+
if (hasCofactor && rec > 1)
|
|
9752
|
+
throw new Error('recovery id is ambiguous for h>1 curve');
|
|
9753
|
+
const radj = rec === 2 || rec === 3 ? r + CURVE_ORDER : r;
|
|
9754
|
+
if (!Fp.isValid(radj))
|
|
9732
9755
|
throw new Error('recovery id 2 or 3 invalid');
|
|
9733
|
-
const
|
|
9734
|
-
const R = Point.fromHex(
|
|
9735
|
-
const ir =
|
|
9736
|
-
const
|
|
9737
|
-
const
|
|
9738
|
-
const
|
|
9739
|
-
|
|
9740
|
-
|
|
9756
|
+
const x = Fp.toBytes(radj);
|
|
9757
|
+
const R = Point.fromHex(concatBytes$2(pprefix((rec & 1) === 0), x));
|
|
9758
|
+
const ir = Fn.inv(radj); // r^-1
|
|
9759
|
+
const h = bits2int_modN(ensureBytes$1('msgHash', msgHash)); // Truncate hash
|
|
9760
|
+
const u1 = Fn.create(-h * ir); // -hr^-1
|
|
9761
|
+
const u2 = Fn.create(s * ir); // sr^-1
|
|
9762
|
+
// (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1). unsafe is fine: there is no private data.
|
|
9763
|
+
const Q = Point.BASE.multiplyUnsafe(u1).add(R.multiplyUnsafe(u2));
|
|
9764
|
+
if (Q.is0())
|
|
9765
|
+
throw new Error('point at infinify');
|
|
9741
9766
|
Q.assertValidity();
|
|
9742
9767
|
return Q;
|
|
9743
9768
|
}
|
|
@@ -9746,24 +9771,31 @@ function weierstrass$1(curveDef) {
|
|
|
9746
9771
|
return isBiggerThanHalfOrder(this.s);
|
|
9747
9772
|
}
|
|
9748
9773
|
normalizeS() {
|
|
9749
|
-
return this.hasHighS() ? new Signature(this.r,
|
|
9774
|
+
return this.hasHighS() ? new Signature(this.r, Fn.neg(this.s), this.recovery) : this;
|
|
9775
|
+
}
|
|
9776
|
+
toBytes(format) {
|
|
9777
|
+
if (format === 'compact')
|
|
9778
|
+
return concatBytes$2(Fn.toBytes(this.r), Fn.toBytes(this.s));
|
|
9779
|
+
if (format === 'der')
|
|
9780
|
+
return hexToBytes$1(DER$1.hexFromSig(this));
|
|
9781
|
+
throw new Error('invalid format');
|
|
9750
9782
|
}
|
|
9751
9783
|
// DER-encoded
|
|
9752
9784
|
toDERRawBytes() {
|
|
9753
|
-
return
|
|
9785
|
+
return this.toBytes('der');
|
|
9754
9786
|
}
|
|
9755
9787
|
toDERHex() {
|
|
9756
|
-
return
|
|
9788
|
+
return bytesToHex$1(this.toBytes('der'));
|
|
9757
9789
|
}
|
|
9758
9790
|
// padded bytes of r, then padded bytes of s
|
|
9759
9791
|
toCompactRawBytes() {
|
|
9760
|
-
return
|
|
9792
|
+
return this.toBytes('compact');
|
|
9761
9793
|
}
|
|
9762
9794
|
toCompactHex() {
|
|
9763
|
-
|
|
9764
|
-
return numToSizedHex(this.r, l) + numToSizedHex(this.s, l);
|
|
9795
|
+
return bytesToHex$1(this.toBytes('compact'));
|
|
9765
9796
|
}
|
|
9766
9797
|
}
|
|
9798
|
+
const normPrivateKeyToScalar = _legacyHelperNormPriv(Fn, curveOpts.allowedPrivateKeyLengths, curveOpts.wrapPrivateKey);
|
|
9767
9799
|
const utils = {
|
|
9768
9800
|
isValidPrivateKey(privateKey) {
|
|
9769
9801
|
try {
|
|
@@ -9780,21 +9812,11 @@ function weierstrass$1(curveDef) {
|
|
|
9780
9812
|
* (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.
|
|
9781
9813
|
*/
|
|
9782
9814
|
randomPrivateKey: () => {
|
|
9783
|
-
const
|
|
9784
|
-
return mapHashToField$1(
|
|
9815
|
+
const n = CURVE_ORDER;
|
|
9816
|
+
return mapHashToField$1(randomBytes_(getMinHashLength$1(n)), n);
|
|
9785
9817
|
},
|
|
9786
|
-
/**
|
|
9787
|
-
* Creates precompute table for an arbitrary EC point. Makes point "cached".
|
|
9788
|
-
* Allows to massively speed-up `point.multiply(scalar)`.
|
|
9789
|
-
* @returns cached point
|
|
9790
|
-
* @example
|
|
9791
|
-
* const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey));
|
|
9792
|
-
* fast.multiply(privKey); // much faster ECDH now
|
|
9793
|
-
*/
|
|
9794
9818
|
precompute(windowSize = 8, point = Point.BASE) {
|
|
9795
|
-
point.
|
|
9796
|
-
point.multiply(BigInt(3)); // 3 is arbitrary, just need any number here
|
|
9797
|
-
return point;
|
|
9819
|
+
return point.precompute(windowSize, false);
|
|
9798
9820
|
},
|
|
9799
9821
|
};
|
|
9800
9822
|
/**
|
|
@@ -9804,7 +9826,7 @@ function weierstrass$1(curveDef) {
|
|
|
9804
9826
|
* @returns Public key, full when isCompressed=false; short when isCompressed=true
|
|
9805
9827
|
*/
|
|
9806
9828
|
function getPublicKey(privateKey, isCompressed = true) {
|
|
9807
|
-
return Point.fromPrivateKey(privateKey).
|
|
9829
|
+
return Point.fromPrivateKey(privateKey).toBytes(isCompressed);
|
|
9808
9830
|
}
|
|
9809
9831
|
/**
|
|
9810
9832
|
* Quick and dirty check for item being public key. Does not validate hex, or being on-curve.
|
|
@@ -9815,15 +9837,15 @@ function weierstrass$1(curveDef) {
|
|
|
9815
9837
|
if (item instanceof Point)
|
|
9816
9838
|
return true;
|
|
9817
9839
|
const arr = ensureBytes$1('key', item);
|
|
9818
|
-
const
|
|
9819
|
-
const
|
|
9820
|
-
const
|
|
9821
|
-
const
|
|
9822
|
-
if (
|
|
9840
|
+
const length = arr.length;
|
|
9841
|
+
const L = Fp.BYTES;
|
|
9842
|
+
const LC = L + 1; // e.g. 33 for 32
|
|
9843
|
+
const LU = 2 * L + 1; // e.g. 65 for 32
|
|
9844
|
+
if (curveOpts.allowedPrivateKeyLengths || Fn.BYTES === LC) {
|
|
9823
9845
|
return undefined;
|
|
9824
9846
|
}
|
|
9825
9847
|
else {
|
|
9826
|
-
return
|
|
9848
|
+
return length === LC || length === LU;
|
|
9827
9849
|
}
|
|
9828
9850
|
}
|
|
9829
9851
|
/**
|
|
@@ -9842,13 +9864,13 @@ function weierstrass$1(curveDef) {
|
|
|
9842
9864
|
if (isProbPub(publicB) === false)
|
|
9843
9865
|
throw new Error('second arg must be public key');
|
|
9844
9866
|
const b = Point.fromHex(publicB); // check for being on-curve
|
|
9845
|
-
return b.multiply(normPrivateKeyToScalar(privateA)).
|
|
9867
|
+
return b.multiply(normPrivateKeyToScalar(privateA)).toBytes(isCompressed);
|
|
9846
9868
|
}
|
|
9847
9869
|
// RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets.
|
|
9848
9870
|
// FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int.
|
|
9849
9871
|
// bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same.
|
|
9850
9872
|
// int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors
|
|
9851
|
-
const bits2int =
|
|
9873
|
+
const bits2int = ecdsaOpts.bits2int ||
|
|
9852
9874
|
function (bytes) {
|
|
9853
9875
|
// Our custom check "just in case", for protection against DoS
|
|
9854
9876
|
if (bytes.length > 8192)
|
|
@@ -9856,22 +9878,22 @@ function weierstrass$1(curveDef) {
|
|
|
9856
9878
|
// For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)
|
|
9857
9879
|
// for some cases, since bytes.length * 8 is not actual bitLength.
|
|
9858
9880
|
const num = bytesToNumberBE$1(bytes); // check for == u8 done here
|
|
9859
|
-
const delta = bytes.length * 8 -
|
|
9881
|
+
const delta = bytes.length * 8 - fnBits; // truncate to nBitLength leftmost bits
|
|
9860
9882
|
return delta > 0 ? num >> BigInt(delta) : num;
|
|
9861
9883
|
};
|
|
9862
|
-
const bits2int_modN =
|
|
9884
|
+
const bits2int_modN = ecdsaOpts.bits2int_modN ||
|
|
9863
9885
|
function (bytes) {
|
|
9864
|
-
return
|
|
9886
|
+
return Fn.create(bits2int(bytes)); // can't use bytesToNumberBE here
|
|
9865
9887
|
};
|
|
9866
9888
|
// NOTE: pads output with zero as per spec
|
|
9867
|
-
const ORDER_MASK = bitMask$1(
|
|
9889
|
+
const ORDER_MASK = bitMask$1(fnBits);
|
|
9868
9890
|
/**
|
|
9869
9891
|
* Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.
|
|
9870
9892
|
*/
|
|
9871
9893
|
function int2octets(num) {
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
return
|
|
9894
|
+
// IMPORTANT: the check ensures working for case `Fn.BYTES != Fn.BITS * 8`
|
|
9895
|
+
aInRange('num < 2^' + fnBits, num, _0n$6, ORDER_MASK);
|
|
9896
|
+
return Fn.toBytes(num);
|
|
9875
9897
|
}
|
|
9876
9898
|
// Steps A, D of RFC6979 3.2
|
|
9877
9899
|
// Creates RFC6979 seed; converts msg/privKey to numbers.
|
|
@@ -9881,7 +9903,7 @@ function weierstrass$1(curveDef) {
|
|
|
9881
9903
|
function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
|
|
9882
9904
|
if (['recovered', 'canonical'].some((k) => k in opts))
|
|
9883
9905
|
throw new Error('sign() legacy options not supported');
|
|
9884
|
-
const { hash
|
|
9906
|
+
const { hash } = ecdsaOpts;
|
|
9885
9907
|
let { lowS, prehash, extraEntropy: ent } = opts; // generates low-s sigs by default
|
|
9886
9908
|
if (lowS == null)
|
|
9887
9909
|
lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash
|
|
@@ -9890,7 +9912,7 @@ function weierstrass$1(curveDef) {
|
|
|
9890
9912
|
if (prehash)
|
|
9891
9913
|
msgHash = ensureBytes$1('prehashed msgHash', hash(msgHash));
|
|
9892
9914
|
// We can't later call bits2octets, since nested bits2int is broken for curves
|
|
9893
|
-
// with
|
|
9915
|
+
// with fnBits % 8 !== 0. Because of that, we unwrap it here as int2octets call.
|
|
9894
9916
|
// const bits2octets = (bits) => int2octets(bits2int_modN(bits))
|
|
9895
9917
|
const h1int = bits2int_modN(msgHash);
|
|
9896
9918
|
const d = normPrivateKeyToScalar(privateKey); // validate private key, convert to bigint
|
|
@@ -9898,27 +9920,28 @@ function weierstrass$1(curveDef) {
|
|
|
9898
9920
|
// extraEntropy. RFC6979 3.6: additional k' (optional).
|
|
9899
9921
|
if (ent != null && ent !== false) {
|
|
9900
9922
|
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
|
|
9901
|
-
const e = ent === true ?
|
|
9923
|
+
const e = ent === true ? randomBytes_(Fp.BYTES) : ent; // generate random bytes OR pass as-is
|
|
9902
9924
|
seedArgs.push(ensureBytes$1('extraEntropy', e)); // check for being bytes
|
|
9903
9925
|
}
|
|
9904
9926
|
const seed = concatBytes$2(...seedArgs); // Step D of RFC6979 3.2
|
|
9905
9927
|
const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!
|
|
9906
9928
|
// Converts signature params into point w r/s, checks result for validity.
|
|
9929
|
+
// Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to
|
|
9930
|
+
// https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it:
|
|
9931
|
+
// a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT
|
|
9907
9932
|
function k2sig(kBytes) {
|
|
9908
9933
|
// RFC 6979 Section 3.2, step 3: k = bits2int(T)
|
|
9934
|
+
// Important: all mod() calls here must be done over N
|
|
9909
9935
|
const k = bits2int(kBytes); // Cannot use fields methods, since it is group element
|
|
9910
|
-
if (!
|
|
9911
|
-
return; //
|
|
9912
|
-
const ik =
|
|
9936
|
+
if (!Fn.isValidNot0(k))
|
|
9937
|
+
return; // Valid scalars (including k) must be in 1..N-1
|
|
9938
|
+
const ik = Fn.inv(k); // k^-1 mod n
|
|
9913
9939
|
const q = Point.BASE.multiply(k).toAffine(); // q = Gk
|
|
9914
|
-
const r =
|
|
9915
|
-
if (r === _0n$
|
|
9940
|
+
const r = Fn.create(q.x); // r = q.x mod n
|
|
9941
|
+
if (r === _0n$6)
|
|
9916
9942
|
return;
|
|
9917
|
-
|
|
9918
|
-
|
|
9919
|
-
// a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT
|
|
9920
|
-
const s = modN(ik * modN(m + r * d)); // Not using blinding here
|
|
9921
|
-
if (s === _0n$7)
|
|
9943
|
+
const s = Fn.create(ik * Fn.create(m + r * d)); // Not using blinding here, see comment above
|
|
9944
|
+
if (s === _0n$6)
|
|
9922
9945
|
return;
|
|
9923
9946
|
let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n$8); // recovery bit (2 or 3, when q.x > n)
|
|
9924
9947
|
let normS = s;
|
|
@@ -9930,8 +9953,8 @@ function weierstrass$1(curveDef) {
|
|
|
9930
9953
|
}
|
|
9931
9954
|
return { seed, k2sig };
|
|
9932
9955
|
}
|
|
9933
|
-
const defaultSigOpts = { lowS:
|
|
9934
|
-
const defaultVerOpts = { lowS:
|
|
9956
|
+
const defaultSigOpts = { lowS: ecdsaOpts.lowS, prehash: false };
|
|
9957
|
+
const defaultVerOpts = { lowS: ecdsaOpts.lowS, prehash: false };
|
|
9935
9958
|
/**
|
|
9936
9959
|
* Signs message hash with a private key.
|
|
9937
9960
|
* ```
|
|
@@ -9947,13 +9970,11 @@ function weierstrass$1(curveDef) {
|
|
|
9947
9970
|
*/
|
|
9948
9971
|
function sign(msgHash, privKey, opts = defaultSigOpts) {
|
|
9949
9972
|
const { seed, k2sig } = prepSig(msgHash, privKey, opts); // Steps A, D of RFC6979 3.2.
|
|
9950
|
-
const
|
|
9951
|
-
const drbg = createHmacDrbg$1(C.hash.outputLen, C.nByteLength, C.hmac);
|
|
9973
|
+
const drbg = createHmacDrbg$1(ecdsaOpts.hash.outputLen, Fn.BYTES, hmac_);
|
|
9952
9974
|
return drbg(seed, k2sig); // Steps B, C, D, E, F, G
|
|
9953
9975
|
}
|
|
9954
9976
|
// Enable precomputes. Slows down first publicKey computation by 20ms.
|
|
9955
|
-
Point.BASE.
|
|
9956
|
-
// utils.precompute(8, ProjectivePoint.BASE)
|
|
9977
|
+
Point.BASE.precompute(8);
|
|
9957
9978
|
/**
|
|
9958
9979
|
* Verifies a signature against message hash and public key.
|
|
9959
9980
|
* Rejects lowS signatures by default: to override,
|
|
@@ -9971,13 +9992,14 @@ function weierstrass$1(curveDef) {
|
|
|
9971
9992
|
const sg = signature;
|
|
9972
9993
|
msgHash = ensureBytes$1('msgHash', msgHash);
|
|
9973
9994
|
publicKey = ensureBytes$1('publicKey', publicKey);
|
|
9974
|
-
|
|
9975
|
-
// Verify opts, deduce signature format
|
|
9995
|
+
// Verify opts
|
|
9976
9996
|
validateSigVerOpts(opts);
|
|
9997
|
+
const { lowS, prehash, format } = opts;
|
|
9998
|
+
// TODO: remove
|
|
9977
9999
|
if ('strict' in opts)
|
|
9978
10000
|
throw new Error('options.strict was renamed to lowS');
|
|
9979
|
-
if (format !== undefined &&
|
|
9980
|
-
throw new Error('format must be compact or
|
|
10001
|
+
if (format !== undefined && !['compact', 'der', 'js'].includes(format))
|
|
10002
|
+
throw new Error('format must be "compact", "der" or "js"');
|
|
9981
10003
|
const isHex = typeof sg === 'string' || isBytes(sg);
|
|
9982
10004
|
const isObj = !isHex &&
|
|
9983
10005
|
!format &&
|
|
@@ -9989,12 +10011,29 @@ function weierstrass$1(curveDef) {
|
|
|
9989
10011
|
throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance');
|
|
9990
10012
|
let _sig = undefined;
|
|
9991
10013
|
let P;
|
|
10014
|
+
// deduce signature format
|
|
9992
10015
|
try {
|
|
9993
|
-
if (
|
|
9994
|
-
|
|
10016
|
+
// if (format === 'js') {
|
|
10017
|
+
// if (sg != null && !isBytes(sg)) _sig = new Signature(sg.r, sg.s);
|
|
10018
|
+
// } else if (format === 'compact') {
|
|
10019
|
+
// _sig = Signature.fromCompact(sg);
|
|
10020
|
+
// } else if (format === 'der') {
|
|
10021
|
+
// _sig = Signature.fromDER(sg);
|
|
10022
|
+
// } else {
|
|
10023
|
+
// throw new Error('invalid format');
|
|
10024
|
+
// }
|
|
10025
|
+
if (isObj) {
|
|
10026
|
+
if (format === undefined || format === 'js') {
|
|
10027
|
+
_sig = new Signature(sg.r, sg.s);
|
|
10028
|
+
}
|
|
10029
|
+
else {
|
|
10030
|
+
throw new Error('invalid format');
|
|
10031
|
+
}
|
|
10032
|
+
}
|
|
9995
10033
|
if (isHex) {
|
|
9996
|
-
//
|
|
9997
|
-
//
|
|
10034
|
+
// TODO: remove this malleable check
|
|
10035
|
+
// Signature can be represented in 2 ways: compact (2*Fn.BYTES) & DER (variable-length).
|
|
10036
|
+
// Since DER can also be 2*Fn.BYTES bytes, we check for it first.
|
|
9998
10037
|
try {
|
|
9999
10038
|
if (format !== 'compact')
|
|
10000
10039
|
_sig = Signature.fromDER(sg);
|
|
@@ -10015,61 +10054,111 @@ function weierstrass$1(curveDef) {
|
|
|
10015
10054
|
return false;
|
|
10016
10055
|
if (lowS && _sig.hasHighS())
|
|
10017
10056
|
return false;
|
|
10057
|
+
// todo: optional.hash => hash
|
|
10018
10058
|
if (prehash)
|
|
10019
|
-
msgHash =
|
|
10059
|
+
msgHash = ecdsaOpts.hash(msgHash);
|
|
10020
10060
|
const { r, s } = _sig;
|
|
10021
10061
|
const h = bits2int_modN(msgHash); // Cannot use fields methods, since it is group element
|
|
10022
|
-
const is =
|
|
10023
|
-
const u1 =
|
|
10024
|
-
const u2 =
|
|
10025
|
-
const R = Point.BASE.
|
|
10026
|
-
if (
|
|
10062
|
+
const is = Fn.inv(s); // s^-1
|
|
10063
|
+
const u1 = Fn.create(h * is); // u1 = hs^-1 mod n
|
|
10064
|
+
const u2 = Fn.create(r * is); // u2 = rs^-1 mod n
|
|
10065
|
+
const R = Point.BASE.multiplyUnsafe(u1).add(P.multiplyUnsafe(u2));
|
|
10066
|
+
if (R.is0())
|
|
10027
10067
|
return false;
|
|
10028
|
-
const v =
|
|
10068
|
+
const v = Fn.create(R.x); // v = r.x mod n
|
|
10029
10069
|
return v === r;
|
|
10030
10070
|
}
|
|
10031
|
-
|
|
10032
|
-
|
|
10071
|
+
// TODO: clarify API for cloning .clone({hash: sha512}) ? .createWith({hash: sha512})?
|
|
10072
|
+
// const clone = (hash: CHash): ECDSA => ecdsa(Point, { ...ecdsaOpts, ...getHash(hash) }, curveOpts);
|
|
10073
|
+
return Object.freeze({
|
|
10033
10074
|
getPublicKey,
|
|
10034
10075
|
getSharedSecret,
|
|
10035
10076
|
sign,
|
|
10036
10077
|
verify,
|
|
10037
|
-
ProjectivePoint: Point,
|
|
10038
|
-
Signature,
|
|
10039
10078
|
utils,
|
|
10079
|
+
Point,
|
|
10080
|
+
Signature,
|
|
10081
|
+
});
|
|
10082
|
+
}
|
|
10083
|
+
function _weierstrass_legacy_opts_to_new(c) {
|
|
10084
|
+
const CURVE = {
|
|
10085
|
+
a: c.a,
|
|
10086
|
+
b: c.b,
|
|
10087
|
+
p: c.Fp.ORDER,
|
|
10088
|
+
n: c.n,
|
|
10089
|
+
h: c.h,
|
|
10090
|
+
Gx: c.Gx,
|
|
10091
|
+
Gy: c.Gy,
|
|
10092
|
+
};
|
|
10093
|
+
const Fp = c.Fp;
|
|
10094
|
+
const Fn = Field$1(CURVE.n, c.nBitLength);
|
|
10095
|
+
const curveOpts = {
|
|
10096
|
+
Fp,
|
|
10097
|
+
Fn,
|
|
10098
|
+
allowedPrivateKeyLengths: c.allowedPrivateKeyLengths,
|
|
10099
|
+
allowInfinityPoint: c.allowInfinityPoint,
|
|
10100
|
+
endo: c.endo,
|
|
10101
|
+
wrapPrivateKey: c.wrapPrivateKey,
|
|
10102
|
+
isTorsionFree: c.isTorsionFree,
|
|
10103
|
+
clearCofactor: c.clearCofactor,
|
|
10104
|
+
fromBytes: c.fromBytes,
|
|
10105
|
+
toBytes: c.toBytes,
|
|
10106
|
+
};
|
|
10107
|
+
return { CURVE, curveOpts };
|
|
10108
|
+
}
|
|
10109
|
+
function _ecdsa_legacy_opts_to_new(c) {
|
|
10110
|
+
const { CURVE, curveOpts } = _weierstrass_legacy_opts_to_new(c);
|
|
10111
|
+
const ecdsaOpts = {
|
|
10112
|
+
hash: c.hash,
|
|
10113
|
+
hmac: c.hmac,
|
|
10114
|
+
randomBytes: c.randomBytes,
|
|
10115
|
+
lowS: c.lowS,
|
|
10116
|
+
bits2int: c.bits2int,
|
|
10117
|
+
bits2int_modN: c.bits2int_modN,
|
|
10040
10118
|
};
|
|
10119
|
+
return { CURVE, curveOpts, ecdsaOpts };
|
|
10120
|
+
}
|
|
10121
|
+
function _ecdsa_new_output_to_legacy(c, ecdsa) {
|
|
10122
|
+
return Object.assign({}, ecdsa, {
|
|
10123
|
+
ProjectivePoint: ecdsa.Point,
|
|
10124
|
+
CURVE: c,
|
|
10125
|
+
});
|
|
10126
|
+
}
|
|
10127
|
+
// _ecdsa_legacy
|
|
10128
|
+
function weierstrass$1(c) {
|
|
10129
|
+
const { CURVE, curveOpts, ecdsaOpts } = _ecdsa_legacy_opts_to_new(c);
|
|
10130
|
+
const Point = weierstrassN(CURVE, curveOpts);
|
|
10131
|
+
const signs = ecdsa(Point, ecdsaOpts, curveOpts);
|
|
10132
|
+
return _ecdsa_new_output_to_legacy(c, signs);
|
|
10041
10133
|
}/**
|
|
10042
10134
|
* Utilities for short weierstrass curves, combined with noble-hashes.
|
|
10043
10135
|
* @module
|
|
10044
10136
|
*/
|
|
10045
10137
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
10046
|
-
/** connects noble-curves to noble-hashes */
|
|
10047
|
-
function getHash$1(hash) {
|
|
10048
|
-
return {
|
|
10049
|
-
hash,
|
|
10050
|
-
hmac: (key, ...msgs) => hmac$1(hash, key, concatBytes$3(...msgs)),
|
|
10051
|
-
randomBytes: randomBytes$3,
|
|
10052
|
-
};
|
|
10053
|
-
}
|
|
10054
10138
|
function createCurve$1(curveDef, defHash) {
|
|
10055
|
-
const create = (hash) => weierstrass$1({ ...curveDef,
|
|
10139
|
+
const create = (hash) => weierstrass$1({ ...curveDef, hash: hash });
|
|
10056
10140
|
return { ...create(defHash), create };
|
|
10057
10141
|
}/**
|
|
10058
|
-
*
|
|
10059
|
-
*
|
|
10060
|
-
* Seems to be rigid (not backdoored)
|
|
10061
|
-
* [as per discussion](https://bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975).
|
|
10142
|
+
* SECG secp256k1. See [pdf](https://www.secg.org/sec2-v2.pdf).
|
|
10062
10143
|
*
|
|
10063
|
-
*
|
|
10064
|
-
*
|
|
10065
|
-
* For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit.
|
|
10066
|
-
* [See explanation](https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066).
|
|
10144
|
+
* Belongs to Koblitz curves: it has efficiently-computable GLV endomorphism ψ,
|
|
10145
|
+
* check out {@link EndomorphismOpts}. Seems to be rigid (not backdoored).
|
|
10067
10146
|
* @module
|
|
10068
10147
|
*/
|
|
10069
10148
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
10070
|
-
|
|
10071
|
-
|
|
10072
|
-
|
|
10149
|
+
// Seems like generator was produced from some seed:
|
|
10150
|
+
// `Point.BASE.multiply(Point.Fn.inv(2n, N)).toAffine().x`
|
|
10151
|
+
// // gives short x 0x3b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63n
|
|
10152
|
+
const secp256k1_CURVE = {
|
|
10153
|
+
p: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'),
|
|
10154
|
+
n: BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'),
|
|
10155
|
+
h: BigInt(1),
|
|
10156
|
+
a: BigInt(0),
|
|
10157
|
+
b: BigInt(7),
|
|
10158
|
+
Gx: BigInt('0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'),
|
|
10159
|
+
Gy: BigInt('0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'),
|
|
10160
|
+
};
|
|
10161
|
+
BigInt(0);
|
|
10073
10162
|
const _1n$7 = BigInt(1);
|
|
10074
10163
|
const _2n$5 = BigInt(2);
|
|
10075
10164
|
const divNearest$1 = (a, b) => (a + b / _2n$5) / b;
|
|
@@ -10078,7 +10167,7 @@ const divNearest$1 = (a, b) => (a + b / _2n$5) / b;
|
|
|
10078
10167
|
* (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00]
|
|
10079
10168
|
*/
|
|
10080
10169
|
function sqrtMod$1(y) {
|
|
10081
|
-
const P =
|
|
10170
|
+
const P = secp256k1_CURVE.p;
|
|
10082
10171
|
// prettier-ignore
|
|
10083
10172
|
const _3n = BigInt(3), _6n = BigInt(6), _11n = BigInt(11), _22n = BigInt(22);
|
|
10084
10173
|
// prettier-ignore
|
|
@@ -10101,7 +10190,7 @@ function sqrtMod$1(y) {
|
|
|
10101
10190
|
throw new Error('Cannot find square root');
|
|
10102
10191
|
return root;
|
|
10103
10192
|
}
|
|
10104
|
-
const Fpk1 = Field$1(
|
|
10193
|
+
const Fpk1 = Field$1(secp256k1_CURVE.p, undefined, undefined, { sqrt: sqrtMod$1 });
|
|
10105
10194
|
/**
|
|
10106
10195
|
* secp256k1 curve, ECDSA and ECDH methods.
|
|
10107
10196
|
*
|
|
@@ -10118,19 +10207,14 @@ const Fpk1 = Field$1(secp256k1P$1, undefined, undefined, { sqrt: sqrtMod$1 });
|
|
|
10118
10207
|
* ```
|
|
10119
10208
|
*/
|
|
10120
10209
|
const secp256k1$1 = createCurve$1({
|
|
10121
|
-
|
|
10122
|
-
b: BigInt(7),
|
|
10210
|
+
...secp256k1_CURVE,
|
|
10123
10211
|
Fp: Fpk1,
|
|
10124
|
-
n: secp256k1N$1,
|
|
10125
|
-
Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),
|
|
10126
|
-
Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),
|
|
10127
|
-
h: BigInt(1),
|
|
10128
10212
|
lowS: true, // Allow only low-S signatures by default in sign() and verify()
|
|
10129
10213
|
endo: {
|
|
10130
10214
|
// Endomorphism, see above
|
|
10131
10215
|
beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
|
|
10132
10216
|
splitScalar: (k) => {
|
|
10133
|
-
const n =
|
|
10217
|
+
const n = secp256k1_CURVE.n;
|
|
10134
10218
|
const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15');
|
|
10135
10219
|
const b1 = -_1n$7 * BigInt('0xe4437ed6010e88286f547fa90abfe4c3');
|
|
10136
10220
|
const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8');
|
|
@@ -10295,7 +10379,7 @@ let Keccak$1=class Keccak extends Hash$1 {
|
|
|
10295
10379
|
update(data) {
|
|
10296
10380
|
aexists(this);
|
|
10297
10381
|
data = toBytes$1(data);
|
|
10298
|
-
abytes
|
|
10382
|
+
abytes(data);
|
|
10299
10383
|
const { blockLen, state } = this;
|
|
10300
10384
|
const len = data.length;
|
|
10301
10385
|
for (let pos = 0; pos < len;) {
|
|
@@ -10321,7 +10405,7 @@ let Keccak$1=class Keccak extends Hash$1 {
|
|
|
10321
10405
|
}
|
|
10322
10406
|
writeInto(out) {
|
|
10323
10407
|
aexists(this, false);
|
|
10324
|
-
abytes
|
|
10408
|
+
abytes(out);
|
|
10325
10409
|
this.finish();
|
|
10326
10410
|
const bufferOut = this.state;
|
|
10327
10411
|
const { blockLen } = this;
|
|
@@ -10431,7 +10515,7 @@ function ethereumEncode(addressOrPublic) {
|
|
|
10431
10515
|
/**
|
|
10432
10516
|
* The current version of Ethers.
|
|
10433
10517
|
*/
|
|
10434
|
-
const version = "6.14.
|
|
10518
|
+
const version = "6.14.4";/**
|
|
10435
10519
|
* Property helper functions.
|
|
10436
10520
|
*
|
|
10437
10521
|
* @_subsection api/utils:Properties [about-properties]
|
|
@@ -10834,7 +10918,7 @@ function getBigInt(value, name) {
|
|
|
10834
10918
|
case "bigint": return value;
|
|
10835
10919
|
case "number":
|
|
10836
10920
|
assertArgument(Number.isInteger(value), "underflow", name || "value", value);
|
|
10837
|
-
assertArgument(value >= -
|
|
10921
|
+
assertArgument(value >= -maxValue && value <= maxValue, "overflow", name || "value", value);
|
|
10838
10922
|
return BigInt(value);
|
|
10839
10923
|
case "string":
|
|
10840
10924
|
try {
|
|
@@ -10886,11 +10970,11 @@ function toBigInt(value) {
|
|
|
10886
10970
|
function getNumber(value, name) {
|
|
10887
10971
|
switch (typeof (value)) {
|
|
10888
10972
|
case "bigint":
|
|
10889
|
-
assertArgument(value >= -
|
|
10973
|
+
assertArgument(value >= -maxValue && value <= maxValue, "overflow", name || "value", value);
|
|
10890
10974
|
return Number(value);
|
|
10891
10975
|
case "number":
|
|
10892
10976
|
assertArgument(Number.isInteger(value), "underflow", name || "value", value);
|
|
10893
|
-
assertArgument(value >= -
|
|
10977
|
+
assertArgument(value >= -maxValue && value <= maxValue, "overflow", name || "value", value);
|
|
10894
10978
|
return value;
|
|
10895
10979
|
case "string":
|
|
10896
10980
|
try {
|
|
@@ -15422,8 +15506,8 @@ function formatAuthorizationList(value) {
|
|
|
15422
15506
|
a.address,
|
|
15423
15507
|
formatNumber(a.nonce, "nonce"),
|
|
15424
15508
|
formatNumber(a.signature.yParity, "yParity"),
|
|
15425
|
-
a.signature.r,
|
|
15426
|
-
a.signature.s
|
|
15509
|
+
toBeArray(a.signature.r),
|
|
15510
|
+
toBeArray(a.signature.s)
|
|
15427
15511
|
];
|
|
15428
15512
|
});
|
|
15429
15513
|
}
|
|
@@ -16490,6 +16574,14 @@ function hashMessage(message) {
|
|
|
16490
16574
|
toUtf8Bytes(String(message.length)),
|
|
16491
16575
|
message
|
|
16492
16576
|
]));
|
|
16577
|
+
}
|
|
16578
|
+
/**
|
|
16579
|
+
* Return the address of the private key that produced
|
|
16580
|
+
* the signature %%sig%% during signing for %%message%%.
|
|
16581
|
+
*/
|
|
16582
|
+
function verifyMessage(message, sig) {
|
|
16583
|
+
const digest = hashMessage(message);
|
|
16584
|
+
return recoverAddress(digest, sig);
|
|
16493
16585
|
}//import { TypedDataDomain, TypedDataField } from "@ethersproject/providerabstract-signer";
|
|
16494
16586
|
const padding = new Uint8Array(32);
|
|
16495
16587
|
padding.fill(0);
|
|
@@ -18759,7 +18851,7 @@ class HDNodeWallet extends BaseWallet {
|
|
|
18759
18851
|
// Base path
|
|
18760
18852
|
let path = this.path;
|
|
18761
18853
|
if (path) {
|
|
18762
|
-
path += "/" + (index &
|
|
18854
|
+
path += "/" + (index & ~HardenedBit);
|
|
18763
18855
|
if (index & HardenedBit) {
|
|
18764
18856
|
path += "'";
|
|
18765
18857
|
}
|
|
@@ -18961,7 +19053,7 @@ class HDNodeVoidWallet extends VoidSigner {
|
|
|
18961
19053
|
// Base path
|
|
18962
19054
|
let path = this.path;
|
|
18963
19055
|
if (path) {
|
|
18964
|
-
path += "/" + (index &
|
|
19056
|
+
path += "/" + (index & ~HardenedBit);
|
|
18965
19057
|
if (index & HardenedBit) {
|
|
18966
19058
|
path += "'";
|
|
18967
19059
|
}
|
|
@@ -19319,8 +19411,15 @@ function assert(condition, message) {
|
|
|
19319
19411
|
},
|
|
19320
19412
|
],
|
|
19321
19413
|
};
|
|
19322
|
-
// using
|
|
19323
|
-
const
|
|
19414
|
+
// using 2091 for mainnet
|
|
19415
|
+
const EIP712_DOMAIN_MAINNET = {
|
|
19416
|
+
name: 'Frequency',
|
|
19417
|
+
version: '1',
|
|
19418
|
+
chainId: '0x082B',
|
|
19419
|
+
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
|
|
19420
|
+
};
|
|
19421
|
+
// using pallet_revive test chain ID for testnet/dev
|
|
19422
|
+
const EIP712_DOMAIN_TESTNET = {
|
|
19324
19423
|
name: 'Frequency',
|
|
19325
19424
|
version: '1',
|
|
19326
19425
|
chainId: '0x190f1b44',
|
|
@@ -19358,6 +19457,22 @@ const ADD_KEY_DATA_DEFINITION = {
|
|
|
19358
19457
|
},
|
|
19359
19458
|
],
|
|
19360
19459
|
};
|
|
19460
|
+
const AUTHORIZED_KEY_DATA_DEFINITION = {
|
|
19461
|
+
AuthorizedKeyData: [
|
|
19462
|
+
{
|
|
19463
|
+
name: 'msaId',
|
|
19464
|
+
type: 'uint64',
|
|
19465
|
+
},
|
|
19466
|
+
{
|
|
19467
|
+
name: 'expiration',
|
|
19468
|
+
type: 'uint32',
|
|
19469
|
+
},
|
|
19470
|
+
{
|
|
19471
|
+
name: 'authorizedPublicKey',
|
|
19472
|
+
type: 'address',
|
|
19473
|
+
},
|
|
19474
|
+
],
|
|
19475
|
+
};
|
|
19361
19476
|
const CLAIM_HANDLE_PAYLOAD_DEFINITION = {
|
|
19362
19477
|
ClaimHandlePayload: [
|
|
19363
19478
|
{
|
|
@@ -19446,34 +19561,68 @@ const ITEMIZED_SIGNATURE_PAYLOAD_DEFINITION_V2 = {
|
|
|
19446
19561
|
{ name: 'data', type: 'bytes' },
|
|
19447
19562
|
{ name: 'index', type: 'uint16' },
|
|
19448
19563
|
],
|
|
19449
|
-
};
|
|
19450
|
-
|
|
19564
|
+
};
|
|
19565
|
+
const SIWF_SIGNED_REQUEST_PAYLOAD_DEFINITION = {
|
|
19566
|
+
SiwfSignedRequestPayload: [
|
|
19567
|
+
{
|
|
19568
|
+
name: 'callback',
|
|
19569
|
+
type: 'string',
|
|
19570
|
+
},
|
|
19571
|
+
{
|
|
19572
|
+
name: 'permissions',
|
|
19573
|
+
type: 'uint16[]',
|
|
19574
|
+
},
|
|
19575
|
+
{
|
|
19576
|
+
name: 'userIdentifierAdminUrl',
|
|
19577
|
+
type: 'string',
|
|
19578
|
+
},
|
|
19579
|
+
],
|
|
19580
|
+
};var signatureDefinitions=/*#__PURE__*/Object.freeze({__proto__:null,ADD_KEY_DATA_DEFINITION:ADD_KEY_DATA_DEFINITION,ADD_PROVIDER_DEFINITION:ADD_PROVIDER_DEFINITION,AUTHORIZED_KEY_DATA_DEFINITION:AUTHORIZED_KEY_DATA_DEFINITION,CLAIM_HANDLE_PAYLOAD_DEFINITION:CLAIM_HANDLE_PAYLOAD_DEFINITION,EIP712_DOMAIN_DEFINITION:EIP712_DOMAIN_DEFINITION,EIP712_DOMAIN_MAINNET:EIP712_DOMAIN_MAINNET,EIP712_DOMAIN_TESTNET:EIP712_DOMAIN_TESTNET,ITEMIZED_SIGNATURE_PAYLOAD_DEFINITION_V2:ITEMIZED_SIGNATURE_PAYLOAD_DEFINITION_V2,PAGINATED_DELETE_SIGNATURE_PAYLOAD_DEFINITION_V2:PAGINATED_DELETE_SIGNATURE_PAYLOAD_DEFINITION_V2,PAGINATED_UPSERT_SIGNATURE_PAYLOAD_DEFINITION_V2:PAGINATED_UPSERT_SIGNATURE_PAYLOAD_DEFINITION_V2,PASSKEY_PUBLIC_KEY_DEFINITION:PASSKEY_PUBLIC_KEY_DEFINITION,SIWF_SIGNED_REQUEST_PAYLOAD_DEFINITION:SIWF_SIGNED_REQUEST_PAYLOAD_DEFINITION});/**
|
|
19581
|
+
* Signing EIP-712 or ERC-191 compatible signature based on payload
|
|
19451
19582
|
* @param secretKey
|
|
19452
19583
|
* @param payload
|
|
19453
19584
|
* @param chain
|
|
19454
19585
|
*/
|
|
19455
|
-
async function
|
|
19456
|
-
const
|
|
19586
|
+
async function sign(secretKey, payload, chain) {
|
|
19587
|
+
const signatureType = getSignatureType(payload.type);
|
|
19457
19588
|
const normalizedPayload = normalizePayload(payload);
|
|
19458
19589
|
const wallet = new Wallet(secretKey);
|
|
19459
|
-
|
|
19460
|
-
|
|
19461
|
-
|
|
19590
|
+
let signature;
|
|
19591
|
+
switch (signatureType) {
|
|
19592
|
+
case 'EIP-712':
|
|
19593
|
+
// TODO: use correct contract address for different payloads
|
|
19594
|
+
signature = await wallet.signTypedData(chain === 'Mainnet-Frequency' ? EIP712_DOMAIN_MAINNET : EIP712_DOMAIN_TESTNET, getTypesFor(payload.type), normalizedPayload);
|
|
19595
|
+
break;
|
|
19596
|
+
case 'EIP-191':
|
|
19597
|
+
signature = await wallet.signMessage(payload.message);
|
|
19598
|
+
break;
|
|
19599
|
+
default:
|
|
19600
|
+
throw new Error(`Unsupported signature type : ${signatureType}`);
|
|
19601
|
+
}
|
|
19462
19602
|
return { Ecdsa: signature };
|
|
19463
19603
|
}
|
|
19464
19604
|
/**
|
|
19465
|
-
* Verify EIP-712 signatures
|
|
19605
|
+
* Verify EIP-712 and ERC-191 signatures based on payload
|
|
19466
19606
|
* @param ethereumAddress
|
|
19467
19607
|
* @param signature
|
|
19468
19608
|
* @param payload
|
|
19469
19609
|
* @param chain
|
|
19470
19610
|
*/
|
|
19471
|
-
function
|
|
19472
|
-
const
|
|
19611
|
+
function verifySignature(ethereumAddress, signature, payload, chain) {
|
|
19612
|
+
const signatureType = getSignatureType(payload.type);
|
|
19473
19613
|
const normalizedPayload = normalizePayload(payload);
|
|
19474
|
-
|
|
19475
|
-
|
|
19476
|
-
|
|
19614
|
+
let recoveredAddress;
|
|
19615
|
+
switch (signatureType) {
|
|
19616
|
+
case 'EIP-712':
|
|
19617
|
+
// TODO: use correct contract address for different payloads
|
|
19618
|
+
recoveredAddress = verifyTypedData(chain === 'Mainnet-Frequency' ? EIP712_DOMAIN_MAINNET : EIP712_DOMAIN_TESTNET, getTypesFor(payload.type), normalizedPayload, signature);
|
|
19619
|
+
break;
|
|
19620
|
+
case 'EIP-191':
|
|
19621
|
+
recoveredAddress = verifyMessage(payload.message, signature);
|
|
19622
|
+
break;
|
|
19623
|
+
default:
|
|
19624
|
+
throw new Error(`Unsupported signature type : ${signatureType}`);
|
|
19625
|
+
}
|
|
19477
19626
|
return recoveredAddress.toLowerCase() === ethereumAddress.toLowerCase();
|
|
19478
19627
|
}
|
|
19479
19628
|
function normalizePayload(payload) {
|
|
@@ -19485,6 +19634,7 @@ function normalizePayload(payload) {
|
|
|
19485
19634
|
case 'PasskeyPublicKey':
|
|
19486
19635
|
case 'ClaimHandlePayload':
|
|
19487
19636
|
case 'AddProvider':
|
|
19637
|
+
case 'SiwfLoginRequestPayload':
|
|
19488
19638
|
break;
|
|
19489
19639
|
case 'AddKeyData':
|
|
19490
19640
|
// convert to 20 bytes ethereum address for signature
|
|
@@ -19493,6 +19643,18 @@ function normalizePayload(payload) {
|
|
|
19493
19643
|
}
|
|
19494
19644
|
clonedPayload.newPublicKey = clonedPayload.newPublicKey.toLowerCase();
|
|
19495
19645
|
break;
|
|
19646
|
+
case 'AuthorizedKeyData':
|
|
19647
|
+
// convert to 20 bytes ethereum address for signature
|
|
19648
|
+
if (clonedPayload.authorizedPublicKey.length !== 42) {
|
|
19649
|
+
clonedPayload.authorizedPublicKey = reverseUnifiedAddressToEthereumAddress(payload.authorizedPublicKey);
|
|
19650
|
+
}
|
|
19651
|
+
clonedPayload.authorizedPublicKey = clonedPayload.authorizedPublicKey.toLowerCase();
|
|
19652
|
+
break;
|
|
19653
|
+
case 'SiwfSignedRequestPayload':
|
|
19654
|
+
if (clonedPayload.userIdentifierAdminUrl == null) {
|
|
19655
|
+
clonedPayload.userIdentifierAdminUrl = '';
|
|
19656
|
+
}
|
|
19657
|
+
break;
|
|
19496
19658
|
default:
|
|
19497
19659
|
throw new Error(`Unsupported payload type: ${JSON.stringify(payload)}`);
|
|
19498
19660
|
}
|
|
@@ -19508,7 +19670,10 @@ function getTypesFor(payloadType) {
|
|
|
19508
19670
|
PasskeyPublicKey: PASSKEY_PUBLIC_KEY_DEFINITION,
|
|
19509
19671
|
ClaimHandlePayload: CLAIM_HANDLE_PAYLOAD_DEFINITION,
|
|
19510
19672
|
AddKeyData: ADD_KEY_DATA_DEFINITION,
|
|
19673
|
+
AuthorizedKeyData: AUTHORIZED_KEY_DATA_DEFINITION,
|
|
19511
19674
|
AddProvider: ADD_PROVIDER_DEFINITION,
|
|
19675
|
+
// offchain signatures
|
|
19676
|
+
SiwfSignedRequestPayload: SIWF_SIGNED_REQUEST_PAYLOAD_DEFINITION,
|
|
19512
19677
|
};
|
|
19513
19678
|
const definition = PAYLOAD_TYPE_DEFINITIONS[payloadType];
|
|
19514
19679
|
if (!definition) {
|
|
@@ -19516,6 +19681,12 @@ function getTypesFor(payloadType) {
|
|
|
19516
19681
|
}
|
|
19517
19682
|
return definition;
|
|
19518
19683
|
}
|
|
19684
|
+
function getSignatureType(payloadType) {
|
|
19685
|
+
if (payloadType === 'SiwfLoginRequestPayload') {
|
|
19686
|
+
return 'EIP-191';
|
|
19687
|
+
}
|
|
19688
|
+
return 'EIP-712';
|
|
19689
|
+
}
|
|
19519
19690
|
/**
|
|
19520
19691
|
* Build an AddKeyData payload for signature.
|
|
19521
19692
|
*
|
|
@@ -19536,6 +19707,26 @@ function createAddKeyData(msaId, newPublicKey, expirationBlock) {
|
|
|
19536
19707
|
newPublicKey: parsedNewPublicKey,
|
|
19537
19708
|
};
|
|
19538
19709
|
}
|
|
19710
|
+
/**
|
|
19711
|
+
* Build an AuthorizedKeyData payload for signature.
|
|
19712
|
+
*
|
|
19713
|
+
* @param msaId MSA ID (uint64) to add the key
|
|
19714
|
+
* @param authorizedPublicKey 32 bytes public key to authorize in hex or Uint8Array
|
|
19715
|
+
* @param expirationBlock Block number after which this payload is invalid
|
|
19716
|
+
*/
|
|
19717
|
+
function createAuthorizedKeyData(msaId, newPublicKey, expirationBlock) {
|
|
19718
|
+
const parsedMsaId = typeof msaId === 'string' ? msaId : `${msaId}`;
|
|
19719
|
+
const parsedNewPublicKey = typeof newPublicKey === 'object' ? u8aToHex(newPublicKey) : newPublicKey;
|
|
19720
|
+
assert(isValidUint64String(parsedMsaId), 'msaId should be a valid uint64');
|
|
19721
|
+
assert(isValidUint32(expirationBlock), 'expiration should be a valid uint32');
|
|
19722
|
+
assert(isHexString(parsedNewPublicKey), 'newPublicKey should be valid hex');
|
|
19723
|
+
return {
|
|
19724
|
+
type: 'AuthorizedKeyData',
|
|
19725
|
+
msaId: parsedMsaId,
|
|
19726
|
+
expiration: expirationBlock,
|
|
19727
|
+
authorizedPublicKey: parsedNewPublicKey,
|
|
19728
|
+
};
|
|
19729
|
+
}
|
|
19539
19730
|
/**
|
|
19540
19731
|
* Build an AddProvider payload for signature.
|
|
19541
19732
|
*
|
|
@@ -19660,6 +19851,35 @@ function createPaginatedUpsertSignaturePayloadV2(schemaId, pageId, targetHash, e
|
|
|
19660
19851
|
payload: parsedPayload,
|
|
19661
19852
|
};
|
|
19662
19853
|
}
|
|
19854
|
+
/**
|
|
19855
|
+
* Build an SiwfSignedRequestPayload payload for signature.
|
|
19856
|
+
*
|
|
19857
|
+
* @param callback Callback URL for login
|
|
19858
|
+
* @param permissions One or more schema IDs (uint16) the provider may use
|
|
19859
|
+
* @param userIdentifierAdminUrl Only used for custom integration situations.
|
|
19860
|
+
*/
|
|
19861
|
+
function createSiwfSignedRequestPayload(callback, permissions, userIdentifierAdminUrl) {
|
|
19862
|
+
permissions.forEach((schemaId) => {
|
|
19863
|
+
assert(isValidUint16(schemaId), 'permission should be a valid uint16');
|
|
19864
|
+
});
|
|
19865
|
+
return {
|
|
19866
|
+
type: 'SiwfSignedRequestPayload',
|
|
19867
|
+
callback: callback,
|
|
19868
|
+
permissions,
|
|
19869
|
+
userIdentifierAdminUrl,
|
|
19870
|
+
};
|
|
19871
|
+
}
|
|
19872
|
+
/**
|
|
19873
|
+
* Build an SiwfLoginRequestPayload payload for signature.
|
|
19874
|
+
*
|
|
19875
|
+
* @param message login message
|
|
19876
|
+
*/
|
|
19877
|
+
function createSiwfLoginRequestPayload(message) {
|
|
19878
|
+
return {
|
|
19879
|
+
type: 'SiwfLoginRequestPayload',
|
|
19880
|
+
message,
|
|
19881
|
+
};
|
|
19882
|
+
}
|
|
19663
19883
|
/**
|
|
19664
19884
|
* Returns the EIP-712 browser request for a AddKeyData for signing.
|
|
19665
19885
|
*
|
|
@@ -19668,11 +19888,24 @@ function createPaginatedUpsertSignaturePayloadV2(schemaId, pageId, targetHash, e
|
|
|
19668
19888
|
* @param expirationBlock Block number after which this payload is invalid
|
|
19669
19889
|
* @param domain
|
|
19670
19890
|
*/
|
|
19671
|
-
function getEip712BrowserRequestAddKeyData(msaId, newPublicKey, expirationBlock, domain =
|
|
19891
|
+
function getEip712BrowserRequestAddKeyData(msaId, newPublicKey, expirationBlock, domain = EIP712_DOMAIN_MAINNET) {
|
|
19672
19892
|
const message = createAddKeyData(msaId, newPublicKey, expirationBlock);
|
|
19673
19893
|
const normalized = normalizePayload(message);
|
|
19674
19894
|
return createEip712Payload(ADD_KEY_DATA_DEFINITION, message.type, domain, normalized);
|
|
19675
19895
|
}
|
|
19896
|
+
/**
|
|
19897
|
+
* Returns the EIP-712 browser request for a AuthorizedKeyData for signing.
|
|
19898
|
+
*
|
|
19899
|
+
* @param msaId MSA ID (uint64) to add the key
|
|
19900
|
+
* @param authorizedPublicKey 32 bytes public key to add in hex or Uint8Array
|
|
19901
|
+
* @param expirationBlock Block number after which this payload is invalid
|
|
19902
|
+
* @param domain
|
|
19903
|
+
*/
|
|
19904
|
+
function getEip712BrowserRequestAuthorizedKeyData(msaId, authorizedPublicKey, expirationBlock, domain = EIP712_DOMAIN_MAINNET) {
|
|
19905
|
+
const message = createAuthorizedKeyData(msaId, authorizedPublicKey, expirationBlock);
|
|
19906
|
+
const normalized = normalizePayload(message);
|
|
19907
|
+
return createEip712Payload(AUTHORIZED_KEY_DATA_DEFINITION, message.type, domain, normalized);
|
|
19908
|
+
}
|
|
19676
19909
|
/**
|
|
19677
19910
|
* Returns the EIP-712 browser request for a AddProvider for signing.
|
|
19678
19911
|
*
|
|
@@ -19681,7 +19914,7 @@ function getEip712BrowserRequestAddKeyData(msaId, newPublicKey, expirationBlock,
|
|
|
19681
19914
|
* @param expirationBlock Block number after which this payload is invalid
|
|
19682
19915
|
* @param domain
|
|
19683
19916
|
*/
|
|
19684
|
-
function getEip712BrowserRequestAddProvider(authorizedMsaId, schemaIds, expirationBlock, domain =
|
|
19917
|
+
function getEip712BrowserRequestAddProvider(authorizedMsaId, schemaIds, expirationBlock, domain = EIP712_DOMAIN_MAINNET) {
|
|
19685
19918
|
const message = createAddProvider(authorizedMsaId, schemaIds, expirationBlock);
|
|
19686
19919
|
const normalized = normalizePayload(message);
|
|
19687
19920
|
return createEip712Payload(ADD_PROVIDER_DEFINITION, message.type, domain, normalized);
|
|
@@ -19696,7 +19929,7 @@ function getEip712BrowserRequestAddProvider(authorizedMsaId, schemaIds, expirati
|
|
|
19696
19929
|
* @param payload HexString or Uint8Array data to upsert
|
|
19697
19930
|
* @param domain
|
|
19698
19931
|
*/
|
|
19699
|
-
function getEip712BrowserRequestPaginatedUpsertSignaturePayloadV2(schemaId, pageId, targetHash, expiration, payload, domain =
|
|
19932
|
+
function getEip712BrowserRequestPaginatedUpsertSignaturePayloadV2(schemaId, pageId, targetHash, expiration, payload, domain = EIP712_DOMAIN_MAINNET) {
|
|
19700
19933
|
const message = createPaginatedUpsertSignaturePayloadV2(schemaId, pageId, targetHash, expiration, payload);
|
|
19701
19934
|
const normalized = normalizePayload(message);
|
|
19702
19935
|
return createEip712Payload(PAGINATED_UPSERT_SIGNATURE_PAYLOAD_DEFINITION_V2, message.type, domain, normalized);
|
|
@@ -19710,7 +19943,7 @@ function getEip712BrowserRequestPaginatedUpsertSignaturePayloadV2(schemaId, page
|
|
|
19710
19943
|
* @param expiration uint32 expiration block
|
|
19711
19944
|
* @param domain
|
|
19712
19945
|
*/
|
|
19713
|
-
function getEip712BrowserRequestPaginatedDeleteSignaturePayloadV2(schemaId, pageId, targetHash, expiration, domain =
|
|
19946
|
+
function getEip712BrowserRequestPaginatedDeleteSignaturePayloadV2(schemaId, pageId, targetHash, expiration, domain = EIP712_DOMAIN_MAINNET) {
|
|
19714
19947
|
const message = createPaginatedDeleteSignaturePayloadV2(schemaId, pageId, targetHash, expiration);
|
|
19715
19948
|
const normalized = normalizePayload(message);
|
|
19716
19949
|
return createEip712Payload(PAGINATED_DELETE_SIGNATURE_PAYLOAD_DEFINITION_V2, message.type, domain, normalized);
|
|
@@ -19724,7 +19957,7 @@ function getEip712BrowserRequestPaginatedDeleteSignaturePayloadV2(schemaId, page
|
|
|
19724
19957
|
* @param actions Array of Add/Delete itemized actions
|
|
19725
19958
|
* @param domain
|
|
19726
19959
|
*/
|
|
19727
|
-
function getEip712BrowserRequestItemizedSignaturePayloadV2(schemaId, targetHash, expiration, actions, domain =
|
|
19960
|
+
function getEip712BrowserRequestItemizedSignaturePayloadV2(schemaId, targetHash, expiration, actions, domain = EIP712_DOMAIN_MAINNET) {
|
|
19728
19961
|
const message = createItemizedSignaturePayloadV2(schemaId, targetHash, expiration, actions);
|
|
19729
19962
|
const normalized = normalizePayload(message);
|
|
19730
19963
|
return createEip712Payload(ITEMIZED_SIGNATURE_PAYLOAD_DEFINITION_V2, message.type, domain, normalized);
|
|
@@ -19736,7 +19969,7 @@ function getEip712BrowserRequestItemizedSignaturePayloadV2(schemaId, targetHash,
|
|
|
19736
19969
|
* @param expirationBlock Block number after which this payload is invalid
|
|
19737
19970
|
* @param domain
|
|
19738
19971
|
*/
|
|
19739
|
-
function getEip712BrowserRequestClaimHandlePayload(handle, expirationBlock, domain =
|
|
19972
|
+
function getEip712BrowserRequestClaimHandlePayload(handle, expirationBlock, domain = EIP712_DOMAIN_MAINNET) {
|
|
19740
19973
|
const message = createClaimHandlePayload(handle, expirationBlock);
|
|
19741
19974
|
const normalized = normalizePayload(message);
|
|
19742
19975
|
return createEip712Payload(CLAIM_HANDLE_PAYLOAD_DEFINITION, message.type, domain, normalized);
|
|
@@ -19747,11 +19980,24 @@ function getEip712BrowserRequestClaimHandlePayload(handle, expirationBlock, doma
|
|
|
19747
19980
|
* @param publicKey The passkey’s public key (hex string or raw bytes)
|
|
19748
19981
|
* @param domain
|
|
19749
19982
|
*/
|
|
19750
|
-
function getEip712BrowserRequestPasskeyPublicKey(publicKey, domain =
|
|
19983
|
+
function getEip712BrowserRequestPasskeyPublicKey(publicKey, domain = EIP712_DOMAIN_MAINNET) {
|
|
19751
19984
|
const message = createPasskeyPublicKey(publicKey);
|
|
19752
19985
|
const normalized = normalizePayload(message);
|
|
19753
19986
|
return createEip712Payload(PASSKEY_PUBLIC_KEY_DEFINITION, message.type, domain, normalized);
|
|
19754
19987
|
}
|
|
19988
|
+
/**
|
|
19989
|
+
* Returns the EIP-712 browser request for a SiwfSignedRequestPayload for signing.
|
|
19990
|
+
*
|
|
19991
|
+
* @param callback Callback URL for login
|
|
19992
|
+
* @param permissions One or more schema IDs (uint16) the provider may use
|
|
19993
|
+
* @param userIdentifierAdminUrl Only used for custom integration situations.
|
|
19994
|
+
* @param domain
|
|
19995
|
+
*/
|
|
19996
|
+
function getEip712BrowserRequestSiwfSignedRequestPayload(callback, permissions, userIdentifierAdminUrl, domain = EIP712_DOMAIN_MAINNET) {
|
|
19997
|
+
const message = createSiwfSignedRequestPayload(callback, permissions, userIdentifierAdminUrl);
|
|
19998
|
+
const normalized = normalizePayload(message);
|
|
19999
|
+
return createEip712Payload(SIWF_SIGNED_REQUEST_PAYLOAD_DEFINITION, message.type, domain, normalized);
|
|
20000
|
+
}
|
|
19755
20001
|
function createEip712Payload(typeDefinition, primaryType, domain, message) {
|
|
19756
20002
|
return {
|
|
19757
20003
|
types: {
|
|
@@ -19808,4 +20054,4 @@ function prefixEthereumTags(hexPayload) {
|
|
|
19808
20054
|
const wrapped = `\x19Ethereum Signed Message:\n${hexPayload.length}${hexPayload}`;
|
|
19809
20055
|
const buffer = Buffer.from(wrapped, 'utf-8');
|
|
19810
20056
|
return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.length);
|
|
19811
|
-
}var signature=/*#__PURE__*/Object.freeze({__proto__:null,createAddKeyData:createAddKeyData,createAddProvider:createAddProvider,createClaimHandlePayload:createClaimHandlePayload,createItemizedAddAction:createItemizedAddAction,createItemizedDeleteAction:createItemizedDeleteAction,createItemizedSignaturePayloadV2:createItemizedSignaturePayloadV2,createPaginatedDeleteSignaturePayloadV2:createPaginatedDeleteSignaturePayloadV2,createPaginatedUpsertSignaturePayloadV2:createPaginatedUpsertSignaturePayloadV2,createPasskeyPublicKey:createPasskeyPublicKey,getEip712BrowserRequestAddKeyData:getEip712BrowserRequestAddKeyData,getEip712BrowserRequestAddProvider:getEip712BrowserRequestAddProvider,getEip712BrowserRequestClaimHandlePayload:getEip712BrowserRequestClaimHandlePayload,getEip712BrowserRequestItemizedSignaturePayloadV2:getEip712BrowserRequestItemizedSignaturePayloadV2,getEip712BrowserRequestPaginatedDeleteSignaturePayloadV2:getEip712BrowserRequestPaginatedDeleteSignaturePayloadV2,getEip712BrowserRequestPaginatedUpsertSignaturePayloadV2:getEip712BrowserRequestPaginatedUpsertSignaturePayloadV2,getEip712BrowserRequestPasskeyPublicKey:getEip712BrowserRequestPasskeyPublicKey,getEthereumMessageSigner:getEthereumMessageSigner,getEthereumRegularSigner:getEthereumRegularSigner,
|
|
20057
|
+
}var signature=/*#__PURE__*/Object.freeze({__proto__:null,createAddKeyData:createAddKeyData,createAddProvider:createAddProvider,createAuthorizedKeyData:createAuthorizedKeyData,createClaimHandlePayload:createClaimHandlePayload,createItemizedAddAction:createItemizedAddAction,createItemizedDeleteAction:createItemizedDeleteAction,createItemizedSignaturePayloadV2:createItemizedSignaturePayloadV2,createPaginatedDeleteSignaturePayloadV2:createPaginatedDeleteSignaturePayloadV2,createPaginatedUpsertSignaturePayloadV2:createPaginatedUpsertSignaturePayloadV2,createPasskeyPublicKey:createPasskeyPublicKey,createSiwfLoginRequestPayload:createSiwfLoginRequestPayload,createSiwfSignedRequestPayload:createSiwfSignedRequestPayload,getEip712BrowserRequestAddKeyData:getEip712BrowserRequestAddKeyData,getEip712BrowserRequestAddProvider:getEip712BrowserRequestAddProvider,getEip712BrowserRequestAuthorizedKeyData:getEip712BrowserRequestAuthorizedKeyData,getEip712BrowserRequestClaimHandlePayload:getEip712BrowserRequestClaimHandlePayload,getEip712BrowserRequestItemizedSignaturePayloadV2:getEip712BrowserRequestItemizedSignaturePayloadV2,getEip712BrowserRequestPaginatedDeleteSignaturePayloadV2:getEip712BrowserRequestPaginatedDeleteSignaturePayloadV2,getEip712BrowserRequestPaginatedUpsertSignaturePayloadV2:getEip712BrowserRequestPaginatedUpsertSignaturePayloadV2,getEip712BrowserRequestPasskeyPublicKey:getEip712BrowserRequestPasskeyPublicKey,getEip712BrowserRequestSiwfSignedRequestPayload:getEip712BrowserRequestSiwfSignedRequestPayload,getEthereumMessageSigner:getEthereumMessageSigner,getEthereumRegularSigner:getEthereumRegularSigner,sign:sign,verifySignature:verifySignature});var index = { ...payloads, ...address, ...signatureDefinitions, ...signature };export{ADD_KEY_DATA_DEFINITION,ADD_PROVIDER_DEFINITION,AUTHORIZED_KEY_DATA_DEFINITION,CLAIM_HANDLE_PAYLOAD_DEFINITION,EIP712_DOMAIN_DEFINITION,EIP712_DOMAIN_MAINNET,EIP712_DOMAIN_TESTNET,ITEMIZED_SIGNATURE_PAYLOAD_DEFINITION_V2,PAGINATED_DELETE_SIGNATURE_PAYLOAD_DEFINITION_V2,PAGINATED_UPSERT_SIGNATURE_PAYLOAD_DEFINITION_V2,PASSKEY_PUBLIC_KEY_DEFINITION,SIWF_SIGNED_REQUEST_PAYLOAD_DEFINITION,createAddKeyData,createAddProvider,createAuthorizedKeyData,createClaimHandlePayload,createItemizedAddAction,createItemizedDeleteAction,createItemizedSignaturePayloadV2,createPaginatedDeleteSignaturePayloadV2,createPaginatedUpsertSignaturePayloadV2,createPasskeyPublicKey,createRandomKey,createSiwfLoginRequestPayload,createSiwfSignedRequestPayload,index as default,ethereumAddressToKeyringPair,getAccountId20MultiAddress,getEip712BrowserRequestAddKeyData,getEip712BrowserRequestAddProvider,getEip712BrowserRequestAuthorizedKeyData,getEip712BrowserRequestClaimHandlePayload,getEip712BrowserRequestItemizedSignaturePayloadV2,getEip712BrowserRequestPaginatedDeleteSignaturePayloadV2,getEip712BrowserRequestPaginatedUpsertSignaturePayloadV2,getEip712BrowserRequestPasskeyPublicKey,getEip712BrowserRequestSiwfSignedRequestPayload,getEthereumMessageSigner,getEthereumRegularSigner,getKeyringPairFromSecp256k1PrivateKey,getSS58AccountFromEthereumAccount,getUnifiedAddress,getUnifiedPublicKey,reverseUnifiedAddressToEthereumAddress,sign,verifySignature};
|