@noble/curves 1.9.3 → 1.9.5
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/abstract/curve.d.ts +47 -46
- package/abstract/curve.d.ts.map +1 -1
- package/abstract/curve.js +9 -6
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.d.ts +33 -29
- package/abstract/edwards.d.ts.map +1 -1
- package/abstract/edwards.js +123 -122
- package/abstract/edwards.js.map +1 -1
- package/abstract/modular.d.ts +1 -1
- package/abstract/modular.d.ts.map +1 -1
- package/abstract/modular.js +4 -4
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts +2 -6
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +13 -10
- package/abstract/montgomery.js.map +1 -1
- package/abstract/weierstrass.d.ts +161 -91
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +340 -267
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +4 -4
- package/bls12-381.js.map +1 -1
- package/ed25519.d.ts +15 -15
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +41 -38
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +13 -13
- package/ed448.d.ts.map +1 -1
- package/ed448.js +43 -35
- package/ed448.js.map +1 -1
- package/esm/abstract/curve.d.ts +47 -46
- package/esm/abstract/curve.d.ts.map +1 -1
- package/esm/abstract/curve.js +9 -6
- package/esm/abstract/curve.js.map +1 -1
- package/esm/abstract/edwards.d.ts +33 -29
- package/esm/abstract/edwards.d.ts.map +1 -1
- package/esm/abstract/edwards.js +124 -123
- package/esm/abstract/edwards.js.map +1 -1
- package/esm/abstract/modular.d.ts +1 -1
- package/esm/abstract/modular.d.ts.map +1 -1
- package/esm/abstract/modular.js +4 -4
- package/esm/abstract/modular.js.map +1 -1
- package/esm/abstract/montgomery.d.ts +2 -6
- package/esm/abstract/montgomery.d.ts.map +1 -1
- package/esm/abstract/montgomery.js +14 -11
- package/esm/abstract/montgomery.js.map +1 -1
- package/esm/abstract/weierstrass.d.ts +161 -91
- package/esm/abstract/weierstrass.d.ts.map +1 -1
- package/esm/abstract/weierstrass.js +342 -270
- package/esm/abstract/weierstrass.js.map +1 -1
- package/esm/bls12-381.d.ts.map +1 -1
- package/esm/bls12-381.js +5 -5
- package/esm/bls12-381.js.map +1 -1
- package/esm/ed25519.d.ts +15 -15
- package/esm/ed25519.d.ts.map +1 -1
- package/esm/ed25519.js +40 -37
- package/esm/ed25519.js.map +1 -1
- package/esm/ed448.d.ts +13 -13
- package/esm/ed448.d.ts.map +1 -1
- package/esm/ed448.js +42 -34
- package/esm/ed448.js.map +1 -1
- package/esm/misc.js +2 -2
- package/esm/misc.js.map +1 -1
- package/esm/nist.d.ts +6 -0
- package/esm/nist.d.ts.map +1 -1
- package/esm/nist.js +6 -0
- package/esm/nist.js.map +1 -1
- package/esm/secp256k1.d.ts +2 -6
- package/esm/secp256k1.d.ts.map +1 -1
- package/esm/secp256k1.js +8 -11
- package/esm/secp256k1.js.map +1 -1
- package/esm/utils.d.ts +14 -0
- package/esm/utils.d.ts.map +1 -1
- package/esm/utils.js +43 -0
- package/esm/utils.js.map +1 -1
- package/misc.js +2 -2
- package/misc.js.map +1 -1
- package/nist.d.ts +6 -0
- package/nist.d.ts.map +1 -1
- package/nist.js +7 -1
- package/nist.js.map +1 -1
- package/package.json +1 -1
- package/secp256k1.d.ts +2 -6
- package/secp256k1.d.ts.map +1 -1
- package/secp256k1.js +7 -10
- package/secp256k1.js.map +1 -1
- package/src/abstract/curve.ts +131 -68
- package/src/abstract/edwards.ts +162 -164
- package/src/abstract/modular.ts +4 -4
- package/src/abstract/montgomery.ts +16 -16
- package/src/abstract/weierstrass.ts +510 -394
- package/src/bls12-381.ts +5 -4
- package/src/ed25519.ts +51 -46
- package/src/ed448.ts +46 -44
- package/src/misc.ts +2 -2
- package/src/nist.ts +7 -0
- package/src/secp256k1.ts +10 -12
- package/src/utils.ts +48 -0
- package/utils.d.ts +14 -0
- package/utils.d.ts.map +1 -1
- package/utils.js +47 -0
- package/utils.js.map +1 -1
package/src/abstract/curve.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
7
|
-
import { bitLen, bitMask, validateObject
|
|
7
|
+
import { bitLen, bitMask, validateObject } from '../utils.ts';
|
|
8
8
|
import { Field, FpInvertBatch, nLength, validateField, type IField } from './modular.ts';
|
|
9
9
|
|
|
10
10
|
const _0n = BigInt(0);
|
|
@@ -13,7 +13,7 @@ const _1n = BigInt(1);
|
|
|
13
13
|
export type AffinePoint<T> = {
|
|
14
14
|
x: T;
|
|
15
15
|
y: T;
|
|
16
|
-
} & {
|
|
16
|
+
} & { Z?: never };
|
|
17
17
|
|
|
18
18
|
// This was initialy do this way to re-use montgomery ladder in field (add->mul,double->sqr), but
|
|
19
19
|
// that didn't happen and there is probably not much reason to have separate Group like this?
|
|
@@ -29,6 +29,11 @@ export interface Group<T extends Group<T>> {
|
|
|
29
29
|
|
|
30
30
|
// We can't "abstract out" coordinates (X, Y, Z; and T in Edwards): argument names of constructor
|
|
31
31
|
// are not accessible. See Typescript gh-56093, gh-41594.
|
|
32
|
+
//
|
|
33
|
+
// We have to use recursive types, so it will return actual point, not constained `CurvePoint`.
|
|
34
|
+
// If, at any point, P is `any`, it will erase all types and replace it
|
|
35
|
+
// with `any`, because of recursion, `any implements CurvePoint`,
|
|
36
|
+
// but we lose all constrains on methods.
|
|
32
37
|
|
|
33
38
|
/** Base interface for all elliptic curve Points. */
|
|
34
39
|
export interface CurvePoint<F, P extends CurvePoint<F, P>> extends Group<P> {
|
|
@@ -37,6 +42,12 @@ export interface CurvePoint<F, P extends CurvePoint<F, P>> extends Group<P> {
|
|
|
37
42
|
/** Affine y coordinate. Different from projective / extended Y coordinate. */
|
|
38
43
|
y: F;
|
|
39
44
|
Z?: F;
|
|
45
|
+
double(): P;
|
|
46
|
+
negate(): P;
|
|
47
|
+
add(other: P): P;
|
|
48
|
+
subtract(other: P): P;
|
|
49
|
+
equals(other: P): boolean;
|
|
50
|
+
multiply(scalar: bigint): P;
|
|
40
51
|
assertValidity(): void;
|
|
41
52
|
clearCofactor(): P;
|
|
42
53
|
is0(): boolean;
|
|
@@ -55,35 +66,73 @@ export interface CurvePoint<F, P extends CurvePoint<F, P>> extends Group<P> {
|
|
|
55
66
|
}
|
|
56
67
|
|
|
57
68
|
/** Base interface for all elliptic curve Point constructors. */
|
|
58
|
-
export interface CurvePointCons<
|
|
69
|
+
export interface CurvePointCons<P extends CurvePoint<any, P>> {
|
|
70
|
+
[Symbol.hasInstance]: (item: unknown) => boolean;
|
|
59
71
|
BASE: P;
|
|
60
72
|
ZERO: P;
|
|
61
73
|
/** Field for basic curve math */
|
|
62
|
-
Fp: IField<
|
|
74
|
+
Fp: IField<P_F<P>>;
|
|
63
75
|
/** Scalar field, for scalars in multiply and others */
|
|
64
76
|
Fn: IField<bigint>;
|
|
65
77
|
/** Creates point from x, y. Does NOT validate if the point is valid. Use `.assertValidity()`. */
|
|
66
|
-
fromAffine(p: AffinePoint<
|
|
78
|
+
fromAffine(p: AffinePoint<P_F<P>>): P;
|
|
67
79
|
fromBytes(bytes: Uint8Array): P;
|
|
68
|
-
fromHex(hex:
|
|
80
|
+
fromHex(hex: Uint8Array | string): P;
|
|
69
81
|
}
|
|
70
82
|
|
|
71
|
-
// Type inference helpers
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
// Type inference helpers: PC - PointConstructor, P - Point, Fp - Field element
|
|
84
|
+
// Short names, because we use them a lot in result types:
|
|
85
|
+
// * we can't do 'P = GetCurvePoint<PC>': this is default value and doesn't constrain anything
|
|
86
|
+
// * we can't do 'type X = GetCurvePoint<PC>': it won't be accesible for arguments/return types
|
|
87
|
+
// * `CurvePointCons<P extends CurvePoint<any, P>>` constraints from interface definition
|
|
88
|
+
// won't propagate, if `PC extends CurvePointCons<any>`: the P would be 'any', which is incorrect
|
|
89
|
+
// * PC could be super specific with super specific P, which implements CurvePoint<any, P>.
|
|
90
|
+
// this means we need to do stuff like
|
|
91
|
+
// `function test<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(`
|
|
92
|
+
// if we want type safety around P, otherwise PC_P<PC> will be any
|
|
93
|
+
|
|
94
|
+
/** Returns Fp type from Point (P_F<P> == P.F) */
|
|
95
|
+
export type P_F<P extends CurvePoint<any, P>> = P extends CurvePoint<infer F, P> ? F : never;
|
|
96
|
+
/** Returns Fp type from PointCons (PC_F<PC> == PC.P.F) */
|
|
97
|
+
export type PC_F<PC extends CurvePointCons<CurvePoint<any, any>>> = PC['Fp']['ZERO'];
|
|
98
|
+
/** Returns Point type from PointCons (PC_P<PC> == PC.P) */
|
|
99
|
+
export type PC_P<PC extends CurvePointCons<CurvePoint<any, any>>> = PC['ZERO'];
|
|
100
|
+
|
|
101
|
+
// Ugly hack to get proper type inference, because in typescript fails to infer resursively.
|
|
102
|
+
// The hack allows to do up to 10 chained operations without applying type erasure.
|
|
103
|
+
//
|
|
104
|
+
// Types which won't work:
|
|
105
|
+
// * `CurvePointCons<CurvePoint<any, any>>`, will return `any` after 1 operation
|
|
106
|
+
// * `CurvePointCons<any>: WeierstrassPointCons<bigint> extends CurvePointCons<any> = false`
|
|
107
|
+
// * `P extends CurvePoint, PC extends CurvePointCons<P>`
|
|
108
|
+
// * It can't infer P from PC alone
|
|
109
|
+
// * Too many relations between F, P & PC
|
|
110
|
+
// * It will infer P/F if `arg: CurvePointCons<F, P>`, but will fail if PC is generic
|
|
111
|
+
// * It will work correctly if there is an additional argument of type P
|
|
112
|
+
// * But generally, we don't want to parametrize `CurvePointCons` over `F`: it will complicate
|
|
113
|
+
// types, making them un-inferable
|
|
114
|
+
// prettier-ignore
|
|
115
|
+
export type PC_ANY = CurvePointCons<
|
|
116
|
+
CurvePoint<any,
|
|
117
|
+
CurvePoint<any,
|
|
118
|
+
CurvePoint<any,
|
|
119
|
+
CurvePoint<any,
|
|
120
|
+
CurvePoint<any,
|
|
121
|
+
CurvePoint<any,
|
|
122
|
+
CurvePoint<any,
|
|
123
|
+
CurvePoint<any,
|
|
124
|
+
CurvePoint<any,
|
|
125
|
+
CurvePoint<any, any>
|
|
126
|
+
>>>>>>>>>
|
|
127
|
+
>;
|
|
128
|
+
|
|
129
|
+
export interface CurveLengths {
|
|
130
|
+
secret?: number;
|
|
131
|
+
public?: number;
|
|
132
|
+
publicUncompressed?: number;
|
|
79
133
|
publicKeyHasPrefix?: boolean;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
public: number;
|
|
83
|
-
publicUncompressed?: number;
|
|
84
|
-
signature: number;
|
|
85
|
-
seed: number;
|
|
86
|
-
};
|
|
134
|
+
signature?: number;
|
|
135
|
+
seed?: number;
|
|
87
136
|
}
|
|
88
137
|
export type GroupConstructor<T> = {
|
|
89
138
|
BASE: T;
|
|
@@ -108,11 +157,10 @@ export function negateCt<T extends { negate: () => T }>(condition: boolean, item
|
|
|
108
157
|
* so this improves performance massively.
|
|
109
158
|
* Optimization: converts a list of projective points to a list of identical points with Z=1.
|
|
110
159
|
*/
|
|
111
|
-
export function normalizeZ<
|
|
112
|
-
PC
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
>(c: CurvePointCons<F, P>, points: P[]): P[] {
|
|
160
|
+
export function normalizeZ<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(
|
|
161
|
+
c: PC,
|
|
162
|
+
points: P[]
|
|
163
|
+
): P[] {
|
|
116
164
|
const invertedZs = FpInvertBatch(
|
|
117
165
|
c.Fp,
|
|
118
166
|
points.map((p) => p.Z!)
|
|
@@ -216,14 +264,14 @@ function assert0(n: bigint): void {
|
|
|
216
264
|
* @todo Research returning 2d JS array of windows, instead of a single window.
|
|
217
265
|
* This would allow windows to be in different memory locations
|
|
218
266
|
*/
|
|
219
|
-
export class wNAF<
|
|
220
|
-
private readonly BASE:
|
|
221
|
-
private readonly ZERO:
|
|
222
|
-
private readonly Fn:
|
|
267
|
+
export class wNAF<PC extends PC_ANY> {
|
|
268
|
+
private readonly BASE: PC_P<PC>;
|
|
269
|
+
private readonly ZERO: PC_P<PC>;
|
|
270
|
+
private readonly Fn: PC['Fn'];
|
|
223
271
|
readonly bits: number;
|
|
224
272
|
|
|
225
273
|
// Parametrized with a given Point class (not individual point)
|
|
226
|
-
constructor(Point:
|
|
274
|
+
constructor(Point: PC, bits: number) {
|
|
227
275
|
this.BASE = Point.BASE;
|
|
228
276
|
this.ZERO = Point.ZERO;
|
|
229
277
|
this.Fn = Point.Fn;
|
|
@@ -231,8 +279,8 @@ export class wNAF<F, P extends CurvePoint<F, P>> {
|
|
|
231
279
|
}
|
|
232
280
|
|
|
233
281
|
// non-const time multiplication ladder
|
|
234
|
-
_unsafeLadder(elm:
|
|
235
|
-
let d:
|
|
282
|
+
_unsafeLadder(elm: PC_P<PC>, n: bigint, p: PC_P<PC> = this.ZERO): PC_P<PC> {
|
|
283
|
+
let d: PC_P<PC> = elm;
|
|
236
284
|
while (n > _0n) {
|
|
237
285
|
if (n & _1n) p = p.add(d);
|
|
238
286
|
d = d.double();
|
|
@@ -253,10 +301,10 @@ export class wNAF<F, P extends CurvePoint<F, P>> {
|
|
|
253
301
|
* @param W window size
|
|
254
302
|
* @returns precomputed point tables flattened to a single array
|
|
255
303
|
*/
|
|
256
|
-
private precomputeWindow(point:
|
|
304
|
+
private precomputeWindow(point: PC_P<PC>, W: number): PC_P<PC>[] {
|
|
257
305
|
const { windows, windowSize } = calcWOpts(W, this.bits);
|
|
258
|
-
const points:
|
|
259
|
-
let p:
|
|
306
|
+
const points: PC_P<PC>[] = [];
|
|
307
|
+
let p: PC_P<PC> = point;
|
|
260
308
|
let base = p;
|
|
261
309
|
for (let window = 0; window < windows; window++) {
|
|
262
310
|
base = p;
|
|
@@ -277,7 +325,7 @@ export class wNAF<F, P extends CurvePoint<F, P>> {
|
|
|
277
325
|
* https://github.com/paulmillr/noble-secp256k1/blob/47cb1669b6e506ad66b35fe7d76132ae97465da2/index.ts#L502-L541
|
|
278
326
|
* @returns real and fake (for const-time) points
|
|
279
327
|
*/
|
|
280
|
-
private wNAF(W: number, precomputes:
|
|
328
|
+
private wNAF(W: number, precomputes: PC_P<PC>[], n: bigint): { p: PC_P<PC>; f: PC_P<PC> } {
|
|
281
329
|
// Scalar should be smaller than field order
|
|
282
330
|
if (!this.Fn.isValid(n)) throw new Error('invalid scalar');
|
|
283
331
|
// Accumulators
|
|
@@ -314,7 +362,12 @@ export class wNAF<F, P extends CurvePoint<F, P>> {
|
|
|
314
362
|
* @param acc accumulator point to add result of multiplication
|
|
315
363
|
* @returns point
|
|
316
364
|
*/
|
|
317
|
-
private wNAFUnsafe(
|
|
365
|
+
private wNAFUnsafe(
|
|
366
|
+
W: number,
|
|
367
|
+
precomputes: PC_P<PC>[],
|
|
368
|
+
n: bigint,
|
|
369
|
+
acc: PC_P<PC> = this.ZERO
|
|
370
|
+
): PC_P<PC> {
|
|
318
371
|
const wo = calcWOpts(W, this.bits);
|
|
319
372
|
for (let window = 0; window < wo.windows; window++) {
|
|
320
373
|
if (n === _0n) break; // Early-exit, skip 0 value
|
|
@@ -333,11 +386,11 @@ export class wNAF<F, P extends CurvePoint<F, P>> {
|
|
|
333
386
|
return acc;
|
|
334
387
|
}
|
|
335
388
|
|
|
336
|
-
private getPrecomputes(W: number, point:
|
|
389
|
+
private getPrecomputes(W: number, point: PC_P<PC>, transform?: Mapper<PC_P<PC>>): PC_P<PC>[] {
|
|
337
390
|
// Calculate precomputes on a first run, reuse them after
|
|
338
391
|
let comp = pointPrecomputes.get(point);
|
|
339
392
|
if (!comp) {
|
|
340
|
-
comp = this.precomputeWindow(point, W) as
|
|
393
|
+
comp = this.precomputeWindow(point, W) as PC_P<PC>[];
|
|
341
394
|
if (W !== 1) {
|
|
342
395
|
// Doing transform outside of if brings 15% perf hit
|
|
343
396
|
if (typeof transform === 'function') comp = transform(comp);
|
|
@@ -347,12 +400,16 @@ export class wNAF<F, P extends CurvePoint<F, P>> {
|
|
|
347
400
|
return comp;
|
|
348
401
|
}
|
|
349
402
|
|
|
350
|
-
cached(
|
|
403
|
+
cached(
|
|
404
|
+
point: PC_P<PC>,
|
|
405
|
+
scalar: bigint,
|
|
406
|
+
transform?: Mapper<PC_P<PC>>
|
|
407
|
+
): { p: PC_P<PC>; f: PC_P<PC> } {
|
|
351
408
|
const W = getW(point);
|
|
352
409
|
return this.wNAF(W, this.getPrecomputes(W, point, transform), scalar);
|
|
353
410
|
}
|
|
354
411
|
|
|
355
|
-
unsafe(point:
|
|
412
|
+
unsafe(point: PC_P<PC>, scalar: bigint, transform?: Mapper<PC_P<PC>>, prev?: PC_P<PC>): PC_P<PC> {
|
|
356
413
|
const W = getW(point);
|
|
357
414
|
if (W === 1) return this._unsafeLadder(point, scalar, prev); // For W=1 ladder is ~x2 faster
|
|
358
415
|
return this.wNAFUnsafe(W, this.getPrecomputes(W, point, transform), scalar, prev);
|
|
@@ -361,13 +418,13 @@ export class wNAF<F, P extends CurvePoint<F, P>> {
|
|
|
361
418
|
// We calculate precomputes for elliptic curve point multiplication
|
|
362
419
|
// using windowed method. This specifies window size and
|
|
363
420
|
// stores precomputed values. Usually only base point would be precomputed.
|
|
364
|
-
createCache(P:
|
|
421
|
+
createCache(P: PC_P<PC>, W: number): void {
|
|
365
422
|
validateW(W, this.bits);
|
|
366
423
|
pointWindowSizes.set(P, W);
|
|
367
424
|
pointPrecomputes.delete(P);
|
|
368
425
|
}
|
|
369
426
|
|
|
370
|
-
hasCache(elm:
|
|
427
|
+
hasCache(elm: PC_P<PC>): boolean {
|
|
371
428
|
return getW(elm) !== 1;
|
|
372
429
|
}
|
|
373
430
|
}
|
|
@@ -376,12 +433,12 @@ export class wNAF<F, P extends CurvePoint<F, P>> {
|
|
|
376
433
|
* Endomorphism-specific multiplication for Koblitz curves.
|
|
377
434
|
* Cost: 128 dbl, 0-256 adds.
|
|
378
435
|
*/
|
|
379
|
-
export function mulEndoUnsafe<
|
|
380
|
-
Point:
|
|
381
|
-
point:
|
|
436
|
+
export function mulEndoUnsafe<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(
|
|
437
|
+
Point: PC,
|
|
438
|
+
point: P,
|
|
382
439
|
k1: bigint,
|
|
383
440
|
k2: bigint
|
|
384
|
-
): { p1:
|
|
441
|
+
): { p1: P; p2: P } {
|
|
385
442
|
let acc = point;
|
|
386
443
|
let p1 = Point.ZERO;
|
|
387
444
|
let p2 = Point.ZERO;
|
|
@@ -405,12 +462,12 @@ export function mulEndoUnsafe<T extends Group<T>>(
|
|
|
405
462
|
* @param points array of L curve points
|
|
406
463
|
* @param scalars array of L scalars (aka secret keys / bigints)
|
|
407
464
|
*/
|
|
408
|
-
export function pippenger<
|
|
409
|
-
c:
|
|
465
|
+
export function pippenger<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(
|
|
466
|
+
c: PC,
|
|
410
467
|
fieldN: IField<bigint>,
|
|
411
|
-
points:
|
|
468
|
+
points: P[],
|
|
412
469
|
scalars: bigint[]
|
|
413
|
-
):
|
|
470
|
+
): P {
|
|
414
471
|
// If we split scalars by some window (let's say 8 bits), every chunk will only
|
|
415
472
|
// take 256 buckets even if there are 4096 scalars, also re-uses double.
|
|
416
473
|
// TODO:
|
|
@@ -449,7 +506,7 @@ export function pippenger<T extends Group<T>>(
|
|
|
449
506
|
sum = sum.add(resI);
|
|
450
507
|
if (i !== 0) for (let j = 0; j < windowSize; j++) sum = sum.double();
|
|
451
508
|
}
|
|
452
|
-
return sum as
|
|
509
|
+
return sum as P;
|
|
453
510
|
}
|
|
454
511
|
/**
|
|
455
512
|
* Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
|
|
@@ -458,12 +515,12 @@ export function pippenger<T extends Group<T>>(
|
|
|
458
515
|
* @param points array of L curve points
|
|
459
516
|
* @returns function which multiplies points with scaars
|
|
460
517
|
*/
|
|
461
|
-
export function precomputeMSMUnsafe<
|
|
462
|
-
c:
|
|
518
|
+
export function precomputeMSMUnsafe<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(
|
|
519
|
+
c: PC,
|
|
463
520
|
fieldN: IField<bigint>,
|
|
464
|
-
points:
|
|
521
|
+
points: P[],
|
|
465
522
|
windowSize: number
|
|
466
|
-
): (scalars: bigint[]) =>
|
|
523
|
+
): (scalars: bigint[]) => P {
|
|
467
524
|
/**
|
|
468
525
|
* Performance Analysis of Window-based Precomputation
|
|
469
526
|
*
|
|
@@ -505,7 +562,7 @@ export function precomputeMSMUnsafe<T extends Group<T>>(
|
|
|
505
562
|
const tableSize = 2 ** windowSize - 1; // table size (without zero)
|
|
506
563
|
const chunks = Math.ceil(fieldN.BITS / windowSize); // chunks of item
|
|
507
564
|
const MASK = bitMask(windowSize);
|
|
508
|
-
const tables = points.map((p:
|
|
565
|
+
const tables = points.map((p: P) => {
|
|
509
566
|
const res = [];
|
|
510
567
|
for (let i = 0, acc = p; i < tableSize; i++) {
|
|
511
568
|
res.push(acc);
|
|
@@ -513,7 +570,7 @@ export function precomputeMSMUnsafe<T extends Group<T>>(
|
|
|
513
570
|
}
|
|
514
571
|
return res;
|
|
515
572
|
});
|
|
516
|
-
return (scalars: bigint[]):
|
|
573
|
+
return (scalars: bigint[]): P => {
|
|
517
574
|
validateMSMScalars(scalars, fieldN);
|
|
518
575
|
if (scalars.length > points.length)
|
|
519
576
|
throw new Error('array of scalars must be smaller than array of points');
|
|
@@ -586,38 +643,43 @@ export function validateBasic<FP, T>(
|
|
|
586
643
|
}
|
|
587
644
|
|
|
588
645
|
export type ValidCurveParams<T> = {
|
|
589
|
-
a: T;
|
|
590
646
|
p: bigint;
|
|
591
647
|
n: bigint;
|
|
592
648
|
h: bigint;
|
|
649
|
+
a: T;
|
|
650
|
+
b?: T;
|
|
651
|
+
d?: T;
|
|
593
652
|
Gx: T;
|
|
594
653
|
Gy: T;
|
|
595
|
-
}
|
|
654
|
+
};
|
|
596
655
|
|
|
597
|
-
function createField<T>(order: bigint, field?: IField<T
|
|
656
|
+
function createField<T>(order: bigint, field?: IField<T>, isLE?: boolean): IField<T> {
|
|
598
657
|
if (field) {
|
|
599
658
|
if (field.ORDER !== order) throw new Error('Field.ORDER must match order: Fp == p, Fn == n');
|
|
600
659
|
validateField(field);
|
|
601
660
|
return field;
|
|
602
661
|
} else {
|
|
603
|
-
return Field(order) as unknown as IField<T>;
|
|
662
|
+
return Field(order, { isLE }) as unknown as IField<T>;
|
|
604
663
|
}
|
|
605
664
|
}
|
|
606
665
|
export type FpFn<T> = { Fp: IField<T>; Fn: IField<bigint> };
|
|
666
|
+
|
|
607
667
|
/** Validates CURVE opts and creates fields */
|
|
608
668
|
export function _createCurveFields<T>(
|
|
609
669
|
type: 'weierstrass' | 'edwards',
|
|
610
670
|
CURVE: ValidCurveParams<T>,
|
|
611
|
-
curveOpts: Partial<FpFn<T>> = {}
|
|
612
|
-
|
|
671
|
+
curveOpts: Partial<FpFn<T>> = {},
|
|
672
|
+
FpFnLE?: boolean
|
|
673
|
+
): FpFn<T> & { CURVE: ValidCurveParams<T> } {
|
|
674
|
+
if (FpFnLE === undefined) FpFnLE = type === 'edwards';
|
|
613
675
|
if (!CURVE || typeof CURVE !== 'object') throw new Error(`expected valid ${type} CURVE object`);
|
|
614
676
|
for (const p of ['p', 'n', 'h'] as const) {
|
|
615
677
|
const val = CURVE[p];
|
|
616
678
|
if (!(typeof val === 'bigint' && val > _0n))
|
|
617
679
|
throw new Error(`CURVE.${p} must be positive bigint`);
|
|
618
680
|
}
|
|
619
|
-
const Fp = createField(CURVE.p, curveOpts.Fp);
|
|
620
|
-
const Fn = createField(CURVE.n, curveOpts.Fn);
|
|
681
|
+
const Fp = createField(CURVE.p, curveOpts.Fp, FpFnLE);
|
|
682
|
+
const Fn = createField(CURVE.n, curveOpts.Fn, FpFnLE);
|
|
621
683
|
const _b: 'b' | 'd' = type === 'weierstrass' ? 'b' : 'd';
|
|
622
684
|
const params = ['Gx', 'Gy', 'a', _b] as const;
|
|
623
685
|
for (const p of params) {
|
|
@@ -625,5 +687,6 @@ export function _createCurveFields<T>(
|
|
|
625
687
|
if (!Fp.isValid(CURVE[p]))
|
|
626
688
|
throw new Error(`CURVE.${p} must be valid field element of CURVE.Fp`);
|
|
627
689
|
}
|
|
628
|
-
|
|
690
|
+
CURVE = Object.freeze(Object.assign({}, CURVE));
|
|
691
|
+
return { CURVE, Fp, Fn };
|
|
629
692
|
}
|