@noble/curves 1.8.0 → 1.8.2
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 +282 -419
- package/_shortw_utils.d.ts +2 -2
- package/_shortw_utils.d.ts.map +1 -1
- package/_shortw_utils.js +2 -2
- package/_shortw_utils.js.map +1 -1
- package/abstract/bls.d.ts +5 -5
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +14 -15
- package/abstract/bls.js.map +1 -1
- package/abstract/curve.d.ts +10 -2
- package/abstract/curve.d.ts.map +1 -1
- package/abstract/curve.js +81 -78
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.d.ts +2 -2
- package/abstract/edwards.d.ts.map +1 -1
- package/abstract/edwards.js +55 -69
- package/abstract/edwards.js.map +1 -1
- package/abstract/hash-to-curve.d.ts +5 -4
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +20 -18
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.d.ts.map +1 -1
- package/abstract/modular.js +9 -9
- package/abstract/montgomery.js +12 -12
- package/abstract/poseidon.d.ts +1 -1
- package/abstract/poseidon.d.ts.map +1 -1
- package/abstract/poseidon.js +3 -3
- package/abstract/poseidon.js.map +1 -1
- package/abstract/tower.d.ts +2 -2
- package/abstract/tower.js +13 -13
- package/abstract/utils.d.ts +4 -2
- package/abstract/utils.d.ts.map +1 -1
- package/abstract/utils.js +25 -14
- package/abstract/utils.js.map +1 -1
- package/abstract/weierstrass.d.ts +19 -6
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +97 -80
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts +1 -1
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +48 -49
- package/bls12-381.js.map +1 -1
- package/bn254.d.ts +2 -2
- package/bn254.d.ts.map +1 -1
- package/bn254.js +29 -30
- package/bn254.js.map +1 -1
- package/ed25519.d.ts +8 -6
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +65 -66
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +6 -6
- package/ed448.d.ts.map +1 -1
- package/ed448.js +50 -52
- package/ed448.js.map +1 -1
- package/esm/_shortw_utils.d.ts +2 -2
- package/esm/_shortw_utils.d.ts.map +1 -1
- package/esm/_shortw_utils.js +1 -1
- package/esm/_shortw_utils.js.map +1 -1
- package/esm/abstract/bls.d.ts +5 -5
- package/esm/abstract/bls.d.ts.map +1 -1
- package/esm/abstract/bls.js +5 -6
- package/esm/abstract/bls.js.map +1 -1
- package/esm/abstract/curve.d.ts +10 -2
- package/esm/abstract/curve.d.ts.map +1 -1
- package/esm/abstract/curve.js +77 -74
- package/esm/abstract/curve.js.map +1 -1
- package/esm/abstract/edwards.d.ts +2 -2
- package/esm/abstract/edwards.d.ts.map +1 -1
- package/esm/abstract/edwards.js +36 -50
- package/esm/abstract/edwards.js.map +1 -1
- package/esm/abstract/hash-to-curve.d.ts +5 -4
- package/esm/abstract/hash-to-curve.d.ts.map +1 -1
- package/esm/abstract/hash-to-curve.js +4 -2
- package/esm/abstract/hash-to-curve.js.map +1 -1
- package/esm/abstract/modular.d.ts.map +1 -1
- package/esm/abstract/modular.js +1 -1
- package/esm/abstract/montgomery.js +2 -2
- package/esm/abstract/poseidon.d.ts +1 -1
- package/esm/abstract/poseidon.d.ts.map +1 -1
- package/esm/abstract/poseidon.js +1 -1
- package/esm/abstract/poseidon.js.map +1 -1
- package/esm/abstract/tower.d.ts +2 -2
- package/esm/abstract/tower.js +5 -5
- package/esm/abstract/utils.d.ts +4 -2
- package/esm/abstract/utils.d.ts.map +1 -1
- package/esm/abstract/utils.js +24 -13
- package/esm/abstract/utils.js.map +1 -1
- package/esm/abstract/weierstrass.d.ts +19 -6
- package/esm/abstract/weierstrass.d.ts.map +1 -1
- package/esm/abstract/weierstrass.js +77 -60
- package/esm/abstract/weierstrass.js.map +1 -1
- package/esm/bls12-381.d.ts +1 -1
- package/esm/bls12-381.d.ts.map +1 -1
- package/esm/bls12-381.js +16 -17
- package/esm/bls12-381.js.map +1 -1
- package/esm/bn254.d.ts +2 -2
- package/esm/bn254.d.ts.map +1 -1
- package/esm/bn254.js +7 -8
- package/esm/bn254.js.map +1 -1
- package/esm/ed25519.d.ts +8 -6
- package/esm/ed25519.d.ts.map +1 -1
- package/esm/ed25519.js +20 -21
- package/esm/ed25519.js.map +1 -1
- package/esm/ed448.d.ts +6 -6
- package/esm/ed448.d.ts.map +1 -1
- package/esm/ed448.js +13 -15
- package/esm/ed448.js.map +1 -1
- package/esm/index.js +13 -1
- package/esm/index.js.map +1 -1
- package/esm/jubjub.d.ts +1 -4
- package/esm/jubjub.d.ts.map +1 -1
- package/esm/jubjub.js +1 -60
- package/esm/jubjub.js.map +1 -1
- package/esm/misc.d.ts +15 -0
- package/esm/misc.d.ts.map +1 -0
- package/esm/misc.js +101 -0
- package/esm/misc.js.map +1 -0
- package/esm/p256.d.ts +8 -5
- package/esm/p256.d.ts.map +1 -1
- package/esm/p256.js +13 -12
- package/esm/p256.js.map +1 -1
- package/esm/p384.d.ts +8 -5
- package/esm/p384.d.ts.map +1 -1
- package/esm/p384.js +14 -15
- package/esm/p384.js.map +1 -1
- package/esm/p521.d.ts +6 -5
- package/esm/p521.d.ts.map +1 -1
- package/esm/p521.js +19 -28
- package/esm/p521.js.map +1 -1
- package/esm/pasta.d.ts +1 -7
- package/esm/pasta.d.ts.map +1 -1
- package/esm/pasta.js +1 -33
- package/esm/pasta.js.map +1 -1
- package/esm/secp256k1.d.ts +15 -10
- package/esm/secp256k1.d.ts.map +1 -1
- package/esm/secp256k1.js +18 -14
- package/esm/secp256k1.js.map +1 -1
- package/index.js +13 -1
- package/index.js.map +1 -1
- package/jubjub.d.ts +1 -4
- package/jubjub.d.ts.map +1 -1
- package/jubjub.js +5 -63
- package/jubjub.js.map +1 -1
- package/misc.d.ts +15 -0
- package/misc.d.ts.map +1 -0
- package/misc.js +106 -0
- package/misc.js.map +1 -0
- package/p256.d.ts +8 -5
- package/p256.d.ts.map +1 -1
- package/p256.js +19 -18
- package/p256.js.map +1 -1
- package/p384.d.ts +8 -5
- package/p384.d.ts.map +1 -1
- package/p384.js +19 -20
- package/p384.js.map +1 -1
- package/p521.d.ts +6 -5
- package/p521.d.ts.map +1 -1
- package/p521.js +23 -32
- package/p521.js.map +1 -1
- package/package.json +21 -16
- package/pasta.d.ts +1 -7
- package/pasta.d.ts.map +1 -1
- package/pasta.js +4 -34
- package/pasta.js.map +1 -1
- package/secp256k1.d.ts +15 -10
- package/secp256k1.d.ts.map +1 -1
- package/secp256k1.js +57 -53
- package/secp256k1.js.map +1 -1
- package/src/_shortw_utils.ts +2 -2
- package/src/abstract/bls.ts +14 -12
- package/src/abstract/curve.ts +88 -79
- package/src/abstract/edwards.ts +52 -59
- package/src/abstract/hash-to-curve.ts +7 -5
- package/src/abstract/modular.ts +1 -1
- package/src/abstract/montgomery.ts +2 -2
- package/src/abstract/poseidon.ts +1 -1
- package/src/abstract/tower.ts +6 -6
- package/src/abstract/utils.ts +26 -15
- package/src/abstract/weierstrass.ts +99 -77
- package/src/bls12-381.ts +30 -28
- package/src/bn254.ts +11 -13
- package/src/ed25519.ts +27 -26
- package/src/ed448.ts +21 -20
- package/src/index.ts +13 -1
- package/src/jubjub.ts +5 -63
- package/src/misc.ts +117 -0
- package/src/p256.ts +13 -12
- package/src/p384.ts +18 -15
- package/src/p521.ts +27 -32
- package/src/pasta.ts +1 -39
- package/src/secp256k1.ts +20 -16
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Short Weierstrass curve methods. The formula is: y² = x³ + ax + b.
|
|
3
3
|
*
|
|
4
|
+
* ### Parameters
|
|
5
|
+
*
|
|
6
|
+
* To initialize a weierstrass curve, one needs to pass following params:
|
|
7
|
+
*
|
|
8
|
+
* * a: formula param
|
|
9
|
+
* * b: formula param
|
|
10
|
+
* * Fp: finite Field over which we'll do calculations. Can be complex (Fp2, Fp12)
|
|
11
|
+
* * n: Curve prime subgroup order, total count of valid points in the field
|
|
12
|
+
* * Gx: Base point (x, y) aka generator point x coordinate
|
|
13
|
+
* * Gy: ...y coordinate
|
|
14
|
+
* * h: cofactor, usually 1. h*n = curve group order (n is only subgroup order)
|
|
15
|
+
* * lowS: whether to enable (default) or disable "low-s" non-malleable signatures
|
|
16
|
+
*
|
|
4
17
|
* ### Design rationale for types
|
|
5
18
|
*
|
|
6
19
|
* * Interaction between classes from different curves should fail:
|
|
@@ -25,18 +38,23 @@
|
|
|
25
38
|
* @module
|
|
26
39
|
*/
|
|
27
40
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
41
|
+
// prettier-ignore
|
|
28
42
|
import {
|
|
29
|
-
AffinePoint,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
import
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
type AffinePoint, type BasicCurve, type Group, type GroupConstructor,
|
|
44
|
+
pippenger, validateBasic, wNAF,
|
|
45
|
+
} from './curve.ts';
|
|
46
|
+
// prettier-ignore
|
|
47
|
+
import {
|
|
48
|
+
Field, type IField, getMinHashLength, invert, mapHashToField, mod, validateField,
|
|
49
|
+
} from './modular.ts';
|
|
50
|
+
// prettier-ignore
|
|
51
|
+
import {
|
|
52
|
+
type CHash, type Hex, type PrivKey,
|
|
53
|
+
aInRange, abool,
|
|
54
|
+
bitMask,
|
|
55
|
+
bytesToHex, bytesToNumberBE, concatBytes, createHmacDrbg, ensureBytes, hexToBytes,
|
|
56
|
+
inRange, isBytes, memoized, numberToBytesBE, numberToHexUnpadded, validateObject
|
|
57
|
+
} from './utils.ts';
|
|
40
58
|
|
|
41
59
|
export type { AffinePoint };
|
|
42
60
|
type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
|
@@ -60,7 +78,7 @@ export type BasicWCurve<T> = BasicCurve<T> & {
|
|
|
60
78
|
clearCofactor?: (c: ProjConstructor<T>, point: ProjPointType<T>) => ProjPointType<T>;
|
|
61
79
|
};
|
|
62
80
|
|
|
63
|
-
type Entropy = Hex | boolean;
|
|
81
|
+
export type Entropy = Hex | boolean;
|
|
64
82
|
export type SignOpts = { lowS?: boolean; extraEntropy?: Entropy; prehash?: boolean };
|
|
65
83
|
export type VerOpts = { lowS?: boolean; prehash?: boolean; format?: 'compact' | 'der' | undefined };
|
|
66
84
|
|
|
@@ -111,7 +129,7 @@ export type CurvePointsTypeWithLength<T> = Readonly<
|
|
|
111
129
|
|
|
112
130
|
function validatePointOpts<T>(curve: CurvePointsType<T>): CurvePointsTypeWithLength<T> {
|
|
113
131
|
const opts = validateBasic(curve);
|
|
114
|
-
|
|
132
|
+
validateObject(
|
|
115
133
|
opts,
|
|
116
134
|
{
|
|
117
135
|
a: 'field',
|
|
@@ -151,8 +169,6 @@ export type CurvePointsRes<T> = {
|
|
|
151
169
|
isWithinCurveOrder: (num: bigint) => boolean;
|
|
152
170
|
};
|
|
153
171
|
|
|
154
|
-
const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;
|
|
155
|
-
|
|
156
172
|
export class DERErr extends Error {
|
|
157
173
|
constructor(m = '') {
|
|
158
174
|
super(m);
|
|
@@ -195,11 +211,11 @@ export const DER: IDER = {
|
|
|
195
211
|
if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag');
|
|
196
212
|
if (data.length & 1) throw new E('tlv.encode: unpadded data');
|
|
197
213
|
const dataLen = data.length / 2;
|
|
198
|
-
const len =
|
|
214
|
+
const len = numberToHexUnpadded(dataLen);
|
|
199
215
|
if ((len.length / 2) & 0b1000_0000) throw new E('tlv.encode: long form length too big');
|
|
200
216
|
// length of length with long form flag
|
|
201
|
-
const lenLen = dataLen > 127 ?
|
|
202
|
-
const t =
|
|
217
|
+
const lenLen = dataLen > 127 ? numberToHexUnpadded((len.length / 2) | 0b1000_0000) : '';
|
|
218
|
+
const t = numberToHexUnpadded(tag);
|
|
203
219
|
return t + lenLen + len + data;
|
|
204
220
|
},
|
|
205
221
|
// v - value, l - left bytes (unparsed)
|
|
@@ -237,7 +253,7 @@ export const DER: IDER = {
|
|
|
237
253
|
encode(num: bigint): string {
|
|
238
254
|
const { Err: E } = DER;
|
|
239
255
|
if (num < _0n) throw new E('integer: negative integers are not allowed');
|
|
240
|
-
let hex =
|
|
256
|
+
let hex = numberToHexUnpadded(num);
|
|
241
257
|
// Pad with zero byte if negative flag is present
|
|
242
258
|
if (Number.parseInt(hex[0], 16) & 0b1000) hex = '00' + hex;
|
|
243
259
|
if (hex.length & 1) throw new E('unexpected DER parsing assertion: unpadded hex');
|
|
@@ -248,14 +264,13 @@ export const DER: IDER = {
|
|
|
248
264
|
if (data[0] & 0b1000_0000) throw new E('invalid signature integer: negative');
|
|
249
265
|
if (data[0] === 0x00 && !(data[1] & 0b1000_0000))
|
|
250
266
|
throw new E('invalid signature integer: unnecessary leading zero');
|
|
251
|
-
return
|
|
267
|
+
return bytesToNumberBE(data);
|
|
252
268
|
},
|
|
253
269
|
},
|
|
254
270
|
toSig(hex: string | Uint8Array): { r: bigint; s: bigint } {
|
|
255
271
|
// parse DER signature
|
|
256
272
|
const { Err: E, _int: int, _tlv: tlv } = DER;
|
|
257
|
-
const data =
|
|
258
|
-
ut.abytes(data);
|
|
273
|
+
const data = ensureBytes('signature', hex);
|
|
259
274
|
const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data);
|
|
260
275
|
if (seqLeftBytes.length) throw new E('invalid signature: left bytes after parsing');
|
|
261
276
|
const { v: rBytes, l: rLeftBytes } = tlv.decode(0x02, seqBytes);
|
|
@@ -279,13 +294,13 @@ const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n =
|
|
|
279
294
|
export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T> {
|
|
280
295
|
const CURVE = validatePointOpts(opts);
|
|
281
296
|
const { Fp } = CURVE; // All curves has same field / group length as for now, but they can differ
|
|
282
|
-
const Fn =
|
|
297
|
+
const Fn = Field(CURVE.n, CURVE.nBitLength);
|
|
283
298
|
|
|
284
299
|
const toBytes =
|
|
285
300
|
CURVE.toBytes ||
|
|
286
301
|
((_c: ProjConstructor<T>, point: ProjPointType<T>, _isCompressed: boolean) => {
|
|
287
302
|
const a = point.toAffine();
|
|
288
|
-
return
|
|
303
|
+
return concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y));
|
|
289
304
|
});
|
|
290
305
|
const fromBytes =
|
|
291
306
|
CURVE.fromBytes ||
|
|
@@ -299,7 +314,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
299
314
|
});
|
|
300
315
|
|
|
301
316
|
/**
|
|
302
|
-
* y² = x³ + ax + b: Short weierstrass curve formula
|
|
317
|
+
* y² = x³ + ax + b: Short weierstrass curve formula. Takes x, returns y².
|
|
303
318
|
* @returns y²
|
|
304
319
|
*/
|
|
305
320
|
function weierstrassEquation(x: T): T {
|
|
@@ -317,14 +332,14 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
317
332
|
|
|
318
333
|
// Valid group elements reside in range 1..n-1
|
|
319
334
|
function isWithinCurveOrder(num: bigint): boolean {
|
|
320
|
-
return
|
|
335
|
+
return inRange(num, _1n, CURVE.n);
|
|
321
336
|
}
|
|
322
337
|
// Validates if priv key is valid and converts it to bigint.
|
|
323
338
|
// Supports options allowedPrivateKeyLengths and wrapPrivateKey.
|
|
324
339
|
function normPrivateKeyToScalar(key: PrivKey): bigint {
|
|
325
340
|
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n: N } = CURVE;
|
|
326
341
|
if (lengths && typeof key !== 'bigint') {
|
|
327
|
-
if (
|
|
342
|
+
if (isBytes(key)) key = bytesToHex(key);
|
|
328
343
|
// Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes
|
|
329
344
|
if (typeof key !== 'string' || !lengths.includes(key.length))
|
|
330
345
|
throw new Error('invalid private key');
|
|
@@ -335,18 +350,18 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
335
350
|
num =
|
|
336
351
|
typeof key === 'bigint'
|
|
337
352
|
? key
|
|
338
|
-
:
|
|
353
|
+
: bytesToNumberBE(ensureBytes('private key', key, nByteLength));
|
|
339
354
|
} catch (error) {
|
|
340
355
|
throw new Error(
|
|
341
356
|
'invalid private key, expected hex or ' + nByteLength + ' bytes, got ' + typeof key
|
|
342
357
|
);
|
|
343
358
|
}
|
|
344
|
-
if (wrapPrivateKey) num = mod
|
|
345
|
-
|
|
359
|
+
if (wrapPrivateKey) num = mod(num, N); // disabled by default, enabled for BLS
|
|
360
|
+
aInRange('private key', num, _1n, N); // num in range [1..N-1]
|
|
346
361
|
return num;
|
|
347
362
|
}
|
|
348
363
|
|
|
349
|
-
function
|
|
364
|
+
function aprjpoint(other: unknown) {
|
|
350
365
|
if (!(other instanceof Point)) throw new Error('ProjectivePoint expected');
|
|
351
366
|
}
|
|
352
367
|
|
|
@@ -399,15 +414,17 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
399
414
|
class Point implements ProjPointType<T> {
|
|
400
415
|
static readonly BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE);
|
|
401
416
|
static readonly ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO);
|
|
417
|
+
readonly px: T;
|
|
418
|
+
readonly py: T;
|
|
419
|
+
readonly pz: T;
|
|
402
420
|
|
|
403
|
-
constructor(
|
|
404
|
-
readonly px: T,
|
|
405
|
-
readonly py: T,
|
|
406
|
-
readonly pz: T
|
|
407
|
-
) {
|
|
421
|
+
constructor(px: T, py: T, pz: T) {
|
|
408
422
|
if (px == null || !Fp.isValid(px)) throw new Error('x required');
|
|
409
423
|
if (py == null || !Fp.isValid(py)) throw new Error('y required');
|
|
410
424
|
if (pz == null || !Fp.isValid(pz)) throw new Error('z required');
|
|
425
|
+
this.px = px;
|
|
426
|
+
this.py = py;
|
|
427
|
+
this.pz = pz;
|
|
411
428
|
Object.freeze(this);
|
|
412
429
|
}
|
|
413
430
|
|
|
@@ -481,7 +498,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
481
498
|
* Compare one point to another.
|
|
482
499
|
*/
|
|
483
500
|
equals(other: Point): boolean {
|
|
484
|
-
|
|
501
|
+
aprjpoint(other);
|
|
485
502
|
const { px: X1, py: Y1, pz: Z1 } = this;
|
|
486
503
|
const { px: X2, py: Y2, pz: Z2 } = other;
|
|
487
504
|
const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1));
|
|
@@ -544,7 +561,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
544
561
|
// https://eprint.iacr.org/2015/1060, algorithm 1
|
|
545
562
|
// Cost: 12M + 0S + 3*a + 3*b3 + 23add.
|
|
546
563
|
add(other: Point): Point {
|
|
547
|
-
|
|
564
|
+
aprjpoint(other);
|
|
548
565
|
const { px: X1, py: Y1, pz: Z1 } = this;
|
|
549
566
|
const { px: X2, py: Y2, pz: Z2 } = other;
|
|
550
567
|
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
|
|
@@ -611,7 +628,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
611
628
|
*/
|
|
612
629
|
multiplyUnsafe(sc: bigint): Point {
|
|
613
630
|
const { endo, n: N } = CURVE;
|
|
614
|
-
|
|
631
|
+
aInRange('scalar', sc, _0n, N);
|
|
615
632
|
const I = Point.ZERO;
|
|
616
633
|
if (sc === _0n) return I;
|
|
617
634
|
if (this.is0() || sc === _1n) return this;
|
|
@@ -649,7 +666,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
649
666
|
*/
|
|
650
667
|
multiply(scalar: bigint): Point {
|
|
651
668
|
const { endo, n: N } = CURVE;
|
|
652
|
-
|
|
669
|
+
aInRange('scalar', scalar, _1n, N);
|
|
653
670
|
let point: Point, fake: Point; // Fake point is used to const-time mult
|
|
654
671
|
if (endo) {
|
|
655
672
|
const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar);
|
|
@@ -712,7 +729,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
712
729
|
|
|
713
730
|
toHex(isCompressed = true): string {
|
|
714
731
|
abool('isCompressed', isCompressed);
|
|
715
|
-
return
|
|
732
|
+
return bytesToHex(this.toRawBytes(isCompressed));
|
|
716
733
|
}
|
|
717
734
|
}
|
|
718
735
|
const _bits = CURVE.nBitLength;
|
|
@@ -769,7 +786,7 @@ function validateOpts(
|
|
|
769
786
|
curve: CurveType
|
|
770
787
|
): Readonly<CurveType & { nByteLength: number; nBitLength: number }> {
|
|
771
788
|
const opts = validateBasic(curve);
|
|
772
|
-
|
|
789
|
+
validateObject(
|
|
773
790
|
opts,
|
|
774
791
|
{
|
|
775
792
|
hash: 'hash',
|
|
@@ -815,10 +832,10 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
815
832
|
const uncompressedLen = 2 * Fp.BYTES + 1; // e.g. 65 for 32
|
|
816
833
|
|
|
817
834
|
function modN(a: bigint) {
|
|
818
|
-
return mod
|
|
835
|
+
return mod(a, CURVE_ORDER);
|
|
819
836
|
}
|
|
820
837
|
function invN(a: bigint) {
|
|
821
|
-
return
|
|
838
|
+
return invert(a, CURVE_ORDER);
|
|
822
839
|
}
|
|
823
840
|
|
|
824
841
|
const {
|
|
@@ -831,7 +848,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
831
848
|
toBytes(_c, point, isCompressed: boolean): Uint8Array {
|
|
832
849
|
const a = point.toAffine();
|
|
833
850
|
const x = Fp.toBytes(a.x);
|
|
834
|
-
const cat =
|
|
851
|
+
const cat = concatBytes;
|
|
835
852
|
abool('isCompressed', isCompressed);
|
|
836
853
|
if (isCompressed) {
|
|
837
854
|
return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x);
|
|
@@ -845,8 +862,8 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
845
862
|
const tail = bytes.subarray(1);
|
|
846
863
|
// this.assertValidity() is done inside of fromHex
|
|
847
864
|
if (len === compressedLen && (head === 0x02 || head === 0x03)) {
|
|
848
|
-
const x =
|
|
849
|
-
if (!
|
|
865
|
+
const x = bytesToNumberBE(tail);
|
|
866
|
+
if (!inRange(x, _1n, Fp.ORDER)) throw new Error('Point is not on curve');
|
|
850
867
|
const y2 = weierstrassEquation(x); // y² = x³ + ax + b
|
|
851
868
|
let y: bigint;
|
|
852
869
|
try {
|
|
@@ -873,8 +890,8 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
873
890
|
}
|
|
874
891
|
},
|
|
875
892
|
});
|
|
876
|
-
const
|
|
877
|
-
|
|
893
|
+
const numToNByteHex = (num: bigint): string =>
|
|
894
|
+
bytesToHex(numberToBytesBE(num, CURVE.nByteLength));
|
|
878
895
|
|
|
879
896
|
function isBiggerThanHalfOrder(number: bigint) {
|
|
880
897
|
const HALF = CURVE_ORDER >> _1n;
|
|
@@ -885,18 +902,22 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
885
902
|
return isBiggerThanHalfOrder(s) ? modN(-s) : s;
|
|
886
903
|
}
|
|
887
904
|
// slice bytes num
|
|
888
|
-
const slcNum = (b: Uint8Array, from: number, to: number) =>
|
|
905
|
+
const slcNum = (b: Uint8Array, from: number, to: number) => bytesToNumberBE(b.slice(from, to));
|
|
889
906
|
|
|
890
907
|
/**
|
|
891
908
|
* ECDSA signature with its (r, s) properties. Supports DER & compact representations.
|
|
892
909
|
*/
|
|
893
910
|
class Signature implements SignatureType {
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
911
|
+
readonly r: bigint;
|
|
912
|
+
readonly s: bigint;
|
|
913
|
+
readonly recovery?: number;
|
|
914
|
+
constructor(r: bigint, s: bigint, recovery?: number) {
|
|
915
|
+
aInRange('r', r, _1n, CURVE_ORDER); // r in [1..N]
|
|
916
|
+
aInRange('s', s, _1n, CURVE_ORDER); // s in [1..N]
|
|
917
|
+
this.r = r;
|
|
918
|
+
this.s = s;
|
|
919
|
+
if (recovery != null) this.recovery = recovery;
|
|
920
|
+
Object.freeze(this);
|
|
900
921
|
}
|
|
901
922
|
|
|
902
923
|
// pair (bytes of r, bytes of s)
|
|
@@ -913,10 +934,11 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
913
934
|
return new Signature(r, s);
|
|
914
935
|
}
|
|
915
936
|
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
937
|
+
/**
|
|
938
|
+
* @todo remove
|
|
939
|
+
* @deprecated
|
|
940
|
+
*/
|
|
941
|
+
assertValidity(): void {}
|
|
920
942
|
|
|
921
943
|
addRecoveryBit(recovery: number): RecoveredSignature {
|
|
922
944
|
return new Signature(this.r, this.s, recovery) as RecoveredSignature;
|
|
@@ -929,7 +951,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
929
951
|
const radj = rec === 2 || rec === 3 ? r + CURVE.n : r;
|
|
930
952
|
if (radj >= Fp.ORDER) throw new Error('recovery id 2 or 3 invalid');
|
|
931
953
|
const prefix = (rec & 1) === 0 ? '02' : '03';
|
|
932
|
-
const R = Point.fromHex(prefix +
|
|
954
|
+
const R = Point.fromHex(prefix + numToNByteHex(radj));
|
|
933
955
|
const ir = invN(radj); // r^-1
|
|
934
956
|
const u1 = modN(-h * ir); // -hr^-1
|
|
935
957
|
const u2 = modN(s * ir); // sr^-1
|
|
@@ -950,7 +972,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
950
972
|
|
|
951
973
|
// DER-encoded
|
|
952
974
|
toDERRawBytes() {
|
|
953
|
-
return
|
|
975
|
+
return hexToBytes(this.toDERHex());
|
|
954
976
|
}
|
|
955
977
|
toDERHex() {
|
|
956
978
|
return DER.hexFromSig({ r: this.r, s: this.s });
|
|
@@ -958,10 +980,10 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
958
980
|
|
|
959
981
|
// padded bytes of r, then padded bytes of s
|
|
960
982
|
toCompactRawBytes() {
|
|
961
|
-
return
|
|
983
|
+
return hexToBytes(this.toCompactHex());
|
|
962
984
|
}
|
|
963
985
|
toCompactHex() {
|
|
964
|
-
return
|
|
986
|
+
return numToNByteHex(this.r) + numToNByteHex(this.s);
|
|
965
987
|
}
|
|
966
988
|
}
|
|
967
989
|
type RecoveredSignature = Signature & { recovery: number };
|
|
@@ -982,8 +1004,8 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
982
1004
|
* (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.
|
|
983
1005
|
*/
|
|
984
1006
|
randomPrivateKey: (): Uint8Array => {
|
|
985
|
-
const length =
|
|
986
|
-
return
|
|
1007
|
+
const length = getMinHashLength(CURVE.n);
|
|
1008
|
+
return mapHashToField(CURVE.randomBytes(length), CURVE.n);
|
|
987
1009
|
},
|
|
988
1010
|
|
|
989
1011
|
/**
|
|
@@ -1015,7 +1037,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
1015
1037
|
* Quick and dirty check for item being public key. Does not validate hex, or being on-curve.
|
|
1016
1038
|
*/
|
|
1017
1039
|
function isProbPub(item: PrivKey | PubKey): boolean {
|
|
1018
|
-
const arr =
|
|
1040
|
+
const arr = isBytes(item);
|
|
1019
1041
|
const str = typeof item === 'string';
|
|
1020
1042
|
const len = (arr || str) && (item as Hex).length;
|
|
1021
1043
|
if (arr) return len === compressedLen || len === uncompressedLen;
|
|
@@ -1052,7 +1074,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
1052
1074
|
if (bytes.length > 8192) throw new Error('input is too large');
|
|
1053
1075
|
// For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)
|
|
1054
1076
|
// for some cases, since bytes.length * 8 is not actual bitLength.
|
|
1055
|
-
const num =
|
|
1077
|
+
const num = bytesToNumberBE(bytes); // check for == u8 done here
|
|
1056
1078
|
const delta = bytes.length * 8 - CURVE.nBitLength; // truncate to nBitLength leftmost bits
|
|
1057
1079
|
return delta > 0 ? num >> BigInt(delta) : num;
|
|
1058
1080
|
};
|
|
@@ -1062,14 +1084,14 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
1062
1084
|
return modN(bits2int(bytes)); // can't use bytesToNumberBE here
|
|
1063
1085
|
};
|
|
1064
1086
|
// NOTE: pads output with zero as per spec
|
|
1065
|
-
const ORDER_MASK =
|
|
1087
|
+
const ORDER_MASK = bitMask(CURVE.nBitLength);
|
|
1066
1088
|
/**
|
|
1067
1089
|
* Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.
|
|
1068
1090
|
*/
|
|
1069
1091
|
function int2octets(num: bigint): Uint8Array {
|
|
1070
|
-
|
|
1092
|
+
aInRange('num < 2^' + CURVE.nBitLength, num, _0n, ORDER_MASK);
|
|
1071
1093
|
// works with order, can have different size than numToField!
|
|
1072
|
-
return
|
|
1094
|
+
return numberToBytesBE(num, CURVE.nByteLength);
|
|
1073
1095
|
}
|
|
1074
1096
|
|
|
1075
1097
|
// Steps A, D of RFC6979 3.2
|
|
@@ -1099,7 +1121,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
1099
1121
|
const e = ent === true ? randomBytes(Fp.BYTES) : ent; // generate random bytes OR pass as-is
|
|
1100
1122
|
seedArgs.push(ensureBytes('extraEntropy', e)); // check for being bytes
|
|
1101
1123
|
}
|
|
1102
|
-
const seed =
|
|
1124
|
+
const seed = concatBytes(...seedArgs); // Step D of RFC6979 3.2
|
|
1103
1125
|
const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!
|
|
1104
1126
|
// Converts signature params into point w r/s, checks result for validity.
|
|
1105
1127
|
function k2sig(kBytes: Uint8Array): RecoveredSignature | undefined {
|
|
@@ -1144,7 +1166,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
1144
1166
|
function sign(msgHash: Hex, privKey: PrivKey, opts = defaultSigOpts): RecoveredSignature {
|
|
1145
1167
|
const { seed, k2sig } = prepSig(msgHash, privKey, opts); // Steps A, D of RFC6979 3.2.
|
|
1146
1168
|
const C = CURVE;
|
|
1147
|
-
const drbg =
|
|
1169
|
+
const drbg = createHmacDrbg<RecoveredSignature>(C.hash.outputLen, C.nByteLength, C.hmac);
|
|
1148
1170
|
return drbg(seed, k2sig); // Steps B, C, D, E, F, G
|
|
1149
1171
|
}
|
|
1150
1172
|
|
|
@@ -1181,7 +1203,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
1181
1203
|
if ('strict' in opts) throw new Error('options.strict was renamed to lowS');
|
|
1182
1204
|
if (format !== undefined && format !== 'compact' && format !== 'der')
|
|
1183
1205
|
throw new Error('format must be compact or der');
|
|
1184
|
-
const isHex = typeof sg === 'string' ||
|
|
1206
|
+
const isHex = typeof sg === 'string' || isBytes(sg);
|
|
1185
1207
|
const isObj =
|
|
1186
1208
|
!isHex &&
|
|
1187
1209
|
!format &&
|
|
@@ -1245,7 +1267,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
1245
1267
|
* @returns
|
|
1246
1268
|
*/
|
|
1247
1269
|
export function SWUFpSqrtRatio<T>(
|
|
1248
|
-
Fp:
|
|
1270
|
+
Fp: IField<T>,
|
|
1249
1271
|
Z: T
|
|
1250
1272
|
): (u: T, v: T) => { isValid: boolean; value: T } {
|
|
1251
1273
|
// Generic implementation
|
|
@@ -1320,14 +1342,14 @@ export function SWUFpSqrtRatio<T>(
|
|
|
1320
1342
|
* https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2
|
|
1321
1343
|
*/
|
|
1322
1344
|
export function mapToCurveSimpleSWU<T>(
|
|
1323
|
-
Fp:
|
|
1345
|
+
Fp: IField<T>,
|
|
1324
1346
|
opts: {
|
|
1325
1347
|
A: T;
|
|
1326
1348
|
B: T;
|
|
1327
1349
|
Z: T;
|
|
1328
1350
|
}
|
|
1329
1351
|
): (u: T) => { x: T; y: T } {
|
|
1330
|
-
|
|
1352
|
+
validateField(Fp);
|
|
1331
1353
|
if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z))
|
|
1332
1354
|
throw new Error('mapToCurveSimpleSWU: invalid opts');
|
|
1333
1355
|
const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z);
|
package/src/bls12-381.ts
CHANGED
|
@@ -1,24 +1,3 @@
|
|
|
1
|
-
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
2
|
-
import { sha256 } from '@noble/hashes/sha256';
|
|
3
|
-
import { randomBytes } from '@noble/hashes/utils';
|
|
4
|
-
import { bls, CurveFn } from './abstract/bls.js';
|
|
5
|
-
import * as mod from './abstract/modular.js';
|
|
6
|
-
import {
|
|
7
|
-
bitGet,
|
|
8
|
-
bitLen,
|
|
9
|
-
bytesToHex,
|
|
10
|
-
bytesToNumberBE,
|
|
11
|
-
concatBytes as concatB,
|
|
12
|
-
ensureBytes,
|
|
13
|
-
Hex,
|
|
14
|
-
numberToBytesBE,
|
|
15
|
-
} from './abstract/utils.js';
|
|
16
|
-
// Types
|
|
17
|
-
import { isogenyMap } from './abstract/hash-to-curve.js';
|
|
18
|
-
import { AffinePoint, mapToCurveSimpleSWU, ProjPointType } from './abstract/weierstrass.js';
|
|
19
|
-
import { tower12, psiFrobenius } from './abstract/tower.js';
|
|
20
|
-
import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.js';
|
|
21
|
-
|
|
22
1
|
/**
|
|
23
2
|
* bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to:
|
|
24
3
|
* * Construct zk-SNARKs at the ~120-bit security
|
|
@@ -50,7 +29,7 @@ import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.js';
|
|
|
50
29
|
* 4. Compatible with specs:
|
|
51
30
|
* [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
|
|
52
31
|
* [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05),
|
|
53
|
-
*
|
|
32
|
+
* RFC 9380.
|
|
54
33
|
*
|
|
55
34
|
* ### Params
|
|
56
35
|
* To verify curve parameters, see
|
|
@@ -58,11 +37,6 @@ import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.js';
|
|
|
58
37
|
* Basic math is done over finite fields over p.
|
|
59
38
|
* More complicated math is done over polynominal extension fields.
|
|
60
39
|
* To simplify calculations in Fp12, we construct extension tower:
|
|
61
|
-
* - Fp₁₂ = Fp₆² => Fp₂³
|
|
62
|
-
* - Fp(u) / (u² - β) where β = -1
|
|
63
|
-
* - Fp₂(v) / (v³ - ξ) where ξ = u + 1
|
|
64
|
-
* - Fp₆(w) / (w² - γ) where γ = v
|
|
65
|
-
* Here goes constants && point encoding format
|
|
66
40
|
*
|
|
67
41
|
* Embedding degree (k): 12
|
|
68
42
|
* Seed (X): -15132376222941642752
|
|
@@ -73,6 +47,10 @@ import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.js';
|
|
|
73
47
|
* Ate loop size: X
|
|
74
48
|
*
|
|
75
49
|
* ### Towers
|
|
50
|
+
* - Fp₁₂ = Fp₆² => Fp₂³
|
|
51
|
+
* - Fp(u) / (u² - β) where β = -1
|
|
52
|
+
* - Fp₂(v) / (v³ - ξ) where ξ = u + 1
|
|
53
|
+
* - Fp₆(w) / (w² - γ) where γ = v
|
|
76
54
|
* - Fp²[u] = Fp/u²+1
|
|
77
55
|
* - Fp⁶[v] = Fp²/v³-1-u
|
|
78
56
|
* - Fp¹²[w] = Fp⁶/w²-v
|
|
@@ -80,6 +58,30 @@ import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.js';
|
|
|
80
58
|
* @todo construct bls & bn fp/fr from seed.
|
|
81
59
|
* @module
|
|
82
60
|
*/
|
|
61
|
+
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
62
|
+
import { sha256 } from '@noble/hashes/sha2';
|
|
63
|
+
import { randomBytes } from '@noble/hashes/utils';
|
|
64
|
+
import { bls, type CurveFn } from './abstract/bls.ts';
|
|
65
|
+
import { Field } from './abstract/modular.ts';
|
|
66
|
+
import {
|
|
67
|
+
bitGet,
|
|
68
|
+
bitLen,
|
|
69
|
+
bytesToHex,
|
|
70
|
+
bytesToNumberBE,
|
|
71
|
+
concatBytes as concatB,
|
|
72
|
+
ensureBytes,
|
|
73
|
+
type Hex,
|
|
74
|
+
numberToBytesBE,
|
|
75
|
+
} from './abstract/utils.ts';
|
|
76
|
+
// Types
|
|
77
|
+
import { isogenyMap } from './abstract/hash-to-curve.ts';
|
|
78
|
+
import type { Fp, Fp12, Fp2, Fp6 } from './abstract/tower.ts';
|
|
79
|
+
import { psiFrobenius, tower12 } from './abstract/tower.ts';
|
|
80
|
+
import {
|
|
81
|
+
type AffinePoint,
|
|
82
|
+
mapToCurveSimpleSWU,
|
|
83
|
+
type ProjPointType,
|
|
84
|
+
} from './abstract/weierstrass.ts';
|
|
83
85
|
|
|
84
86
|
// Be friendly to bad ECMAScript parsers by not using bigint literals
|
|
85
87
|
// prettier-ignore
|
|
@@ -162,7 +164,7 @@ const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({
|
|
|
162
164
|
|
|
163
165
|
// Finite field over r.
|
|
164
166
|
// This particular field is not used anywhere in bls12-381, but it is still useful.
|
|
165
|
-
const Fr =
|
|
167
|
+
const Fr = Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001'));
|
|
166
168
|
|
|
167
169
|
// END OF CURVE FIELDS
|
|
168
170
|
|
package/src/bn254.ts
CHANGED
|
@@ -45,24 +45,22 @@ Ate loop size: 6x+2
|
|
|
45
45
|
* @module
|
|
46
46
|
*/
|
|
47
47
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
48
|
-
import { sha256 } from '@noble/hashes/
|
|
49
|
-
import { getHash } from './_shortw_utils.js';
|
|
50
|
-
import { CurveFn, weierstrass } from './abstract/weierstrass.js';
|
|
48
|
+
import { sha256 } from '@noble/hashes/sha2';
|
|
51
49
|
import { randomBytes } from '@noble/hashes/utils';
|
|
50
|
+
import { getHash } from './_shortw_utils.ts';
|
|
52
51
|
import {
|
|
53
52
|
bls,
|
|
54
|
-
CurveFn as BLSCurveFn,
|
|
55
|
-
PostPrecomputeFn,
|
|
56
|
-
PostPrecomputePointAddFn,
|
|
57
|
-
} from './abstract/bls.
|
|
58
|
-
import { Field } from './abstract/modular.
|
|
59
|
-
import {
|
|
60
|
-
import {
|
|
61
|
-
|
|
62
|
-
import
|
|
53
|
+
type CurveFn as BLSCurveFn,
|
|
54
|
+
type PostPrecomputeFn,
|
|
55
|
+
type PostPrecomputePointAddFn,
|
|
56
|
+
} from './abstract/bls.ts';
|
|
57
|
+
import { Field } from './abstract/modular.ts';
|
|
58
|
+
import type { Fp, Fp12, Fp2, Fp6 } from './abstract/tower.ts';
|
|
59
|
+
import { psiFrobenius, tower12 } from './abstract/tower.ts';
|
|
60
|
+
import { bitGet, bitLen, notImplemented } from './abstract/utils.ts';
|
|
61
|
+
import { type CurveFn, weierstrass } from './abstract/weierstrass.ts';
|
|
63
62
|
// prettier-ignore
|
|
64
63
|
const _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
|
|
65
|
-
// prettier-ignore
|
|
66
64
|
const _6n = BigInt(6);
|
|
67
65
|
|
|
68
66
|
const BN_X = BigInt('4965661367192848881');
|