@noble/curves 0.5.2 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -41
- package/lib/_shortw_utils.d.ts +13 -24
- package/lib/abstract/bls.d.ts +39 -32
- package/lib/abstract/bls.js +74 -73
- package/lib/abstract/{group.d.ts → curve.d.ts} +30 -1
- package/lib/abstract/{group.js → curve.js} +33 -2
- package/lib/abstract/edwards.d.ts +30 -72
- package/lib/abstract/edwards.js +206 -389
- package/lib/abstract/hash-to-curve.d.ts +25 -6
- package/lib/abstract/hash-to-curve.js +40 -12
- package/lib/abstract/modular.d.ts +21 -8
- package/lib/abstract/modular.js +72 -48
- package/lib/abstract/montgomery.js +23 -68
- package/lib/abstract/poseidon.d.ts +29 -0
- package/lib/abstract/poseidon.js +115 -0
- package/lib/abstract/utils.d.ts +9 -37
- package/lib/abstract/utils.js +61 -87
- package/lib/abstract/weierstrass.d.ts +58 -81
- package/lib/abstract/weierstrass.js +485 -679
- package/lib/bls12-381.js +63 -58
- package/lib/bn.js +1 -1
- package/lib/ed25519.d.ts +7 -5
- package/lib/ed25519.js +82 -79
- package/lib/ed448.d.ts +3 -0
- package/lib/ed448.js +86 -83
- package/lib/esm/abstract/bls.js +75 -74
- package/lib/esm/abstract/{group.js → curve.js} +31 -1
- package/lib/esm/abstract/edwards.js +204 -387
- package/lib/esm/abstract/hash-to-curve.js +38 -11
- package/lib/esm/abstract/modular.js +69 -47
- package/lib/esm/abstract/montgomery.js +24 -69
- package/lib/esm/abstract/poseidon.js +109 -0
- package/lib/esm/abstract/utils.js +58 -82
- package/lib/esm/abstract/weierstrass.js +484 -678
- package/lib/esm/bls12-381.js +75 -70
- package/lib/esm/bn.js +1 -1
- package/lib/esm/ed25519.js +80 -78
- package/lib/esm/ed448.js +84 -82
- package/lib/esm/jubjub.js +1 -1
- package/lib/esm/p224.js +1 -1
- package/lib/esm/p256.js +11 -9
- package/lib/esm/p384.js +11 -9
- package/lib/esm/p521.js +12 -23
- package/lib/esm/secp256k1.js +124 -162
- package/lib/esm/stark.js +105 -41
- package/lib/jubjub.d.ts +2 -2
- package/lib/jubjub.js +1 -1
- package/lib/p192.d.ts +26 -48
- package/lib/p224.d.ts +26 -48
- package/lib/p224.js +1 -1
- package/lib/p256.d.ts +29 -48
- package/lib/p256.js +13 -10
- package/lib/p384.d.ts +29 -48
- package/lib/p384.js +13 -10
- package/lib/p521.d.ts +37 -57
- package/lib/p521.js +14 -24
- package/lib/secp256k1.d.ts +37 -46
- package/lib/secp256k1.js +124 -162
- package/lib/stark.d.ts +39 -22
- package/lib/stark.js +108 -41
- package/package.json +15 -10
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.poseidon = exports.splitConstants = exports.validateOpts = void 0;
|
|
4
|
+
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
5
|
+
// Poseidon Hash: https://eprint.iacr.org/2019/458.pdf, https://www.poseidon-hash.info
|
|
6
|
+
const modular_js_1 = require("./modular.js");
|
|
7
|
+
function validateOpts(opts) {
|
|
8
|
+
const { Fp } = opts;
|
|
9
|
+
(0, modular_js_1.validateField)(Fp);
|
|
10
|
+
for (const i of ['t', 'roundsFull', 'roundsPartial']) {
|
|
11
|
+
if (typeof opts[i] !== 'number' || !Number.isSafeInteger(opts[i]))
|
|
12
|
+
throw new Error(`Poseidon: invalid param ${i}=${opts[i]} (${typeof opts[i]})`);
|
|
13
|
+
}
|
|
14
|
+
if (opts.reversePartialPowIdx !== undefined && typeof opts.reversePartialPowIdx !== 'boolean')
|
|
15
|
+
throw new Error(`Poseidon: invalid param reversePartialPowIdx=${opts.reversePartialPowIdx}`);
|
|
16
|
+
// Default is 5, but by some reasons stark uses 3
|
|
17
|
+
let sboxPower = opts.sboxPower;
|
|
18
|
+
if (sboxPower === undefined)
|
|
19
|
+
sboxPower = 5;
|
|
20
|
+
if (typeof sboxPower !== 'number' || !Number.isSafeInteger(sboxPower))
|
|
21
|
+
throw new Error(`Poseidon wrong sboxPower=${sboxPower}`);
|
|
22
|
+
const _sboxPower = BigInt(sboxPower);
|
|
23
|
+
let sboxFn = (n) => (0, modular_js_1.FpPow)(Fp, n, _sboxPower);
|
|
24
|
+
// Unwrapped sbox power for common cases (195->142μs)
|
|
25
|
+
if (sboxPower === 3)
|
|
26
|
+
sboxFn = (n) => Fp.mul(Fp.sqrN(n), n);
|
|
27
|
+
else if (sboxPower === 5)
|
|
28
|
+
sboxFn = (n) => Fp.mul(Fp.sqrN(Fp.sqrN(n)), n);
|
|
29
|
+
if (opts.roundsFull % 2 !== 0)
|
|
30
|
+
throw new Error(`Poseidon roundsFull is not even: ${opts.roundsFull}`);
|
|
31
|
+
const rounds = opts.roundsFull + opts.roundsPartial;
|
|
32
|
+
if (!Array.isArray(opts.roundConstants) || opts.roundConstants.length !== rounds)
|
|
33
|
+
throw new Error('Poseidon: wrong round constants');
|
|
34
|
+
const roundConstants = opts.roundConstants.map((rc) => {
|
|
35
|
+
if (!Array.isArray(rc) || rc.length !== opts.t)
|
|
36
|
+
throw new Error(`Poseidon wrong round constants: ${rc}`);
|
|
37
|
+
return rc.map((i) => {
|
|
38
|
+
if (typeof i !== 'bigint' || !Fp.isValid(i))
|
|
39
|
+
throw new Error(`Poseidon wrong round constant=${i}`);
|
|
40
|
+
return Fp.create(i);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
// MDS is TxT matrix
|
|
44
|
+
if (!Array.isArray(opts.mds) || opts.mds.length !== opts.t)
|
|
45
|
+
throw new Error('Poseidon: wrong MDS matrix');
|
|
46
|
+
const mds = opts.mds.map((mdsRow) => {
|
|
47
|
+
if (!Array.isArray(mdsRow) || mdsRow.length !== opts.t)
|
|
48
|
+
throw new Error(`Poseidon MDS matrix row: ${mdsRow}`);
|
|
49
|
+
return mdsRow.map((i) => {
|
|
50
|
+
if (typeof i !== 'bigint')
|
|
51
|
+
throw new Error(`Poseidon MDS matrix value=${i}`);
|
|
52
|
+
return Fp.create(i);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
return Object.freeze({ ...opts, rounds, sboxFn, roundConstants, mds });
|
|
56
|
+
}
|
|
57
|
+
exports.validateOpts = validateOpts;
|
|
58
|
+
function splitConstants(rc, t) {
|
|
59
|
+
if (typeof t !== 'number')
|
|
60
|
+
throw new Error('poseidonSplitConstants: wrong t');
|
|
61
|
+
if (!Array.isArray(rc) || rc.length % t)
|
|
62
|
+
throw new Error('poseidonSplitConstants: wrong rc');
|
|
63
|
+
const res = [];
|
|
64
|
+
let tmp = [];
|
|
65
|
+
for (let i = 0; i < rc.length; i++) {
|
|
66
|
+
tmp.push(rc[i]);
|
|
67
|
+
if (tmp.length === t) {
|
|
68
|
+
res.push(tmp);
|
|
69
|
+
tmp = [];
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return res;
|
|
73
|
+
}
|
|
74
|
+
exports.splitConstants = splitConstants;
|
|
75
|
+
function poseidon(opts) {
|
|
76
|
+
const { t, Fp, rounds, sboxFn, reversePartialPowIdx } = validateOpts(opts);
|
|
77
|
+
const halfRoundsFull = Math.floor(opts.roundsFull / 2);
|
|
78
|
+
const partialIdx = reversePartialPowIdx ? t - 1 : 0;
|
|
79
|
+
const poseidonRound = (values, isFull, idx) => {
|
|
80
|
+
values = values.map((i, j) => Fp.add(i, opts.roundConstants[idx][j]));
|
|
81
|
+
if (isFull)
|
|
82
|
+
values = values.map((i) => sboxFn(i));
|
|
83
|
+
else
|
|
84
|
+
values[partialIdx] = sboxFn(values[partialIdx]);
|
|
85
|
+
// Matrix multiplication
|
|
86
|
+
values = opts.mds.map((i) => i.reduce((acc, i, j) => Fp.add(acc, Fp.mulN(i, values[j])), Fp.ZERO));
|
|
87
|
+
return values;
|
|
88
|
+
};
|
|
89
|
+
const poseidonHash = function poseidonHash(values) {
|
|
90
|
+
if (!Array.isArray(values) || values.length !== t)
|
|
91
|
+
throw new Error(`Poseidon: wrong values (expected array of bigints with length ${t})`);
|
|
92
|
+
values = values.map((i) => {
|
|
93
|
+
if (typeof i !== 'bigint')
|
|
94
|
+
throw new Error(`Poseidon: wrong value=${i} (${typeof i})`);
|
|
95
|
+
return Fp.create(i);
|
|
96
|
+
});
|
|
97
|
+
let round = 0;
|
|
98
|
+
// Apply r_f/2 full rounds.
|
|
99
|
+
for (let i = 0; i < halfRoundsFull; i++)
|
|
100
|
+
values = poseidonRound(values, true, round++);
|
|
101
|
+
// Apply r_p partial rounds.
|
|
102
|
+
for (let i = 0; i < opts.roundsPartial; i++)
|
|
103
|
+
values = poseidonRound(values, false, round++);
|
|
104
|
+
// Apply r_f/2 full rounds.
|
|
105
|
+
for (let i = 0; i < halfRoundsFull; i++)
|
|
106
|
+
values = poseidonRound(values, true, round++);
|
|
107
|
+
if (round !== rounds)
|
|
108
|
+
throw new Error(`Poseidon: wrong number of rounds: last round=${round}, total=${rounds}`);
|
|
109
|
+
return values;
|
|
110
|
+
};
|
|
111
|
+
// For verification in tests
|
|
112
|
+
poseidonHash.roundConstants = opts.roundConstants;
|
|
113
|
+
return poseidonHash;
|
|
114
|
+
}
|
|
115
|
+
exports.poseidon = poseidon;
|
package/lib/abstract/utils.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
2
|
-
import * as mod from './modular.js';
|
|
3
1
|
export declare type Hex = Uint8Array | string;
|
|
4
|
-
export declare type PrivKey = Hex | bigint
|
|
2
|
+
export declare type PrivKey = Hex | bigint;
|
|
5
3
|
export declare type CHash = {
|
|
6
4
|
(message: Uint8Array | string): Uint8Array;
|
|
7
5
|
blockLen: number;
|
|
@@ -10,49 +8,23 @@ export declare type CHash = {
|
|
|
10
8
|
dkLen?: number;
|
|
11
9
|
}): any;
|
|
12
10
|
};
|
|
13
|
-
export declare type
|
|
14
|
-
|
|
15
|
-
n: bigint;
|
|
16
|
-
nBitLength?: number;
|
|
17
|
-
nByteLength?: number;
|
|
18
|
-
h: bigint;
|
|
19
|
-
hEff?: bigint;
|
|
20
|
-
Gx: T;
|
|
21
|
-
Gy: T;
|
|
22
|
-
wrapPrivateKey?: boolean;
|
|
23
|
-
allowInfinityPoint?: boolean;
|
|
24
|
-
};
|
|
25
|
-
export declare function isPositiveInt(num: any): num is number;
|
|
26
|
-
export declare function validateOpts<FP, T>(curve: BasicCurve<FP> & T): Readonly<{
|
|
27
|
-
readonly nBitLength: number;
|
|
28
|
-
readonly nByteLength: number;
|
|
29
|
-
} & BasicCurve<FP> & T>;
|
|
30
|
-
export declare function bytesToHex(uint8a: Uint8Array): string;
|
|
11
|
+
export declare type FHash = (message: Uint8Array | string) => Uint8Array;
|
|
12
|
+
export declare function bytesToHex(bytes: Uint8Array): string;
|
|
31
13
|
export declare function numberToHexUnpadded(num: number | bigint): string;
|
|
32
14
|
export declare function hexToNumber(hex: string): bigint;
|
|
33
15
|
export declare function hexToBytes(hex: string): Uint8Array;
|
|
34
16
|
export declare function bytesToNumberBE(bytes: Uint8Array): bigint;
|
|
35
|
-
export declare function bytesToNumberLE(
|
|
17
|
+
export declare function bytesToNumberLE(bytes: Uint8Array): bigint;
|
|
36
18
|
export declare const numberToBytesBE: (n: bigint, len: number) => Uint8Array;
|
|
37
19
|
export declare const numberToBytesLE: (n: bigint, len: number) => Uint8Array;
|
|
20
|
+
export declare const numberToVarBytesBE: (n: bigint) => Uint8Array;
|
|
38
21
|
export declare function ensureBytes(hex: Hex, expectedLength?: number): Uint8Array;
|
|
39
|
-
export declare function concatBytes(...
|
|
40
|
-
export declare function nLength(n: bigint, nBitLength?: number): {
|
|
41
|
-
nBitLength: number;
|
|
42
|
-
nByteLength: number;
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
* FIPS 186 B.4.1-compliant "constant-time" private key generation utility.
|
|
46
|
-
* Can take (n+8) or more bytes of uniform input e.g. from CSPRNG or KDF
|
|
47
|
-
* and convert them into private scalar, with the modulo bias being neglible.
|
|
48
|
-
* Needs at least 40 bytes of input for 32-byte private key.
|
|
49
|
-
* https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
|
|
50
|
-
* @param hash hash output from SHA3 or a similar function
|
|
51
|
-
* @returns valid private scalar
|
|
52
|
-
*/
|
|
53
|
-
export declare function hashToPrivateScalar(hash: Hex, groupOrder: bigint, isLE?: boolean): bigint;
|
|
22
|
+
export declare function concatBytes(...arrs: Uint8Array[]): Uint8Array;
|
|
54
23
|
export declare function equalBytes(b1: Uint8Array, b2: Uint8Array): boolean;
|
|
55
24
|
export declare function bitLen(n: bigint): number;
|
|
56
25
|
export declare const bitGet: (n: bigint, pos: number) => bigint;
|
|
57
26
|
export declare const bitSet: (n: bigint, pos: number, value: boolean) => bigint;
|
|
58
27
|
export declare const bitMask: (n: number) => bigint;
|
|
28
|
+
declare type ValMap = Record<string, string>;
|
|
29
|
+
export declare function validateObject(object: object, validators: ValMap, optValidators?: ValMap): object;
|
|
30
|
+
export {};
|
package/lib/abstract/utils.js
CHANGED
|
@@ -1,46 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.bitMask = exports.bitSet = exports.bitGet = exports.bitLen = exports.equalBytes = exports.
|
|
3
|
+
exports.validateObject = exports.bitMask = exports.bitSet = exports.bitGet = exports.bitLen = exports.equalBytes = exports.concatBytes = exports.ensureBytes = exports.numberToVarBytesBE = exports.numberToBytesLE = exports.numberToBytesBE = exports.bytesToNumberLE = exports.bytesToNumberBE = exports.hexToBytes = exports.hexToNumber = exports.numberToHexUnpadded = exports.bytesToHex = void 0;
|
|
4
4
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
5
|
-
const mod = require("./modular.js");
|
|
6
5
|
const _0n = BigInt(0);
|
|
7
6
|
const _1n = BigInt(1);
|
|
8
7
|
const _2n = BigInt(2);
|
|
9
|
-
|
|
10
|
-
function isPositiveInt(num) {
|
|
11
|
-
return typeof num === 'number' && Number.isSafeInteger(num) && num > 0;
|
|
12
|
-
}
|
|
13
|
-
exports.isPositiveInt = isPositiveInt;
|
|
14
|
-
function validateOpts(curve) {
|
|
15
|
-
mod.validateField(curve.Fp);
|
|
16
|
-
for (const i of ['n', 'h']) {
|
|
17
|
-
const val = curve[i];
|
|
18
|
-
if (typeof val !== 'bigint')
|
|
19
|
-
throw new Error(`Invalid curve param ${i}=${val} (${typeof val})`);
|
|
20
|
-
}
|
|
21
|
-
if (!curve.Fp.isValid(curve.Gx))
|
|
22
|
-
throw new Error('Invalid generator X coordinate Fp element');
|
|
23
|
-
if (!curve.Fp.isValid(curve.Gy))
|
|
24
|
-
throw new Error('Invalid generator Y coordinate Fp element');
|
|
25
|
-
for (const i of ['nBitLength', 'nByteLength']) {
|
|
26
|
-
const val = curve[i];
|
|
27
|
-
if (val === undefined)
|
|
28
|
-
continue; // Optional
|
|
29
|
-
if (!isPositiveInt(val))
|
|
30
|
-
throw new Error(`Invalid curve param ${i}=${val} (${typeof val})`);
|
|
31
|
-
}
|
|
32
|
-
// Set defaults
|
|
33
|
-
return Object.freeze({ ...nLength(curve.n, curve.nBitLength), ...curve });
|
|
34
|
-
}
|
|
35
|
-
exports.validateOpts = validateOpts;
|
|
8
|
+
const u8a = (a) => a instanceof Uint8Array;
|
|
36
9
|
const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'));
|
|
37
|
-
function bytesToHex(
|
|
38
|
-
if (!(
|
|
39
|
-
throw new Error('
|
|
10
|
+
function bytesToHex(bytes) {
|
|
11
|
+
if (!u8a(bytes))
|
|
12
|
+
throw new Error('Uint8Array expected');
|
|
40
13
|
// pre-caching improves the speed 6x
|
|
41
14
|
let hex = '';
|
|
42
|
-
for (let i = 0; i <
|
|
43
|
-
hex += hexes[
|
|
15
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
16
|
+
hex += hexes[bytes[i]];
|
|
44
17
|
}
|
|
45
18
|
return hex;
|
|
46
19
|
}
|
|
@@ -51,27 +24,25 @@ function numberToHexUnpadded(num) {
|
|
|
51
24
|
}
|
|
52
25
|
exports.numberToHexUnpadded = numberToHexUnpadded;
|
|
53
26
|
function hexToNumber(hex) {
|
|
54
|
-
if (typeof hex !== 'string')
|
|
55
|
-
throw new
|
|
56
|
-
}
|
|
27
|
+
if (typeof hex !== 'string')
|
|
28
|
+
throw new Error('string expected, got ' + typeof hex);
|
|
57
29
|
// Big Endian
|
|
58
30
|
return BigInt(`0x${hex}`);
|
|
59
31
|
}
|
|
60
32
|
exports.hexToNumber = hexToNumber;
|
|
61
33
|
// Caching slows it down 2-3x
|
|
62
34
|
function hexToBytes(hex) {
|
|
63
|
-
if (typeof hex !== 'string')
|
|
64
|
-
throw new
|
|
65
|
-
}
|
|
35
|
+
if (typeof hex !== 'string')
|
|
36
|
+
throw new Error('string expected, got ' + typeof hex);
|
|
66
37
|
if (hex.length % 2)
|
|
67
|
-
throw new Error('
|
|
38
|
+
throw new Error('hex string is invalid: unpadded ' + hex.length);
|
|
68
39
|
const array = new Uint8Array(hex.length / 2);
|
|
69
40
|
for (let i = 0; i < array.length; i++) {
|
|
70
41
|
const j = i * 2;
|
|
71
42
|
const hexByte = hex.slice(j, j + 2);
|
|
72
43
|
const byte = Number.parseInt(hexByte, 16);
|
|
73
44
|
if (Number.isNaN(byte) || byte < 0)
|
|
74
|
-
throw new Error('
|
|
45
|
+
throw new Error('invalid byte sequence');
|
|
75
46
|
array[i] = byte;
|
|
76
47
|
}
|
|
77
48
|
return array;
|
|
@@ -82,68 +53,41 @@ function bytesToNumberBE(bytes) {
|
|
|
82
53
|
return hexToNumber(bytesToHex(bytes));
|
|
83
54
|
}
|
|
84
55
|
exports.bytesToNumberBE = bytesToNumberBE;
|
|
85
|
-
function bytesToNumberLE(
|
|
86
|
-
if (!(
|
|
87
|
-
throw new Error('
|
|
88
|
-
return
|
|
56
|
+
function bytesToNumberLE(bytes) {
|
|
57
|
+
if (!u8a(bytes))
|
|
58
|
+
throw new Error('Uint8Array expected');
|
|
59
|
+
return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
|
|
89
60
|
}
|
|
90
61
|
exports.bytesToNumberLE = bytesToNumberLE;
|
|
91
62
|
const numberToBytesBE = (n, len) => hexToBytes(n.toString(16).padStart(len * 2, '0'));
|
|
92
63
|
exports.numberToBytesBE = numberToBytesBE;
|
|
93
64
|
const numberToBytesLE = (n, len) => (0, exports.numberToBytesBE)(n, len).reverse();
|
|
94
65
|
exports.numberToBytesLE = numberToBytesLE;
|
|
66
|
+
// Returns variable number bytes (minimal bigint encoding?)
|
|
67
|
+
const numberToVarBytesBE = (n) => hexToBytes(numberToHexUnpadded(n));
|
|
68
|
+
exports.numberToVarBytesBE = numberToVarBytesBE;
|
|
95
69
|
function ensureBytes(hex, expectedLength) {
|
|
96
70
|
// Uint8Array.from() instead of hash.slice() because node.js Buffer
|
|
97
71
|
// is instance of Uint8Array, and its slice() creates **mutable** copy
|
|
98
|
-
const bytes = hex
|
|
72
|
+
const bytes = u8a(hex) ? Uint8Array.from(hex) : hexToBytes(hex);
|
|
99
73
|
if (typeof expectedLength === 'number' && bytes.length !== expectedLength)
|
|
100
74
|
throw new Error(`Expected ${expectedLength} bytes`);
|
|
101
75
|
return bytes;
|
|
102
76
|
}
|
|
103
77
|
exports.ensureBytes = ensureBytes;
|
|
104
78
|
// Copies several Uint8Arrays into one.
|
|
105
|
-
function concatBytes(...
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
pad += arr.length;
|
|
116
|
-
}
|
|
117
|
-
return result;
|
|
79
|
+
function concatBytes(...arrs) {
|
|
80
|
+
const r = new Uint8Array(arrs.reduce((sum, a) => sum + a.length, 0));
|
|
81
|
+
let pad = 0; // walk through each item, ensure they have proper type
|
|
82
|
+
arrs.forEach((a) => {
|
|
83
|
+
if (!u8a(a))
|
|
84
|
+
throw new Error('Uint8Array expected');
|
|
85
|
+
r.set(a, pad);
|
|
86
|
+
pad += a.length;
|
|
87
|
+
});
|
|
88
|
+
return r;
|
|
118
89
|
}
|
|
119
90
|
exports.concatBytes = concatBytes;
|
|
120
|
-
// CURVE.n lengths
|
|
121
|
-
function nLength(n, nBitLength) {
|
|
122
|
-
// Bit size, byte size of CURVE.n
|
|
123
|
-
const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length;
|
|
124
|
-
const nByteLength = Math.ceil(_nBitLength / 8);
|
|
125
|
-
return { nBitLength: _nBitLength, nByteLength };
|
|
126
|
-
}
|
|
127
|
-
exports.nLength = nLength;
|
|
128
|
-
/**
|
|
129
|
-
* FIPS 186 B.4.1-compliant "constant-time" private key generation utility.
|
|
130
|
-
* Can take (n+8) or more bytes of uniform input e.g. from CSPRNG or KDF
|
|
131
|
-
* and convert them into private scalar, with the modulo bias being neglible.
|
|
132
|
-
* Needs at least 40 bytes of input for 32-byte private key.
|
|
133
|
-
* https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
|
|
134
|
-
* @param hash hash output from SHA3 or a similar function
|
|
135
|
-
* @returns valid private scalar
|
|
136
|
-
*/
|
|
137
|
-
function hashToPrivateScalar(hash, groupOrder, isLE = false) {
|
|
138
|
-
hash = ensureBytes(hash);
|
|
139
|
-
const hashLen = hash.length;
|
|
140
|
-
const minLen = nLength(groupOrder).nByteLength + 8;
|
|
141
|
-
if (minLen < 24 || hashLen < minLen || hashLen > 1024)
|
|
142
|
-
throw new Error(`hashToPrivateScalar: expected ${minLen}-1024 bytes of input, got ${hashLen}`);
|
|
143
|
-
const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash);
|
|
144
|
-
return mod.mod(num, groupOrder - _1n) + _1n;
|
|
145
|
-
}
|
|
146
|
-
exports.hashToPrivateScalar = hashToPrivateScalar;
|
|
147
91
|
function equalBytes(b1, b2) {
|
|
148
92
|
// We don't care about timing attacks here
|
|
149
93
|
if (b1.length !== b2.length)
|
|
@@ -174,3 +118,33 @@ exports.bitSet = bitSet;
|
|
|
174
118
|
// Not using ** operator with bigints for old engines.
|
|
175
119
|
const bitMask = (n) => (_2n << BigInt(n - 1)) - _1n;
|
|
176
120
|
exports.bitMask = bitMask;
|
|
121
|
+
function validateObject(object, validators, optValidators = {}) {
|
|
122
|
+
const validatorFns = {
|
|
123
|
+
bigint: (val) => typeof val === 'bigint',
|
|
124
|
+
function: (val) => typeof val === 'function',
|
|
125
|
+
boolean: (val) => typeof val === 'boolean',
|
|
126
|
+
string: (val) => typeof val === 'string',
|
|
127
|
+
isSafeInteger: (val) => Number.isSafeInteger(val),
|
|
128
|
+
array: (val) => Array.isArray(val),
|
|
129
|
+
field: (val) => object.Fp.isValid(val),
|
|
130
|
+
hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
|
|
131
|
+
};
|
|
132
|
+
// type Key = keyof typeof validators;
|
|
133
|
+
const checkField = (fieldName, type, isOptional) => {
|
|
134
|
+
const checkVal = validatorFns[type];
|
|
135
|
+
if (typeof checkVal !== 'function')
|
|
136
|
+
throw new Error(`Invalid validator "${type}", expected function`);
|
|
137
|
+
const val = object[fieldName];
|
|
138
|
+
if (isOptional && val === undefined)
|
|
139
|
+
return;
|
|
140
|
+
if (!checkVal(val)) {
|
|
141
|
+
throw new Error(`Invalid param ${fieldName}=${val} (${typeof val}), expected ${type}`);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
for (let [fieldName, type] of Object.entries(validators))
|
|
145
|
+
checkField(fieldName, type, false);
|
|
146
|
+
for (let [fieldName, type] of Object.entries(optValidators))
|
|
147
|
+
checkField(fieldName, type, true);
|
|
148
|
+
return object;
|
|
149
|
+
}
|
|
150
|
+
exports.validateObject = validateObject;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
2
2
|
import * as mod from './modular.js';
|
|
3
3
|
import * as ut from './utils.js';
|
|
4
|
-
import { Hex, PrivKey } from './utils.js';
|
|
5
|
-
import {
|
|
6
|
-
|
|
4
|
+
import { CHash, Hex, PrivKey } from './utils.js';
|
|
5
|
+
import { Group, GroupConstructor, BasicCurve, AffinePoint } from './curve.js';
|
|
6
|
+
export type { AffinePoint };
|
|
7
7
|
declare type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
|
8
8
|
declare type EndomorphismOpts = {
|
|
9
9
|
beta: bigint;
|
|
@@ -14,24 +14,24 @@ declare type EndomorphismOpts = {
|
|
|
14
14
|
k2: bigint;
|
|
15
15
|
};
|
|
16
16
|
};
|
|
17
|
-
export declare type
|
|
17
|
+
export declare type BasicWCurve<T> = BasicCurve<T> & {
|
|
18
18
|
a: T;
|
|
19
19
|
b: T;
|
|
20
|
-
|
|
20
|
+
allowedPrivateKeyLengths?: readonly number[];
|
|
21
21
|
wrapPrivateKey?: boolean;
|
|
22
22
|
endo?: EndomorphismOpts;
|
|
23
|
-
isTorsionFree?: (c:
|
|
24
|
-
clearCofactor?: (c:
|
|
25
|
-
htfDefaults?: htfOpts;
|
|
26
|
-
mapToCurve?: (scalar: bigint[]) => {
|
|
27
|
-
x: T;
|
|
28
|
-
y: T;
|
|
29
|
-
};
|
|
23
|
+
isTorsionFree?: (c: ProjConstructor<T>, point: ProjPointType<T>) => boolean;
|
|
24
|
+
clearCofactor?: (c: ProjConstructor<T>, point: ProjPointType<T>) => ProjPointType<T>;
|
|
30
25
|
};
|
|
31
26
|
declare type Entropy = Hex | true;
|
|
32
27
|
export declare type SignOpts = {
|
|
33
28
|
lowS?: boolean;
|
|
34
29
|
extraEntropy?: Entropy;
|
|
30
|
+
prehash?: boolean;
|
|
31
|
+
};
|
|
32
|
+
export declare type VerOpts = {
|
|
33
|
+
lowS?: boolean;
|
|
34
|
+
prehash?: boolean;
|
|
35
35
|
};
|
|
36
36
|
/**
|
|
37
37
|
* ### Design rationale for types
|
|
@@ -54,54 +54,41 @@ export declare type SignOpts = {
|
|
|
54
54
|
*
|
|
55
55
|
* TODO: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol
|
|
56
56
|
*/
|
|
57
|
-
export interface
|
|
58
|
-
readonly
|
|
59
|
-
readonly
|
|
60
|
-
readonly
|
|
61
|
-
multiply(scalar:
|
|
62
|
-
multiplyUnsafe(scalar: bigint):
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
export interface ProjectiveConstructor<T> extends GroupConstructor<ProjectivePointType<T>> {
|
|
66
|
-
new (x: T, y: T, z: T): ProjectivePointType<T>;
|
|
67
|
-
fromAffine(p: PointType<T>): ProjectivePointType<T>;
|
|
68
|
-
toAffineBatch(points: ProjectivePointType<T>[]): PointType<T>[];
|
|
69
|
-
normalizeZ(points: ProjectivePointType<T>[]): ProjectivePointType<T>[];
|
|
70
|
-
}
|
|
71
|
-
export interface PointType<T> extends Group<PointType<T>> {
|
|
72
|
-
readonly x: T;
|
|
73
|
-
readonly y: T;
|
|
57
|
+
export interface ProjPointType<T> extends Group<ProjPointType<T>> {
|
|
58
|
+
readonly px: T;
|
|
59
|
+
readonly py: T;
|
|
60
|
+
readonly pz: T;
|
|
61
|
+
multiply(scalar: bigint): ProjPointType<T>;
|
|
62
|
+
multiplyUnsafe(scalar: bigint): ProjPointType<T>;
|
|
63
|
+
multiplyAndAddUnsafe(Q: ProjPointType<T>, a: bigint, b: bigint): ProjPointType<T> | undefined;
|
|
74
64
|
_setWindowSize(windowSize: number): void;
|
|
65
|
+
toAffine(iz?: T): AffinePoint<T>;
|
|
66
|
+
isTorsionFree(): boolean;
|
|
67
|
+
clearCofactor(): ProjPointType<T>;
|
|
68
|
+
assertValidity(): void;
|
|
75
69
|
hasEvenY(): boolean;
|
|
76
70
|
toRawBytes(isCompressed?: boolean): Uint8Array;
|
|
77
71
|
toHex(isCompressed?: boolean): string;
|
|
78
|
-
assertValidity(): void;
|
|
79
|
-
multiplyAndAddUnsafe(Q: PointType<T>, a: bigint, b: bigint): PointType<T> | undefined;
|
|
80
72
|
}
|
|
81
|
-
export interface
|
|
82
|
-
new (x: T, y: T):
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
73
|
+
export interface ProjConstructor<T> extends GroupConstructor<ProjPointType<T>> {
|
|
74
|
+
new (x: T, y: T, z: T): ProjPointType<T>;
|
|
75
|
+
fromAffine(p: AffinePoint<T>): ProjPointType<T>;
|
|
76
|
+
fromHex(hex: Hex): ProjPointType<T>;
|
|
77
|
+
fromPrivateKey(privateKey: PrivKey): ProjPointType<T>;
|
|
78
|
+
normalizeZ(points: ProjPointType<T>[]): ProjPointType<T>[];
|
|
87
79
|
}
|
|
88
|
-
export declare type CurvePointsType<T> =
|
|
89
|
-
fromBytes: (bytes: Uint8Array) =>
|
|
90
|
-
|
|
91
|
-
y: T;
|
|
92
|
-
};
|
|
93
|
-
toBytes: (c: PointConstructor<T>, point: PointType<T>, compressed: boolean) => Uint8Array;
|
|
80
|
+
export declare type CurvePointsType<T> = BasicWCurve<T> & {
|
|
81
|
+
fromBytes: (bytes: Uint8Array) => AffinePoint<T>;
|
|
82
|
+
toBytes: (c: ProjConstructor<T>, point: ProjPointType<T>, compressed: boolean) => Uint8Array;
|
|
94
83
|
};
|
|
95
84
|
export declare type CurvePointsRes<T> = {
|
|
96
|
-
|
|
97
|
-
ProjectivePoint: ProjectiveConstructor<T>;
|
|
85
|
+
ProjectivePoint: ProjConstructor<T>;
|
|
98
86
|
normalizePrivateKey: (key: PrivKey) => bigint;
|
|
99
87
|
weierstrassEquation: (x: T) => T;
|
|
100
88
|
isWithinCurveOrder: (num: bigint) => boolean;
|
|
101
89
|
};
|
|
102
90
|
export declare function weierstrassPoints<T>(opts: CurvePointsType<T>): {
|
|
103
|
-
|
|
104
|
-
ProjectivePoint: ProjectiveConstructor<T>;
|
|
91
|
+
ProjectivePoint: ProjConstructor<T>;
|
|
105
92
|
normalizePrivateKey: (key: PrivKey) => bigint;
|
|
106
93
|
weierstrassEquation: (x: T) => T;
|
|
107
94
|
isWithinCurveOrder: (num: bigint) => boolean;
|
|
@@ -111,27 +98,32 @@ export interface SignatureType {
|
|
|
111
98
|
readonly s: bigint;
|
|
112
99
|
readonly recovery?: number;
|
|
113
100
|
assertValidity(): void;
|
|
114
|
-
|
|
101
|
+
addRecoveryBit(recovery: number): SignatureType;
|
|
115
102
|
hasHighS(): boolean;
|
|
116
103
|
normalizeS(): SignatureType;
|
|
117
|
-
recoverPublicKey(msgHash: Hex):
|
|
118
|
-
toDERRawBytes(isCompressed?: boolean): Uint8Array;
|
|
119
|
-
toDERHex(isCompressed?: boolean): string;
|
|
104
|
+
recoverPublicKey(msgHash: Hex): ProjPointType<bigint>;
|
|
120
105
|
toCompactRawBytes(): Uint8Array;
|
|
121
106
|
toCompactHex(): string;
|
|
107
|
+
toDERRawBytes(isCompressed?: boolean): Uint8Array;
|
|
108
|
+
toDERHex(isCompressed?: boolean): string;
|
|
122
109
|
}
|
|
123
110
|
export declare type SignatureConstructor = {
|
|
124
111
|
new (r: bigint, s: bigint): SignatureType;
|
|
125
112
|
fromCompact(hex: Hex): SignatureType;
|
|
126
113
|
fromDER(hex: Hex): SignatureType;
|
|
127
114
|
};
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
115
|
+
declare type SignatureLike = {
|
|
116
|
+
r: bigint;
|
|
117
|
+
s: bigint;
|
|
118
|
+
};
|
|
119
|
+
export declare type PubKey = Hex | ProjPointType<bigint>;
|
|
120
|
+
export declare type CurveType = BasicWCurve<bigint> & {
|
|
121
|
+
hash: CHash;
|
|
132
122
|
hmac: HmacFnSync;
|
|
133
123
|
randomBytes: (bytesLength?: number) => Uint8Array;
|
|
134
|
-
|
|
124
|
+
lowS?: boolean;
|
|
125
|
+
bits2int?: (bytes: Uint8Array) => bigint;
|
|
126
|
+
bits2int_modN?: (bytes: Uint8Array) => bigint;
|
|
135
127
|
};
|
|
136
128
|
declare function validateOpts(curve: CurveType): Readonly<{
|
|
137
129
|
readonly nBitLength: number;
|
|
@@ -142,45 +134,31 @@ declare function validateOpts(curve: CurveType): Readonly<{
|
|
|
142
134
|
readonly hEff?: bigint | undefined;
|
|
143
135
|
readonly Gx: bigint;
|
|
144
136
|
readonly Gy: bigint;
|
|
145
|
-
readonly wrapPrivateKey?: boolean | undefined;
|
|
146
137
|
readonly allowInfinityPoint?: boolean | undefined;
|
|
147
138
|
readonly a: bigint;
|
|
148
139
|
readonly b: bigint;
|
|
149
|
-
readonly
|
|
140
|
+
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
|
|
141
|
+
readonly wrapPrivateKey?: boolean | undefined;
|
|
150
142
|
readonly endo?: EndomorphismOpts | undefined;
|
|
151
|
-
readonly isTorsionFree?: ((c:
|
|
152
|
-
readonly clearCofactor?: ((c:
|
|
153
|
-
readonly htfDefaults?: htfOpts | undefined;
|
|
154
|
-
readonly mapToCurve?: ((scalar: bigint[]) => {
|
|
155
|
-
x: bigint;
|
|
156
|
-
y: bigint;
|
|
157
|
-
}) | undefined;
|
|
158
|
-
lowS: boolean;
|
|
143
|
+
readonly isTorsionFree?: ((c: ProjConstructor<bigint>, point: ProjPointType<bigint>) => boolean) | undefined;
|
|
144
|
+
readonly clearCofactor?: ((c: ProjConstructor<bigint>, point: ProjPointType<bigint>) => ProjPointType<bigint>) | undefined;
|
|
159
145
|
readonly hash: ut.CHash;
|
|
160
146
|
readonly hmac: HmacFnSync;
|
|
161
147
|
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
|
|
162
|
-
|
|
148
|
+
lowS: boolean;
|
|
149
|
+
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
150
|
+
readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
163
151
|
}>;
|
|
164
152
|
export declare type CurveFn = {
|
|
165
153
|
CURVE: ReturnType<typeof validateOpts>;
|
|
166
154
|
getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array;
|
|
167
|
-
getSharedSecret: (privateA: PrivKey, publicB:
|
|
155
|
+
getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array;
|
|
168
156
|
sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => SignatureType;
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
lowS?: boolean;
|
|
172
|
-
}) => boolean;
|
|
173
|
-
Point: PointConstructor<bigint>;
|
|
174
|
-
ProjectivePoint: ProjectiveConstructor<bigint>;
|
|
157
|
+
verify: (signature: Hex | SignatureLike, msgHash: Hex, publicKey: Hex, opts?: VerOpts) => boolean;
|
|
158
|
+
ProjectivePoint: ProjConstructor<bigint>;
|
|
175
159
|
Signature: SignatureConstructor;
|
|
176
160
|
utils: {
|
|
177
|
-
_bigintToBytes: (num: bigint) => Uint8Array;
|
|
178
|
-
_bigintToString: (num: bigint) => string;
|
|
179
161
|
_normalizePrivateKey: (key: PrivKey) => bigint;
|
|
180
|
-
_normalizePublicKey: (publicKey: PubKey) => PointType<bigint>;
|
|
181
|
-
_isWithinCurveOrder: (num: bigint) => boolean;
|
|
182
|
-
_isValidFieldElement: (num: bigint) => boolean;
|
|
183
|
-
_weierstrassEquation: (x: bigint) => bigint;
|
|
184
162
|
isValidPrivateKey(privateKey: PrivKey): boolean;
|
|
185
163
|
hashToPrivateKey: (hash: Hex) => Uint8Array;
|
|
186
164
|
randomPrivateKey: () => Uint8Array;
|
|
@@ -199,4 +177,3 @@ export declare function mapToCurveSimpleSWU<T>(Fp: mod.Field<T>, opts: {
|
|
|
199
177
|
x: T;
|
|
200
178
|
y: T;
|
|
201
179
|
};
|
|
202
|
-
export {};
|