@protontech/openpgp 6.0.0 → 6.0.2-patch.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.
Files changed (38) hide show
  1. package/dist/lightweight/argon2id.min.mjs +1 -1
  2. package/dist/lightweight/argon2id.mjs +1 -1
  3. package/dist/lightweight/legacy_ciphers.min.mjs +1 -1
  4. package/dist/lightweight/legacy_ciphers.mjs +1 -1
  5. package/dist/lightweight/noble_curves.min.mjs +11 -11
  6. package/dist/lightweight/noble_curves.min.mjs.map +1 -1
  7. package/dist/lightweight/noble_curves.mjs +260 -158
  8. package/dist/lightweight/noble_hashes.min.mjs +2 -2
  9. package/dist/lightweight/noble_hashes.min.mjs.map +1 -1
  10. package/dist/lightweight/noble_hashes.mjs +3 -2
  11. package/dist/lightweight/noble_post_quantum.min.mjs +5 -0
  12. package/dist/lightweight/noble_post_quantum.min.mjs.map +1 -0
  13. package/dist/lightweight/noble_post_quantum.mjs +1002 -0
  14. package/dist/lightweight/openpgp.min.mjs +4 -4
  15. package/dist/lightweight/openpgp.min.mjs.map +1 -1
  16. package/dist/lightweight/openpgp.mjs +626 -111
  17. package/dist/lightweight/seek-bzip.min.mjs +1 -1
  18. package/dist/lightweight/seek-bzip.mjs +1 -1
  19. package/dist/lightweight/sha3.min.mjs +3 -3
  20. package/dist/lightweight/sha3.min.mjs.map +1 -1
  21. package/dist/lightweight/sha3.mjs +27 -456
  22. package/dist/lightweight/sha512.min.mjs +3 -0
  23. package/dist/lightweight/sha512.min.mjs.map +1 -0
  24. package/dist/lightweight/sha512.mjs +436 -0
  25. package/dist/node/openpgp.cjs +2247 -621
  26. package/dist/node/openpgp.min.cjs +16 -14
  27. package/dist/node/openpgp.min.cjs.map +1 -1
  28. package/dist/node/openpgp.min.mjs +16 -14
  29. package/dist/node/openpgp.min.mjs.map +1 -1
  30. package/dist/node/openpgp.mjs +2247 -621
  31. package/dist/openpgp.js +2247 -621
  32. package/dist/openpgp.min.js +16 -14
  33. package/dist/openpgp.min.js.map +1 -1
  34. package/dist/openpgp.min.mjs +16 -14
  35. package/dist/openpgp.min.mjs.map +1 -1
  36. package/dist/openpgp.mjs +2247 -621
  37. package/openpgp.d.ts +7 -11
  38. package/package.json +5 -4
@@ -1,17 +1,18 @@
1
- /*! OpenPGP.js v6.0.0 - 2024-11-06 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */
1
+ /*! OpenPGP.js v6.0.2-patch.0 - 2024-11-27 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */
2
2
  const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
3
3
 
4
- import { H as Hash, h as hash, t as toBytes, e as exists, b as bytes, c as concatBytes$1, r as randomBytes, s as sha256, a as sha384, d as sha512, w as wrapConstructor, u as utf8ToBytes$1, f as shake256 } from './sha3.mjs';
4
+ import { s as sha256, a as sha384, b as sha512 } from './sha512.mjs';
5
+ import { H as Hash, a as ahash, t as toBytes, b as aexists, c as abytes$1, d as concatBytes$1, r as randomBytes, w as wrapConstructor, u as utf8ToBytes$1, s as shake256 } from './sha3.mjs';
5
6
 
6
7
  // HMAC (RFC 2104)
7
8
  class HMAC extends Hash {
8
- constructor(hash$1, _key) {
9
+ constructor(hash, _key) {
9
10
  super();
10
11
  this.finished = false;
11
12
  this.destroyed = false;
12
- hash(hash$1);
13
+ ahash(hash);
13
14
  const key = toBytes(_key);
14
- this.iHash = hash$1.create();
15
+ this.iHash = hash.create();
15
16
  if (typeof this.iHash.update !== 'function')
16
17
  throw new Error('Expected instance of class which extends utils.Hash');
17
18
  this.blockLen = this.iHash.blockLen;
@@ -19,12 +20,12 @@ class HMAC extends Hash {
19
20
  const blockLen = this.blockLen;
20
21
  const pad = new Uint8Array(blockLen);
21
22
  // blockLen can be bigger than outputLen
22
- pad.set(key.length > blockLen ? hash$1.create().update(key).digest() : key);
23
+ pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
23
24
  for (let i = 0; i < pad.length; i++)
24
25
  pad[i] ^= 0x36;
25
26
  this.iHash.update(pad);
26
27
  // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone
27
- this.oHash = hash$1.create();
28
+ this.oHash = hash.create();
28
29
  // Undo internal XOR && apply outer XOR
29
30
  for (let i = 0; i < pad.length; i++)
30
31
  pad[i] ^= 0x36 ^ 0x5c;
@@ -32,13 +33,13 @@ class HMAC extends Hash {
32
33
  pad.fill(0);
33
34
  }
34
35
  update(buf) {
35
- exists(this);
36
+ aexists(this);
36
37
  this.iHash.update(buf);
37
38
  return this;
38
39
  }
39
40
  digestInto(out) {
40
- exists(this);
41
- bytes(out, this.outputLen);
41
+ aexists(this);
42
+ abytes$1(out, this.outputLen);
42
43
  this.finished = true;
43
44
  this.iHash.digestInto(out);
44
45
  this.oHash.update(out);
@@ -91,8 +92,7 @@ const _0n$5 = /* @__PURE__ */ BigInt(0);
91
92
  const _1n$7 = /* @__PURE__ */ BigInt(1);
92
93
  const _2n$4 = /* @__PURE__ */ BigInt(2);
93
94
  function isBytes(a) {
94
- return (a instanceof Uint8Array ||
95
- (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array'));
95
+ return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
96
96
  }
97
97
  function abytes(item) {
98
98
  if (!isBytes(item))
@@ -100,7 +100,7 @@ function abytes(item) {
100
100
  }
101
101
  function abool(title, value) {
102
102
  if (typeof value !== 'boolean')
103
- throw new Error(`${title} must be valid boolean, got "${value}".`);
103
+ throw new Error(title + ' boolean expected, got ' + value);
104
104
  }
105
105
  // Array where index 0xf0 (240) is mapped to string 'f0'
106
106
  const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));
@@ -118,23 +118,22 @@ function bytesToHex(bytes) {
118
118
  }
119
119
  function numberToHexUnpadded(num) {
120
120
  const hex = num.toString(16);
121
- return hex.length & 1 ? `0${hex}` : hex;
121
+ return hex.length & 1 ? '0' + hex : hex;
122
122
  }
123
123
  function hexToNumber(hex) {
124
124
  if (typeof hex !== 'string')
125
125
  throw new Error('hex string expected, got ' + typeof hex);
126
- // Big Endian
127
- return BigInt(hex === '' ? '0' : `0x${hex}`);
126
+ return hex === '' ? _0n$5 : BigInt('0x' + hex); // Big Endian
128
127
  }
129
128
  // We use optimized technique to convert hex string to byte array
130
- const asciis = { _0: 48, _9: 57, _A: 65, _F: 70, _a: 97, _f: 102 };
131
- function asciiToBase16(char) {
132
- if (char >= asciis._0 && char <= asciis._9)
133
- return char - asciis._0;
134
- if (char >= asciis._A && char <= asciis._F)
135
- return char - (asciis._A - 10);
136
- if (char >= asciis._a && char <= asciis._f)
137
- return char - (asciis._a - 10);
129
+ const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
130
+ function asciiToBase16(ch) {
131
+ if (ch >= asciis._0 && ch <= asciis._9)
132
+ return ch - asciis._0; // '2' => 50-48
133
+ if (ch >= asciis.A && ch <= asciis.F)
134
+ return ch - (asciis.A - 10); // 'B' => 66-(65-10)
135
+ if (ch >= asciis.a && ch <= asciis.f)
136
+ return ch - (asciis.a - 10); // 'b' => 98-(97-10)
138
137
  return;
139
138
  }
140
139
  /**
@@ -146,7 +145,7 @@ function hexToBytes(hex) {
146
145
  const hl = hex.length;
147
146
  const al = hl / 2;
148
147
  if (hl % 2)
149
- throw new Error('padded hex string expected, got unpadded hex of length ' + hl);
148
+ throw new Error('hex string expected, got unpadded hex of length ' + hl);
150
149
  const array = new Uint8Array(al);
151
150
  for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
152
151
  const n1 = asciiToBase16(hex.charCodeAt(hi));
@@ -155,7 +154,7 @@ function hexToBytes(hex) {
155
154
  const char = hex[hi] + hex[hi + 1];
156
155
  throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
157
156
  }
158
- array[ai] = n1 * 16 + n2;
157
+ array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163
159
158
  }
160
159
  return array;
161
160
  }
@@ -193,7 +192,7 @@ function ensureBytes(title, hex, expectedLength) {
193
192
  res = hexToBytes(hex);
194
193
  }
195
194
  catch (e) {
196
- throw new Error(`${title} must be valid hex string, got "${hex}". Cause: ${e}`);
195
+ throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e);
197
196
  }
198
197
  }
199
198
  else if (isBytes(hex)) {
@@ -202,11 +201,11 @@ function ensureBytes(title, hex, expectedLength) {
202
201
  res = Uint8Array.from(hex);
203
202
  }
204
203
  else {
205
- throw new Error(`${title} must be hex string or Uint8Array`);
204
+ throw new Error(title + ' must be hex string or Uint8Array');
206
205
  }
207
206
  const len = res.length;
208
207
  if (typeof expectedLength === 'number' && len !== expectedLength)
209
- throw new Error(`${title} expected ${expectedLength} bytes, got ${len}`);
208
+ throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len);
210
209
  return res;
211
210
  }
212
211
  /**
@@ -241,7 +240,7 @@ function equalBytes(a, b) {
241
240
  */
242
241
  function utf8ToBytes(str) {
243
242
  if (typeof str !== 'string')
244
- throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
243
+ throw new Error('string expected');
245
244
  return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
246
245
  }
247
246
  // Is positive bigint
@@ -261,7 +260,7 @@ function aInRange(title, n, min, max) {
261
260
  // - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)`
262
261
  // - our way is the cleanest: `inRange('x', x, 0n, P)
263
262
  if (!inRange(n, min, max))
264
- throw new Error(`expected valid ${title}: ${min} <= n < ${max}, got ${typeof n} ${n}`);
263
+ throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n);
265
264
  }
266
265
  // Bit operations
267
266
  /**
@@ -371,12 +370,12 @@ function validateObject(object, validators, optValidators = {}) {
371
370
  const checkField = (fieldName, type, isOptional) => {
372
371
  const checkVal = validatorFns[type];
373
372
  if (typeof checkVal !== 'function')
374
- throw new Error(`Invalid validator "${type}", expected function`);
373
+ throw new Error('invalid validator function');
375
374
  const val = object[fieldName];
376
375
  if (isOptional && val === undefined)
377
376
  return;
378
377
  if (!checkVal(val, object)) {
379
- throw new Error(`Invalid param ${String(fieldName)}=${val} (${typeof val}), expected ${type}`);
378
+ throw new Error('param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val);
380
379
  }
381
380
  };
382
381
  for (const [fieldName, type] of Object.entries(validators))
@@ -448,11 +447,9 @@ var ut = /*#__PURE__*/Object.freeze({
448
447
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
449
448
  // Utilities for modular arithmetics and finite fields
450
449
  // prettier-ignore
451
- const _0n$4 = BigInt(0), _1n$6 = BigInt(1), _2n$3 = BigInt(2), _3n$2 = BigInt(3);
450
+ const _0n$4 = BigInt(0), _1n$6 = BigInt(1), _2n$3 = /* @__PURE__ */ BigInt(2), _3n$2 = /* @__PURE__ */ BigInt(3);
452
451
  // prettier-ignore
453
- const _4n = BigInt(4), _5n = BigInt(5), _8n$1 = BigInt(8);
454
- // prettier-ignore
455
- BigInt(9); BigInt(16);
452
+ const _4n = /* @__PURE__ */ BigInt(4), _5n = /* @__PURE__ */ BigInt(5), _8n$1 = /* @__PURE__ */ BigInt(8);
456
453
  // Calculates a modulo b
457
454
  function mod(a, b) {
458
455
  const result = a % b;
@@ -466,8 +463,10 @@ function mod(a, b) {
466
463
  */
467
464
  // TODO: use field version && remove
468
465
  function pow(num, power, modulo) {
469
- if (modulo <= _0n$4 || power < _0n$4)
470
- throw new Error('Expected power/modulo > 0');
466
+ if (power < _0n$4)
467
+ throw new Error('invalid exponent, negatives unsupported');
468
+ if (modulo <= _0n$4)
469
+ throw new Error('invalid modulus');
471
470
  if (modulo === _1n$6)
472
471
  return _0n$4;
473
472
  let res = _1n$6;
@@ -490,9 +489,10 @@ function pow2(x, power, modulo) {
490
489
  }
491
490
  // Inverses number over modulo
492
491
  function invert(number, modulo) {
493
- if (number === _0n$4 || modulo <= _0n$4) {
494
- throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`);
495
- }
492
+ if (number === _0n$4)
493
+ throw new Error('invert: expected non-zero number');
494
+ if (modulo <= _0n$4)
495
+ throw new Error('invert: expected positive modulus, got ' + modulo);
496
496
  // Euclidean GCD https://brilliant.org/wiki/extended-euclidean-algorithm/
497
497
  // Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower.
498
498
  let a = mod(number, modulo);
@@ -533,8 +533,11 @@ function tonelliShanks(P) {
533
533
  for (Q = P - _1n$6, S = 0; Q % _2n$3 === _0n$4; Q /= _2n$3, S++)
534
534
  ;
535
535
  // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq
536
- for (Z = _2n$3; Z < P && pow(Z, legendreC, P) !== P - _1n$6; Z++)
537
- ;
536
+ for (Z = _2n$3; Z < P && pow(Z, legendreC, P) !== P - _1n$6; Z++) {
537
+ // Crash instead of infinity loop, we cannot reasonable count until P.
538
+ if (Z > 1000)
539
+ throw new Error('Cannot find square root: likely non-prime P');
540
+ }
538
541
  // Fast-path
539
542
  if (S === 1) {
540
543
  const p1div4 = (P + _1n$6) / _4n;
@@ -640,7 +643,7 @@ function FpPow(f, num, power) {
640
643
  // Should have same speed as pow for bigints
641
644
  // TODO: benchmark!
642
645
  if (power < _0n$4)
643
- throw new Error('Expected power > 0');
646
+ throw new Error('invalid exponent, negatives unsupported');
644
647
  if (power === _0n$4)
645
648
  return f.ONE;
646
649
  if (power === _1n$6)
@@ -703,11 +706,11 @@ function nLength(n, nBitLength) {
703
706
  */
704
707
  function Field(ORDER, bitLen, isLE = false, redef = {}) {
705
708
  if (ORDER <= _0n$4)
706
- throw new Error(`Expected Field ORDER > 0, got ${ORDER}`);
709
+ throw new Error('invalid field: expected ORDER > 0, got ' + ORDER);
707
710
  const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen);
708
711
  if (BYTES > 2048)
709
- throw new Error('Field lengths over 2048 bytes are not supported');
710
- const sqrtP = FpSqrt(ORDER);
712
+ throw new Error('invalid field: expected ORDER of <= 2048 bytes');
713
+ let sqrtP; // cached sqrtP
711
714
  const f = Object.freeze({
712
715
  ORDER,
713
716
  BITS,
@@ -718,7 +721,7 @@ function Field(ORDER, bitLen, isLE = false, redef = {}) {
718
721
  create: (num) => mod(num, ORDER),
719
722
  isValid: (num) => {
720
723
  if (typeof num !== 'bigint')
721
- throw new Error(`Invalid field element: expected bigint, got ${typeof num}`);
724
+ throw new Error('invalid field element: expected bigint, got ' + typeof num);
722
725
  return _0n$4 <= num && num < ORDER; // 0 is valid element, but it's not invertible
723
726
  },
724
727
  is0: (num) => num === _0n$4,
@@ -737,7 +740,12 @@ function Field(ORDER, bitLen, isLE = false, redef = {}) {
737
740
  subN: (lhs, rhs) => lhs - rhs,
738
741
  mulN: (lhs, rhs) => lhs * rhs,
739
742
  inv: (num) => invert(num, ORDER),
740
- sqrt: redef.sqrt || ((n) => sqrtP(f, n)),
743
+ sqrt: redef.sqrt ||
744
+ ((n) => {
745
+ if (!sqrtP)
746
+ sqrtP = FpSqrt(ORDER);
747
+ return sqrtP(f, n);
748
+ }),
741
749
  invertBatch: (lst) => FpInvertBatch(f, lst),
742
750
  // TODO: do we really need constant cmov?
743
751
  // We don't have const-time bigints anyway, so probably will be not very useful
@@ -745,7 +753,7 @@ function Field(ORDER, bitLen, isLE = false, redef = {}) {
745
753
  toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)),
746
754
  fromBytes: (bytes) => {
747
755
  if (bytes.length !== BYTES)
748
- throw new Error(`Fp.fromBytes: expected ${BYTES}, got ${bytes.length}`);
756
+ throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length);
749
757
  return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
750
758
  },
751
759
  });
@@ -793,7 +801,7 @@ function mapHashToField(key, fieldOrder, isLE = false) {
793
801
  const minLen = getMinHashLength(fieldOrder);
794
802
  // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings.
795
803
  if (len < 16 || len < minLen || len > 1024)
796
- throw new Error(`expected ${minLen}-1024 bytes of input, got ${len}`);
804
+ throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len);
797
805
  const num = isLE ? bytesToNumberBE(key) : bytesToNumberLE(key);
798
806
  // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0
799
807
  const reduced = mod(num, fieldOrder - _1n$6) + _1n$6;
@@ -804,10 +812,43 @@ function mapHashToField(key, fieldOrder, isLE = false) {
804
812
  // Abelian group utilities
805
813
  const _0n$3 = BigInt(0);
806
814
  const _1n$5 = BigInt(1);
815
+ function constTimeNegate(condition, item) {
816
+ const neg = item.negate();
817
+ return condition ? neg : item;
818
+ }
819
+ function validateW(W, bits) {
820
+ if (!Number.isSafeInteger(W) || W <= 0 || W > bits)
821
+ throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W);
822
+ }
823
+ function calcWOpts(W, bits) {
824
+ validateW(W, bits);
825
+ const windows = Math.ceil(bits / W) + 1; // +1, because
826
+ const windowSize = 2 ** (W - 1); // -1 because we skip zero
827
+ return { windows, windowSize };
828
+ }
829
+ function validateMSMPoints(points, c) {
830
+ if (!Array.isArray(points))
831
+ throw new Error('array expected');
832
+ points.forEach((p, i) => {
833
+ if (!(p instanceof c))
834
+ throw new Error('invalid point at index ' + i);
835
+ });
836
+ }
837
+ function validateMSMScalars(scalars, field) {
838
+ if (!Array.isArray(scalars))
839
+ throw new Error('array of scalars expected');
840
+ scalars.forEach((s, i) => {
841
+ if (!field.isValid(s))
842
+ throw new Error('invalid scalar at index ' + i);
843
+ });
844
+ }
807
845
  // Since points in different groups cannot be equal (different object constructor),
808
846
  // we can have single place to store precomputes
809
847
  const pointPrecomputes = new WeakMap();
810
848
  const pointWindowSizes = new WeakMap(); // This allows use make points immutable (nothing changes inside)
849
+ function getW(P) {
850
+ return pointWindowSizes.get(P) || 1;
851
+ }
811
852
  // Elliptic curve multiplication of Point by scalar. Fragile.
812
853
  // Scalars should always be less than curve order: this should be checked inside of a curve itself.
813
854
  // Creates precomputation tables for fast multiplication:
@@ -820,25 +861,13 @@ const pointWindowSizes = new WeakMap(); // This allows use make points immutable
820
861
  // TODO: Research returning 2d JS array of windows, instead of a single window. This would allow
821
862
  // windows to be in different memory locations
822
863
  function wNAF(c, bits) {
823
- const constTimeNegate = (condition, item) => {
824
- const neg = item.negate();
825
- return condition ? neg : item;
826
- };
827
- const validateW = (W) => {
828
- if (!Number.isSafeInteger(W) || W <= 0 || W > bits)
829
- throw new Error(`Wrong window size=${W}, should be [1..${bits}]`);
830
- };
831
- const opts = (W) => {
832
- validateW(W);
833
- const windows = Math.ceil(bits / W) + 1; // +1, because
834
- const windowSize = 2 ** (W - 1); // -1 because we skip zero
835
- return { windows, windowSize };
836
- };
837
864
  return {
838
865
  constTimeNegate,
866
+ hasPrecomputes(elm) {
867
+ return getW(elm) !== 1;
868
+ },
839
869
  // non-const time multiplication ladder
840
- unsafeLadder(elm, n) {
841
- let p = c.ZERO;
870
+ unsafeLadder(elm, n, p = c.ZERO) {
842
871
  let d = elm;
843
872
  while (n > _0n$3) {
844
873
  if (n & _1n$5)
@@ -856,10 +885,12 @@ function wNAF(c, bits) {
856
885
  * - 𝑊 is the window size
857
886
  * - 𝑛 is the bitlength of the curve order.
858
887
  * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
888
+ * @param elm Point instance
889
+ * @param W window size
859
890
  * @returns precomputed point tables flattened to a single array
860
891
  */
861
892
  precomputeWindow(elm, W) {
862
- const { windows, windowSize } = opts(W);
893
+ const { windows, windowSize } = calcWOpts(W, bits);
863
894
  const points = [];
864
895
  let p = elm;
865
896
  let base = p;
@@ -885,7 +916,7 @@ function wNAF(c, bits) {
885
916
  wNAF(W, precomputes, n) {
886
917
  // TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise
887
918
  // But need to carefully remove other checks before wNAF. ORDER == bits here
888
- const { windows, windowSize } = opts(W);
919
+ const { windows, windowSize } = calcWOpts(W, bits);
889
920
  let p = c.ZERO;
890
921
  let f = c.BASE;
891
922
  const mask = BigInt(2 ** W - 1); // Create mask with W ones: 0b1111 for W=4 etc.
@@ -929,8 +960,44 @@ function wNAF(c, bits) {
929
960
  // which makes it less const-time: around 1 bigint multiply.
930
961
  return { p, f };
931
962
  },
932
- wNAFCached(P, n, transform) {
933
- const W = pointWindowSizes.get(P) || 1;
963
+ /**
964
+ * Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form.
965
+ * @param W window size
966
+ * @param precomputes precomputed tables
967
+ * @param n scalar (we don't check here, but should be less than curve order)
968
+ * @param acc accumulator point to add result of multiplication
969
+ * @returns point
970
+ */
971
+ wNAFUnsafe(W, precomputes, n, acc = c.ZERO) {
972
+ const { windows, windowSize } = calcWOpts(W, bits);
973
+ const mask = BigInt(2 ** W - 1); // Create mask with W ones: 0b1111 for W=4 etc.
974
+ const maxNumber = 2 ** W;
975
+ const shiftBy = BigInt(W);
976
+ for (let window = 0; window < windows; window++) {
977
+ const offset = window * windowSize;
978
+ if (n === _0n$3)
979
+ break; // No need to go over empty scalar
980
+ // Extract W bits.
981
+ let wbits = Number(n & mask);
982
+ // Shift number by W bits.
983
+ n >>= shiftBy;
984
+ // If the bits are bigger than max size, we'll split those.
985
+ // +224 => 256 - 32
986
+ if (wbits > windowSize) {
987
+ wbits -= maxNumber;
988
+ n += _1n$5;
989
+ }
990
+ if (wbits === 0)
991
+ continue;
992
+ let curr = precomputes[offset + Math.abs(wbits) - 1]; // -1 because we skip zero
993
+ if (wbits < 0)
994
+ curr = curr.negate();
995
+ // NOTE: by re-using acc, we can save a lot of additions in case of MSM
996
+ acc = acc.add(curr);
997
+ }
998
+ return acc;
999
+ },
1000
+ getPrecomputes(W, P, transform) {
934
1001
  // Calculate precomputes on a first run, reuse them after
935
1002
  let comp = pointPrecomputes.get(P);
936
1003
  if (!comp) {
@@ -938,62 +1005,66 @@ function wNAF(c, bits) {
938
1005
  if (W !== 1)
939
1006
  pointPrecomputes.set(P, transform(comp));
940
1007
  }
941
- return this.wNAF(W, comp, n);
1008
+ return comp;
1009
+ },
1010
+ wNAFCached(P, n, transform) {
1011
+ const W = getW(P);
1012
+ return this.wNAF(W, this.getPrecomputes(W, P, transform), n);
1013
+ },
1014
+ wNAFCachedUnsafe(P, n, transform, prev) {
1015
+ const W = getW(P);
1016
+ if (W === 1)
1017
+ return this.unsafeLadder(P, n, prev); // For W=1 ladder is ~x2 faster
1018
+ return this.wNAFUnsafe(W, this.getPrecomputes(W, P, transform), n, prev);
942
1019
  },
943
1020
  // We calculate precomputes for elliptic curve point multiplication
944
1021
  // using windowed method. This specifies window size and
945
1022
  // stores precomputed values. Usually only base point would be precomputed.
946
1023
  setWindowSize(P, W) {
947
- validateW(W);
1024
+ validateW(W, bits);
948
1025
  pointWindowSizes.set(P, W);
949
1026
  pointPrecomputes.delete(P);
950
1027
  },
951
1028
  };
952
1029
  }
953
1030
  /**
954
- * Pippenger algorithm for multi-scalar multiplication (MSM).
955
- * MSM is basically (Pa + Qb + Rc + ...).
1031
+ * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
956
1032
  * 30x faster vs naive addition on L=4096, 10x faster with precomputes.
957
1033
  * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL.
958
1034
  * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0.
959
1035
  * @param c Curve Point constructor
960
- * @param field field over CURVE.N - important that it's not over CURVE.P
1036
+ * @param fieldN field over CURVE.N - important that it's not over CURVE.P
961
1037
  * @param points array of L curve points
962
1038
  * @param scalars array of L scalars (aka private keys / bigints)
963
1039
  */
964
- function pippenger(c, field, points, scalars) {
1040
+ function pippenger(c, fieldN, points, scalars) {
965
1041
  // If we split scalars by some window (let's say 8 bits), every chunk will only
966
1042
  // take 256 buckets even if there are 4096 scalars, also re-uses double.
967
1043
  // TODO:
968
1044
  // - https://eprint.iacr.org/2024/750.pdf
969
1045
  // - https://tches.iacr.org/index.php/TCHES/article/view/10287
970
1046
  // 0 is accepted in scalars
971
- if (!Array.isArray(points) || !Array.isArray(scalars) || scalars.length !== points.length)
1047
+ validateMSMPoints(points, c);
1048
+ validateMSMScalars(scalars, fieldN);
1049
+ if (points.length !== scalars.length)
972
1050
  throw new Error('arrays of points and scalars must have equal length');
973
- scalars.forEach((s, i) => {
974
- if (!field.isValid(s))
975
- throw new Error(`wrong scalar at index ${i}`);
976
- });
977
- points.forEach((p, i) => {
978
- if (!(p instanceof c))
979
- throw new Error(`wrong point at index ${i}`);
980
- });
1051
+ const zero = c.ZERO;
981
1052
  const wbits = bitLen(BigInt(points.length));
982
1053
  const windowSize = wbits > 12 ? wbits - 3 : wbits > 4 ? wbits - 2 : wbits ? 2 : 1; // in bits
983
1054
  const MASK = (1 << windowSize) - 1;
984
- const buckets = new Array(MASK + 1).fill(c.ZERO); // +1 for zero array
985
- const lastBits = Math.floor((field.BITS - 1) / windowSize) * windowSize;
986
- let sum = c.ZERO;
1055
+ const buckets = new Array(MASK + 1).fill(zero); // +1 for zero array
1056
+ const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize;
1057
+ let sum = zero;
987
1058
  for (let i = lastBits; i >= 0; i -= windowSize) {
988
- buckets.fill(c.ZERO);
1059
+ buckets.fill(zero);
989
1060
  for (let j = 0; j < scalars.length; j++) {
990
1061
  const scalar = scalars[j];
991
1062
  const wbits = Number((scalar >> BigInt(i)) & BigInt(MASK));
992
1063
  buckets[wbits] = buckets[wbits].add(points[j]);
993
1064
  }
994
- let resI = c.ZERO; // not using this will do small speed-up, but will lose ct
1065
+ let resI = zero; // not using this will do small speed-up, but will lose ct
995
1066
  // Skip first bucket, because it is zero
996
- for (let j = buckets.length - 1, sumI = c.ZERO; j > 0; j--) {
1067
+ for (let j = buckets.length - 1, sumI = zero; j > 0; j--) {
997
1068
  sumI = sumI.add(buckets[j]);
998
1069
  resI = resI.add(sumI);
999
1070
  }
@@ -1048,12 +1119,12 @@ function validatePointOpts(curve) {
1048
1119
  const { endo, Fp, a } = opts;
1049
1120
  if (endo) {
1050
1121
  if (!Fp.eql(a, Fp.ZERO)) {
1051
- throw new Error('Endomorphism can only be defined for Koblitz curves that have a=0');
1122
+ throw new Error('invalid endomorphism, can only be defined for Koblitz curves that have a=0');
1052
1123
  }
1053
1124
  if (typeof endo !== 'object' ||
1054
1125
  typeof endo.beta !== 'bigint' ||
1055
1126
  typeof endo.splitScalar !== 'function') {
1056
- throw new Error('Expected endomorphism with beta: bigint and splitScalar: function');
1127
+ throw new Error('invalid endomorphism, expected beta: bigint and splitScalar: function');
1057
1128
  }
1058
1129
  }
1059
1130
  return Object.freeze({ ...opts });
@@ -1087,7 +1158,8 @@ const DER = {
1087
1158
  throw new E('tlv.encode: long form length too big');
1088
1159
  // length of length with long form flag
1089
1160
  const lenLen = dataLen > 127 ? numberToHexUnpadded((len.length / 2) | 128) : '';
1090
- return `${numberToHexUnpadded(tag)}${lenLen}${len}${data}`;
1161
+ const t = numberToHexUnpadded(tag);
1162
+ return t + lenLen + len + data;
1091
1163
  },
1092
1164
  // v - value, l - left bytes (unparsed)
1093
1165
  decode(tag, data) {
@@ -1140,15 +1212,15 @@ const DER = {
1140
1212
  if (Number.parseInt(hex[0], 16) & 0b1000)
1141
1213
  hex = '00' + hex;
1142
1214
  if (hex.length & 1)
1143
- throw new E('unexpected assertion');
1215
+ throw new E('unexpected DER parsing assertion: unpadded hex');
1144
1216
  return hex;
1145
1217
  },
1146
1218
  decode(data) {
1147
1219
  const { Err: E } = DER;
1148
1220
  if (data[0] & 128)
1149
- throw new E('Invalid signature integer: negative');
1221
+ throw new E('invalid signature integer: negative');
1150
1222
  if (data[0] === 0x00 && !(data[1] & 128))
1151
- throw new E('Invalid signature integer: unnecessary leading zero');
1223
+ throw new E('invalid signature integer: unnecessary leading zero');
1152
1224
  return b2n(data);
1153
1225
  },
1154
1226
  },
@@ -1159,16 +1231,18 @@ const DER = {
1159
1231
  abytes(data);
1160
1232
  const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data);
1161
1233
  if (seqLeftBytes.length)
1162
- throw new E('Invalid signature: left bytes after parsing');
1234
+ throw new E('invalid signature: left bytes after parsing');
1163
1235
  const { v: rBytes, l: rLeftBytes } = tlv.decode(0x02, seqBytes);
1164
1236
  const { v: sBytes, l: sLeftBytes } = tlv.decode(0x02, rLeftBytes);
1165
1237
  if (sLeftBytes.length)
1166
- throw new E('Invalid signature: left bytes after parsing');
1238
+ throw new E('invalid signature: left bytes after parsing');
1167
1239
  return { r: int.decode(rBytes), s: int.decode(sBytes) };
1168
1240
  },
1169
1241
  hexFromSig(sig) {
1170
1242
  const { _tlv: tlv, _int: int } = DER;
1171
- const seq = `${tlv.encode(0x02, int.encode(sig.r))}${tlv.encode(0x02, int.encode(sig.s))}`;
1243
+ const rs = tlv.encode(0x02, int.encode(sig.r));
1244
+ const ss = tlv.encode(0x02, int.encode(sig.s));
1245
+ const seq = rs + ss;
1172
1246
  return tlv.encode(0x30, seq);
1173
1247
  },
1174
1248
  };
@@ -1222,7 +1296,7 @@ function weierstrassPoints(opts) {
1222
1296
  key = bytesToHex(key);
1223
1297
  // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes
1224
1298
  if (typeof key !== 'string' || !lengths.includes(key.length))
1225
- throw new Error('Invalid key');
1299
+ throw new Error('invalid private key');
1226
1300
  key = key.padStart(nByteLength * 2, '0');
1227
1301
  }
1228
1302
  let num;
@@ -1233,7 +1307,7 @@ function weierstrassPoints(opts) {
1233
1307
  : bytesToNumberBE(ensureBytes('private key', key, nByteLength));
1234
1308
  }
1235
1309
  catch (error) {
1236
- throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);
1310
+ throw new Error('invalid private key, expected hex or ' + nByteLength + ' bytes, got ' + typeof key);
1237
1311
  }
1238
1312
  if (wrapPrivateKey)
1239
1313
  num = mod(num, N); // disabled by default, enabled for BLS
@@ -1273,7 +1347,7 @@ function weierstrassPoints(opts) {
1273
1347
  if (p.is0()) {
1274
1348
  // (0, 1, 0) aka ZERO is invalid in most contexts.
1275
1349
  // In BLS, ZERO can be serialized, so we allow it.
1276
- // (0, 0, 0) is wrong representation of ZERO and is always invalid.
1350
+ // (0, 0, 0) is invalid representation of ZERO.
1277
1351
  if (CURVE.allowInfinityPoint && !Fp.is0(p.py))
1278
1352
  return;
1279
1353
  throw new Error('bad point: ZERO');
@@ -1497,16 +1571,17 @@ function weierstrassPoints(opts) {
1497
1571
  * an exposed private key e.g. sig verification, which works over *public* keys.
1498
1572
  */
1499
1573
  multiplyUnsafe(sc) {
1500
- aInRange('scalar', sc, _0n$2, CURVE.n);
1574
+ const { endo, n: N } = CURVE;
1575
+ aInRange('scalar', sc, _0n$2, N);
1501
1576
  const I = Point.ZERO;
1502
1577
  if (sc === _0n$2)
1503
1578
  return I;
1504
- if (sc === _1n$4)
1579
+ if (this.is0() || sc === _1n$4)
1505
1580
  return this;
1506
- const { endo } = CURVE;
1507
- if (!endo)
1508
- return wnaf.unsafeLadder(this, sc);
1509
- // Apply endomorphism
1581
+ // Case a: no endomorphism. Case b: has precomputes.
1582
+ if (!endo || wnaf.hasPrecomputes(this))
1583
+ return wnaf.wNAFCachedUnsafe(this, sc, Point.normalizeZ);
1584
+ // Case c: endomorphism
1510
1585
  let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc);
1511
1586
  let k1p = I;
1512
1587
  let k2p = I;
@@ -1692,7 +1767,9 @@ function weierstrass(curveDef) {
1692
1767
  return { x, y };
1693
1768
  }
1694
1769
  else {
1695
- throw new Error(`Point of length ${len} was invalid. Expected ${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes`);
1770
+ const cl = compressedLen;
1771
+ const ul = uncompressedLen;
1772
+ throw new Error('invalid Point, expected length of ' + cl + ', or uncompressed ' + ul + ', got ' + len);
1696
1773
  }
1697
1774
  },
1698
1775
  });
@@ -1857,6 +1934,9 @@ function weierstrass(curveDef) {
1857
1934
  // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors
1858
1935
  const bits2int = CURVE.bits2int ||
1859
1936
  function (bytes) {
1937
+ // Our custom check "just in case"
1938
+ if (bytes.length > 8192)
1939
+ throw new Error('input is too large');
1860
1940
  // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)
1861
1941
  // for some cases, since bytes.length * 8 is not actual bitLength.
1862
1942
  const num = bytesToNumberBE(bytes); // check for == u8 done here
@@ -1873,15 +1953,15 @@ function weierstrass(curveDef) {
1873
1953
  * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.
1874
1954
  */
1875
1955
  function int2octets(num) {
1876
- aInRange(`num < 2^${CURVE.nBitLength}`, num, _0n$2, ORDER_MASK);
1956
+ aInRange('num < 2^' + CURVE.nBitLength, num, _0n$2, ORDER_MASK);
1877
1957
  // works with order, can have different size than numToField!
1878
1958
  return numberToBytesBE(num, CURVE.nByteLength);
1879
1959
  }
1880
1960
  // Steps A, D of RFC6979 3.2
1881
1961
  // Creates RFC6979 seed; converts msg/privKey to numbers.
1882
1962
  // Used only in sign, not in verify.
1883
- // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, this will be wrong at least for P521.
1884
- // Also it can be bigger for P224 + SHA256
1963
+ // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order,
1964
+ // this will be invalid at least for P521. Also it can be bigger for P224 + SHA256
1885
1965
  function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
1886
1966
  if (['recovered', 'canonical'].some((k) => k in opts))
1887
1967
  throw new Error('sign() legacy options not supported');
@@ -1975,39 +2055,48 @@ function weierstrass(curveDef) {
1975
2055
  const sg = signature;
1976
2056
  msgHash = ensureBytes('msgHash', msgHash);
1977
2057
  publicKey = ensureBytes('publicKey', publicKey);
2058
+ const { lowS, prehash, format } = opts;
2059
+ // Verify opts, deduce signature format
2060
+ validateSigVerOpts(opts);
1978
2061
  if ('strict' in opts)
1979
2062
  throw new Error('options.strict was renamed to lowS');
1980
- validateSigVerOpts(opts);
1981
- const { lowS, prehash } = opts;
2063
+ if (format !== undefined && format !== 'compact' && format !== 'der')
2064
+ throw new Error('format must be compact or der');
2065
+ const isHex = typeof sg === 'string' || isBytes(sg);
2066
+ const isObj = !isHex &&
2067
+ !format &&
2068
+ typeof sg === 'object' &&
2069
+ sg !== null &&
2070
+ typeof sg.r === 'bigint' &&
2071
+ typeof sg.s === 'bigint';
2072
+ if (!isHex && !isObj)
2073
+ throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance');
1982
2074
  let _sig = undefined;
1983
2075
  let P;
1984
2076
  try {
1985
- if (typeof sg === 'string' || isBytes(sg)) {
2077
+ if (isObj)
2078
+ _sig = new Signature(sg.r, sg.s);
2079
+ if (isHex) {
1986
2080
  // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length).
1987
2081
  // Since DER can also be 2*nByteLength bytes, we check for it first.
1988
2082
  try {
1989
- _sig = Signature.fromDER(sg);
2083
+ if (format !== 'compact')
2084
+ _sig = Signature.fromDER(sg);
1990
2085
  }
1991
2086
  catch (derError) {
1992
2087
  if (!(derError instanceof DER.Err))
1993
2088
  throw derError;
1994
- _sig = Signature.fromCompact(sg);
1995
2089
  }
1996
- }
1997
- else if (typeof sg === 'object' && typeof sg.r === 'bigint' && typeof sg.s === 'bigint') {
1998
- const { r, s } = sg;
1999
- _sig = new Signature(r, s);
2000
- }
2001
- else {
2002
- throw new Error('PARSE');
2090
+ if (!_sig && format !== 'der')
2091
+ _sig = Signature.fromCompact(sg);
2003
2092
  }
2004
2093
  P = Point.fromHex(publicKey);
2005
2094
  }
2006
2095
  catch (error) {
2007
- if (error.message === 'PARSE')
2008
- throw new Error(`signature must be Signature instance, Uint8Array or hex string`);
2009
2096
  return false;
2010
2097
  }
2098
+ if (!_sig)
2099
+ return false;
2011
2100
  if (lowS && _sig.hasHighS())
2012
2101
  return false;
2013
2102
  if (prehash)
@@ -2052,14 +2141,14 @@ function createCurve(curveDef, defHash) {
2052
2141
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2053
2142
  // NIST secp256r1 aka p256
2054
2143
  // https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256
2055
- const Fp$7 = Field(BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'));
2056
- const CURVE_A$4 = Fp$7.create(BigInt('-3'));
2144
+ const Fp256 = Field(BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'));
2145
+ const CURVE_A$4 = Fp256.create(BigInt('-3'));
2057
2146
  const CURVE_B$4 = BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b');
2058
2147
  // prettier-ignore
2059
2148
  const p256 = createCurve({
2060
2149
  a: CURVE_A$4, // Equation params: a, b
2061
2150
  b: CURVE_B$4,
2062
- Fp: Fp$7, // Field: 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n
2151
+ Fp: Fp256, // Field: 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n
2063
2152
  // Curve order, total count of valid points in the field
2064
2153
  n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),
2065
2154
  // Base (generator) point (x, y)
@@ -2075,15 +2164,15 @@ const p256 = createCurve({
2075
2164
  // Field over which we'll do calculations.
2076
2165
  // prettier-ignore
2077
2166
  const P$1 = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff');
2078
- const Fp$6 = Field(P$1);
2079
- const CURVE_A$3 = Fp$6.create(BigInt('-3'));
2167
+ const Fp384 = Field(P$1);
2168
+ const CURVE_A$3 = Fp384.create(BigInt('-3'));
2080
2169
  // prettier-ignore
2081
2170
  const CURVE_B$3 = BigInt('0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef');
2082
2171
  // prettier-ignore
2083
2172
  const p384 = createCurve({
2084
2173
  a: CURVE_A$3, // Equation params: a, b
2085
2174
  b: CURVE_B$3,
2086
- Fp: Fp$6, // Field: 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
2175
+ Fp: Fp384, // Field: 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
2087
2176
  // Curve order, total count of valid points in the field.
2088
2177
  n: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'),
2089
2178
  // Base (generator) point (x, y)
@@ -2100,11 +2189,11 @@ const p384 = createCurve({
2100
2189
  // Field over which we'll do calculations.
2101
2190
  // prettier-ignore
2102
2191
  const P = BigInt('0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
2103
- const Fp$5 = Field(P);
2192
+ const Fp521 = Field(P);
2104
2193
  const CURVE = {
2105
- a: Fp$5.create(BigInt('-3')),
2194
+ a: Fp521.create(BigInt('-3')),
2106
2195
  b: BigInt('0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00'),
2107
- Fp: Fp$5,
2196
+ Fp: Fp521,
2108
2197
  n: BigInt('0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409'),
2109
2198
  Gx: BigInt('0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66'),
2110
2199
  Gy: BigInt('0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'),
@@ -2114,7 +2203,7 @@ const CURVE = {
2114
2203
  const p521 = createCurve({
2115
2204
  a: CURVE.a, // Equation params: a, b
2116
2205
  b: CURVE.b,
2117
- Fp: Fp$5, // Field: 2n**521n - 1n
2206
+ Fp: Fp521, // Field: 2n**521n - 1n
2118
2207
  // Curve order, total count of valid points in the field
2119
2208
  n: CURVE.n,
2120
2209
  Gx: CURVE.Gx, // Base point (x, y) aka generator point
@@ -2157,6 +2246,10 @@ function validateOpts$1(curve) {
2157
2246
  function twistedEdwards(curveDef) {
2158
2247
  const CURVE = validateOpts$1(curveDef);
2159
2248
  const { Fp, n: CURVE_ORDER, prehash: prehash, hash: cHash, randomBytes, nByteLength, h: cofactor, } = CURVE;
2249
+ // Important:
2250
+ // There are some places where Fp.BYTES is used instead of nByteLength.
2251
+ // So far, everything has been tested with curves of Fp.BYTES == nByteLength.
2252
+ // TODO: test and find curves which behave otherwise.
2160
2253
  const MASK = _2n$2 << (BigInt(nByteLength * 8) - _1n$3);
2161
2254
  const modP = Fp.create; // Function overrides
2162
2255
  const Fn = Field(CURVE.n, CURVE.nBitLength);
@@ -2370,16 +2463,15 @@ function twistedEdwards(curveDef) {
2370
2463
  // It's faster, but should only be used when you don't care about
2371
2464
  // an exposed private key e.g. sig verification.
2372
2465
  // Does NOT allow scalars higher than CURVE.n.
2373
- multiplyUnsafe(scalar) {
2466
+ // Accepts optional accumulator to merge with multiply (important for sparse scalars)
2467
+ multiplyUnsafe(scalar, acc = Point.ZERO) {
2374
2468
  const n = scalar;
2375
2469
  aInRange('scalar', n, _0n$1, CURVE_ORDER); // 0 <= scalar < L
2376
2470
  if (n === _0n$1)
2377
2471
  return I;
2378
- if (this.equals(I) || n === _1n$3)
2472
+ if (this.is0() || n === _1n$3)
2379
2473
  return this;
2380
- if (this.equals(G))
2381
- return this.wNAF(n).p;
2382
- return wnaf.unsafeLadder(this, n);
2474
+ return wnaf.wNAFCachedUnsafe(this, n, Point.normalizeZ, acc);
2383
2475
  }
2384
2476
  // Checks if point is of small order.
2385
2477
  // If you add something to small order point, you will have "dirty"
@@ -2415,6 +2507,7 @@ function twistedEdwards(curveDef) {
2415
2507
  const lastByte = hex[len - 1]; // select last byte
2416
2508
  normed[len - 1] = lastByte & ~0x80; // clear last bit
2417
2509
  const y = bytesToNumberLE(normed);
2510
+ // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5.
2418
2511
  // RFC8032 prohibits >= p, but ZIP215 doesn't
2419
2512
  // zip215=true: 0 <= y < MASK (2^256 for ed25519)
2420
2513
  // zip215=false: 0 <= y < P (2^255-19 for ed25519)
@@ -2463,7 +2556,7 @@ function twistedEdwards(curveDef) {
2463
2556
  }
2464
2557
  /** Convenience method that creates public key and other stuff. RFC8032 5.1.5 */
2465
2558
  function getExtendedPublicKey(key) {
2466
- const len = nByteLength;
2559
+ const len = Fp.BYTES;
2467
2560
  key = ensureBytes('private key', key, len);
2468
2561
  // Hash private key with curve's hash function to produce uniformingly random input
2469
2562
  // Check byte lengths: ensure(64, h(ensure(32, key)))
@@ -2496,23 +2589,29 @@ function twistedEdwards(curveDef) {
2496
2589
  const s = modN(r + k * scalar); // S = (r + k * s) mod L
2497
2590
  aInRange('signature.s', s, _0n$1, CURVE_ORDER); // 0 <= s < l
2498
2591
  const res = concatBytes(R, numberToBytesLE(s, Fp.BYTES));
2499
- return ensureBytes('result', res, nByteLength * 2); // 64-byte signature
2592
+ return ensureBytes('result', res, Fp.BYTES * 2); // 64-byte signature
2500
2593
  }
2501
2594
  const verifyOpts = VERIFY_DEFAULT;
2595
+ /**
2596
+ * Verifies EdDSA signature against message and public key. RFC8032 5.1.7.
2597
+ * An extended group equation is checked.
2598
+ */
2502
2599
  function verify(sig, msg, publicKey, options = verifyOpts) {
2503
2600
  const { context, zip215 } = options;
2504
2601
  const len = Fp.BYTES; // Verifies EdDSA signature against message and public key. RFC8032 5.1.7.
2505
2602
  sig = ensureBytes('signature', sig, 2 * len); // An extended group equation is checked.
2506
2603
  msg = ensureBytes('message', msg);
2604
+ publicKey = ensureBytes('publicKey', publicKey, len);
2507
2605
  if (zip215 !== undefined)
2508
2606
  abool('zip215', zip215);
2509
2607
  if (prehash)
2510
2608
  msg = prehash(msg); // for ed25519ph, etc
2511
2609
  const s = bytesToNumberLE(sig.slice(len, 2 * len));
2512
- // zip215: true is good for consensus-critical apps and allows points < 2^256
2513
- // zip215: false follows RFC8032 / NIST186-5 and restricts points to CURVE.p
2514
2610
  let A, R, SB;
2515
2611
  try {
2612
+ // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5.
2613
+ // zip215=true: 0 <= y < MASK (2^256 for ed25519)
2614
+ // zip215=false: 0 <= y < P (2^255-19 for ed25519)
2516
2615
  A = Point.fromHex(publicKey, zip215);
2517
2616
  R = Point.fromHex(sig.slice(0, len), zip215);
2518
2617
  SB = G.multiplyUnsafe(s); // 0 <= s < l is done inside
@@ -2524,6 +2623,7 @@ function twistedEdwards(curveDef) {
2524
2623
  return false;
2525
2624
  const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg);
2526
2625
  const RkA = R.add(A.multiplyUnsafe(k));
2626
+ // Extended group equation
2527
2627
  // [8][S]B = [8]R + [8][k]A'
2528
2628
  return RkA.subtract(SB).clearCofactor().equals(Point.ZERO);
2529
2629
  }
@@ -2673,8 +2773,10 @@ function montgomery(curveDef) {
2673
2773
  function decodeScalar(n) {
2674
2774
  const bytes = ensureBytes('scalar', n);
2675
2775
  const len = bytes.length;
2676
- if (len !== montgomeryBytes && len !== fieldLen)
2677
- throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${len}`);
2776
+ if (len !== montgomeryBytes && len !== fieldLen) {
2777
+ let valid = '' + montgomeryBytes + ' or ' + fieldLen;
2778
+ throw new Error('invalid scalar, expected ' + valid + ' bytes, got ' + len);
2779
+ }
2678
2780
  return bytesToNumberLE(adjustScalarBytes(bytes));
2679
2781
  }
2680
2782
  function scalarMult(scalar, u) {
@@ -2684,7 +2786,7 @@ function montgomery(curveDef) {
2684
2786
  // The result was not contributory
2685
2787
  // https://cr.yp.to/ecdh.html#validate
2686
2788
  if (pu === _0n)
2687
- throw new Error('Invalid private or public key received');
2789
+ throw new Error('invalid private or public key received');
2688
2790
  return encodeUCoordinate(pu);
2689
2791
  }
2690
2792
  // Computes public key from private. By doing scalar multiplication of base point.
@@ -2767,14 +2869,14 @@ function uvRatio(u, v) {
2767
2869
  // square root exists, and the decoding fails.
2768
2870
  return { isValid: mod(x2 * v, P) === u, value: x };
2769
2871
  }
2770
- const Fp$4 = Field(ed448P, 456, true);
2872
+ const Fp$3 = Field(ed448P, 456, true);
2771
2873
  const ED448_DEF = {
2772
2874
  // Param: a
2773
2875
  a: BigInt(1),
2774
2876
  // -39081. Negative number is P - number
2775
2877
  d: BigInt('726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358'),
2776
2878
  // Finite field 𝔽p over which we'll do calculations; 2n**448n - 2n**224n - 1n
2777
- Fp: Fp$4,
2879
+ Fp: Fp$3,
2778
2880
  // Subgroup order: how many points curve has;
2779
2881
  // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n
2780
2882
  n: BigInt('181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779'),
@@ -2792,7 +2894,7 @@ const ED448_DEF = {
2792
2894
  // dom4
2793
2895
  domain: (data, ctx, phflag) => {
2794
2896
  if (ctx.length > 255)
2795
- throw new Error(`Context is too big: ${ctx.length}`);
2897
+ throw new Error('context must be smaller than 255, got: ' + ctx.length);
2796
2898
  return concatBytes$1(utf8ToBytes$1('SigEd448'), new Uint8Array([phflag ? 1 : 0, ctx.length]), ctx, data);
2797
2899
  },
2798
2900
  uvRatio,
@@ -2818,7 +2920,7 @@ const x448 = /* @__PURE__ */ (() => montgomery({
2818
2920
  }))();
2819
2921
  // TODO: add edwardsToMontgomeryPriv, similar to ed25519 version
2820
2922
  // Hash To Curve Elligator2 Map
2821
- (Fp$4.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic
2923
+ (Fp$3.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic
2822
2924
  BigInt(156326);
2823
2925
  // 1-d
2824
2926
  BigInt('39082');
@@ -2860,18 +2962,18 @@ function sqrtMod(y) {
2860
2962
  const t1 = (pow2(b223, _23n, P) * b22) % P;
2861
2963
  const t2 = (pow2(t1, _6n, P) * b2) % P;
2862
2964
  const root = pow2(t2, _2n, P);
2863
- if (!Fp$3.eql(Fp$3.sqr(root), y))
2965
+ if (!Fpk1.eql(Fpk1.sqr(root), y))
2864
2966
  throw new Error('Cannot find square root');
2865
2967
  return root;
2866
2968
  }
2867
- const Fp$3 = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod });
2969
+ const Fpk1 = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod });
2868
2970
  /**
2869
2971
  * secp256k1 short weierstrass curve and ECDSA signatures over it.
2870
2972
  */
2871
2973
  const secp256k1 = createCurve({
2872
2974
  a: BigInt(0), // equation params: a, b
2873
2975
  b: BigInt(7), // Seem to be rigid: bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975
2874
- Fp: Fp$3, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n
2976
+ Fp: Fpk1, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n
2875
2977
  n: secp256k1N, // Curve order, total count of valid points in the field
2876
2978
  // Base point (x, y) aka generator point
2877
2979
  Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),