@noble/curves 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +143 -194
- package/abstract/bls.d.ts +29 -12
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +58 -8
- package/abstract/bls.js.map +1 -1
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.js.map +1 -1
- package/abstract/hash-to-curve.d.ts +1 -1
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +10 -21
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +5 -7
- package/abstract/montgomery.js.map +1 -1
- package/abstract/poseidon.js.map +1 -1
- package/abstract/utils.d.ts +4 -2
- package/abstract/utils.d.ts.map +1 -1
- package/abstract/utils.js +61 -36
- package/abstract/utils.js.map +1 -1
- package/abstract/weierstrass.d.ts +24 -28
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +13 -7
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +138 -83
- package/bls12-381.js.map +1 -1
- package/bn254.d.ts +3 -2
- package/bn254.d.ts.map +1 -1
- package/bn254.js +3 -2
- package/bn254.js.map +1 -1
- package/ed25519.d.ts +4 -2
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +8 -2
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +4 -2
- package/ed448.d.ts.map +1 -1
- package/ed448.js +10 -1
- package/ed448.js.map +1 -1
- package/esm/abstract/bls.js +58 -8
- package/esm/abstract/bls.js.map +1 -1
- package/esm/abstract/curve.js.map +1 -1
- package/esm/abstract/edwards.js.map +1 -1
- package/esm/abstract/hash-to-curve.js +11 -22
- package/esm/abstract/hash-to-curve.js.map +1 -1
- package/esm/abstract/modular.js.map +1 -1
- package/esm/abstract/montgomery.js +5 -7
- package/esm/abstract/montgomery.js.map +1 -1
- package/esm/abstract/poseidon.js.map +1 -1
- package/esm/abstract/utils.js +58 -35
- package/esm/abstract/utils.js.map +1 -1
- package/esm/abstract/weierstrass.js +13 -7
- package/esm/abstract/weierstrass.js.map +1 -1
- package/esm/bls12-381.js +139 -84
- package/esm/bls12-381.js.map +1 -1
- package/esm/bn254.js +3 -2
- package/esm/bn254.js.map +1 -1
- package/esm/ed25519.js +8 -2
- package/esm/ed25519.js.map +1 -1
- package/esm/ed448.js +10 -1
- package/esm/ed448.js.map +1 -1
- package/esm/index.js +1 -1
- package/esm/index.js.map +1 -1
- package/esm/jubjub.js.map +1 -1
- package/esm/p256.js +2 -2
- package/esm/p256.js.map +1 -1
- package/esm/p384.js +2 -2
- package/esm/p384.js.map +1 -1
- package/esm/p521.js +3 -3
- package/esm/p521.js.map +1 -1
- package/esm/secp256k1.js +6 -6
- package/esm/secp256k1.js.map +1 -1
- package/jubjub.js.map +1 -1
- package/p256.js +2 -2
- package/p256.js.map +1 -1
- package/p384.js +2 -2
- package/p384.js.map +1 -1
- package/p521.js +3 -3
- package/p521.js.map +1 -1
- package/package.json +7 -7
- package/secp256k1.js +6 -6
- package/secp256k1.js.map +1 -1
- package/src/abstract/bls.ts +119 -21
- package/src/abstract/hash-to-curve.ts +12 -20
- package/src/abstract/montgomery.ts +4 -6
- package/src/abstract/utils.ts +57 -28
- package/src/abstract/weierstrass.ts +25 -10
- package/src/bls12-381.ts +128 -70
- package/src/bn254.ts +3 -2
- package/src/ed25519.ts +10 -2
- package/src/ed448.ts +18 -3
- package/src/package.json +3 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
2
2
|
import type { Group, GroupConstructor, AffinePoint } from './curve.js';
|
|
3
3
|
import { mod, IField } from './modular.js';
|
|
4
|
-
import {
|
|
4
|
+
import type { CHash } from './utils.js';
|
|
5
|
+
import { bytesToNumberBE, abytes, concatBytes, utf8ToBytes, validateObject } from './utils.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* * `DST` is a domain separation tag, defined in section 2.2.5
|
|
@@ -21,12 +22,6 @@ export type Opts = {
|
|
|
21
22
|
hash: CHash;
|
|
22
23
|
};
|
|
23
24
|
|
|
24
|
-
function validateDST(dst: UnicodeOrBytes): Uint8Array {
|
|
25
|
-
if (dst instanceof Uint8Array) return dst;
|
|
26
|
-
if (typeof dst === 'string') return utf8ToBytes(dst);
|
|
27
|
-
throw new Error('DST must be Uint8Array or string');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
25
|
// Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE.
|
|
31
26
|
const os2ip = bytesToNumberBE;
|
|
32
27
|
|
|
@@ -51,10 +46,7 @@ function strxor(a: Uint8Array, b: Uint8Array): Uint8Array {
|
|
|
51
46
|
return arr;
|
|
52
47
|
}
|
|
53
48
|
|
|
54
|
-
function
|
|
55
|
-
if (!(item instanceof Uint8Array)) throw new Error('Uint8Array expected');
|
|
56
|
-
}
|
|
57
|
-
function isNum(item: unknown): void {
|
|
49
|
+
function anum(item: unknown): void {
|
|
58
50
|
if (!Number.isSafeInteger(item)) throw new Error('number expected');
|
|
59
51
|
}
|
|
60
52
|
|
|
@@ -66,9 +58,9 @@ export function expand_message_xmd(
|
|
|
66
58
|
lenInBytes: number,
|
|
67
59
|
H: CHash
|
|
68
60
|
): Uint8Array {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
61
|
+
abytes(msg);
|
|
62
|
+
abytes(DST);
|
|
63
|
+
anum(lenInBytes);
|
|
72
64
|
// https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3
|
|
73
65
|
if (DST.length > 255) DST = H(concatBytes(utf8ToBytes('H2C-OVERSIZE-DST-'), DST));
|
|
74
66
|
const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H;
|
|
@@ -100,9 +92,9 @@ export function expand_message_xof(
|
|
|
100
92
|
k: number,
|
|
101
93
|
H: CHash
|
|
102
94
|
): Uint8Array {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
95
|
+
abytes(msg);
|
|
96
|
+
abytes(DST);
|
|
97
|
+
anum(lenInBytes);
|
|
106
98
|
// https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3
|
|
107
99
|
// DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));
|
|
108
100
|
if (DST.length > 255) {
|
|
@@ -139,9 +131,9 @@ export function hash_to_field(msg: Uint8Array, count: number, options: Opts): bi
|
|
|
139
131
|
hash: 'hash',
|
|
140
132
|
});
|
|
141
133
|
const { p, k, m, hash, expand, DST: _DST } = options;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const DST =
|
|
134
|
+
abytes(msg);
|
|
135
|
+
anum(count);
|
|
136
|
+
const DST = typeof _DST === 'string' ? utf8ToBytes(_DST) : _DST;
|
|
145
137
|
const log2p = p.toString(2).length;
|
|
146
138
|
const L = Math.ceil((log2p + k) / 8); // section 5.1 of ietf draft link above
|
|
147
139
|
const len_in_bytes = count * m * L;
|
|
@@ -150,17 +150,15 @@ export function montgomery(curveDef: CurveType): CurveFn {
|
|
|
150
150
|
function decodeUCoordinate(uEnc: Hex): bigint {
|
|
151
151
|
// Section 5: When receiving such an array, implementations of X25519
|
|
152
152
|
// MUST mask the most significant bit in the final byte.
|
|
153
|
-
// This is very ugly way, but it works because fieldLen-1 is outside of bounds for X448, so this becomes NOOP
|
|
154
|
-
// fieldLen - scalaryBytes = 1 for X448 and = 0 for X25519
|
|
155
153
|
const u = ensureBytes('u coordinate', uEnc, montgomeryBytes);
|
|
156
|
-
|
|
157
|
-
if (fieldLen === montgomeryBytes) u[fieldLen - 1] &= 127; // 0b0111_1111
|
|
154
|
+
if (fieldLen === 32) u[31] &= 127; // 0b0111_1111
|
|
158
155
|
return bytesToNumberLE(u);
|
|
159
156
|
}
|
|
160
157
|
function decodeScalar(n: Hex): bigint {
|
|
161
158
|
const bytes = ensureBytes('scalar', n);
|
|
162
|
-
|
|
163
|
-
|
|
159
|
+
const len = bytes.length;
|
|
160
|
+
if (len !== montgomeryBytes && len !== fieldLen)
|
|
161
|
+
throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${len}`);
|
|
164
162
|
return bytesToNumberLE(adjustScalarBytes(bytes));
|
|
165
163
|
}
|
|
166
164
|
function scalarMult(scalar: Hex, u: Hex): Uint8Array {
|
package/src/abstract/utils.ts
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
const _0n = BigInt(0);
|
|
7
7
|
const _1n = BigInt(1);
|
|
8
8
|
const _2n = BigInt(2);
|
|
9
|
-
const u8a = (a: any): a is Uint8Array => a instanceof Uint8Array;
|
|
10
9
|
export type Hex = Uint8Array | string; // hex strings are accepted for simplicity
|
|
11
10
|
export type PrivKey = Hex | bigint; // bigints are accepted to ease learning curve
|
|
12
11
|
export type CHash = {
|
|
@@ -17,6 +16,18 @@ export type CHash = {
|
|
|
17
16
|
};
|
|
18
17
|
export type FHash = (message: Uint8Array | string) => Uint8Array;
|
|
19
18
|
|
|
19
|
+
export function isBytes(a: unknown): a is Uint8Array {
|
|
20
|
+
return (
|
|
21
|
+
a instanceof Uint8Array ||
|
|
22
|
+
(a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array')
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function abytes(item: unknown): void {
|
|
27
|
+
if (!isBytes(item)) throw new Error('Uint8Array expected');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Array where index 0xf0 (240) is mapped to string 'f0'
|
|
20
31
|
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) =>
|
|
21
32
|
i.toString(16).padStart(2, '0')
|
|
22
33
|
);
|
|
@@ -24,7 +35,7 @@ const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) =>
|
|
|
24
35
|
* @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'
|
|
25
36
|
*/
|
|
26
37
|
export function bytesToHex(bytes: Uint8Array): string {
|
|
27
|
-
|
|
38
|
+
abytes(bytes);
|
|
28
39
|
// pre-caching improves the speed 6x
|
|
29
40
|
let hex = '';
|
|
30
41
|
for (let i = 0; i < bytes.length; i++) {
|
|
@@ -44,20 +55,32 @@ export function hexToNumber(hex: string): bigint {
|
|
|
44
55
|
return BigInt(hex === '' ? '0' : `0x${hex}`);
|
|
45
56
|
}
|
|
46
57
|
|
|
58
|
+
// We use optimized technique to convert hex string to byte array
|
|
59
|
+
const asciis = { _0: 48, _9: 57, _A: 65, _F: 70, _a: 97, _f: 102 } as const;
|
|
60
|
+
function asciiToBase16(char: number): number | undefined {
|
|
61
|
+
if (char >= asciis._0 && char <= asciis._9) return char - asciis._0;
|
|
62
|
+
if (char >= asciis._A && char <= asciis._F) return char - (asciis._A - 10);
|
|
63
|
+
if (char >= asciis._a && char <= asciis._f) return char - (asciis._a - 10);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
47
67
|
/**
|
|
48
68
|
* @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])
|
|
49
69
|
*/
|
|
50
70
|
export function hexToBytes(hex: string): Uint8Array {
|
|
51
71
|
if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
if (
|
|
60
|
-
|
|
72
|
+
const hl = hex.length;
|
|
73
|
+
const al = hl / 2;
|
|
74
|
+
if (hl % 2) throw new Error('padded hex string expected, got unpadded hex of length ' + hl);
|
|
75
|
+
const array = new Uint8Array(al);
|
|
76
|
+
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
|
|
77
|
+
const n1 = asciiToBase16(hex.charCodeAt(hi));
|
|
78
|
+
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
|
|
79
|
+
if (n1 === undefined || n2 === undefined) {
|
|
80
|
+
const char = hex[hi] + hex[hi + 1];
|
|
81
|
+
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
|
|
82
|
+
}
|
|
83
|
+
array[ai] = n1 * 16 + n2;
|
|
61
84
|
}
|
|
62
85
|
return array;
|
|
63
86
|
}
|
|
@@ -67,7 +90,7 @@ export function bytesToNumberBE(bytes: Uint8Array): bigint {
|
|
|
67
90
|
return hexToNumber(bytesToHex(bytes));
|
|
68
91
|
}
|
|
69
92
|
export function bytesToNumberLE(bytes: Uint8Array): bigint {
|
|
70
|
-
|
|
93
|
+
abytes(bytes);
|
|
71
94
|
return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
|
|
72
95
|
}
|
|
73
96
|
|
|
@@ -99,7 +122,7 @@ export function ensureBytes(title: string, hex: Hex, expectedLength?: number): U
|
|
|
99
122
|
} catch (e) {
|
|
100
123
|
throw new Error(`${title} must be valid hex string, got "${hex}". Cause: ${e}`);
|
|
101
124
|
}
|
|
102
|
-
} else if (
|
|
125
|
+
} else if (isBytes(hex)) {
|
|
103
126
|
// Uint8Array.from() instead of hash.slice() because node.js Buffer
|
|
104
127
|
// is instance of Uint8Array, and its slice() creates **mutable** copy
|
|
105
128
|
res = Uint8Array.from(hex);
|
|
@@ -116,21 +139,27 @@ export function ensureBytes(title: string, hex: Hex, expectedLength?: number): U
|
|
|
116
139
|
* Copies several Uint8Arrays into one.
|
|
117
140
|
*/
|
|
118
141
|
export function concatBytes(...arrays: Uint8Array[]): Uint8Array {
|
|
119
|
-
|
|
120
|
-
let
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
142
|
+
let sum = 0;
|
|
143
|
+
for (let i = 0; i < arrays.length; i++) {
|
|
144
|
+
const a = arrays[i];
|
|
145
|
+
abytes(a);
|
|
146
|
+
sum += a.length;
|
|
147
|
+
}
|
|
148
|
+
const res = new Uint8Array(sum);
|
|
149
|
+
for (let i = 0, pad = 0; i < arrays.length; i++) {
|
|
150
|
+
const a = arrays[i];
|
|
151
|
+
res.set(a, pad);
|
|
124
152
|
pad += a.length;
|
|
125
|
-
}
|
|
126
|
-
return
|
|
153
|
+
}
|
|
154
|
+
return res;
|
|
127
155
|
}
|
|
128
156
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
|
|
157
|
+
// Compares 2 u8a-s in kinda constant time
|
|
158
|
+
export function equalBytes(a: Uint8Array, b: Uint8Array) {
|
|
159
|
+
if (a.length !== b.length) return false;
|
|
160
|
+
let diff = 0;
|
|
161
|
+
for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];
|
|
162
|
+
return diff === 0;
|
|
134
163
|
}
|
|
135
164
|
|
|
136
165
|
// Global symbols in both browsers and Node.js since v11
|
|
@@ -169,9 +198,9 @@ export function bitGet(n: bigint, pos: number) {
|
|
|
169
198
|
/**
|
|
170
199
|
* Sets single bit at position.
|
|
171
200
|
*/
|
|
172
|
-
export
|
|
201
|
+
export function bitSet(n: bigint, pos: number, value: boolean) {
|
|
173
202
|
return n | ((value ? _1n : _0n) << BigInt(pos));
|
|
174
|
-
}
|
|
203
|
+
}
|
|
175
204
|
|
|
176
205
|
/**
|
|
177
206
|
* Calculate mask for N bits. Not using ** operator with bigints because of old engines.
|
|
@@ -248,7 +277,7 @@ const validatorFns = {
|
|
|
248
277
|
function: (val: any) => typeof val === 'function',
|
|
249
278
|
boolean: (val: any) => typeof val === 'boolean',
|
|
250
279
|
string: (val: any) => typeof val === 'string',
|
|
251
|
-
stringOrUint8Array: (val: any) => typeof val === 'string' || val
|
|
280
|
+
stringOrUint8Array: (val: any) => typeof val === 'string' || isBytes(val),
|
|
252
281
|
isSafeInteger: (val: any) => Number.isSafeInteger(val),
|
|
253
282
|
array: (val: any) => Array.isArray(val),
|
|
254
283
|
field: (val: any, object: any) => (object as any).Fp.isValid(val),
|
|
@@ -27,7 +27,7 @@ export type BasicWCurve<T> = BasicCurve<T> & {
|
|
|
27
27
|
clearCofactor?: (c: ProjConstructor<T>, point: ProjPointType<T>) => ProjPointType<T>;
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
type Entropy = Hex |
|
|
30
|
+
type Entropy = Hex | boolean;
|
|
31
31
|
export type SignOpts = { lowS?: boolean; extraEntropy?: Entropy; prehash?: boolean };
|
|
32
32
|
export type VerOpts = { lowS?: boolean; prehash?: boolean };
|
|
33
33
|
|
|
@@ -123,6 +123,7 @@ function validatePointOpts<T>(curve: CurvePointsType<T>) {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
export type CurvePointsRes<T> = {
|
|
126
|
+
CURVE: ReturnType<typeof validatePointOpts<T>>;
|
|
126
127
|
ProjectivePoint: ProjConstructor<T>;
|
|
127
128
|
normPrivateKeyToScalar: (key: PrivKey) => bigint;
|
|
128
129
|
weierstrassEquation: (x: T) => T;
|
|
@@ -157,7 +158,7 @@ export const DER = {
|
|
|
157
158
|
// parse DER signature
|
|
158
159
|
const { Err: E } = DER;
|
|
159
160
|
const data = typeof hex === 'string' ? h2b(hex) : hex;
|
|
160
|
-
|
|
161
|
+
ut.abytes(data);
|
|
161
162
|
let l = data.length;
|
|
162
163
|
if (l < 2 || data[0] != 0x30) throw new E('Invalid signature tag');
|
|
163
164
|
if (data[1] !== l - 2) throw new E('Invalid signature: incorrect length');
|
|
@@ -187,7 +188,7 @@ export const DER = {
|
|
|
187
188
|
// prettier-ignore
|
|
188
189
|
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
|
|
189
190
|
|
|
190
|
-
export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
|
|
191
|
+
export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T> {
|
|
191
192
|
const CURVE = validatePointOpts(opts);
|
|
192
193
|
const { Fp } = CURVE; // All curves has same field / group length as for now, but they can differ
|
|
193
194
|
|
|
@@ -237,7 +238,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
|
|
|
237
238
|
function normPrivateKeyToScalar(key: PrivKey): bigint {
|
|
238
239
|
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
|
|
239
240
|
if (lengths && typeof key !== 'bigint') {
|
|
240
|
-
if (key
|
|
241
|
+
if (ut.isBytes(key)) key = ut.bytesToHex(key);
|
|
241
242
|
// Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes
|
|
242
243
|
if (typeof key !== 'string' || !lengths.includes(key.length)) throw new Error('Invalid key');
|
|
243
244
|
key = key.padStart(nByteLength * 2, '0');
|
|
@@ -269,7 +270,11 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
|
|
|
269
270
|
static readonly BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE);
|
|
270
271
|
static readonly ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO);
|
|
271
272
|
|
|
272
|
-
constructor(
|
|
273
|
+
constructor(
|
|
274
|
+
readonly px: T,
|
|
275
|
+
readonly py: T,
|
|
276
|
+
readonly pz: T
|
|
277
|
+
) {
|
|
273
278
|
if (px == null || !Fp.isValid(px)) throw new Error('x required');
|
|
274
279
|
if (py == null || !Fp.isValid(py)) throw new Error('y required');
|
|
275
280
|
if (pz == null || !Fp.isValid(pz)) throw new Error('z required');
|
|
@@ -728,7 +733,13 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
728
733
|
const x = ut.bytesToNumberBE(tail);
|
|
729
734
|
if (!isValidFieldElement(x)) throw new Error('Point is not on curve');
|
|
730
735
|
const y2 = weierstrassEquation(x); // y² = x³ + ax + b
|
|
731
|
-
let y
|
|
736
|
+
let y: bigint;
|
|
737
|
+
try {
|
|
738
|
+
y = Fp.sqrt(y2); // y = y² ^ (p+1)/4
|
|
739
|
+
} catch (sqrtError) {
|
|
740
|
+
const suffix = sqrtError instanceof Error ? ': ' + sqrtError.message : '';
|
|
741
|
+
throw new Error('Point is not on curve' + suffix);
|
|
742
|
+
}
|
|
732
743
|
const isYOdd = (y & _1n) === _1n;
|
|
733
744
|
// ECDSA
|
|
734
745
|
const isHeadOdd = (head & 1) === 1;
|
|
@@ -763,7 +774,11 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
763
774
|
* ECDSA signature with its (r, s) properties. Supports DER & compact representations.
|
|
764
775
|
*/
|
|
765
776
|
class Signature implements SignatureType {
|
|
766
|
-
constructor(
|
|
777
|
+
constructor(
|
|
778
|
+
readonly r: bigint,
|
|
779
|
+
readonly s: bigint,
|
|
780
|
+
readonly recovery?: number
|
|
781
|
+
) {
|
|
767
782
|
this.assertValidity();
|
|
768
783
|
}
|
|
769
784
|
|
|
@@ -884,7 +899,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
884
899
|
* Quick and dirty check for item being public key. Does not validate hex, or being on-curve.
|
|
885
900
|
*/
|
|
886
901
|
function isProbPub(item: PrivKey | PubKey): boolean {
|
|
887
|
-
const arr = item
|
|
902
|
+
const arr = ut.isBytes(item);
|
|
888
903
|
const str = typeof item === 'string';
|
|
889
904
|
const len = (arr || str) && (item as Hex).length;
|
|
890
905
|
if (arr) return len === compressedLen || len === uncompressedLen;
|
|
@@ -962,7 +977,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
962
977
|
const d = normPrivateKeyToScalar(privateKey); // validate private key, convert to bigint
|
|
963
978
|
const seedArgs = [int2octets(d), int2octets(h1int)];
|
|
964
979
|
// extraEntropy. RFC6979 3.6: additional k' (optional).
|
|
965
|
-
if (ent != null) {
|
|
980
|
+
if (ent != null && ent !== false) {
|
|
966
981
|
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
|
|
967
982
|
const e = ent === true ? randomBytes(Fp.BYTES) : ent; // generate random bytes OR pass as-is
|
|
968
983
|
seedArgs.push(ensureBytes('extraEntropy', e)); // check for being bytes
|
|
@@ -1048,7 +1063,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
1048
1063
|
let _sig: Signature | undefined = undefined;
|
|
1049
1064
|
let P: ProjPointType<bigint>;
|
|
1050
1065
|
try {
|
|
1051
|
-
if (typeof sg === 'string' || sg
|
|
1066
|
+
if (typeof sg === 'string' || ut.isBytes(sg)) {
|
|
1052
1067
|
// Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length).
|
|
1053
1068
|
// Since DER can also be 2*nByteLength bytes, we check for it first.
|
|
1054
1069
|
try {
|