@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
|
@@ -1,41 +1,16 @@
|
|
|
1
1
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
2
|
-
import * as mod from './modular.js';
|
|
3
2
|
const _0n = BigInt(0);
|
|
4
3
|
const _1n = BigInt(1);
|
|
5
4
|
const _2n = BigInt(2);
|
|
6
|
-
|
|
7
|
-
export function isPositiveInt(num) {
|
|
8
|
-
return typeof num === 'number' && Number.isSafeInteger(num) && num > 0;
|
|
9
|
-
}
|
|
10
|
-
export function validateOpts(curve) {
|
|
11
|
-
mod.validateField(curve.Fp);
|
|
12
|
-
for (const i of ['n', 'h']) {
|
|
13
|
-
const val = curve[i];
|
|
14
|
-
if (typeof val !== 'bigint')
|
|
15
|
-
throw new Error(`Invalid curve param ${i}=${val} (${typeof val})`);
|
|
16
|
-
}
|
|
17
|
-
if (!curve.Fp.isValid(curve.Gx))
|
|
18
|
-
throw new Error('Invalid generator X coordinate Fp element');
|
|
19
|
-
if (!curve.Fp.isValid(curve.Gy))
|
|
20
|
-
throw new Error('Invalid generator Y coordinate Fp element');
|
|
21
|
-
for (const i of ['nBitLength', 'nByteLength']) {
|
|
22
|
-
const val = curve[i];
|
|
23
|
-
if (val === undefined)
|
|
24
|
-
continue; // Optional
|
|
25
|
-
if (!isPositiveInt(val))
|
|
26
|
-
throw new Error(`Invalid curve param ${i}=${val} (${typeof val})`);
|
|
27
|
-
}
|
|
28
|
-
// Set defaults
|
|
29
|
-
return Object.freeze({ ...nLength(curve.n, curve.nBitLength), ...curve });
|
|
30
|
-
}
|
|
5
|
+
const u8a = (a) => a instanceof Uint8Array;
|
|
31
6
|
const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'));
|
|
32
|
-
export function bytesToHex(
|
|
33
|
-
if (!(
|
|
34
|
-
throw new Error('
|
|
7
|
+
export function bytesToHex(bytes) {
|
|
8
|
+
if (!u8a(bytes))
|
|
9
|
+
throw new Error('Uint8Array expected');
|
|
35
10
|
// pre-caching improves the speed 6x
|
|
36
11
|
let hex = '';
|
|
37
|
-
for (let i = 0; i <
|
|
38
|
-
hex += hexes[
|
|
12
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
13
|
+
hex += hexes[bytes[i]];
|
|
39
14
|
}
|
|
40
15
|
return hex;
|
|
41
16
|
}
|
|
@@ -44,26 +19,24 @@ export function numberToHexUnpadded(num) {
|
|
|
44
19
|
return hex.length & 1 ? `0${hex}` : hex;
|
|
45
20
|
}
|
|
46
21
|
export function hexToNumber(hex) {
|
|
47
|
-
if (typeof hex !== 'string')
|
|
48
|
-
throw new
|
|
49
|
-
}
|
|
22
|
+
if (typeof hex !== 'string')
|
|
23
|
+
throw new Error('string expected, got ' + typeof hex);
|
|
50
24
|
// Big Endian
|
|
51
25
|
return BigInt(`0x${hex}`);
|
|
52
26
|
}
|
|
53
27
|
// Caching slows it down 2-3x
|
|
54
28
|
export function hexToBytes(hex) {
|
|
55
|
-
if (typeof hex !== 'string')
|
|
56
|
-
throw new
|
|
57
|
-
}
|
|
29
|
+
if (typeof hex !== 'string')
|
|
30
|
+
throw new Error('string expected, got ' + typeof hex);
|
|
58
31
|
if (hex.length % 2)
|
|
59
|
-
throw new Error('
|
|
32
|
+
throw new Error('hex string is invalid: unpadded ' + hex.length);
|
|
60
33
|
const array = new Uint8Array(hex.length / 2);
|
|
61
34
|
for (let i = 0; i < array.length; i++) {
|
|
62
35
|
const j = i * 2;
|
|
63
36
|
const hexByte = hex.slice(j, j + 2);
|
|
64
37
|
const byte = Number.parseInt(hexByte, 16);
|
|
65
38
|
if (Number.isNaN(byte) || byte < 0)
|
|
66
|
-
throw new Error('
|
|
39
|
+
throw new Error('invalid byte sequence');
|
|
67
40
|
array[i] = byte;
|
|
68
41
|
}
|
|
69
42
|
return array;
|
|
@@ -72,60 +45,34 @@ export function hexToBytes(hex) {
|
|
|
72
45
|
export function bytesToNumberBE(bytes) {
|
|
73
46
|
return hexToNumber(bytesToHex(bytes));
|
|
74
47
|
}
|
|
75
|
-
export function bytesToNumberLE(
|
|
76
|
-
if (!(
|
|
77
|
-
throw new Error('
|
|
78
|
-
return
|
|
48
|
+
export function bytesToNumberLE(bytes) {
|
|
49
|
+
if (!u8a(bytes))
|
|
50
|
+
throw new Error('Uint8Array expected');
|
|
51
|
+
return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
|
|
79
52
|
}
|
|
80
53
|
export const numberToBytesBE = (n, len) => hexToBytes(n.toString(16).padStart(len * 2, '0'));
|
|
81
54
|
export const numberToBytesLE = (n, len) => numberToBytesBE(n, len).reverse();
|
|
55
|
+
// Returns variable number bytes (minimal bigint encoding?)
|
|
56
|
+
export const numberToVarBytesBE = (n) => hexToBytes(numberToHexUnpadded(n));
|
|
82
57
|
export function ensureBytes(hex, expectedLength) {
|
|
83
58
|
// Uint8Array.from() instead of hash.slice() because node.js Buffer
|
|
84
59
|
// is instance of Uint8Array, and its slice() creates **mutable** copy
|
|
85
|
-
const bytes = hex
|
|
60
|
+
const bytes = u8a(hex) ? Uint8Array.from(hex) : hexToBytes(hex);
|
|
86
61
|
if (typeof expectedLength === 'number' && bytes.length !== expectedLength)
|
|
87
62
|
throw new Error(`Expected ${expectedLength} bytes`);
|
|
88
63
|
return bytes;
|
|
89
64
|
}
|
|
90
65
|
// Copies several Uint8Arrays into one.
|
|
91
|
-
export function concatBytes(...
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
pad += arr.length;
|
|
102
|
-
}
|
|
103
|
-
return result;
|
|
104
|
-
}
|
|
105
|
-
// CURVE.n lengths
|
|
106
|
-
export function nLength(n, nBitLength) {
|
|
107
|
-
// Bit size, byte size of CURVE.n
|
|
108
|
-
const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length;
|
|
109
|
-
const nByteLength = Math.ceil(_nBitLength / 8);
|
|
110
|
-
return { nBitLength: _nBitLength, nByteLength };
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* FIPS 186 B.4.1-compliant "constant-time" private key generation utility.
|
|
114
|
-
* Can take (n+8) or more bytes of uniform input e.g. from CSPRNG or KDF
|
|
115
|
-
* and convert them into private scalar, with the modulo bias being neglible.
|
|
116
|
-
* Needs at least 40 bytes of input for 32-byte private key.
|
|
117
|
-
* https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
|
|
118
|
-
* @param hash hash output from SHA3 or a similar function
|
|
119
|
-
* @returns valid private scalar
|
|
120
|
-
*/
|
|
121
|
-
export function hashToPrivateScalar(hash, groupOrder, isLE = false) {
|
|
122
|
-
hash = ensureBytes(hash);
|
|
123
|
-
const hashLen = hash.length;
|
|
124
|
-
const minLen = nLength(groupOrder).nByteLength + 8;
|
|
125
|
-
if (minLen < 24 || hashLen < minLen || hashLen > 1024)
|
|
126
|
-
throw new Error(`hashToPrivateScalar: expected ${minLen}-1024 bytes of input, got ${hashLen}`);
|
|
127
|
-
const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash);
|
|
128
|
-
return mod.mod(num, groupOrder - _1n) + _1n;
|
|
66
|
+
export function concatBytes(...arrs) {
|
|
67
|
+
const r = new Uint8Array(arrs.reduce((sum, a) => sum + a.length, 0));
|
|
68
|
+
let pad = 0; // walk through each item, ensure they have proper type
|
|
69
|
+
arrs.forEach((a) => {
|
|
70
|
+
if (!u8a(a))
|
|
71
|
+
throw new Error('Uint8Array expected');
|
|
72
|
+
r.set(a, pad);
|
|
73
|
+
pad += a.length;
|
|
74
|
+
});
|
|
75
|
+
return r;
|
|
129
76
|
}
|
|
130
77
|
export function equalBytes(b1, b2) {
|
|
131
78
|
// We don't care about timing attacks here
|
|
@@ -152,3 +99,32 @@ export const bitSet = (n, pos, value) => n | ((value ? _1n : _0n) << BigInt(pos)
|
|
|
152
99
|
// Return mask for N bits (Same as BigInt(`0b${Array(i).fill('1').join('')}`))
|
|
153
100
|
// Not using ** operator with bigints for old engines.
|
|
154
101
|
export const bitMask = (n) => (_2n << BigInt(n - 1)) - _1n;
|
|
102
|
+
export function validateObject(object, validators, optValidators = {}) {
|
|
103
|
+
const validatorFns = {
|
|
104
|
+
bigint: (val) => typeof val === 'bigint',
|
|
105
|
+
function: (val) => typeof val === 'function',
|
|
106
|
+
boolean: (val) => typeof val === 'boolean',
|
|
107
|
+
string: (val) => typeof val === 'string',
|
|
108
|
+
isSafeInteger: (val) => Number.isSafeInteger(val),
|
|
109
|
+
array: (val) => Array.isArray(val),
|
|
110
|
+
field: (val) => object.Fp.isValid(val),
|
|
111
|
+
hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
|
|
112
|
+
};
|
|
113
|
+
// type Key = keyof typeof validators;
|
|
114
|
+
const checkField = (fieldName, type, isOptional) => {
|
|
115
|
+
const checkVal = validatorFns[type];
|
|
116
|
+
if (typeof checkVal !== 'function')
|
|
117
|
+
throw new Error(`Invalid validator "${type}", expected function`);
|
|
118
|
+
const val = object[fieldName];
|
|
119
|
+
if (isOptional && val === undefined)
|
|
120
|
+
return;
|
|
121
|
+
if (!checkVal(val)) {
|
|
122
|
+
throw new Error(`Invalid param ${fieldName}=${val} (${typeof val}), expected ${type}`);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
for (let [fieldName, type] of Object.entries(validators))
|
|
126
|
+
checkField(fieldName, type, false);
|
|
127
|
+
for (let [fieldName, type] of Object.entries(optValidators))
|
|
128
|
+
checkField(fieldName, type, true);
|
|
129
|
+
return object;
|
|
130
|
+
}
|