@noble/curves 1.6.0 → 1.7.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 +54 -22
- package/_shortw_utils.d.ts.map +1 -1
- package/abstract/bls.d.ts +7 -5
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +9 -9
- package/abstract/bls.js.map +1 -1
- package/abstract/curve.d.ts +29 -6
- package/abstract/curve.d.ts.map +1 -1
- package/abstract/curve.js +184 -41
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.d.ts +2 -0
- package/abstract/edwards.d.ts.map +1 -1
- package/abstract/edwards.js +20 -9
- package/abstract/edwards.js.map +1 -1
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +3 -4
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.d.ts.map +1 -1
- package/abstract/modular.js +32 -21
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +5 -3
- package/abstract/montgomery.js.map +1 -1
- package/abstract/poseidon.d.ts.map +1 -1
- package/abstract/poseidon.js +22 -22
- package/abstract/poseidon.js.map +1 -1
- package/abstract/tower.d.ts +1 -0
- package/abstract/tower.d.ts.map +1 -1
- package/abstract/tower.js +6 -6
- package/abstract/tower.js.map +1 -1
- package/abstract/utils.d.ts.map +1 -1
- package/abstract/utils.js +21 -23
- package/abstract/utils.js.map +1 -1
- package/abstract/weierstrass.d.ts +1 -0
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +54 -36
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.js +8 -8
- package/bn254.d.ts +2 -1
- package/bn254.d.ts.map +1 -1
- package/bn254.js +9 -7
- package/bn254.js.map +1 -1
- package/ed448.js +1 -1
- package/ed448.js.map +1 -1
- package/esm/_shortw_utils.d.ts.map +1 -1
- package/esm/abstract/bls.d.ts +7 -5
- package/esm/abstract/bls.d.ts.map +1 -1
- package/esm/abstract/bls.js +9 -9
- package/esm/abstract/bls.js.map +1 -1
- package/esm/abstract/curve.d.ts +29 -6
- package/esm/abstract/curve.d.ts.map +1 -1
- package/esm/abstract/curve.js +183 -41
- package/esm/abstract/curve.js.map +1 -1
- package/esm/abstract/edwards.d.ts +2 -0
- package/esm/abstract/edwards.d.ts.map +1 -1
- package/esm/abstract/edwards.js +20 -9
- package/esm/abstract/edwards.js.map +1 -1
- package/esm/abstract/hash-to-curve.d.ts.map +1 -1
- package/esm/abstract/hash-to-curve.js +3 -4
- package/esm/abstract/hash-to-curve.js.map +1 -1
- package/esm/abstract/modular.d.ts.map +1 -1
- package/esm/abstract/modular.js +32 -21
- package/esm/abstract/modular.js.map +1 -1
- package/esm/abstract/montgomery.d.ts.map +1 -1
- package/esm/abstract/montgomery.js +5 -3
- package/esm/abstract/montgomery.js.map +1 -1
- package/esm/abstract/poseidon.d.ts.map +1 -1
- package/esm/abstract/poseidon.js +22 -22
- package/esm/abstract/poseidon.js.map +1 -1
- package/esm/abstract/tower.d.ts +1 -0
- package/esm/abstract/tower.d.ts.map +1 -1
- package/esm/abstract/tower.js +6 -6
- package/esm/abstract/tower.js.map +1 -1
- package/esm/abstract/utils.d.ts.map +1 -1
- package/esm/abstract/utils.js +21 -23
- package/esm/abstract/utils.js.map +1 -1
- package/esm/abstract/weierstrass.d.ts +1 -0
- package/esm/abstract/weierstrass.d.ts.map +1 -1
- package/esm/abstract/weierstrass.js +54 -36
- package/esm/abstract/weierstrass.js.map +1 -1
- package/esm/bls12-381.js +8 -8
- package/esm/bn254.d.ts +2 -1
- package/esm/bn254.d.ts.map +1 -1
- package/esm/bn254.js +7 -6
- package/esm/bn254.js.map +1 -1
- package/esm/ed448.js +1 -1
- package/esm/ed448.js.map +1 -1
- package/esm/p256.d.ts.map +1 -1
- package/esm/p256.js +6 -6
- package/esm/p256.js.map +1 -1
- package/esm/p384.d.ts.map +1 -1
- package/esm/p384.js +6 -6
- package/esm/p384.js.map +1 -1
- package/esm/p521.d.ts.map +1 -1
- package/esm/p521.js +7 -7
- package/esm/p521.js.map +1 -1
- package/esm/secp256k1.d.ts.map +1 -1
- package/esm/secp256k1.js +8 -8
- package/esm/secp256k1.js.map +1 -1
- package/p256.d.ts.map +1 -1
- package/p256.js +6 -6
- package/p256.js.map +1 -1
- package/p384.d.ts.map +1 -1
- package/p384.js +6 -6
- package/p384.js.map +1 -1
- package/p521.d.ts.map +1 -1
- package/p521.js +7 -7
- package/p521.js.map +1 -1
- package/package.json +4 -3
- package/secp256k1.d.ts.map +1 -1
- package/secp256k1.js +8 -8
- package/secp256k1.js.map +1 -1
- package/src/abstract/bls.ts +25 -13
- package/src/abstract/curve.ts +188 -39
- package/src/abstract/edwards.ts +25 -10
- package/src/abstract/hash-to-curve.ts +2 -5
- package/src/abstract/modular.ts +29 -19
- package/src/abstract/montgomery.ts +5 -3
- package/src/abstract/poseidon.ts +20 -24
- package/src/abstract/tower.ts +7 -6
- package/src/abstract/utils.ts +18 -24
- package/src/abstract/weierstrass.ts +57 -35
- package/src/bls12-381.ts +9 -9
- package/src/bn254.ts +16 -7
- package/src/ed448.ts +1 -1
- package/src/p256.ts +6 -6
- package/src/p384.ts +6 -6
- package/src/p521.ts +7 -7
- package/src/secp256k1.ts +8 -8
|
@@ -37,7 +37,7 @@ export type BasicWCurve<T> = BasicCurve<T> & {
|
|
|
37
37
|
|
|
38
38
|
type Entropy = Hex | boolean;
|
|
39
39
|
export type SignOpts = { lowS?: boolean; extraEntropy?: Entropy; prehash?: boolean };
|
|
40
|
-
export type VerOpts = { lowS?: boolean; prehash?: boolean };
|
|
40
|
+
export type VerOpts = { lowS?: boolean; prehash?: boolean; format?: 'compact' | 'der' | undefined };
|
|
41
41
|
|
|
42
42
|
function validateSigVerOpts(opts: SignOpts | VerOpts) {
|
|
43
43
|
if (opts.lowS !== undefined) abool('lowS', opts.lowS);
|
|
@@ -123,14 +123,14 @@ function validatePointOpts<T>(curve: CurvePointsType<T>) {
|
|
|
123
123
|
const { endo, Fp, a } = opts;
|
|
124
124
|
if (endo) {
|
|
125
125
|
if (!Fp.eql(a, Fp.ZERO)) {
|
|
126
|
-
throw new Error('
|
|
126
|
+
throw new Error('invalid endomorphism, can only be defined for Koblitz curves that have a=0');
|
|
127
127
|
}
|
|
128
128
|
if (
|
|
129
129
|
typeof endo !== 'object' ||
|
|
130
130
|
typeof endo.beta !== 'bigint' ||
|
|
131
131
|
typeof endo.splitScalar !== 'function'
|
|
132
132
|
) {
|
|
133
|
-
throw new Error('
|
|
133
|
+
throw new Error('invalid endomorphism, expected beta: bigint and splitScalar: function');
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
return Object.freeze({ ...opts } as const);
|
|
@@ -171,7 +171,8 @@ export const DER = {
|
|
|
171
171
|
if ((len.length / 2) & 0b1000_0000) throw new E('tlv.encode: long form length too big');
|
|
172
172
|
// length of length with long form flag
|
|
173
173
|
const lenLen = dataLen > 127 ? ut.numberToHexUnpadded((len.length / 2) | 0b1000_0000) : '';
|
|
174
|
-
|
|
174
|
+
const t = ut.numberToHexUnpadded(tag);
|
|
175
|
+
return t + lenLen + len + data;
|
|
175
176
|
},
|
|
176
177
|
// v - value, l - left bytes (unparsed)
|
|
177
178
|
decode(tag: number, data: Uint8Array): { v: Uint8Array; l: Uint8Array } {
|
|
@@ -211,14 +212,14 @@ export const DER = {
|
|
|
211
212
|
let hex = ut.numberToHexUnpadded(num);
|
|
212
213
|
// Pad with zero byte if negative flag is present
|
|
213
214
|
if (Number.parseInt(hex[0], 16) & 0b1000) hex = '00' + hex;
|
|
214
|
-
if (hex.length & 1) throw new E('unexpected assertion');
|
|
215
|
+
if (hex.length & 1) throw new E('unexpected DER parsing assertion: unpadded hex');
|
|
215
216
|
return hex;
|
|
216
217
|
},
|
|
217
218
|
decode(data: Uint8Array): bigint {
|
|
218
219
|
const { Err: E } = DER;
|
|
219
|
-
if (data[0] & 0b1000_0000) throw new E('
|
|
220
|
+
if (data[0] & 0b1000_0000) throw new E('invalid signature integer: negative');
|
|
220
221
|
if (data[0] === 0x00 && !(data[1] & 0b1000_0000))
|
|
221
|
-
throw new E('
|
|
222
|
+
throw new E('invalid signature integer: unnecessary leading zero');
|
|
222
223
|
return b2n(data);
|
|
223
224
|
},
|
|
224
225
|
},
|
|
@@ -228,15 +229,17 @@ export const DER = {
|
|
|
228
229
|
const data = typeof hex === 'string' ? h2b(hex) : hex;
|
|
229
230
|
ut.abytes(data);
|
|
230
231
|
const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data);
|
|
231
|
-
if (seqLeftBytes.length) throw new E('
|
|
232
|
+
if (seqLeftBytes.length) throw new E('invalid signature: left bytes after parsing');
|
|
232
233
|
const { v: rBytes, l: rLeftBytes } = tlv.decode(0x02, seqBytes);
|
|
233
234
|
const { v: sBytes, l: sLeftBytes } = tlv.decode(0x02, rLeftBytes);
|
|
234
|
-
if (sLeftBytes.length) throw new E('
|
|
235
|
+
if (sLeftBytes.length) throw new E('invalid signature: left bytes after parsing');
|
|
235
236
|
return { r: int.decode(rBytes), s: int.decode(sBytes) };
|
|
236
237
|
},
|
|
237
238
|
hexFromSig(sig: { r: bigint; s: bigint }): string {
|
|
238
239
|
const { _tlv: tlv, _int: int } = DER;
|
|
239
|
-
const
|
|
240
|
+
const rs = tlv.encode(0x02, int.encode(sig.r));
|
|
241
|
+
const ss = tlv.encode(0x02, int.encode(sig.s));
|
|
242
|
+
const seq = rs + ss;
|
|
240
243
|
return tlv.encode(0x30, seq);
|
|
241
244
|
},
|
|
242
245
|
};
|
|
@@ -295,7 +298,8 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
295
298
|
if (lengths && typeof key !== 'bigint') {
|
|
296
299
|
if (ut.isBytes(key)) key = ut.bytesToHex(key);
|
|
297
300
|
// Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes
|
|
298
|
-
if (typeof key !== 'string' || !lengths.includes(key.length))
|
|
301
|
+
if (typeof key !== 'string' || !lengths.includes(key.length))
|
|
302
|
+
throw new Error('invalid private key');
|
|
299
303
|
key = key.padStart(nByteLength * 2, '0');
|
|
300
304
|
}
|
|
301
305
|
let num: bigint;
|
|
@@ -305,7 +309,9 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
305
309
|
? key
|
|
306
310
|
: ut.bytesToNumberBE(ensureBytes('private key', key, nByteLength));
|
|
307
311
|
} catch (error) {
|
|
308
|
-
throw new Error(
|
|
312
|
+
throw new Error(
|
|
313
|
+
'invalid private key, expected hex or ' + nByteLength + ' bytes, got ' + typeof key
|
|
314
|
+
);
|
|
309
315
|
}
|
|
310
316
|
if (wrapPrivateKey) num = mod.mod(num, N); // disabled by default, enabled for BLS
|
|
311
317
|
ut.aInRange('private key', num, _1n, N); // num in range [1..N-1]
|
|
@@ -342,7 +348,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
342
348
|
if (p.is0()) {
|
|
343
349
|
// (0, 1, 0) aka ZERO is invalid in most contexts.
|
|
344
350
|
// In BLS, ZERO can be serialized, so we allow it.
|
|
345
|
-
// (0, 0, 0) is
|
|
351
|
+
// (0, 0, 0) is invalid representation of ZERO.
|
|
346
352
|
if (CURVE.allowInfinityPoint && !Fp.is0(p.py)) return;
|
|
347
353
|
throw new Error('bad point: ZERO');
|
|
348
354
|
}
|
|
@@ -423,7 +429,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
423
429
|
}
|
|
424
430
|
|
|
425
431
|
// Multiscalar Multiplication
|
|
426
|
-
static msm(points: Point[], scalars: bigint[]) {
|
|
432
|
+
static msm(points: Point[], scalars: bigint[]): Point {
|
|
427
433
|
return pippenger(Point, Fn, points, scalars);
|
|
428
434
|
}
|
|
429
435
|
|
|
@@ -576,14 +582,17 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T
|
|
|
576
582
|
* an exposed private key e.g. sig verification, which works over *public* keys.
|
|
577
583
|
*/
|
|
578
584
|
multiplyUnsafe(sc: bigint): Point {
|
|
579
|
-
|
|
585
|
+
const { endo, n: N } = CURVE;
|
|
586
|
+
ut.aInRange('scalar', sc, _0n, N);
|
|
580
587
|
const I = Point.ZERO;
|
|
581
588
|
if (sc === _0n) return I;
|
|
582
|
-
if (sc === _1n) return this;
|
|
583
|
-
|
|
584
|
-
|
|
589
|
+
if (this.is0() || sc === _1n) return this;
|
|
590
|
+
|
|
591
|
+
// Case a: no endomorphism. Case b: has precomputes.
|
|
592
|
+
if (!endo || wnaf.hasPrecomputes(this))
|
|
593
|
+
return wnaf.wNAFCachedUnsafe(this, sc, Point.normalizeZ);
|
|
585
594
|
|
|
586
|
-
//
|
|
595
|
+
// Case c: endomorphism
|
|
587
596
|
let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc);
|
|
588
597
|
let k1p = I;
|
|
589
598
|
let k2p = I;
|
|
@@ -826,8 +835,10 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
826
835
|
const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));
|
|
827
836
|
return { x, y };
|
|
828
837
|
} else {
|
|
838
|
+
const cl = compressedLen;
|
|
839
|
+
const ul = uncompressedLen;
|
|
829
840
|
throw new Error(
|
|
830
|
-
|
|
841
|
+
'invalid Point, expected length of ' + cl + ', or uncompressed ' + ul + ', got ' + len
|
|
831
842
|
);
|
|
832
843
|
}
|
|
833
844
|
},
|
|
@@ -1007,6 +1018,8 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
1007
1018
|
const bits2int =
|
|
1008
1019
|
CURVE.bits2int ||
|
|
1009
1020
|
function (bytes: Uint8Array): bigint {
|
|
1021
|
+
// Our custom check "just in case"
|
|
1022
|
+
if (bytes.length > 8192) throw new Error('input is too large');
|
|
1010
1023
|
// For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)
|
|
1011
1024
|
// for some cases, since bytes.length * 8 is not actual bitLength.
|
|
1012
1025
|
const num = ut.bytesToNumberBE(bytes); // check for == u8 done here
|
|
@@ -1024,7 +1037,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
1024
1037
|
* Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.
|
|
1025
1038
|
*/
|
|
1026
1039
|
function int2octets(num: bigint): Uint8Array {
|
|
1027
|
-
ut.aInRange(
|
|
1040
|
+
ut.aInRange('num < 2^' + CURVE.nBitLength, num, _0n, ORDER_MASK);
|
|
1028
1041
|
// works with order, can have different size than numToField!
|
|
1029
1042
|
return ut.numberToBytesBE(num, CURVE.nByteLength);
|
|
1030
1043
|
}
|
|
@@ -1032,8 +1045,8 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
1032
1045
|
// Steps A, D of RFC6979 3.2
|
|
1033
1046
|
// Creates RFC6979 seed; converts msg/privKey to numbers.
|
|
1034
1047
|
// Used only in sign, not in verify.
|
|
1035
|
-
// NOTE: we cannot assume here that msgHash has same amount of bytes as curve order,
|
|
1036
|
-
// Also it can be bigger for P224 + SHA256
|
|
1048
|
+
// NOTE: we cannot assume here that msgHash has same amount of bytes as curve order,
|
|
1049
|
+
// this will be invalid at least for P521. Also it can be bigger for P224 + SHA256
|
|
1037
1050
|
function prepSig(msgHash: Hex, privateKey: PrivKey, opts = defaultSigOpts) {
|
|
1038
1051
|
if (['recovered', 'canonical'].some((k) => k in opts))
|
|
1039
1052
|
throw new Error('sign() legacy options not supported');
|
|
@@ -1131,34 +1144,43 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|
|
1131
1144
|
const sg = signature;
|
|
1132
1145
|
msgHash = ensureBytes('msgHash', msgHash);
|
|
1133
1146
|
publicKey = ensureBytes('publicKey', publicKey);
|
|
1134
|
-
|
|
1147
|
+
const { lowS, prehash, format } = opts;
|
|
1148
|
+
|
|
1149
|
+
// Verify opts, deduce signature format
|
|
1135
1150
|
validateSigVerOpts(opts);
|
|
1136
|
-
|
|
1151
|
+
if ('strict' in opts) throw new Error('options.strict was renamed to lowS');
|
|
1152
|
+
if (format !== undefined && format !== 'compact' && format !== 'der')
|
|
1153
|
+
throw new Error('format must be compact or der');
|
|
1154
|
+
const isHex = typeof sg === 'string' || ut.isBytes(sg);
|
|
1155
|
+
const isObj =
|
|
1156
|
+
!isHex &&
|
|
1157
|
+
!format &&
|
|
1158
|
+
typeof sg === 'object' &&
|
|
1159
|
+
sg !== null &&
|
|
1160
|
+
typeof sg.r === 'bigint' &&
|
|
1161
|
+
typeof sg.s === 'bigint';
|
|
1162
|
+
if (!isHex && !isObj)
|
|
1163
|
+
throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance');
|
|
1137
1164
|
|
|
1138
1165
|
let _sig: Signature | undefined = undefined;
|
|
1139
1166
|
let P: ProjPointType<bigint>;
|
|
1140
1167
|
try {
|
|
1141
|
-
if (
|
|
1168
|
+
if (isObj) _sig = new Signature(sg.r, sg.s);
|
|
1169
|
+
if (isHex) {
|
|
1142
1170
|
// Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length).
|
|
1143
1171
|
// Since DER can also be 2*nByteLength bytes, we check for it first.
|
|
1144
1172
|
try {
|
|
1145
|
-
_sig = Signature.fromDER(sg);
|
|
1173
|
+
if (format !== 'compact') _sig = Signature.fromDER(sg);
|
|
1146
1174
|
} catch (derError) {
|
|
1147
1175
|
if (!(derError instanceof DER.Err)) throw derError;
|
|
1148
|
-
_sig = Signature.fromCompact(sg);
|
|
1149
1176
|
}
|
|
1150
|
-
|
|
1151
|
-
const { r, s } = sg;
|
|
1152
|
-
_sig = new Signature(r, s);
|
|
1153
|
-
} else {
|
|
1154
|
-
throw new Error('PARSE');
|
|
1177
|
+
if (!_sig && format !== 'der') _sig = Signature.fromCompact(sg);
|
|
1155
1178
|
}
|
|
1156
1179
|
P = Point.fromHex(publicKey);
|
|
1157
1180
|
} catch (error) {
|
|
1158
|
-
if ((error as Error).message === 'PARSE')
|
|
1159
|
-
throw new Error(`signature must be Signature instance, Uint8Array or hex string`);
|
|
1160
1181
|
return false;
|
|
1161
1182
|
}
|
|
1183
|
+
if (!_sig) return false;
|
|
1162
1184
|
if (lowS && _sig.hasHighS()) return false;
|
|
1163
1185
|
if (prehash) msgHash = CURVE.hash(msgHash);
|
|
1164
1186
|
const { r, s } = _sig;
|
package/src/bls12-381.ts
CHANGED
|
@@ -56,7 +56,7 @@ bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction all
|
|
|
56
56
|
// prettier-ignore
|
|
57
57
|
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
|
|
58
58
|
|
|
59
|
-
/*
|
|
59
|
+
/*
|
|
60
60
|
Embedding degree (k): 12
|
|
61
61
|
Seed (X): -15132376222941642752
|
|
62
62
|
Fr: (x⁴-x²+1)
|
|
@@ -509,7 +509,7 @@ export const bls12_381: CurveFn = bls({
|
|
|
509
509
|
}
|
|
510
510
|
const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)); // y² = x³ + b
|
|
511
511
|
let y = Fp.sqrt(right);
|
|
512
|
-
if (!y) throw new Error('
|
|
512
|
+
if (!y) throw new Error('invalid compressed G1 point');
|
|
513
513
|
if ((y * _2n) / P !== BigInt(sort)) y = Fp.neg(y);
|
|
514
514
|
return { x: Fp.create(x), y: Fp.create(y) };
|
|
515
515
|
} else if (value.length === 96 && !compressed) {
|
|
@@ -522,7 +522,7 @@ export const bls12_381: CurveFn = bls({
|
|
|
522
522
|
}
|
|
523
523
|
return { x: Fp.create(x), y: Fp.create(y) };
|
|
524
524
|
} else {
|
|
525
|
-
throw new Error('
|
|
525
|
+
throw new Error('invalid point G1, expected 48/96 bytes');
|
|
526
526
|
}
|
|
527
527
|
},
|
|
528
528
|
toBytes: (c, point, isCompressed) => {
|
|
@@ -553,7 +553,7 @@ export const bls12_381: CurveFn = bls({
|
|
|
553
553
|
const x = Fp.create(compressedValue & Fp.MASK);
|
|
554
554
|
const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)); // y² = x³ + b
|
|
555
555
|
let y = Fp.sqrt(right);
|
|
556
|
-
if (!y) throw new Error('
|
|
556
|
+
if (!y) throw new Error('invalid compressed G1 point');
|
|
557
557
|
const aflag = BigInt(sort);
|
|
558
558
|
if ((y * _2n) / P !== aflag) y = Fp.neg(y);
|
|
559
559
|
const point = bls12_381.G1.ProjectivePoint.fromAffine({ x, y });
|
|
@@ -644,7 +644,7 @@ export const bls12_381: CurveFn = bls({
|
|
|
644
644
|
(!compressed && infinity && sort) || // 01100000
|
|
645
645
|
(sort && infinity && compressed) // 11100000
|
|
646
646
|
) {
|
|
647
|
-
throw new Error('
|
|
647
|
+
throw new Error('invalid encoding flag: ' + (bytes[0] & 0b1110_0000));
|
|
648
648
|
}
|
|
649
649
|
const L = Fp.BYTES;
|
|
650
650
|
const slc = (b: Uint8Array, from: number, to?: number) => bytesToNumberBE(b.slice(from, to));
|
|
@@ -654,7 +654,7 @@ export const bls12_381: CurveFn = bls({
|
|
|
654
654
|
if (infinity) {
|
|
655
655
|
// check that all bytes are 0
|
|
656
656
|
if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
|
|
657
|
-
throw new Error('
|
|
657
|
+
throw new Error('invalid compressed G2 point');
|
|
658
658
|
}
|
|
659
659
|
return { x: Fp2.ZERO, y: Fp2.ZERO };
|
|
660
660
|
}
|
|
@@ -669,7 +669,7 @@ export const bls12_381: CurveFn = bls({
|
|
|
669
669
|
} else if (value.length === 192 && !compressed) {
|
|
670
670
|
if (infinity) {
|
|
671
671
|
if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
|
|
672
|
-
throw new Error('
|
|
672
|
+
throw new Error('invalid uncompressed G2 point');
|
|
673
673
|
}
|
|
674
674
|
return { x: Fp2.ZERO, y: Fp2.ZERO };
|
|
675
675
|
}
|
|
@@ -679,7 +679,7 @@ export const bls12_381: CurveFn = bls({
|
|
|
679
679
|
const y0 = slc(value, 3 * L, 4 * L);
|
|
680
680
|
return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) };
|
|
681
681
|
} else {
|
|
682
|
-
throw new Error('
|
|
682
|
+
throw new Error('invalid point G2, expected 96/192 bytes');
|
|
683
683
|
}
|
|
684
684
|
},
|
|
685
685
|
toBytes: (c, point, isCompressed) => {
|
|
@@ -712,7 +712,7 @@ export const bls12_381: CurveFn = bls({
|
|
|
712
712
|
const P = Fp.ORDER;
|
|
713
713
|
const half = value.length / 2;
|
|
714
714
|
if (half !== 48 && half !== 96)
|
|
715
|
-
throw new Error('
|
|
715
|
+
throw new Error('invalid compressed signature length, must be 96 or 192');
|
|
716
716
|
const z1 = bytesToNumberBE(value.slice(0, half));
|
|
717
717
|
const z2 = bytesToNumberBE(value.slice(half));
|
|
718
718
|
// Indicates the infinity point
|
package/src/bn254.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { sha256 } from '@noble/hashes/sha256';
|
|
|
3
3
|
import { getHash } from './_shortw_utils.js';
|
|
4
4
|
import { weierstrass } from './abstract/weierstrass.js';
|
|
5
5
|
import { randomBytes } from '@noble/hashes/utils';
|
|
6
|
-
import { bls, CurveFn } from './abstract/bls.js';
|
|
6
|
+
import { bls, CurveFn, PostPrecomputeFn, PostPrecomputePointAddFn } from './abstract/bls.js';
|
|
7
7
|
import { Field } from './abstract/modular.js';
|
|
8
8
|
import { bitGet, bitLen, notImplemented } from './abstract/utils.js';
|
|
9
9
|
import { tower12, psiFrobenius } from './abstract/tower.js';
|
|
@@ -148,6 +148,20 @@ const htfDefaults = Object.freeze({
|
|
|
148
148
|
hash: sha256,
|
|
149
149
|
} as const);
|
|
150
150
|
|
|
151
|
+
export const _postPrecompute: PostPrecomputeFn = (
|
|
152
|
+
Rx: Fp2,
|
|
153
|
+
Ry: Fp2,
|
|
154
|
+
Rz: Fp2,
|
|
155
|
+
Qx: Fp2,
|
|
156
|
+
Qy: Fp2,
|
|
157
|
+
pointAdd: PostPrecomputePointAddFn
|
|
158
|
+
) => {
|
|
159
|
+
const q = psi(Qx, Qy);
|
|
160
|
+
({ Rx, Ry, Rz } = pointAdd(Rx, Ry, Rz, q[0], q[1]));
|
|
161
|
+
const q2 = psi(q[0], q[1]);
|
|
162
|
+
pointAdd(Rx, Ry, Rz, q2[0], Fp2.neg(q2[1]));
|
|
163
|
+
};
|
|
164
|
+
|
|
151
165
|
/**
|
|
152
166
|
* bn254 (a.k.a. alt_bn128) pairing-friendly curve.
|
|
153
167
|
* Contains G1 / G2 operations and pairings.
|
|
@@ -212,12 +226,7 @@ export const bn254: CurveFn = bls({
|
|
|
212
226
|
hash: sha256,
|
|
213
227
|
randomBytes,
|
|
214
228
|
|
|
215
|
-
postPrecompute:
|
|
216
|
-
const q = psi(Qx, Qy);
|
|
217
|
-
({ Rx, Ry, Rz } = pointAdd(Rx, Ry, Rz, q[0], q[1]));
|
|
218
|
-
const q2 = psi(q[0], q[1]);
|
|
219
|
-
pointAdd(Rx, Ry, Rz, q2[0], Fp2.neg(q2[1]));
|
|
220
|
-
},
|
|
229
|
+
postPrecompute: _postPrecompute,
|
|
221
230
|
});
|
|
222
231
|
|
|
223
232
|
/**
|
package/src/ed448.ts
CHANGED
|
@@ -120,7 +120,7 @@ const ED448_DEF = {
|
|
|
120
120
|
adjustScalarBytes,
|
|
121
121
|
// dom4
|
|
122
122
|
domain: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => {
|
|
123
|
-
if (ctx.length > 255) throw new Error(
|
|
123
|
+
if (ctx.length > 255) throw new Error('context must be smaller than 255, got: ' + ctx.length);
|
|
124
124
|
return concatBytes(
|
|
125
125
|
utf8ToBytes('SigEd448'),
|
|
126
126
|
new Uint8Array([phflag ? 1 : 0, ctx.length]),
|
package/src/p256.ts
CHANGED
|
@@ -8,15 +8,15 @@ import { mapToCurveSimpleSWU } from './abstract/weierstrass.js';
|
|
|
8
8
|
// NIST secp256r1 aka p256
|
|
9
9
|
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256
|
|
10
10
|
|
|
11
|
-
const
|
|
12
|
-
const CURVE_A =
|
|
11
|
+
const Fp256 = Field(BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'));
|
|
12
|
+
const CURVE_A = Fp256.create(BigInt('-3'));
|
|
13
13
|
const CURVE_B = BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b');
|
|
14
14
|
|
|
15
15
|
// prettier-ignore
|
|
16
16
|
export const p256 = createCurve({
|
|
17
17
|
a: CURVE_A, // Equation params: a, b
|
|
18
18
|
b: CURVE_B,
|
|
19
|
-
Fp, // Field: 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n
|
|
19
|
+
Fp: Fp256, // Field: 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n
|
|
20
20
|
// Curve order, total count of valid points in the field
|
|
21
21
|
n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),
|
|
22
22
|
// Base (generator) point (x, y)
|
|
@@ -28,17 +28,17 @@ export const p256 = createCurve({
|
|
|
28
28
|
export const secp256r1 = p256;
|
|
29
29
|
|
|
30
30
|
const mapSWU = /* @__PURE__ */ (() =>
|
|
31
|
-
mapToCurveSimpleSWU(
|
|
31
|
+
mapToCurveSimpleSWU(Fp256, {
|
|
32
32
|
A: CURVE_A,
|
|
33
33
|
B: CURVE_B,
|
|
34
|
-
Z:
|
|
34
|
+
Z: Fp256.create(BigInt('-10')),
|
|
35
35
|
}))();
|
|
36
36
|
|
|
37
37
|
const htf = /* @__PURE__ */ (() =>
|
|
38
38
|
createHasher(secp256r1.ProjectivePoint, (scalars: bigint[]) => mapSWU(scalars[0]), {
|
|
39
39
|
DST: 'P256_XMD:SHA-256_SSWU_RO_',
|
|
40
40
|
encodeDST: 'P256_XMD:SHA-256_SSWU_NU_',
|
|
41
|
-
p:
|
|
41
|
+
p: Fp256.ORDER,
|
|
42
42
|
m: 1,
|
|
43
43
|
k: 128,
|
|
44
44
|
expand: 'xmd',
|
package/src/p384.ts
CHANGED
|
@@ -11,8 +11,8 @@ import { mapToCurveSimpleSWU } from './abstract/weierstrass.js';
|
|
|
11
11
|
// Field over which we'll do calculations.
|
|
12
12
|
// prettier-ignore
|
|
13
13
|
const P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff');
|
|
14
|
-
const
|
|
15
|
-
const CURVE_A =
|
|
14
|
+
const Fp384 = Field(P);
|
|
15
|
+
const CURVE_A = Fp384.create(BigInt('-3'));
|
|
16
16
|
// prettier-ignore
|
|
17
17
|
const CURVE_B = BigInt('0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef');
|
|
18
18
|
|
|
@@ -20,7 +20,7 @@ const CURVE_B = BigInt('0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe814112031408
|
|
|
20
20
|
export const p384 = createCurve({
|
|
21
21
|
a: CURVE_A, // Equation params: a, b
|
|
22
22
|
b: CURVE_B,
|
|
23
|
-
Fp, // Field: 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
|
|
23
|
+
Fp: Fp384, // Field: 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
|
|
24
24
|
// Curve order, total count of valid points in the field.
|
|
25
25
|
n: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'),
|
|
26
26
|
// Base (generator) point (x, y)
|
|
@@ -32,17 +32,17 @@ export const p384 = createCurve({
|
|
|
32
32
|
export const secp384r1 = p384;
|
|
33
33
|
|
|
34
34
|
const mapSWU = /* @__PURE__ */ (() =>
|
|
35
|
-
mapToCurveSimpleSWU(
|
|
35
|
+
mapToCurveSimpleSWU(Fp384, {
|
|
36
36
|
A: CURVE_A,
|
|
37
37
|
B: CURVE_B,
|
|
38
|
-
Z:
|
|
38
|
+
Z: Fp384.create(BigInt('-12')),
|
|
39
39
|
}))();
|
|
40
40
|
|
|
41
41
|
const htf = /* @__PURE__ */ (() =>
|
|
42
42
|
createHasher(secp384r1.ProjectivePoint, (scalars: bigint[]) => mapSWU(scalars[0]), {
|
|
43
43
|
DST: 'P384_XMD:SHA-384_SSWU_RO_',
|
|
44
44
|
encodeDST: 'P384_XMD:SHA-384_SSWU_NU_',
|
|
45
|
-
p:
|
|
45
|
+
p: Fp384.ORDER,
|
|
46
46
|
m: 1,
|
|
47
47
|
k: 192,
|
|
48
48
|
expand: 'xmd',
|
package/src/p521.ts
CHANGED
|
@@ -12,14 +12,14 @@ import { mapToCurveSimpleSWU } from './abstract/weierstrass.js';
|
|
|
12
12
|
// Field over which we'll do calculations.
|
|
13
13
|
// prettier-ignore
|
|
14
14
|
const P = BigInt('0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
|
|
15
|
-
const
|
|
15
|
+
const Fp521 = Field(P);
|
|
16
16
|
|
|
17
17
|
const CURVE = {
|
|
18
|
-
a:
|
|
18
|
+
a: Fp521.create(BigInt('-3')),
|
|
19
19
|
b: BigInt(
|
|
20
20
|
'0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00'
|
|
21
21
|
),
|
|
22
|
-
Fp,
|
|
22
|
+
Fp: Fp521,
|
|
23
23
|
n: BigInt(
|
|
24
24
|
'0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409'
|
|
25
25
|
),
|
|
@@ -36,7 +36,7 @@ const CURVE = {
|
|
|
36
36
|
export const p521 = createCurve({
|
|
37
37
|
a: CURVE.a, // Equation params: a, b
|
|
38
38
|
b: CURVE.b,
|
|
39
|
-
Fp, // Field: 2n**521n - 1n
|
|
39
|
+
Fp: Fp521, // Field: 2n**521n - 1n
|
|
40
40
|
// Curve order, total count of valid points in the field
|
|
41
41
|
n: CURVE.n,
|
|
42
42
|
Gx: CURVE.Gx, // Base point (x, y) aka generator point
|
|
@@ -48,17 +48,17 @@ export const p521 = createCurve({
|
|
|
48
48
|
export const secp521r1 = p521;
|
|
49
49
|
|
|
50
50
|
const mapSWU = /* @__PURE__ */ (() =>
|
|
51
|
-
mapToCurveSimpleSWU(
|
|
51
|
+
mapToCurveSimpleSWU(Fp521, {
|
|
52
52
|
A: CURVE.a,
|
|
53
53
|
B: CURVE.b,
|
|
54
|
-
Z:
|
|
54
|
+
Z: Fp521.create(BigInt('-4')),
|
|
55
55
|
}))();
|
|
56
56
|
|
|
57
57
|
const htf = /* @__PURE__ */ (() =>
|
|
58
58
|
createHasher(secp521r1.ProjectivePoint, (scalars: bigint[]) => mapSWU(scalars[0]), {
|
|
59
59
|
DST: 'P521_XMD:SHA-512_SSWU_RO_',
|
|
60
60
|
encodeDST: 'P521_XMD:SHA-512_SSWU_NU_',
|
|
61
|
-
p:
|
|
61
|
+
p: Fp521.ORDER,
|
|
62
62
|
m: 1,
|
|
63
63
|
k: 256,
|
|
64
64
|
expand: 'xmd',
|
package/src/secp256k1.ts
CHANGED
|
@@ -45,11 +45,11 @@ function sqrtMod(y: bigint): bigint {
|
|
|
45
45
|
const t1 = (pow2(b223, _23n, P) * b22) % P;
|
|
46
46
|
const t2 = (pow2(t1, _6n, P) * b2) % P;
|
|
47
47
|
const root = pow2(t2, _2n, P);
|
|
48
|
-
if (!
|
|
48
|
+
if (!Fpk1.eql(Fpk1.sqr(root), y)) throw new Error('Cannot find square root');
|
|
49
49
|
return root;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
const
|
|
52
|
+
const Fpk1 = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod });
|
|
53
53
|
|
|
54
54
|
/**
|
|
55
55
|
* secp256k1 short weierstrass curve and ECDSA signatures over it.
|
|
@@ -58,7 +58,7 @@ export const secp256k1 = createCurve(
|
|
|
58
58
|
{
|
|
59
59
|
a: BigInt(0), // equation params: a, b
|
|
60
60
|
b: BigInt(7), // Seem to be rigid: bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975
|
|
61
|
-
Fp, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n
|
|
61
|
+
Fp: Fpk1, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n
|
|
62
62
|
n: secp256k1N, // Curve order, total count of valid points in the field
|
|
63
63
|
// Base point (x, y) aka generator point
|
|
64
64
|
Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),
|
|
@@ -228,7 +228,7 @@ export const schnorr = /* @__PURE__ */ (() => ({
|
|
|
228
228
|
|
|
229
229
|
const isoMap = /* @__PURE__ */ (() =>
|
|
230
230
|
isogenyMap(
|
|
231
|
-
|
|
231
|
+
Fpk1,
|
|
232
232
|
[
|
|
233
233
|
// xNum
|
|
234
234
|
[
|
|
@@ -260,22 +260,22 @@ const isoMap = /* @__PURE__ */ (() =>
|
|
|
260
260
|
].map((i) => i.map((j) => BigInt(j))) as [bigint[], bigint[], bigint[], bigint[]]
|
|
261
261
|
))();
|
|
262
262
|
const mapSWU = /* @__PURE__ */ (() =>
|
|
263
|
-
mapToCurveSimpleSWU(
|
|
263
|
+
mapToCurveSimpleSWU(Fpk1, {
|
|
264
264
|
A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'),
|
|
265
265
|
B: BigInt('1771'),
|
|
266
|
-
Z:
|
|
266
|
+
Z: Fpk1.create(BigInt('-11')),
|
|
267
267
|
}))();
|
|
268
268
|
const htf = /* @__PURE__ */ (() =>
|
|
269
269
|
createHasher(
|
|
270
270
|
secp256k1.ProjectivePoint,
|
|
271
271
|
(scalars: bigint[]) => {
|
|
272
|
-
const { x, y } = mapSWU(
|
|
272
|
+
const { x, y } = mapSWU(Fpk1.create(scalars[0]));
|
|
273
273
|
return isoMap(x, y);
|
|
274
274
|
},
|
|
275
275
|
{
|
|
276
276
|
DST: 'secp256k1_XMD:SHA-256_SSWU_RO_',
|
|
277
277
|
encodeDST: 'secp256k1_XMD:SHA-256_SSWU_NU_',
|
|
278
|
-
p:
|
|
278
|
+
p: Fpk1.ORDER,
|
|
279
279
|
m: 1,
|
|
280
280
|
k: 128,
|
|
281
281
|
expand: 'xmd',
|