@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.
Files changed (103) hide show
  1. package/abstract/curve.d.ts +47 -46
  2. package/abstract/curve.d.ts.map +1 -1
  3. package/abstract/curve.js +9 -6
  4. package/abstract/curve.js.map +1 -1
  5. package/abstract/edwards.d.ts +33 -29
  6. package/abstract/edwards.d.ts.map +1 -1
  7. package/abstract/edwards.js +123 -122
  8. package/abstract/edwards.js.map +1 -1
  9. package/abstract/modular.d.ts +1 -1
  10. package/abstract/modular.d.ts.map +1 -1
  11. package/abstract/modular.js +4 -4
  12. package/abstract/modular.js.map +1 -1
  13. package/abstract/montgomery.d.ts +2 -6
  14. package/abstract/montgomery.d.ts.map +1 -1
  15. package/abstract/montgomery.js +13 -10
  16. package/abstract/montgomery.js.map +1 -1
  17. package/abstract/weierstrass.d.ts +161 -91
  18. package/abstract/weierstrass.d.ts.map +1 -1
  19. package/abstract/weierstrass.js +340 -267
  20. package/abstract/weierstrass.js.map +1 -1
  21. package/bls12-381.d.ts.map +1 -1
  22. package/bls12-381.js +4 -4
  23. package/bls12-381.js.map +1 -1
  24. package/ed25519.d.ts +15 -15
  25. package/ed25519.d.ts.map +1 -1
  26. package/ed25519.js +41 -38
  27. package/ed25519.js.map +1 -1
  28. package/ed448.d.ts +13 -13
  29. package/ed448.d.ts.map +1 -1
  30. package/ed448.js +43 -35
  31. package/ed448.js.map +1 -1
  32. package/esm/abstract/curve.d.ts +47 -46
  33. package/esm/abstract/curve.d.ts.map +1 -1
  34. package/esm/abstract/curve.js +9 -6
  35. package/esm/abstract/curve.js.map +1 -1
  36. package/esm/abstract/edwards.d.ts +33 -29
  37. package/esm/abstract/edwards.d.ts.map +1 -1
  38. package/esm/abstract/edwards.js +124 -123
  39. package/esm/abstract/edwards.js.map +1 -1
  40. package/esm/abstract/modular.d.ts +1 -1
  41. package/esm/abstract/modular.d.ts.map +1 -1
  42. package/esm/abstract/modular.js +4 -4
  43. package/esm/abstract/modular.js.map +1 -1
  44. package/esm/abstract/montgomery.d.ts +2 -6
  45. package/esm/abstract/montgomery.d.ts.map +1 -1
  46. package/esm/abstract/montgomery.js +14 -11
  47. package/esm/abstract/montgomery.js.map +1 -1
  48. package/esm/abstract/weierstrass.d.ts +161 -91
  49. package/esm/abstract/weierstrass.d.ts.map +1 -1
  50. package/esm/abstract/weierstrass.js +342 -270
  51. package/esm/abstract/weierstrass.js.map +1 -1
  52. package/esm/bls12-381.d.ts.map +1 -1
  53. package/esm/bls12-381.js +5 -5
  54. package/esm/bls12-381.js.map +1 -1
  55. package/esm/ed25519.d.ts +15 -15
  56. package/esm/ed25519.d.ts.map +1 -1
  57. package/esm/ed25519.js +40 -37
  58. package/esm/ed25519.js.map +1 -1
  59. package/esm/ed448.d.ts +13 -13
  60. package/esm/ed448.d.ts.map +1 -1
  61. package/esm/ed448.js +42 -34
  62. package/esm/ed448.js.map +1 -1
  63. package/esm/misc.js +2 -2
  64. package/esm/misc.js.map +1 -1
  65. package/esm/nist.d.ts +6 -0
  66. package/esm/nist.d.ts.map +1 -1
  67. package/esm/nist.js +6 -0
  68. package/esm/nist.js.map +1 -1
  69. package/esm/secp256k1.d.ts +2 -6
  70. package/esm/secp256k1.d.ts.map +1 -1
  71. package/esm/secp256k1.js +8 -11
  72. package/esm/secp256k1.js.map +1 -1
  73. package/esm/utils.d.ts +14 -0
  74. package/esm/utils.d.ts.map +1 -1
  75. package/esm/utils.js +43 -0
  76. package/esm/utils.js.map +1 -1
  77. package/misc.js +2 -2
  78. package/misc.js.map +1 -1
  79. package/nist.d.ts +6 -0
  80. package/nist.d.ts.map +1 -1
  81. package/nist.js +7 -1
  82. package/nist.js.map +1 -1
  83. package/package.json +1 -1
  84. package/secp256k1.d.ts +2 -6
  85. package/secp256k1.d.ts.map +1 -1
  86. package/secp256k1.js +7 -10
  87. package/secp256k1.js.map +1 -1
  88. package/src/abstract/curve.ts +131 -68
  89. package/src/abstract/edwards.ts +162 -164
  90. package/src/abstract/modular.ts +4 -4
  91. package/src/abstract/montgomery.ts +16 -16
  92. package/src/abstract/weierstrass.ts +510 -394
  93. package/src/bls12-381.ts +5 -4
  94. package/src/ed25519.ts +51 -46
  95. package/src/ed448.ts +46 -44
  96. package/src/misc.ts +2 -2
  97. package/src/nist.ts +7 -0
  98. package/src/secp256k1.ts +10 -12
  99. package/src/utils.ts +48 -0
  100. package/utils.d.ts +14 -0
  101. package/utils.d.ts.map +1 -1
  102. package/utils.js +47 -0
  103. package/utils.js.map +1 -1
@@ -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, type Hex } from '../utils.ts';
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
- } & { z?: never; t?: never };
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<F, P extends CurvePoint<F, P>> extends GroupConstructor<P> {
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<F>;
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<F>): P;
78
+ fromAffine(p: AffinePoint<P_F<P>>): P;
67
79
  fromBytes(bytes: Uint8Array): P;
68
- fromHex(hex: Hex): P;
80
+ fromHex(hex: Uint8Array | string): P;
69
81
  }
70
82
 
71
- // Type inference helpers
72
- // PC - PointConstructor, P - Point, Fp - Field element
73
- export type GetPointConsF<PC> = PC extends CurvePointCons<infer F, any> ? F : never;
74
- export type GetPointConsPoint<PC> = PC extends CurvePointCons<any, infer P> ? P : never;
75
-
76
- // More like SigAlgorithmInfo, not CurveInfo
77
- export interface CurveInfo {
78
- type: 'weierstrass' | 'edwards' | 'montgomery';
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
- lengths: {
81
- secret: number;
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 extends CurvePointCons<any, any>,
113
- F = GetPointConsF<PC>,
114
- P extends CurvePoint<F, P> = GetPointConsPoint<PC>,
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<F, P extends CurvePoint<F, P>> {
220
- private readonly BASE: P;
221
- private readonly ZERO: P;
222
- private readonly Fn: CurvePointCons<F, P>['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: CurvePointCons<F, P>, bits: number) {
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: P, n: bigint, p: P = this.ZERO): P {
235
- let d: P = elm;
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: P, W: number): Group<P>[] {
304
+ private precomputeWindow(point: PC_P<PC>, W: number): PC_P<PC>[] {
257
305
  const { windows, windowSize } = calcWOpts(W, this.bits);
258
- const points: P[] = [];
259
- let p: P = point;
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: P[], n: bigint): { p: P; f: P } {
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(W: number, precomputes: P[], n: bigint, acc: P = this.ZERO): P {
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: P, transform?: Mapper<P>): P[] {
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 P[];
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(point: P, scalar: bigint, transform?: Mapper<P>): { p: P; f: P } {
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: P, scalar: bigint, transform?: Mapper<P>, prev?: P): P {
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: P, W: number): void {
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: P): boolean {
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<T extends Group<T>>(
380
- Point: GroupConstructor<T>,
381
- point: T,
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: T; p2: T } {
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<T extends Group<T>>(
409
- c: GroupConstructor<T>,
465
+ export function pippenger<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(
466
+ c: PC,
410
467
  fieldN: IField<bigint>,
411
- points: T[],
468
+ points: P[],
412
469
  scalars: bigint[]
413
- ): T {
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 T;
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<T extends Group<T>>(
462
- c: GroupConstructor<T>,
518
+ export function precomputeMSMUnsafe<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(
519
+ c: PC,
463
520
  fieldN: IField<bigint>,
464
- points: T[],
521
+ points: P[],
465
522
  windowSize: number
466
- ): (scalars: bigint[]) => T {
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: T) => {
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[]): T => {
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
- } & ({ b: T } | { d: T });
654
+ };
596
655
 
597
- function createField<T>(order: bigint, field?: IField<T>): 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
- ): FpFn<T> {
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
- return { Fp, Fn };
690
+ CURVE = Object.freeze(Object.assign({}, CURVE));
691
+ return { CURVE, Fp, Fn };
629
692
  }