@protontech/openpgp 6.1.1-patch.4 → 6.2.1

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 (49) hide show
  1. package/README.md +13 -2
  2. package/dist/lightweight/argon2id.min.mjs +2 -2
  3. package/dist/lightweight/argon2id.min.mjs.map +1 -1
  4. package/dist/lightweight/argon2id.mjs +4 -4
  5. package/dist/lightweight/legacy_ciphers.min.mjs +1 -1
  6. package/dist/lightweight/legacy_ciphers.min.mjs.map +1 -1
  7. package/dist/lightweight/legacy_ciphers.mjs +10 -10
  8. package/dist/lightweight/nacl-fast.min.mjs +3 -0
  9. package/dist/lightweight/nacl-fast.min.mjs.map +1 -0
  10. package/dist/lightweight/nacl-fast.mjs +1382 -0
  11. package/dist/lightweight/noble_curves.min.mjs +11 -12
  12. package/dist/lightweight/noble_curves.min.mjs.map +1 -1
  13. package/dist/lightweight/noble_curves.mjs +2175 -1752
  14. package/dist/lightweight/noble_hashes.min.mjs +2 -2
  15. package/dist/lightweight/noble_hashes.min.mjs.map +1 -1
  16. package/dist/lightweight/noble_hashes.mjs +80 -51
  17. package/dist/lightweight/noble_post_quantum.min.mjs +3 -4
  18. package/dist/lightweight/noble_post_quantum.min.mjs.map +1 -1
  19. package/dist/lightweight/noble_post_quantum.mjs +352 -10
  20. package/dist/lightweight/openpgp.min.mjs +3 -4
  21. package/dist/lightweight/openpgp.min.mjs.map +1 -1
  22. package/dist/lightweight/openpgp.mjs +998 -2820
  23. package/dist/lightweight/seek-bzip.min.mjs +2 -2
  24. package/dist/lightweight/seek-bzip.min.mjs.map +1 -1
  25. package/dist/lightweight/seek-bzip.mjs +780 -746
  26. package/dist/lightweight/sha512.min.mjs +4 -2
  27. package/dist/lightweight/sha512.min.mjs.map +1 -1
  28. package/dist/lightweight/sha512.mjs +672 -130
  29. package/dist/node/openpgp.cjs +10685 -10141
  30. package/dist/node/openpgp.min.cjs +14 -17
  31. package/dist/node/openpgp.min.cjs.map +1 -1
  32. package/dist/node/openpgp.min.mjs +14 -17
  33. package/dist/node/openpgp.min.mjs.map +1 -1
  34. package/dist/node/openpgp.mjs +10685 -10140
  35. package/dist/openpgp.js +11728 -11188
  36. package/dist/openpgp.min.js +14 -17
  37. package/dist/openpgp.min.js.map +1 -1
  38. package/dist/openpgp.min.mjs +14 -17
  39. package/dist/openpgp.min.mjs.map +1 -1
  40. package/dist/openpgp.mjs +11728 -11188
  41. package/{src → dist/types}/config/config.d.ts +1 -21
  42. package/{openpgp.d.ts → dist/types/index.d.ts} +94 -76
  43. package/dist/types/packet/grammar.d.ts +33 -0
  44. package/package.json +40 -39
  45. package/dist/lightweight/sha3.min.mjs +0 -4
  46. package/dist/lightweight/sha3.min.mjs.map +0 -1
  47. package/dist/lightweight/sha3.mjs +0 -401
  48. /package/{src → dist/types}/config/index.d.ts +0 -0
  49. /package/{src → dist/types}/enums.d.ts +0 -0
@@ -1,121 +1,38 @@
1
- /*! OpenPGP.js v6.1.1-patch.4 - 2025-07-14 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */
1
+ /*! OpenPGP.js v6.2.1 - 2025-08-28 - 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 { 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';
4
+ import { h as hexToBytes, a as abytes, b as bytesToHex, i as isBytes, c as concatBytes, d as anumber, H as Hash, e as ahash, t as toBytes, f as clean, g as aexists, r as randomBytes, s as sha256, j as sha384, k as sha512, l as createHasher, m as shake256, n as sha256$1, o as sha384$1, p as sha512$1 } from './sha512.mjs';
6
5
 
7
- // HMAC (RFC 2104)
8
- class HMAC extends Hash {
9
- constructor(hash, _key) {
10
- super();
11
- this.finished = false;
12
- this.destroyed = false;
13
- ahash(hash);
14
- const key = toBytes(_key);
15
- this.iHash = hash.create();
16
- if (typeof this.iHash.update !== 'function')
17
- throw new Error('Expected instance of class which extends utils.Hash');
18
- this.blockLen = this.iHash.blockLen;
19
- this.outputLen = this.iHash.outputLen;
20
- const blockLen = this.blockLen;
21
- const pad = new Uint8Array(blockLen);
22
- // blockLen can be bigger than outputLen
23
- pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
24
- for (let i = 0; i < pad.length; i++)
25
- pad[i] ^= 0x36;
26
- this.iHash.update(pad);
27
- // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone
28
- this.oHash = hash.create();
29
- // Undo internal XOR && apply outer XOR
30
- for (let i = 0; i < pad.length; i++)
31
- pad[i] ^= 0x36 ^ 0x5c;
32
- this.oHash.update(pad);
33
- pad.fill(0);
34
- }
35
- update(buf) {
36
- aexists(this);
37
- this.iHash.update(buf);
38
- return this;
39
- }
40
- digestInto(out) {
41
- aexists(this);
42
- abytes$1(out, this.outputLen);
43
- this.finished = true;
44
- this.iHash.digestInto(out);
45
- this.oHash.update(out);
46
- this.oHash.digestInto(out);
47
- this.destroy();
48
- }
49
- digest() {
50
- const out = new Uint8Array(this.oHash.outputLen);
51
- this.digestInto(out);
52
- return out;
53
- }
54
- _cloneInto(to) {
55
- // Create new instance without calling constructor since key already in state and we don't know it.
56
- to || (to = Object.create(Object.getPrototypeOf(this), {}));
57
- const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
58
- to = to;
59
- to.finished = finished;
60
- to.destroyed = destroyed;
61
- to.blockLen = blockLen;
62
- to.outputLen = outputLen;
63
- to.oHash = oHash._cloneInto(to.oHash);
64
- to.iHash = iHash._cloneInto(to.iHash);
65
- return to;
66
- }
67
- destroy() {
68
- this.destroyed = true;
69
- this.oHash.destroy();
70
- this.iHash.destroy();
71
- }
72
- }
73
6
  /**
74
- * HMAC: RFC2104 message authentication code.
75
- * @param hash - function that would be used e.g. sha256
76
- * @param key - message key
77
- * @param message - message data
78
- * @example
79
- * import { hmac } from '@noble/hashes/hmac';
80
- * import { sha256 } from '@noble/hashes/sha2';
81
- * const mac1 = hmac(sha256, 'key', 'message');
7
+ * Hex, bytes and number utilities.
8
+ * @module
82
9
  */
83
- const hmac = (hash, key, message) => new HMAC(hash, key).update(message).digest();
84
- hmac.create = (hash, key) => new HMAC(hash, key);
85
-
86
10
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
87
- // 100 lines of code in the file are duplicated from noble-hashes (utils).
88
- // This is OK: `abstract` directory does not use noble-hashes.
89
- // User may opt-in into using different hashing library. This way, noble-hashes
90
- // won't be included into their bundle.
91
11
  const _0n$5 = /* @__PURE__ */ BigInt(0);
92
- const _1n$7 = /* @__PURE__ */ BigInt(1);
93
- const _2n$4 = /* @__PURE__ */ BigInt(2);
94
- function isBytes(a) {
95
- return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
96
- }
97
- function abytes(item) {
98
- if (!isBytes(item))
99
- throw new Error('Uint8Array expected');
100
- }
101
- function abool(title, value) {
102
- if (typeof value !== 'boolean')
103
- throw new Error(title + ' boolean expected, got ' + value);
104
- }
105
- // Array where index 0xf0 (240) is mapped to string 'f0'
106
- const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));
107
- /**
108
- * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'
109
- */
110
- function bytesToHex(bytes) {
111
- abytes(bytes);
112
- // pre-caching improves the speed 6x
113
- let hex = '';
114
- for (let i = 0; i < bytes.length; i++) {
115
- hex += hexes[bytes[i]];
12
+ const _1n$6 = /* @__PURE__ */ BigInt(1);
13
+ // tmp name until v2
14
+ function _abool2(value, title = '') {
15
+ if (typeof value !== 'boolean') {
16
+ const prefix = title && `"${title}"`;
17
+ throw new Error(prefix + 'expected boolean, got type=' + typeof value);
116
18
  }
117
- return hex;
19
+ return value;
20
+ }
21
+ // tmp name until v2
22
+ /** Asserts something is Uint8Array. */
23
+ function _abytes2(value, length, title = '') {
24
+ const bytes = isBytes(value);
25
+ const len = value?.length;
26
+ const needsLen = length !== undefined;
27
+ if (!bytes || (needsLen && len !== length)) {
28
+ const prefix = title && `"${title}" `;
29
+ const ofLen = needsLen ? ` of length ${length}` : '';
30
+ const got = bytes ? `length=${len}` : `type=${typeof value}`;
31
+ throw new Error(prefix + 'expected Uint8Array' + ofLen + ', got ' + got);
32
+ }
33
+ return value;
118
34
  }
35
+ // Used in weierstrass, der
119
36
  function numberToHexUnpadded(num) {
120
37
  const hex = num.toString(16);
121
38
  return hex.length & 1 ? '0' + hex : hex;
@@ -125,39 +42,6 @@ function hexToNumber(hex) {
125
42
  throw new Error('hex string expected, got ' + typeof hex);
126
43
  return hex === '' ? _0n$5 : BigInt('0x' + hex); // Big Endian
127
44
  }
128
- // We use optimized technique to convert hex string to byte array
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)
137
- return;
138
- }
139
- /**
140
- * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])
141
- */
142
- function hexToBytes(hex) {
143
- if (typeof hex !== 'string')
144
- throw new Error('hex string expected, got ' + typeof hex);
145
- const hl = hex.length;
146
- const al = hl / 2;
147
- if (hl % 2)
148
- throw new Error('hex string expected, got unpadded hex of length ' + hl);
149
- const array = new Uint8Array(al);
150
- for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
151
- const n1 = asciiToBase16(hex.charCodeAt(hi));
152
- const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
153
- if (n1 === undefined || n2 === undefined) {
154
- const char = hex[hi] + hex[hi + 1];
155
- throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
156
- }
157
- array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163
158
- }
159
- return array;
160
- }
161
45
  // BE: Big Endian, LE: Little Endian
162
46
  function bytesToNumberBE(bytes) {
163
47
  return hexToNumber(bytesToHex(bytes));
@@ -172,15 +56,11 @@ function numberToBytesBE(n, len) {
172
56
  function numberToBytesLE(n, len) {
173
57
  return numberToBytesBE(n, len).reverse();
174
58
  }
175
- // Unpadded, rarely used
176
- function numberToVarBytesBE(n) {
177
- return hexToBytes(numberToHexUnpadded(n));
178
- }
179
59
  /**
180
60
  * Takes hex string or Uint8Array, converts to Uint8Array.
181
61
  * Validates output length.
182
62
  * Will throw error for other types.
183
- * @param title descriptive title for an error e.g. 'private key'
63
+ * @param title descriptive title for an error e.g. 'secret key'
184
64
  * @param hex hex string or Uint8Array
185
65
  * @param expectedLength optional, will compare to result array's length
186
66
  * @returns
@@ -209,40 +89,35 @@ function ensureBytes(title, hex, expectedLength) {
209
89
  return res;
210
90
  }
211
91
  /**
212
- * Copies several Uint8Arrays into one.
92
+ * Copies Uint8Array. We can't use u8a.slice(), because u8a can be Buffer,
93
+ * and Buffer#slice creates mutable copy. Never use Buffers!
213
94
  */
214
- function concatBytes(...arrays) {
215
- let sum = 0;
216
- for (let i = 0; i < arrays.length; i++) {
217
- const a = arrays[i];
218
- abytes(a);
219
- sum += a.length;
220
- }
221
- const res = new Uint8Array(sum);
222
- for (let i = 0, pad = 0; i < arrays.length; i++) {
223
- const a = arrays[i];
224
- res.set(a, pad);
225
- pad += a.length;
226
- }
227
- return res;
95
+ function copyBytes(bytes) {
96
+ return Uint8Array.from(bytes);
228
97
  }
229
- // Compares 2 u8a-s in kinda constant time
230
- function equalBytes(a, b) {
231
- if (a.length !== b.length)
232
- return false;
233
- let diff = 0;
234
- for (let i = 0; i < a.length; i++)
235
- diff |= a[i] ^ b[i];
236
- return diff === 0;
98
+ /**
99
+ * Decodes 7-bit ASCII string to Uint8Array, throws on non-ascii symbols
100
+ * Should be safe to use for things expected to be ASCII.
101
+ * Returns exact same result as utf8ToBytes for ASCII or throws.
102
+ */
103
+ function asciiToBytes(ascii) {
104
+ return Uint8Array.from(ascii, (c, i) => {
105
+ const charCode = c.charCodeAt(0);
106
+ if (c.length !== 1 || charCode > 127) {
107
+ throw new Error(`string contains non-ASCII character "${ascii[i]}" with code ${charCode} at position ${i}`);
108
+ }
109
+ return charCode;
110
+ });
237
111
  }
238
112
  /**
239
113
  * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
240
114
  */
241
- function utf8ToBytes(str) {
242
- if (typeof str !== 'string')
243
- throw new Error('string expected');
244
- return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
245
- }
115
+ // export const utf8ToBytes: typeof utf8ToBytes_ = utf8ToBytes_;
116
+ /**
117
+ * Converts bytes to string using UTF8 encoding.
118
+ * @example bytesToUtf8(Uint8Array.from([97, 98, 99])) // 'abc'
119
+ */
120
+ // export const bytesToUtf8: typeof bytesToUtf8_ = bytesToUtf8_;
246
121
  // Is positive bigint
247
122
  const isPosBig = (n) => typeof n === 'bigint' && _0n$5 <= n;
248
123
  function inRange(n, min, max) {
@@ -266,35 +141,19 @@ function aInRange(title, n, min, max) {
266
141
  /**
267
142
  * Calculates amount of bits in a bigint.
268
143
  * Same as `n.toString(2).length`
144
+ * TODO: merge with nLength in modular
269
145
  */
270
146
  function bitLen(n) {
271
147
  let len;
272
- for (len = 0; n > _0n$5; n >>= _1n$7, len += 1)
148
+ for (len = 0; n > _0n$5; n >>= _1n$6, len += 1)
273
149
  ;
274
150
  return len;
275
151
  }
276
- /**
277
- * Gets single bit at position.
278
- * NOTE: first bit position is 0 (same as arrays)
279
- * Same as `!!+Array.from(n.toString(2)).reverse()[pos]`
280
- */
281
- function bitGet(n, pos) {
282
- return (n >> BigInt(pos)) & _1n$7;
283
- }
284
- /**
285
- * Sets single bit at position.
286
- */
287
- function bitSet(n, pos, value) {
288
- return n | ((value ? _1n$7 : _0n$5) << BigInt(pos));
289
- }
290
152
  /**
291
153
  * Calculate mask for N bits. Not using ** operator with bigints because of old engines.
292
154
  * Same as BigInt(`0b${Array(i).fill('1').join('')}`)
293
155
  */
294
- const bitMask = (n) => (_2n$4 << BigInt(n - 1)) - _1n$7;
295
- // DRBG
296
- const u8n = (data) => new Uint8Array(data); // creates Uint8Array
297
- const u8fr = (arr) => Uint8Array.from(arr); // another shortcut
156
+ const bitMask = (n) => (_1n$6 << BigInt(n)) - _1n$6;
298
157
  /**
299
158
  * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
300
159
  * @returns function that will call DRBG until 2nd arg returns something meaningful
@@ -310,6 +169,8 @@ function createHmacDrbg(hashLen, qByteLen, hmacFn) {
310
169
  if (typeof hmacFn !== 'function')
311
170
  throw new Error('hmacFn must be a function');
312
171
  // Step B, Step C: set hashLen to 8*ceil(hlen/8)
172
+ const u8n = (len) => new Uint8Array(len); // creates Uint8Array
173
+ const u8of = (byte) => Uint8Array.of(byte); // another shortcut
313
174
  let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
314
175
  let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same
315
176
  let i = 0; // Iterations counter, will throw when over 1000
@@ -319,13 +180,13 @@ function createHmacDrbg(hashLen, qByteLen, hmacFn) {
319
180
  i = 0;
320
181
  };
321
182
  const h = (...b) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)
322
- const reseed = (seed = u8n()) => {
183
+ const reseed = (seed = u8n(0)) => {
323
184
  // HMAC-DRBG reseed() function. Steps D-G
324
- k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed)
185
+ k = h(u8of(0x00), seed); // k = hmac(k || v || 0x00 || seed)
325
186
  v = h(); // v = hmac(k || v)
326
187
  if (seed.length === 0)
327
188
  return;
328
- k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed)
189
+ k = h(u8of(0x01), seed); // k = hmac(k || v || 0x01 || seed)
329
190
  v = h(); // v = hmac(k || v)
330
191
  };
331
192
  const gen = () => {
@@ -353,51 +214,20 @@ function createHmacDrbg(hashLen, qByteLen, hmacFn) {
353
214
  };
354
215
  return genUntil;
355
216
  }
356
- // Validating curves and fields
357
- const validatorFns = {
358
- bigint: (val) => typeof val === 'bigint',
359
- function: (val) => typeof val === 'function',
360
- boolean: (val) => typeof val === 'boolean',
361
- string: (val) => typeof val === 'string',
362
- stringOrUint8Array: (val) => typeof val === 'string' || isBytes(val),
363
- isSafeInteger: (val) => Number.isSafeInteger(val),
364
- array: (val) => Array.isArray(val),
365
- field: (val, object) => object.Fp.isValid(val),
366
- hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
367
- };
368
- // type Record<K extends string | number | symbol, T> = { [P in K]: T; }
369
- function validateObject(object, validators, optValidators = {}) {
370
- const checkField = (fieldName, type, isOptional) => {
371
- const checkVal = validatorFns[type];
372
- if (typeof checkVal !== 'function')
373
- throw new Error('invalid validator function');
217
+ function _validateObject(object, fields, optFields = {}) {
218
+ if (!object || typeof object !== 'object')
219
+ throw new Error('expected valid options object');
220
+ function checkField(fieldName, expectedType, isOpt) {
374
221
  const val = object[fieldName];
375
- if (isOptional && val === undefined)
222
+ if (isOpt && val === undefined)
376
223
  return;
377
- if (!checkVal(val, object)) {
378
- throw new Error('param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val);
379
- }
380
- };
381
- for (const [fieldName, type] of Object.entries(validators))
382
- checkField(fieldName, type, false);
383
- for (const [fieldName, type] of Object.entries(optValidators))
384
- checkField(fieldName, type, true);
385
- return object;
386
- }
387
- // validate type tests
388
- // const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 };
389
- // const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok!
390
- // // Should fail type-check
391
- // const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' });
392
- // const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' });
393
- // const z3 = validateObject(o, { test: 'boolean', z: 'bug' });
394
- // const z4 = validateObject(o, { a: 'boolean', z: 'bug' });
395
- /**
396
- * throws not implemented error
397
- */
398
- const notImplemented = () => {
399
- throw new Error('not implemented');
400
- };
224
+ const current = typeof val;
225
+ if (current !== expectedType || val === null)
226
+ throw new Error(`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`);
227
+ }
228
+ Object.entries(fields).forEach(([k, v]) => checkField(k, v, false));
229
+ Object.entries(optFields).forEach(([k, v]) => checkField(k, v, true));
230
+ }
401
231
  /**
402
232
  * Memoizes (caches) computation result.
403
233
  * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed.
@@ -414,71 +244,25 @@ function memoized(fn) {
414
244
  };
415
245
  }
416
246
 
417
- var ut = /*#__PURE__*/Object.freeze({
418
- __proto__: null,
419
- aInRange: aInRange,
420
- abool: abool,
421
- abytes: abytes,
422
- bitGet: bitGet,
423
- bitLen: bitLen,
424
- bitMask: bitMask,
425
- bitSet: bitSet,
426
- bytesToHex: bytesToHex,
427
- bytesToNumberBE: bytesToNumberBE,
428
- bytesToNumberLE: bytesToNumberLE,
429
- concatBytes: concatBytes,
430
- createHmacDrbg: createHmacDrbg,
431
- ensureBytes: ensureBytes,
432
- equalBytes: equalBytes,
433
- hexToBytes: hexToBytes,
434
- hexToNumber: hexToNumber,
435
- inRange: inRange,
436
- isBytes: isBytes,
437
- memoized: memoized,
438
- notImplemented: notImplemented,
439
- numberToBytesBE: numberToBytesBE,
440
- numberToBytesLE: numberToBytesLE,
441
- numberToHexUnpadded: numberToHexUnpadded,
442
- numberToVarBytesBE: numberToVarBytesBE,
443
- utf8ToBytes: utf8ToBytes,
444
- validateObject: validateObject
445
- });
446
-
247
+ /**
248
+ * Utils for modular division and fields.
249
+ * Field over 11 is a finite (Galois) field is integer number operations `mod 11`.
250
+ * There is no division: it is replaced by modular multiplicative inverse.
251
+ * @module
252
+ */
447
253
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
448
- // Utilities for modular arithmetics and finite fields
449
254
  // prettier-ignore
450
- const _0n$4 = BigInt(0), _1n$6 = BigInt(1), _2n$3 = /* @__PURE__ */ BigInt(2), _3n$2 = /* @__PURE__ */ BigInt(3);
255
+ const _0n$4 = BigInt(0), _1n$5 = BigInt(1), _2n$5 = /* @__PURE__ */ BigInt(2), _3n$2 = /* @__PURE__ */ BigInt(3);
256
+ // prettier-ignore
257
+ const _4n$1 = /* @__PURE__ */ BigInt(4), _5n = /* @__PURE__ */ BigInt(5), _7n = /* @__PURE__ */ BigInt(7);
451
258
  // prettier-ignore
452
- const _4n = /* @__PURE__ */ BigInt(4), _5n = /* @__PURE__ */ BigInt(5), _8n$1 = /* @__PURE__ */ BigInt(8);
259
+ const _8n$1 = /* @__PURE__ */ BigInt(8), _9n = /* @__PURE__ */ BigInt(9), _16n = /* @__PURE__ */ BigInt(16);
453
260
  // Calculates a modulo b
454
261
  function mod(a, b) {
455
262
  const result = a % b;
456
263
  return result >= _0n$4 ? result : b + result;
457
264
  }
458
- /**
459
- * Efficiently raise num to power and do modular division.
460
- * Unsafe in some contexts: uses ladder, so can expose bigint bits.
461
- * @example
462
- * pow(2n, 6n, 11n) // 64n % 11n == 9n
463
- */
464
- // TODO: use field version && remove
465
- function pow(num, power, modulo) {
466
- if (power < _0n$4)
467
- throw new Error('invalid exponent, negatives unsupported');
468
- if (modulo <= _0n$4)
469
- throw new Error('invalid modulus');
470
- if (modulo === _1n$6)
471
- return _0n$4;
472
- let res = _1n$6;
473
- while (power > _0n$4) {
474
- if (power & _1n$6)
475
- res = (res * num) % modulo;
476
- num = (num * num) % modulo;
477
- power >>= _1n$6;
478
- }
479
- return res;
480
- }
481
- // Does x ^ (2 ^ power) mod p. pow2(30, 4) == 30 ^ (2 ^ 4)
265
+ /** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */
482
266
  function pow2(x, power, modulo) {
483
267
  let res = x;
484
268
  while (power-- > _0n$4) {
@@ -487,18 +271,20 @@ function pow2(x, power, modulo) {
487
271
  }
488
272
  return res;
489
273
  }
490
- // Inverses number over modulo
274
+ /**
275
+ * Inverses number over modulo.
276
+ * Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/).
277
+ */
491
278
  function invert(number, modulo) {
492
279
  if (number === _0n$4)
493
280
  throw new Error('invert: expected non-zero number');
494
281
  if (modulo <= _0n$4)
495
282
  throw new Error('invert: expected positive modulus, got ' + modulo);
496
- // Euclidean GCD https://brilliant.org/wiki/extended-euclidean-algorithm/
497
283
  // Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower.
498
284
  let a = mod(number, modulo);
499
285
  let b = modulo;
500
286
  // prettier-ignore
501
- let x = _0n$4, u = _1n$6;
287
+ let x = _0n$4, u = _1n$5;
502
288
  while (a !== _0n$4) {
503
289
  // JIT applies optimization if those two lines follow each other
504
290
  const q = b / a;
@@ -508,111 +294,152 @@ function invert(number, modulo) {
508
294
  b = a, a = r, x = u, u = m;
509
295
  }
510
296
  const gcd = b;
511
- if (gcd !== _1n$6)
297
+ if (gcd !== _1n$5)
512
298
  throw new Error('invert: does not exist');
513
299
  return mod(x, modulo);
514
300
  }
301
+ function assertIsSquare(Fp, root, n) {
302
+ if (!Fp.eql(Fp.sqr(root), n))
303
+ throw new Error('Cannot find square root');
304
+ }
305
+ // Not all roots are possible! Example which will throw:
306
+ // const NUM =
307
+ // n = 72057594037927816n;
308
+ // Fp = Field(BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab'));
309
+ function sqrt3mod4(Fp, n) {
310
+ const p1div4 = (Fp.ORDER + _1n$5) / _4n$1;
311
+ const root = Fp.pow(n, p1div4);
312
+ assertIsSquare(Fp, root, n);
313
+ return root;
314
+ }
315
+ function sqrt5mod8(Fp, n) {
316
+ const p5div8 = (Fp.ORDER - _5n) / _8n$1;
317
+ const n2 = Fp.mul(n, _2n$5);
318
+ const v = Fp.pow(n2, p5div8);
319
+ const nv = Fp.mul(n, v);
320
+ const i = Fp.mul(Fp.mul(nv, _2n$5), v);
321
+ const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));
322
+ assertIsSquare(Fp, root, n);
323
+ return root;
324
+ }
325
+ // Based on RFC9380, Kong algorithm
326
+ // prettier-ignore
327
+ function sqrt9mod16(P) {
328
+ const Fp_ = Field(P);
329
+ const tn = tonelliShanks(P);
330
+ const c1 = tn(Fp_, Fp_.neg(Fp_.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F
331
+ const c2 = tn(Fp_, c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F
332
+ const c3 = tn(Fp_, Fp_.neg(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F
333
+ const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic
334
+ return (Fp, n) => {
335
+ let tv1 = Fp.pow(n, c4); // 1. tv1 = x^c4
336
+ let tv2 = Fp.mul(tv1, c1); // 2. tv2 = c1 * tv1
337
+ const tv3 = Fp.mul(tv1, c2); // 3. tv3 = c2 * tv1
338
+ const tv4 = Fp.mul(tv1, c3); // 4. tv4 = c3 * tv1
339
+ const e1 = Fp.eql(Fp.sqr(tv2), n); // 5. e1 = (tv2^2) == x
340
+ const e2 = Fp.eql(Fp.sqr(tv3), n); // 6. e2 = (tv3^2) == x
341
+ tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x
342
+ tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x
343
+ const e3 = Fp.eql(Fp.sqr(tv2), n); // 9. e3 = (tv2^2) == x
344
+ const root = Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select sqrt from tv1 & tv2
345
+ assertIsSquare(Fp, root, n);
346
+ return root;
347
+ };
348
+ }
515
349
  /**
516
350
  * Tonelli-Shanks square root search algorithm.
517
351
  * 1. https://eprint.iacr.org/2012/685.pdf (page 12)
518
352
  * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks
519
- * Will start an infinite loop if field order P is not prime.
520
353
  * @param P field order
521
354
  * @returns function that takes field Fp (created from P) and number n
522
355
  */
523
356
  function tonelliShanks(P) {
524
- // Legendre constant: used to calculate Legendre symbol (a | p),
525
- // which denotes the value of a^((p-1)/2) (mod p).
526
- // (a | p) ≡ 1 if a is a square (mod p)
527
- // (a | p) ≡ -1 if a is not a square (mod p)
528
- // (a | p) 0 if a 0 (mod p)
529
- const legendreC = (P - _1n$6) / _2n$3;
530
- let Q, S, Z;
531
- // Step 1: By factoring out powers of 2 from p - 1,
532
- // find q and s such that p - 1 = q*(2^s) with q odd
533
- for (Q = P - _1n$6, S = 0; Q % _2n$3 === _0n$4; Q /= _2n$3, S++)
534
- ;
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
- // 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
- }
541
- // Fast-path
542
- if (S === 1) {
543
- const p1div4 = (P + _1n$6) / _4n;
544
- return function tonelliFast(Fp, n) {
545
- const root = Fp.pow(n, p1div4);
546
- if (!Fp.eql(Fp.sqr(root), n))
547
- throw new Error('Cannot find square root');
548
- return root;
549
- };
357
+ // Initialization (precomputation).
358
+ // Caching initialization could boost perf by 7%.
359
+ if (P < _3n$2)
360
+ throw new Error('sqrt is not defined for small field');
361
+ // Factor P - 1 = Q * 2^S, where Q is odd
362
+ let Q = P - _1n$5;
363
+ let S = 0;
364
+ while (Q % _2n$5 === _0n$4) {
365
+ Q /= _2n$5;
366
+ S++;
550
367
  }
368
+ // Find the first quadratic non-residue Z >= 2
369
+ let Z = _2n$5;
370
+ const _Fp = Field(P);
371
+ while (FpLegendre(_Fp, Z) === 1) {
372
+ // Basic primality test for P. After x iterations, chance of
373
+ // not finding quadratic non-residue is 2^x, so 2^1000.
374
+ if (Z++ > 1000)
375
+ throw new Error('Cannot find square root: probably non-prime P');
376
+ }
377
+ // Fast-path; usually done before Z, but we do "primality test".
378
+ if (S === 1)
379
+ return sqrt3mod4;
551
380
  // Slow-path
552
- const Q1div2 = (Q + _1n$6) / _2n$3;
381
+ // TODO: test on Fp2 and others
382
+ let cc = _Fp.pow(Z, Q); // c = z^Q
383
+ const Q1div2 = (Q + _1n$5) / _2n$5;
553
384
  return function tonelliSlow(Fp, n) {
554
- // Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1
555
- if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE))
385
+ if (Fp.is0(n))
386
+ return n;
387
+ // Check if n is a quadratic residue using Legendre symbol
388
+ if (FpLegendre(Fp, n) !== 1)
556
389
  throw new Error('Cannot find square root');
557
- let r = S;
558
- // TODO: will fail at Fp2/etc
559
- let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q); // will update both x and b
560
- let x = Fp.pow(n, Q1div2); // first guess at the square root
561
- let b = Fp.pow(n, Q); // first guess at the fudge factor
562
- while (!Fp.eql(b, Fp.ONE)) {
563
- if (Fp.eql(b, Fp.ZERO))
564
- return Fp.ZERO; // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0)
565
- // Find m such b^(2^m)==1
566
- let m = 1;
567
- for (let t2 = Fp.sqr(b); m < r; m++) {
568
- if (Fp.eql(t2, Fp.ONE))
569
- break;
570
- t2 = Fp.sqr(t2); // t2 *= t2
390
+ // Initialize variables for the main loop
391
+ let M = S;
392
+ let c = Fp.mul(Fp.ONE, cc); // c = z^Q, move cc from field _Fp into field Fp
393
+ let t = Fp.pow(n, Q); // t = n^Q, first guess at the fudge factor
394
+ let R = Fp.pow(n, Q1div2); // R = n^((Q+1)/2), first guess at the square root
395
+ // Main loop
396
+ // while t != 1
397
+ while (!Fp.eql(t, Fp.ONE)) {
398
+ if (Fp.is0(t))
399
+ return Fp.ZERO; // if t=0 return R=0
400
+ let i = 1;
401
+ // Find the smallest i >= 1 such that t^(2^i) ≡ 1 (mod P)
402
+ let t_tmp = Fp.sqr(t); // t^(2^1)
403
+ while (!Fp.eql(t_tmp, Fp.ONE)) {
404
+ i++;
405
+ t_tmp = Fp.sqr(t_tmp); // t^(2^2)...
406
+ if (i === M)
407
+ throw new Error('Cannot find square root');
571
408
  }
572
- // NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow
573
- const ge = Fp.pow(g, _1n$6 << BigInt(r - m - 1)); // ge = 2^(r-m-1)
574
- g = Fp.sqr(ge); // g = ge * ge
575
- x = Fp.mul(x, ge); // x *= ge
576
- b = Fp.mul(b, g); // b *= g
577
- r = m;
578
- }
579
- return x;
409
+ // Calculate the exponent for b: 2^(M - i - 1)
410
+ const exponent = _1n$5 << BigInt(M - i - 1); // bigint is important
411
+ const b = Fp.pow(c, exponent); // b = 2^(M - i - 1)
412
+ // Update variables
413
+ M = i;
414
+ c = Fp.sqr(b); // c = b^2
415
+ t = Fp.mul(t, c); // t = (t * b^2)
416
+ R = Fp.mul(R, b); // R = R*b
417
+ }
418
+ return R;
580
419
  };
581
420
  }
421
+ /**
422
+ * Square root for a finite field. Will try optimized versions first:
423
+ *
424
+ * 1. P ≡ 3 (mod 4)
425
+ * 2. P ≡ 5 (mod 8)
426
+ * 3. P ≡ 9 (mod 16)
427
+ * 4. Tonelli-Shanks algorithm
428
+ *
429
+ * Different algorithms can give different roots, it is up to user to decide which one they want.
430
+ * For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).
431
+ */
582
432
  function FpSqrt(P) {
583
- // NOTE: different algorithms can give different roots, it is up to user to decide which one they want.
584
- // For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).
585
- // P ≡ 3 (mod 4)
586
- // √n = n^((P+1)/4)
587
- if (P % _4n === _3n$2) {
588
- // Not all roots possible!
589
- // const ORDER =
590
- // 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn;
591
- // const NUM = 72057594037927816n;
592
- const p1div4 = (P + _1n$6) / _4n;
593
- return function sqrt3mod4(Fp, n) {
594
- const root = Fp.pow(n, p1div4);
595
- // Throw if root**2 != n
596
- if (!Fp.eql(Fp.sqr(root), n))
597
- throw new Error('Cannot find square root');
598
- return root;
599
- };
600
- }
601
- // Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10)
602
- if (P % _8n$1 === _5n) {
603
- const c1 = (P - _5n) / _8n$1;
604
- return function sqrt5mod8(Fp, n) {
605
- const n2 = Fp.mul(n, _2n$3);
606
- const v = Fp.pow(n2, c1);
607
- const nv = Fp.mul(n, v);
608
- const i = Fp.mul(Fp.mul(nv, _2n$3), v);
609
- const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));
610
- if (!Fp.eql(Fp.sqr(root), n))
611
- throw new Error('Cannot find square root');
612
- return root;
613
- };
614
- }
615
- // Other cases: Tonelli-Shanks algorithm
433
+ // P 3 (mod 4) => √n = n^((P+1)/4)
434
+ if (P % _4n$1 === _3n$2)
435
+ return sqrt3mod4;
436
+ // P 5 (mod 8) => Atkin algorithm, page 10 of https://eprint.iacr.org/2012/685.pdf
437
+ if (P % _8n$1 === _5n)
438
+ return sqrt5mod8;
439
+ // P 9 (mod 16) => Kong algorithm, page 11 of https://eprint.iacr.org/2012/685.pdf (algorithm 4)
440
+ if (P % _16n === _9n)
441
+ return sqrt9mod16(P);
442
+ // Tonelli-Shanks algorithm
616
443
  return tonelliShanks(P);
617
444
  }
618
445
  // prettier-ignore
@@ -625,99 +452,156 @@ function validateField(field) {
625
452
  const initial = {
626
453
  ORDER: 'bigint',
627
454
  MASK: 'bigint',
628
- BYTES: 'isSafeInteger',
629
- BITS: 'isSafeInteger',
455
+ BYTES: 'number',
456
+ BITS: 'number',
630
457
  };
631
458
  const opts = FIELD_FIELDS.reduce((map, val) => {
632
459
  map[val] = 'function';
633
460
  return map;
634
461
  }, initial);
635
- return validateObject(field, opts);
462
+ _validateObject(field, opts);
463
+ // const max = 16384;
464
+ // if (field.BYTES < 1 || field.BYTES > max) throw new Error('invalid field');
465
+ // if (field.BITS < 1 || field.BITS > 8 * max) throw new Error('invalid field');
466
+ return field;
636
467
  }
637
468
  // Generic field functions
638
469
  /**
639
470
  * Same as `pow` but for Fp: non-constant-time.
640
471
  * Unsafe in some contexts: uses ladder, so can expose bigint bits.
641
472
  */
642
- function FpPow(f, num, power) {
643
- // Should have same speed as pow for bigints
644
- // TODO: benchmark!
473
+ function FpPow(Fp, num, power) {
645
474
  if (power < _0n$4)
646
475
  throw new Error('invalid exponent, negatives unsupported');
647
476
  if (power === _0n$4)
648
- return f.ONE;
649
- if (power === _1n$6)
477
+ return Fp.ONE;
478
+ if (power === _1n$5)
650
479
  return num;
651
- let p = f.ONE;
480
+ let p = Fp.ONE;
652
481
  let d = num;
653
482
  while (power > _0n$4) {
654
- if (power & _1n$6)
655
- p = f.mul(p, d);
656
- d = f.sqr(d);
657
- power >>= _1n$6;
483
+ if (power & _1n$5)
484
+ p = Fp.mul(p, d);
485
+ d = Fp.sqr(d);
486
+ power >>= _1n$5;
658
487
  }
659
488
  return p;
660
489
  }
661
490
  /**
662
491
  * Efficiently invert an array of Field elements.
663
- * `inv(0)` will return `undefined` here: make sure to throw an error.
492
+ * Exception-free. Will return `undefined` for 0 elements.
493
+ * @param passZero map 0 to 0 (instead of undefined)
664
494
  */
665
- function FpInvertBatch(f, nums) {
666
- const tmp = new Array(nums.length);
495
+ function FpInvertBatch(Fp, nums, passZero = false) {
496
+ const inverted = new Array(nums.length).fill(passZero ? Fp.ZERO : undefined);
667
497
  // Walk from first to last, multiply them by each other MOD p
668
- const lastMultiplied = nums.reduce((acc, num, i) => {
669
- if (f.is0(num))
498
+ const multipliedAcc = nums.reduce((acc, num, i) => {
499
+ if (Fp.is0(num))
670
500
  return acc;
671
- tmp[i] = acc;
672
- return f.mul(acc, num);
673
- }, f.ONE);
501
+ inverted[i] = acc;
502
+ return Fp.mul(acc, num);
503
+ }, Fp.ONE);
674
504
  // Invert last element
675
- const inverted = f.inv(lastMultiplied);
505
+ const invertedAcc = Fp.inv(multipliedAcc);
676
506
  // Walk from last to first, multiply them by inverted each other MOD p
677
507
  nums.reduceRight((acc, num, i) => {
678
- if (f.is0(num))
508
+ if (Fp.is0(num))
679
509
  return acc;
680
- tmp[i] = f.mul(acc, tmp[i]);
681
- return f.mul(acc, num);
682
- }, inverted);
683
- return tmp;
510
+ inverted[i] = Fp.mul(acc, inverted[i]);
511
+ return Fp.mul(acc, num);
512
+ }, invertedAcc);
513
+ return inverted;
514
+ }
515
+ /**
516
+ * Legendre symbol.
517
+ * Legendre constant is used to calculate Legendre symbol (a | p)
518
+ * which denotes the value of a^((p-1)/2) (mod p).
519
+ *
520
+ * * (a | p) ≡ 1 if a is a square (mod p), quadratic residue
521
+ * * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue
522
+ * * (a | p) ≡ 0 if a ≡ 0 (mod p)
523
+ */
524
+ function FpLegendre(Fp, n) {
525
+ // We can use 3rd argument as optional cache of this value
526
+ // but seems unneeded for now. The operation is very fast.
527
+ const p1mod2 = (Fp.ORDER - _1n$5) / _2n$5;
528
+ const powered = Fp.pow(n, p1mod2);
529
+ const yes = Fp.eql(powered, Fp.ONE);
530
+ const zero = Fp.eql(powered, Fp.ZERO);
531
+ const no = Fp.eql(powered, Fp.neg(Fp.ONE));
532
+ if (!yes && !zero && !no)
533
+ throw new Error('invalid Legendre symbol result');
534
+ return yes ? 1 : zero ? 0 : -1;
684
535
  }
685
536
  // CURVE.n lengths
686
537
  function nLength(n, nBitLength) {
687
538
  // Bit size, byte size of CURVE.n
539
+ if (nBitLength !== undefined)
540
+ anumber(nBitLength);
688
541
  const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length;
689
542
  const nByteLength = Math.ceil(_nBitLength / 8);
690
543
  return { nBitLength: _nBitLength, nByteLength };
691
544
  }
692
545
  /**
693
- * Initializes a finite field over prime. **Non-primes are not supported.**
694
- * Do not init in loop: slow. Very fragile: always run a benchmark on a change.
695
- * Major performance optimizations:
696
- * * a) denormalized operations like mulN instead of mul
697
- * * b) same object shape: never add or remove keys
698
- * * c) Object.freeze
699
- * NOTE: operations don't check 'isValid' for all elements for performance reasons,
546
+ * Creates a finite field. Major performance optimizations:
547
+ * * 1. Denormalized operations like mulN instead of mul.
548
+ * * 2. Identical object shape: never add or remove keys.
549
+ * * 3. `Object.freeze`.
550
+ * Fragile: always run a benchmark on a change.
551
+ * Security note: operations don't check 'isValid' for all elements for performance reasons,
700
552
  * it is caller responsibility to check this.
701
- * This is low-level code, please make sure you know what you doing.
702
- * @param ORDER prime positive bigint
553
+ * This is low-level code, please make sure you know what you're doing.
554
+ *
555
+ * Note about field properties:
556
+ * * CHARACTERISTIC p = prime number, number of elements in main subgroup.
557
+ * * ORDER q = similar to cofactor in curves, may be composite `q = p^m`.
558
+ *
559
+ * @param ORDER field order, probably prime, or could be composite
703
560
  * @param bitLen how many bits the field consumes
704
- * @param isLE (def: false) if encoding / decoding should be in little-endian
561
+ * @param isLE (default: false) if encoding / decoding should be in little-endian
705
562
  * @param redef optional faster redefinitions of sqrt and other methods
706
563
  */
707
- function Field(ORDER, bitLen, isLE = false, redef = {}) {
564
+ function Field(ORDER, bitLenOrOpts, // TODO: use opts only in v2?
565
+ isLE = false, opts = {}) {
708
566
  if (ORDER <= _0n$4)
709
567
  throw new Error('invalid field: expected ORDER > 0, got ' + ORDER);
710
- const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen);
568
+ let _nbitLength = undefined;
569
+ let _sqrt = undefined;
570
+ let modFromBytes = false;
571
+ let allowedLengths = undefined;
572
+ if (typeof bitLenOrOpts === 'object' && bitLenOrOpts != null) {
573
+ if (opts.sqrt || isLE)
574
+ throw new Error('cannot specify opts in two arguments');
575
+ const _opts = bitLenOrOpts;
576
+ if (_opts.BITS)
577
+ _nbitLength = _opts.BITS;
578
+ if (_opts.sqrt)
579
+ _sqrt = _opts.sqrt;
580
+ if (typeof _opts.isLE === 'boolean')
581
+ isLE = _opts.isLE;
582
+ if (typeof _opts.modFromBytes === 'boolean')
583
+ modFromBytes = _opts.modFromBytes;
584
+ allowedLengths = _opts.allowedLengths;
585
+ }
586
+ else {
587
+ if (typeof bitLenOrOpts === 'number')
588
+ _nbitLength = bitLenOrOpts;
589
+ if (opts.sqrt)
590
+ _sqrt = opts.sqrt;
591
+ }
592
+ const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, _nbitLength);
711
593
  if (BYTES > 2048)
712
594
  throw new Error('invalid field: expected ORDER of <= 2048 bytes');
713
595
  let sqrtP; // cached sqrtP
714
596
  const f = Object.freeze({
715
597
  ORDER,
598
+ isLE,
716
599
  BITS,
717
600
  BYTES,
718
601
  MASK: bitMask(BITS),
719
602
  ZERO: _0n$4,
720
- ONE: _1n$6,
603
+ ONE: _1n$5,
604
+ allowedLengths: allowedLengths,
721
605
  create: (num) => mod(num, ORDER),
722
606
  isValid: (num) => {
723
607
  if (typeof num !== 'bigint')
@@ -725,7 +609,9 @@ function Field(ORDER, bitLen, isLE = false, redef = {}) {
725
609
  return _0n$4 <= num && num < ORDER; // 0 is valid element, but it's not invertible
726
610
  },
727
611
  is0: (num) => num === _0n$4,
728
- isOdd: (num) => (num & _1n$6) === _1n$6,
612
+ // is valid and invertible
613
+ isValidNot0: (num) => !f.is0(num) && f.isValid(num),
614
+ isOdd: (num) => (num & _1n$5) === _1n$5,
729
615
  neg: (num) => mod(-num, ORDER),
730
616
  eql: (lhs, rhs) => lhs === rhs,
731
617
  sqr: (num) => mod(num * num, ORDER),
@@ -740,22 +626,40 @@ function Field(ORDER, bitLen, isLE = false, redef = {}) {
740
626
  subN: (lhs, rhs) => lhs - rhs,
741
627
  mulN: (lhs, rhs) => lhs * rhs,
742
628
  inv: (num) => invert(num, ORDER),
743
- sqrt: redef.sqrt ||
629
+ sqrt: _sqrt ||
744
630
  ((n) => {
745
631
  if (!sqrtP)
746
632
  sqrtP = FpSqrt(ORDER);
747
633
  return sqrtP(f, n);
748
634
  }),
749
- invertBatch: (lst) => FpInvertBatch(f, lst),
750
- // TODO: do we really need constant cmov?
751
- // We don't have const-time bigints anyway, so probably will be not very useful
752
- cmov: (a, b, c) => (c ? b : a),
753
635
  toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)),
754
- fromBytes: (bytes) => {
636
+ fromBytes: (bytes, skipValidation = true) => {
637
+ if (allowedLengths) {
638
+ if (!allowedLengths.includes(bytes.length) || bytes.length > BYTES) {
639
+ throw new Error('Field.fromBytes: expected ' + allowedLengths + ' bytes, got ' + bytes.length);
640
+ }
641
+ const padded = new Uint8Array(BYTES);
642
+ // isLE add 0 to right, !isLE to the left.
643
+ padded.set(bytes, isLE ? 0 : padded.length - bytes.length);
644
+ bytes = padded;
645
+ }
755
646
  if (bytes.length !== BYTES)
756
647
  throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length);
757
- return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
648
+ let scalar = isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
649
+ if (modFromBytes)
650
+ scalar = mod(scalar, ORDER);
651
+ if (!skipValidation)
652
+ if (!f.isValid(scalar))
653
+ throw new Error('invalid field element: outside of range 0..ORDER');
654
+ // NOTE: we don't validate scalar here, please use isValid. This done such way because some
655
+ // protocol may allow non-reduced scalar that reduced later or changed some other way.
656
+ return scalar;
758
657
  },
658
+ // TODO: we don't need it here, move out to separate fn
659
+ invertBatch: (lst) => FpInvertBatch(f, lst),
660
+ // We can't move this out because Fp6, Fp12 implement it
661
+ // and it's unclear what to return in there.
662
+ cmov: (a, b, c) => (c ? b : a),
759
663
  });
760
664
  return Object.freeze(f);
761
665
  }
@@ -802,29 +706,153 @@ function mapHashToField(key, fieldOrder, isLE = false) {
802
706
  // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings.
803
707
  if (len < 16 || len < minLen || len > 1024)
804
708
  throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len);
805
- const num = isLE ? bytesToNumberBE(key) : bytesToNumberLE(key);
709
+ const num = isLE ? bytesToNumberLE(key) : bytesToNumberBE(key);
806
710
  // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0
807
- const reduced = mod(num, fieldOrder - _1n$6) + _1n$6;
711
+ const reduced = mod(num, fieldOrder - _1n$5) + _1n$5;
808
712
  return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);
809
713
  }
810
714
 
715
+ /**
716
+ * HMAC: RFC2104 message authentication code.
717
+ * @module
718
+ */
719
+ class HMAC extends Hash {
720
+ constructor(hash, _key) {
721
+ super();
722
+ this.finished = false;
723
+ this.destroyed = false;
724
+ ahash(hash);
725
+ const key = toBytes(_key);
726
+ this.iHash = hash.create();
727
+ if (typeof this.iHash.update !== 'function')
728
+ throw new Error('Expected instance of class which extends utils.Hash');
729
+ this.blockLen = this.iHash.blockLen;
730
+ this.outputLen = this.iHash.outputLen;
731
+ const blockLen = this.blockLen;
732
+ const pad = new Uint8Array(blockLen);
733
+ // blockLen can be bigger than outputLen
734
+ pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
735
+ for (let i = 0; i < pad.length; i++)
736
+ pad[i] ^= 0x36;
737
+ this.iHash.update(pad);
738
+ // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone
739
+ this.oHash = hash.create();
740
+ // Undo internal XOR && apply outer XOR
741
+ for (let i = 0; i < pad.length; i++)
742
+ pad[i] ^= 0x36 ^ 0x5c;
743
+ this.oHash.update(pad);
744
+ clean(pad);
745
+ }
746
+ update(buf) {
747
+ aexists(this);
748
+ this.iHash.update(buf);
749
+ return this;
750
+ }
751
+ digestInto(out) {
752
+ aexists(this);
753
+ abytes(out, this.outputLen);
754
+ this.finished = true;
755
+ this.iHash.digestInto(out);
756
+ this.oHash.update(out);
757
+ this.oHash.digestInto(out);
758
+ this.destroy();
759
+ }
760
+ digest() {
761
+ const out = new Uint8Array(this.oHash.outputLen);
762
+ this.digestInto(out);
763
+ return out;
764
+ }
765
+ _cloneInto(to) {
766
+ // Create new instance without calling constructor since key already in state and we don't know it.
767
+ to || (to = Object.create(Object.getPrototypeOf(this), {}));
768
+ const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
769
+ to = to;
770
+ to.finished = finished;
771
+ to.destroyed = destroyed;
772
+ to.blockLen = blockLen;
773
+ to.outputLen = outputLen;
774
+ to.oHash = oHash._cloneInto(to.oHash);
775
+ to.iHash = iHash._cloneInto(to.iHash);
776
+ return to;
777
+ }
778
+ clone() {
779
+ return this._cloneInto();
780
+ }
781
+ destroy() {
782
+ this.destroyed = true;
783
+ this.oHash.destroy();
784
+ this.iHash.destroy();
785
+ }
786
+ }
787
+ /**
788
+ * HMAC: RFC2104 message authentication code.
789
+ * @param hash - function that would be used e.g. sha256
790
+ * @param key - message key
791
+ * @param message - message data
792
+ * @example
793
+ * import { hmac } from '@noble/hashes/hmac';
794
+ * import { sha256 } from '@noble/hashes/sha2';
795
+ * const mac1 = hmac(sha256, 'key', 'message');
796
+ */
797
+ const hmac = (hash, key, message) => new HMAC(hash, key).update(message).digest();
798
+ hmac.create = (hash, key) => new HMAC(hash, key);
799
+
800
+ /**
801
+ * Methods for elliptic curve multiplication by scalars.
802
+ * Contains wNAF, pippenger.
803
+ * @module
804
+ */
811
805
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
812
- // Abelian group utilities
813
806
  const _0n$3 = BigInt(0);
814
- const _1n$5 = BigInt(1);
815
- function constTimeNegate(condition, item) {
807
+ const _1n$4 = BigInt(1);
808
+ function negateCt(condition, item) {
816
809
  const neg = item.negate();
817
810
  return condition ? neg : item;
818
811
  }
812
+ /**
813
+ * Takes a bunch of Projective Points but executes only one
814
+ * inversion on all of them. Inversion is very slow operation,
815
+ * so this improves performance massively.
816
+ * Optimization: converts a list of projective points to a list of identical points with Z=1.
817
+ */
818
+ function normalizeZ(c, points) {
819
+ const invertedZs = FpInvertBatch(c.Fp, points.map((p) => p.Z));
820
+ return points.map((p, i) => c.fromAffine(p.toAffine(invertedZs[i])));
821
+ }
819
822
  function validateW(W, bits) {
820
823
  if (!Number.isSafeInteger(W) || W <= 0 || W > bits)
821
824
  throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W);
822
825
  }
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 };
826
+ function calcWOpts(W, scalarBits) {
827
+ validateW(W, scalarBits);
828
+ const windows = Math.ceil(scalarBits / W) + 1; // W=8 33. Not 32, because we skip zero
829
+ const windowSize = 2 ** (W - 1); // W=8 128. Not 256, because we skip zero
830
+ const maxNumber = 2 ** W; // W=8 256
831
+ const mask = bitMask(W); // W=8 255 == mask 0b11111111
832
+ const shiftBy = BigInt(W); // W=8 8
833
+ return { windows, windowSize, mask, maxNumber, shiftBy };
834
+ }
835
+ function calcOffsets(n, window, wOpts) {
836
+ const { windowSize, mask, maxNumber, shiftBy } = wOpts;
837
+ let wbits = Number(n & mask); // extract W bits.
838
+ let nextN = n >> shiftBy; // shift number by W bits.
839
+ // What actually happens here:
840
+ // const highestBit = Number(mask ^ (mask >> 1n));
841
+ // let wbits2 = wbits - 1; // skip zero
842
+ // if (wbits2 & highestBit) { wbits2 ^= Number(mask); // (~);
843
+ // split if bits > max: +224 => 256-32
844
+ if (wbits > windowSize) {
845
+ // we skip zero, which means instead of `>= size-1`, we do `> size`
846
+ wbits -= maxNumber; // -32, can be maxNumber - wbits, but then we need to set isNeg here.
847
+ nextN += _1n$4; // +256 (carry)
848
+ }
849
+ const offsetStart = window * windowSize;
850
+ const offset = offsetStart + Math.abs(wbits) - 1; // -1 because we skip zero
851
+ const isZero = wbits === 0; // is current window slice a 0?
852
+ const isNeg = wbits < 0; // is current window slice negative?
853
+ const isNegF = window % 2 !== 0; // fake random statement for noise
854
+ const offsetF = offsetStart; // fake offset for noise
855
+ return { nextN, offset, isZero, isNeg, isNegF, offsetF };
828
856
  }
829
857
  function validateMSMPoints(points, c) {
830
858
  if (!Array.isArray(points))
@@ -843,199 +871,213 @@ function validateMSMScalars(scalars, field) {
843
871
  });
844
872
  }
845
873
  // Since points in different groups cannot be equal (different object constructor),
846
- // we can have single place to store precomputes
874
+ // we can have single place to store precomputes.
875
+ // Allows to make points frozen / immutable.
847
876
  const pointPrecomputes = new WeakMap();
848
- const pointWindowSizes = new WeakMap(); // This allows use make points immutable (nothing changes inside)
877
+ const pointWindowSizes = new WeakMap();
849
878
  function getW(P) {
879
+ // To disable precomputes:
880
+ // return 1;
850
881
  return pointWindowSizes.get(P) || 1;
851
882
  }
852
- // Elliptic curve multiplication of Point by scalar. Fragile.
853
- // Scalars should always be less than curve order: this should be checked inside of a curve itself.
854
- // Creates precomputation tables for fast multiplication:
855
- // - private scalar is split by fixed size windows of W bits
856
- // - every window point is collected from window's table & added to accumulator
857
- // - since windows are different, same point inside tables won't be accessed more than once per calc
858
- // - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar)
859
- // - +1 window is neccessary for wNAF
860
- // - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication
861
- // TODO: Research returning 2d JS array of windows, instead of a single window. This would allow
862
- // windows to be in different memory locations
863
- function wNAF(c, bits) {
864
- return {
865
- constTimeNegate,
866
- hasPrecomputes(elm) {
867
- return getW(elm) !== 1;
868
- },
869
- // non-const time multiplication ladder
870
- unsafeLadder(elm, n, p = c.ZERO) {
871
- let d = elm;
872
- while (n > _0n$3) {
873
- if (n & _1n$5)
874
- p = p.add(d);
875
- d = d.double();
876
- n >>= _1n$5;
877
- }
878
- return p;
879
- },
880
- /**
881
- * Creates a wNAF precomputation window. Used for caching.
882
- * Default window size is set by `utils.precompute()` and is equal to 8.
883
- * Number of precomputed points depends on the curve size:
884
- * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
885
- * - 𝑊 is the window size
886
- * - 𝑛 is the bitlength of the curve order.
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
890
- * @returns precomputed point tables flattened to a single array
891
- */
892
- precomputeWindow(elm, W) {
893
- const { windows, windowSize } = calcWOpts(W, bits);
894
- const points = [];
895
- let p = elm;
896
- let base = p;
897
- for (let window = 0; window < windows; window++) {
898
- base = p;
883
+ function assert0(n) {
884
+ if (n !== _0n$3)
885
+ throw new Error('invalid wNAF');
886
+ }
887
+ /**
888
+ * Elliptic curve multiplication of Point by scalar. Fragile.
889
+ * Table generation takes **30MB of ram and 10ms on high-end CPU**,
890
+ * but may take much longer on slow devices. Actual generation will happen on
891
+ * first call of `multiply()`. By default, `BASE` point is precomputed.
892
+ *
893
+ * Scalars should always be less than curve order: this should be checked inside of a curve itself.
894
+ * Creates precomputation tables for fast multiplication:
895
+ * - private scalar is split by fixed size windows of W bits
896
+ * - every window point is collected from window's table & added to accumulator
897
+ * - since windows are different, same point inside tables won't be accessed more than once per calc
898
+ * - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar)
899
+ * - +1 window is neccessary for wNAF
900
+ * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication
901
+ *
902
+ * @todo Research returning 2d JS array of windows, instead of a single window.
903
+ * This would allow windows to be in different memory locations
904
+ */
905
+ class wNAF {
906
+ // Parametrized with a given Point class (not individual point)
907
+ constructor(Point, bits) {
908
+ this.BASE = Point.BASE;
909
+ this.ZERO = Point.ZERO;
910
+ this.Fn = Point.Fn;
911
+ this.bits = bits;
912
+ }
913
+ // non-const time multiplication ladder
914
+ _unsafeLadder(elm, n, p = this.ZERO) {
915
+ let d = elm;
916
+ while (n > _0n$3) {
917
+ if (n & _1n$4)
918
+ p = p.add(d);
919
+ d = d.double();
920
+ n >>= _1n$4;
921
+ }
922
+ return p;
923
+ }
924
+ /**
925
+ * Creates a wNAF precomputation window. Used for caching.
926
+ * Default window size is set by `utils.precompute()` and is equal to 8.
927
+ * Number of precomputed points depends on the curve size:
928
+ * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
929
+ * - 𝑊 is the window size
930
+ * - 𝑛 is the bitlength of the curve order.
931
+ * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
932
+ * @param point Point instance
933
+ * @param W window size
934
+ * @returns precomputed point tables flattened to a single array
935
+ */
936
+ precomputeWindow(point, W) {
937
+ const { windows, windowSize } = calcWOpts(W, this.bits);
938
+ const points = [];
939
+ let p = point;
940
+ let base = p;
941
+ for (let window = 0; window < windows; window++) {
942
+ base = p;
943
+ points.push(base);
944
+ // i=1, bc we skip 0
945
+ for (let i = 1; i < windowSize; i++) {
946
+ base = base.add(p);
899
947
  points.push(base);
900
- // =1, because we skip zero
901
- for (let i = 1; i < windowSize; i++) {
902
- base = base.add(p);
903
- points.push(base);
904
- }
905
- p = base.double();
906
948
  }
907
- return points;
908
- },
909
- /**
910
- * Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
911
- * @param W window size
912
- * @param precomputes precomputed tables
913
- * @param n scalar (we don't check here, but should be less than curve order)
914
- * @returns real and fake (for const-time) points
915
- */
916
- wNAF(W, precomputes, n) {
917
- // TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise
918
- // But need to carefully remove other checks before wNAF. ORDER == bits here
919
- const { windows, windowSize } = calcWOpts(W, bits);
920
- let p = c.ZERO;
921
- let f = c.BASE;
922
- const mask = BigInt(2 ** W - 1); // Create mask with W ones: 0b1111 for W=4 etc.
923
- const maxNumber = 2 ** W;
924
- const shiftBy = BigInt(W);
925
- for (let window = 0; window < windows; window++) {
926
- const offset = window * windowSize;
927
- // Extract W bits.
928
- let wbits = Number(n & mask);
929
- // Shift number by W bits.
930
- n >>= shiftBy;
931
- // If the bits are bigger than max size, we'll split those.
932
- // +224 => 256 - 32
933
- if (wbits > windowSize) {
934
- wbits -= maxNumber;
935
- n += _1n$5;
936
- }
937
- // This code was first written with assumption that 'f' and 'p' will never be infinity point:
938
- // since each addition is multiplied by 2 ** W, it cannot cancel each other. However,
939
- // there is negate now: it is possible that negated element from low value
940
- // would be the same as high element, which will create carry into next window.
941
- // It's not obvious how this can fail, but still worth investigating later.
942
- // Check if we're onto Zero point.
943
- // Add random point inside current window to f.
944
- const offset1 = offset;
945
- const offset2 = offset + Math.abs(wbits) - 1; // -1 because we skip zero
946
- const cond1 = window % 2 !== 0;
947
- const cond2 = wbits < 0;
948
- if (wbits === 0) {
949
- // The most important part for const-time getPublicKey
950
- f = f.add(constTimeNegate(cond1, precomputes[offset1]));
951
- }
952
- else {
953
- p = p.add(constTimeNegate(cond2, precomputes[offset2]));
954
- }
949
+ p = base.double();
950
+ }
951
+ return points;
952
+ }
953
+ /**
954
+ * Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
955
+ * More compact implementation:
956
+ * https://github.com/paulmillr/noble-secp256k1/blob/47cb1669b6e506ad66b35fe7d76132ae97465da2/index.ts#L502-L541
957
+ * @returns real and fake (for const-time) points
958
+ */
959
+ wNAF(W, precomputes, n) {
960
+ // Scalar should be smaller than field order
961
+ if (!this.Fn.isValid(n))
962
+ throw new Error('invalid scalar');
963
+ // Accumulators
964
+ let p = this.ZERO;
965
+ let f = this.BASE;
966
+ // This code was first written with assumption that 'f' and 'p' will never be infinity point:
967
+ // since each addition is multiplied by 2 ** W, it cannot cancel each other. However,
968
+ // there is negate now: it is possible that negated element from low value
969
+ // would be the same as high element, which will create carry into next window.
970
+ // It's not obvious how this can fail, but still worth investigating later.
971
+ const wo = calcWOpts(W, this.bits);
972
+ for (let window = 0; window < wo.windows; window++) {
973
+ // (n === _0n) is handled and not early-exited. isEven and offsetF are used for noise
974
+ const { nextN, offset, isZero, isNeg, isNegF, offsetF } = calcOffsets(n, window, wo);
975
+ n = nextN;
976
+ if (isZero) {
977
+ // bits are 0: add garbage to fake point
978
+ // Important part for const-time getPublicKey: add random "noise" point to f.
979
+ f = f.add(negateCt(isNegF, precomputes[offsetF]));
955
980
  }
956
- // JIT-compiler should not eliminate f here, since it will later be used in normalizeZ()
957
- // Even if the variable is still unused, there are some checks which will
958
- // throw an exception, so compiler needs to prove they won't happen, which is hard.
959
- // At this point there is a way to F be infinity-point even if p is not,
960
- // which makes it less const-time: around 1 bigint multiply.
961
- return { p, f };
962
- },
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);
981
+ else {
982
+ // bits are 1: add to result point
983
+ p = p.add(negateCt(isNeg, precomputes[offset]));
997
984
  }
998
- return acc;
999
- },
1000
- getPrecomputes(W, P, transform) {
1001
- // Calculate precomputes on a first run, reuse them after
1002
- let comp = pointPrecomputes.get(P);
1003
- if (!comp) {
1004
- comp = this.precomputeWindow(P, W);
1005
- if (W !== 1)
1006
- pointPrecomputes.set(P, transform(comp));
985
+ }
986
+ assert0(n);
987
+ // Return both real and fake points: JIT won't eliminate f.
988
+ // At this point there is a way to F be infinity-point even if p is not,
989
+ // which makes it less const-time: around 1 bigint multiply.
990
+ return { p, f };
991
+ }
992
+ /**
993
+ * Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form.
994
+ * @param acc accumulator point to add result of multiplication
995
+ * @returns point
996
+ */
997
+ wNAFUnsafe(W, precomputes, n, acc = this.ZERO) {
998
+ const wo = calcWOpts(W, this.bits);
999
+ for (let window = 0; window < wo.windows; window++) {
1000
+ if (n === _0n$3)
1001
+ break; // Early-exit, skip 0 value
1002
+ const { nextN, offset, isZero, isNeg } = calcOffsets(n, window, wo);
1003
+ n = nextN;
1004
+ if (isZero) {
1005
+ // Window bits are 0: skip processing.
1006
+ // Move to next window.
1007
+ continue;
1007
1008
  }
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);
1019
- },
1020
- // We calculate precomputes for elliptic curve point multiplication
1021
- // using windowed method. This specifies window size and
1022
- // stores precomputed values. Usually only base point would be precomputed.
1023
- setWindowSize(P, W) {
1024
- validateW(W, bits);
1025
- pointWindowSizes.set(P, W);
1026
- pointPrecomputes.delete(P);
1027
- },
1028
- };
1009
+ else {
1010
+ const item = precomputes[offset];
1011
+ acc = acc.add(isNeg ? item.negate() : item); // Re-using acc allows to save adds in MSM
1012
+ }
1013
+ }
1014
+ assert0(n);
1015
+ return acc;
1016
+ }
1017
+ getPrecomputes(W, point, transform) {
1018
+ // Calculate precomputes on a first run, reuse them after
1019
+ let comp = pointPrecomputes.get(point);
1020
+ if (!comp) {
1021
+ comp = this.precomputeWindow(point, W);
1022
+ if (W !== 1) {
1023
+ // Doing transform outside of if brings 15% perf hit
1024
+ if (typeof transform === 'function')
1025
+ comp = transform(comp);
1026
+ pointPrecomputes.set(point, comp);
1027
+ }
1028
+ }
1029
+ return comp;
1030
+ }
1031
+ cached(point, scalar, transform) {
1032
+ const W = getW(point);
1033
+ return this.wNAF(W, this.getPrecomputes(W, point, transform), scalar);
1034
+ }
1035
+ unsafe(point, scalar, transform, prev) {
1036
+ const W = getW(point);
1037
+ if (W === 1)
1038
+ return this._unsafeLadder(point, scalar, prev); // For W=1 ladder is ~x2 faster
1039
+ return this.wNAFUnsafe(W, this.getPrecomputes(W, point, transform), scalar, prev);
1040
+ }
1041
+ // We calculate precomputes for elliptic curve point multiplication
1042
+ // using windowed method. This specifies window size and
1043
+ // stores precomputed values. Usually only base point would be precomputed.
1044
+ createCache(P, W) {
1045
+ validateW(W, this.bits);
1046
+ pointWindowSizes.set(P, W);
1047
+ pointPrecomputes.delete(P);
1048
+ }
1049
+ hasCache(elm) {
1050
+ return getW(elm) !== 1;
1051
+ }
1052
+ }
1053
+ /**
1054
+ * Endomorphism-specific multiplication for Koblitz curves.
1055
+ * Cost: 128 dbl, 0-256 adds.
1056
+ */
1057
+ function mulEndoUnsafe(Point, point, k1, k2) {
1058
+ let acc = point;
1059
+ let p1 = Point.ZERO;
1060
+ let p2 = Point.ZERO;
1061
+ while (k1 > _0n$3 || k2 > _0n$3) {
1062
+ if (k1 & _1n$4)
1063
+ p1 = p1.add(acc);
1064
+ if (k2 & _1n$4)
1065
+ p2 = p2.add(acc);
1066
+ acc = acc.double();
1067
+ k1 >>= _1n$4;
1068
+ k2 >>= _1n$4;
1069
+ }
1070
+ return { p1, p2 };
1029
1071
  }
1030
1072
  /**
1031
1073
  * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
1032
- * 30x faster vs naive addition on L=4096, 10x faster with precomputes.
1074
+ * 30x faster vs naive addition on L=4096, 10x faster than precomputes.
1033
1075
  * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL.
1034
1076
  * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0.
1035
1077
  * @param c Curve Point constructor
1036
1078
  * @param fieldN field over CURVE.N - important that it's not over CURVE.P
1037
1079
  * @param points array of L curve points
1038
- * @param scalars array of L scalars (aka private keys / bigints)
1080
+ * @param scalars array of L scalars (aka secret keys / bigints)
1039
1081
  */
1040
1082
  function pippenger(c, fieldN, points, scalars) {
1041
1083
  // If we split scalars by some window (let's say 8 bits), every chunk will only
@@ -1046,20 +1088,29 @@ function pippenger(c, fieldN, points, scalars) {
1046
1088
  // 0 is accepted in scalars
1047
1089
  validateMSMPoints(points, c);
1048
1090
  validateMSMScalars(scalars, fieldN);
1049
- if (points.length !== scalars.length)
1091
+ const plength = points.length;
1092
+ const slength = scalars.length;
1093
+ if (plength !== slength)
1050
1094
  throw new Error('arrays of points and scalars must have equal length');
1095
+ // if (plength === 0) throw new Error('array must be of length >= 2');
1051
1096
  const zero = c.ZERO;
1052
- const wbits = bitLen(BigInt(points.length));
1053
- const windowSize = wbits > 12 ? wbits - 3 : wbits > 4 ? wbits - 2 : wbits ? 2 : 1; // in bits
1054
- const MASK = (1 << windowSize) - 1;
1055
- const buckets = new Array(MASK + 1).fill(zero); // +1 for zero array
1097
+ const wbits = bitLen(BigInt(plength));
1098
+ let windowSize = 1; // bits
1099
+ if (wbits > 12)
1100
+ windowSize = wbits - 3;
1101
+ else if (wbits > 4)
1102
+ windowSize = wbits - 2;
1103
+ else if (wbits > 0)
1104
+ windowSize = 2;
1105
+ const MASK = bitMask(windowSize);
1106
+ const buckets = new Array(Number(MASK) + 1).fill(zero); // +1 for zero array
1056
1107
  const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize;
1057
1108
  let sum = zero;
1058
1109
  for (let i = lastBits; i >= 0; i -= windowSize) {
1059
1110
  buckets.fill(zero);
1060
- for (let j = 0; j < scalars.length; j++) {
1111
+ for (let j = 0; j < slength; j++) {
1061
1112
  const scalar = scalars[j];
1062
- const wbits = Number((scalar >> BigInt(i)) & BigInt(MASK));
1113
+ const wbits = Number((scalar >> BigInt(i)) & MASK);
1063
1114
  buckets[wbits] = buckets[wbits].add(points[j]);
1064
1115
  }
1065
1116
  let resI = zero; // not using this will do small speed-up, but will lose ct
@@ -1075,61 +1126,120 @@ function pippenger(c, fieldN, points, scalars) {
1075
1126
  }
1076
1127
  return sum;
1077
1128
  }
1078
- function validateBasic(curve) {
1079
- validateField(curve.Fp);
1080
- validateObject(curve, {
1081
- n: 'bigint',
1082
- h: 'bigint',
1083
- Gx: 'field',
1084
- Gy: 'field',
1085
- }, {
1086
- nBitLength: 'isSafeInteger',
1087
- nByteLength: 'isSafeInteger',
1088
- });
1089
- // Set defaults
1090
- return Object.freeze({
1091
- ...nLength(curve.n, curve.nBitLength),
1092
- ...curve,
1093
- ...{ p: curve.Fp.ORDER },
1094
- });
1129
+ function createField(order, field, isLE) {
1130
+ if (field) {
1131
+ if (field.ORDER !== order)
1132
+ throw new Error('Field.ORDER must match order: Fp == p, Fn == n');
1133
+ validateField(field);
1134
+ return field;
1135
+ }
1136
+ else {
1137
+ return Field(order, { isLE });
1138
+ }
1139
+ }
1140
+ /** Validates CURVE opts and creates fields */
1141
+ function _createCurveFields(type, CURVE, curveOpts = {}, FpFnLE) {
1142
+ if (FpFnLE === undefined)
1143
+ FpFnLE = type === 'edwards';
1144
+ if (!CURVE || typeof CURVE !== 'object')
1145
+ throw new Error(`expected valid ${type} CURVE object`);
1146
+ for (const p of ['p', 'n', 'h']) {
1147
+ const val = CURVE[p];
1148
+ if (!(typeof val === 'bigint' && val > _0n$3))
1149
+ throw new Error(`CURVE.${p} must be positive bigint`);
1150
+ }
1151
+ const Fp = createField(CURVE.p, curveOpts.Fp, FpFnLE);
1152
+ const Fn = createField(CURVE.n, curveOpts.Fn, FpFnLE);
1153
+ const _b = type === 'weierstrass' ? 'b' : 'd';
1154
+ const params = ['Gx', 'Gy', 'a', _b];
1155
+ for (const p of params) {
1156
+ // @ts-ignore
1157
+ if (!Fp.isValid(CURVE[p]))
1158
+ throw new Error(`CURVE.${p} must be valid field element of CURVE.Fp`);
1159
+ }
1160
+ CURVE = Object.freeze(Object.assign({}, CURVE));
1161
+ return { CURVE, Fp, Fn };
1095
1162
  }
1096
1163
 
1164
+ /**
1165
+ * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b.
1166
+ *
1167
+ * ### Design rationale for types
1168
+ *
1169
+ * * Interaction between classes from different curves should fail:
1170
+ * `k256.Point.BASE.add(p256.Point.BASE)`
1171
+ * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime
1172
+ * * Different calls of `curve()` would return different classes -
1173
+ * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve,
1174
+ * it won't affect others
1175
+ *
1176
+ * TypeScript can't infer types for classes created inside a function. Classes is one instance
1177
+ * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create
1178
+ * unique type for every function call.
1179
+ *
1180
+ * We can use generic types via some param, like curve opts, but that would:
1181
+ * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params)
1182
+ * which is hard to debug.
1183
+ * 2. Params can be generic and we can't enforce them to be constant value:
1184
+ * if somebody creates curve from non-constant params,
1185
+ * it would be allowed to interact with other curves with non-constant params
1186
+ *
1187
+ * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol
1188
+ * @module
1189
+ */
1097
1190
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
1098
- // Short Weierstrass curve. The formula is: = + ax + b
1099
- function validateSigVerOpts(opts) {
1100
- if (opts.lowS !== undefined)
1101
- abool('lowS', opts.lowS);
1102
- if (opts.prehash !== undefined)
1103
- abool('prehash', opts.prehash);
1104
- }
1105
- function validatePointOpts(curve) {
1106
- const opts = validateBasic(curve);
1107
- validateObject(opts, {
1108
- a: 'field',
1109
- b: 'field',
1110
- }, {
1111
- allowedPrivateKeyLengths: 'array',
1112
- wrapPrivateKey: 'boolean',
1113
- isTorsionFree: 'function',
1114
- clearCofactor: 'function',
1115
- allowInfinityPoint: 'boolean',
1116
- fromBytes: 'function',
1117
- toBytes: 'function',
1118
- });
1119
- const { endo, Fp, a } = opts;
1120
- if (endo) {
1121
- if (!Fp.eql(a, Fp.ZERO)) {
1122
- throw new Error('invalid endomorphism, can only be defined for Koblitz curves that have a=0');
1123
- }
1124
- if (typeof endo !== 'object' ||
1125
- typeof endo.beta !== 'bigint' ||
1126
- typeof endo.splitScalar !== 'function') {
1127
- throw new Error('invalid endomorphism, expected beta: bigint and splitScalar: function');
1128
- }
1191
+ // We construct basis in such way that den is always positive and equals n, but num sign depends on basis (not on secret value)
1192
+ const divNearest = (num, den) => (num + (num >= 0 ? den : -den) / _2n$4) / den;
1193
+ /**
1194
+ * Splits scalar for GLV endomorphism.
1195
+ */
1196
+ function _splitEndoScalar(k, basis, n) {
1197
+ // Split scalar into two such that part is ~half bits: `abs(part) < sqrt(N)`
1198
+ // Since part can be negative, we need to do this on point.
1199
+ // TODO: verifyScalar function which consumes lambda
1200
+ const [[a1, b1], [a2, b2]] = basis;
1201
+ const c1 = divNearest(b2 * k, n);
1202
+ const c2 = divNearest(-b1 * k, n);
1203
+ // |k1|/|k2| is < sqrt(N), but can be negative.
1204
+ // If we do `k1 mod N`, we'll get big scalar (`> sqrt(N)`): so, we do cheaper negation instead.
1205
+ let k1 = k - c1 * a1 - c2 * a2;
1206
+ let k2 = -c1 * b1 - c2 * b2;
1207
+ const k1neg = k1 < _0n$2;
1208
+ const k2neg = k2 < _0n$2;
1209
+ if (k1neg)
1210
+ k1 = -k1;
1211
+ if (k2neg)
1212
+ k2 = -k2;
1213
+ // Double check that resulting scalar less than half bits of N: otherwise wNAF will fail.
1214
+ // This should only happen on wrong basises. Also, math inside is too complex and I don't trust it.
1215
+ const MAX_NUM = bitMask(Math.ceil(bitLen(n) / 2)) + _1n$3; // Half bits of N
1216
+ if (k1 < _0n$2 || k1 >= MAX_NUM || k2 < _0n$2 || k2 >= MAX_NUM) {
1217
+ throw new Error('splitScalar (endomorphism): failed, k=' + k);
1218
+ }
1219
+ return { k1neg, k1, k2neg, k2 };
1220
+ }
1221
+ function validateSigFormat(format) {
1222
+ if (!['compact', 'recovered', 'der'].includes(format))
1223
+ throw new Error('Signature format must be "compact", "recovered", or "der"');
1224
+ return format;
1225
+ }
1226
+ function validateSigOpts(opts, def) {
1227
+ const optsn = {};
1228
+ for (let optName of Object.keys(def)) {
1229
+ // @ts-ignore
1230
+ optsn[optName] = opts[optName] === undefined ? def[optName] : opts[optName];
1231
+ }
1232
+ _abool2(optsn.lowS, 'lowS');
1233
+ _abool2(optsn.prehash, 'prehash');
1234
+ if (optsn.format !== undefined)
1235
+ validateSigFormat(optsn.format);
1236
+ return optsn;
1237
+ }
1238
+ class DERErr extends Error {
1239
+ constructor(m = '') {
1240
+ super(m);
1129
1241
  }
1130
- return Object.freeze({ ...opts });
1131
1242
  }
1132
- const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;
1133
1243
  /**
1134
1244
  * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format:
1135
1245
  *
@@ -1139,11 +1249,7 @@ const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;
1139
1249
  */
1140
1250
  const DER = {
1141
1251
  // asn.1 DER encoding utils
1142
- Err: class DERErr extends Error {
1143
- constructor(m = '') {
1144
- super(m);
1145
- }
1146
- },
1252
+ Err: DERErr,
1147
1253
  // Basic building block is TLV (Tag-Length-Value)
1148
1254
  _tlv: {
1149
1255
  encode: (tag, data) => {
@@ -1221,14 +1327,13 @@ const DER = {
1221
1327
  throw new E('invalid signature integer: negative');
1222
1328
  if (data[0] === 0x00 && !(data[1] & 128))
1223
1329
  throw new E('invalid signature integer: unnecessary leading zero');
1224
- return b2n(data);
1330
+ return bytesToNumberBE(data);
1225
1331
  },
1226
1332
  },
1227
1333
  toSig(hex) {
1228
1334
  // parse DER signature
1229
1335
  const { Err: E, _int: int, _tlv: tlv } = DER;
1230
- const data = typeof hex === 'string' ? h2b(hex) : hex;
1231
- abytes(data);
1336
+ const data = ensureBytes('signature', hex);
1232
1337
  const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data);
1233
1338
  if (seqLeftBytes.length)
1234
1339
  throw new E('invalid signature: left bytes after parsing');
@@ -1248,98 +1353,184 @@ const DER = {
1248
1353
  };
1249
1354
  // Be friendly to bad ECMAScript parsers by not using bigint literals
1250
1355
  // prettier-ignore
1251
- const _0n$2 = BigInt(0), _1n$4 = BigInt(1); BigInt(2); const _3n$1 = BigInt(3); BigInt(4);
1252
- function weierstrassPoints(opts) {
1253
- const CURVE = validatePointOpts(opts);
1254
- const { Fp } = CURVE; // All curves has same field / group length as for now, but they can differ
1255
- const Fn = Field(CURVE.n, CURVE.nBitLength);
1256
- const toBytes = CURVE.toBytes ||
1257
- ((_c, point, _isCompressed) => {
1258
- const a = point.toAffine();
1259
- return concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y));
1260
- });
1261
- const fromBytes = CURVE.fromBytes ||
1262
- ((bytes) => {
1263
- // const head = bytes[0];
1264
- const tail = bytes.subarray(1);
1265
- // if (head !== 0x04) throw new Error('Only non-compressed encoding is supported');
1266
- const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));
1267
- const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));
1268
- return { x, y };
1269
- });
1270
- /**
1271
- * y² = x³ + ax + b: Short weierstrass curve formula
1272
- * @returns y²
1273
- */
1274
- function weierstrassEquation(x) {
1275
- const { a, b } = CURVE;
1276
- const x2 = Fp.sqr(x); // x * x
1277
- const x3 = Fp.mul(x2, x); // x2 * x
1278
- return Fp.add(Fp.add(x3, Fp.mul(x, a)), b); // x3 + a * x + b
1356
+ const _0n$2 = BigInt(0), _1n$3 = BigInt(1), _2n$4 = BigInt(2), _3n$1 = BigInt(3), _4n = BigInt(4);
1357
+ function _normFnElement(Fn, key) {
1358
+ const { BYTES: expected } = Fn;
1359
+ let num;
1360
+ if (typeof key === 'bigint') {
1361
+ num = key;
1279
1362
  }
1280
- // Validate whether the passed curve params are valid.
1281
- // We check if curve equation works for generator point.
1282
- // `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381.
1283
- // ProjectivePoint class has not been initialized yet.
1284
- if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx)))
1285
- throw new Error('bad generator point: equation left != right');
1286
- // Valid group elements reside in range 1..n-1
1287
- function isWithinCurveOrder(num) {
1288
- return inRange(num, _1n$4, CURVE.n);
1289
- }
1290
- // Validates if priv key is valid and converts it to bigint.
1291
- // Supports options allowedPrivateKeyLengths and wrapPrivateKey.
1292
- function normPrivateKeyToScalar(key) {
1293
- const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n: N } = CURVE;
1294
- if (lengths && typeof key !== 'bigint') {
1295
- if (isBytes(key))
1296
- key = bytesToHex(key);
1297
- // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes
1298
- if (typeof key !== 'string' || !lengths.includes(key.length))
1299
- throw new Error('invalid private key');
1300
- key = key.padStart(nByteLength * 2, '0');
1301
- }
1302
- let num;
1363
+ else {
1364
+ let bytes = ensureBytes('private key', key);
1303
1365
  try {
1304
- num =
1305
- typeof key === 'bigint'
1306
- ? key
1307
- : bytesToNumberBE(ensureBytes('private key', key, nByteLength));
1366
+ num = Fn.fromBytes(bytes);
1308
1367
  }
1309
1368
  catch (error) {
1310
- throw new Error('invalid private key, expected hex or ' + nByteLength + ' bytes, got ' + typeof key);
1369
+ throw new Error(`invalid private key: expected ui8a of size ${expected}, got ${typeof key}`);
1370
+ }
1371
+ }
1372
+ if (!Fn.isValidNot0(num))
1373
+ throw new Error('invalid private key: out of range [1..N-1]');
1374
+ return num;
1375
+ }
1376
+ /**
1377
+ * Creates weierstrass Point constructor, based on specified curve options.
1378
+ *
1379
+ * @example
1380
+ ```js
1381
+ const opts = {
1382
+ p: BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'),
1383
+ n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),
1384
+ h: BigInt(1),
1385
+ a: BigInt('0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc'),
1386
+ b: BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b'),
1387
+ Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'),
1388
+ Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'),
1389
+ };
1390
+ const p256_Point = weierstrass(opts);
1391
+ ```
1392
+ */
1393
+ function weierstrassN(params, extraOpts = {}) {
1394
+ const validated = _createCurveFields('weierstrass', params, extraOpts);
1395
+ const { Fp, Fn } = validated;
1396
+ let CURVE = validated.CURVE;
1397
+ const { h: cofactor, n: CURVE_ORDER } = CURVE;
1398
+ _validateObject(extraOpts, {}, {
1399
+ allowInfinityPoint: 'boolean',
1400
+ clearCofactor: 'function',
1401
+ isTorsionFree: 'function',
1402
+ fromBytes: 'function',
1403
+ toBytes: 'function',
1404
+ endo: 'object',
1405
+ wrapPrivateKey: 'boolean',
1406
+ });
1407
+ const { endo } = extraOpts;
1408
+ if (endo) {
1409
+ // validateObject(endo, { beta: 'bigint', splitScalar: 'function' });
1410
+ if (!Fp.is0(CURVE.a) || typeof endo.beta !== 'bigint' || !Array.isArray(endo.basises)) {
1411
+ throw new Error('invalid endo: expected "beta": bigint and "basises": array');
1412
+ }
1413
+ }
1414
+ const lengths = getWLengths(Fp, Fn);
1415
+ function assertCompressionIsSupported() {
1416
+ if (!Fp.isOdd)
1417
+ throw new Error('compression is not supported: Field does not have .isOdd()');
1418
+ }
1419
+ // Implements IEEE P1363 point encoding
1420
+ function pointToBytes(_c, point, isCompressed) {
1421
+ const { x, y } = point.toAffine();
1422
+ const bx = Fp.toBytes(x);
1423
+ _abool2(isCompressed, 'isCompressed');
1424
+ if (isCompressed) {
1425
+ assertCompressionIsSupported();
1426
+ const hasEvenY = !Fp.isOdd(y);
1427
+ return concatBytes(pprefix(hasEvenY), bx);
1428
+ }
1429
+ else {
1430
+ return concatBytes(Uint8Array.of(0x04), bx, Fp.toBytes(y));
1311
1431
  }
1312
- if (wrapPrivateKey)
1313
- num = mod(num, N); // disabled by default, enabled for BLS
1314
- aInRange('private key', num, _1n$4, N); // num in range [1..N-1]
1315
- return num;
1316
1432
  }
1317
- function assertPrjPoint(other) {
1433
+ function pointFromBytes(bytes) {
1434
+ _abytes2(bytes, undefined, 'Point');
1435
+ const { publicKey: comp, publicKeyUncompressed: uncomp } = lengths; // e.g. for 32-byte: 33, 65
1436
+ const length = bytes.length;
1437
+ const head = bytes[0];
1438
+ const tail = bytes.subarray(1);
1439
+ // No actual validation is done here: use .assertValidity()
1440
+ if (length === comp && (head === 0x02 || head === 0x03)) {
1441
+ const x = Fp.fromBytes(tail);
1442
+ if (!Fp.isValid(x))
1443
+ throw new Error('bad point: is not on curve, wrong x');
1444
+ const y2 = weierstrassEquation(x); // y² = x³ + ax + b
1445
+ let y;
1446
+ try {
1447
+ y = Fp.sqrt(y2); // y = y² ^ (p+1)/4
1448
+ }
1449
+ catch (sqrtError) {
1450
+ const err = sqrtError instanceof Error ? ': ' + sqrtError.message : '';
1451
+ throw new Error('bad point: is not on curve, sqrt error' + err);
1452
+ }
1453
+ assertCompressionIsSupported();
1454
+ const isYOdd = Fp.isOdd(y); // (y & _1n) === _1n;
1455
+ const isHeadOdd = (head & 1) === 1; // ECDSA-specific
1456
+ if (isHeadOdd !== isYOdd)
1457
+ y = Fp.neg(y);
1458
+ return { x, y };
1459
+ }
1460
+ else if (length === uncomp && head === 0x04) {
1461
+ // TODO: more checks
1462
+ const L = Fp.BYTES;
1463
+ const x = Fp.fromBytes(tail.subarray(0, L));
1464
+ const y = Fp.fromBytes(tail.subarray(L, L * 2));
1465
+ if (!isValidXY(x, y))
1466
+ throw new Error('bad point: is not on curve');
1467
+ return { x, y };
1468
+ }
1469
+ else {
1470
+ throw new Error(`bad point: got length ${length}, expected compressed=${comp} or uncompressed=${uncomp}`);
1471
+ }
1472
+ }
1473
+ const encodePoint = extraOpts.toBytes || pointToBytes;
1474
+ const decodePoint = extraOpts.fromBytes || pointFromBytes;
1475
+ function weierstrassEquation(x) {
1476
+ const x2 = Fp.sqr(x); // x * x
1477
+ const x3 = Fp.mul(x2, x); // x² * x
1478
+ return Fp.add(Fp.add(x3, Fp.mul(x, CURVE.a)), CURVE.b); // x³ + a * x + b
1479
+ }
1480
+ // TODO: move top-level
1481
+ /** Checks whether equation holds for given x, y: y² == x³ + ax + b */
1482
+ function isValidXY(x, y) {
1483
+ const left = Fp.sqr(y); // y²
1484
+ const right = weierstrassEquation(x); // x³ + ax + b
1485
+ return Fp.eql(left, right);
1486
+ }
1487
+ // Validate whether the passed curve params are valid.
1488
+ // Test 1: equation y² = x³ + ax + b should work for generator point.
1489
+ if (!isValidXY(CURVE.Gx, CURVE.Gy))
1490
+ throw new Error('bad curve params: generator point');
1491
+ // Test 2: discriminant Δ part should be non-zero: 4a³ + 27b² != 0.
1492
+ // Guarantees curve is genus-1, smooth (non-singular).
1493
+ const _4a3 = Fp.mul(Fp.pow(CURVE.a, _3n$1), _4n);
1494
+ const _27b2 = Fp.mul(Fp.sqr(CURVE.b), BigInt(27));
1495
+ if (Fp.is0(Fp.add(_4a3, _27b2)))
1496
+ throw new Error('bad curve params: a or b');
1497
+ /** Asserts coordinate is valid: 0 <= n < Fp.ORDER. */
1498
+ function acoord(title, n, banZero = false) {
1499
+ if (!Fp.isValid(n) || (banZero && Fp.is0(n)))
1500
+ throw new Error(`bad point coordinate ${title}`);
1501
+ return n;
1502
+ }
1503
+ function aprjpoint(other) {
1318
1504
  if (!(other instanceof Point))
1319
1505
  throw new Error('ProjectivePoint expected');
1320
1506
  }
1507
+ function splitEndoScalarN(k) {
1508
+ if (!endo || !endo.basises)
1509
+ throw new Error('no endo');
1510
+ return _splitEndoScalar(k, endo.basises, Fn.ORDER);
1511
+ }
1321
1512
  // Memoized toAffine / validity check. They are heavy. Points are immutable.
1322
1513
  // Converts Projective point to affine (x, y) coordinates.
1323
1514
  // Can accept precomputed Z^-1 - for example, from invertBatch.
1324
- // (x, y, z) ∋ (x=x/z, y=y/z)
1515
+ // (X, Y, Z) ∋ (x=X/Z, y=Y/Z)
1325
1516
  const toAffineMemo = memoized((p, iz) => {
1326
- const { px: x, py: y, pz: z } = p;
1517
+ const { X, Y, Z } = p;
1327
1518
  // Fast-path for normalized points
1328
- if (Fp.eql(z, Fp.ONE))
1329
- return { x, y };
1519
+ if (Fp.eql(Z, Fp.ONE))
1520
+ return { x: X, y: Y };
1330
1521
  const is0 = p.is0();
1331
1522
  // If invZ was 0, we return zero point. However we still want to execute
1332
1523
  // all operations, so we replace invZ with a random number, 1.
1333
1524
  if (iz == null)
1334
- iz = is0 ? Fp.ONE : Fp.inv(z);
1335
- const ax = Fp.mul(x, iz);
1336
- const ay = Fp.mul(y, iz);
1337
- const zz = Fp.mul(z, iz);
1525
+ iz = is0 ? Fp.ONE : Fp.inv(Z);
1526
+ const x = Fp.mul(X, iz);
1527
+ const y = Fp.mul(Y, iz);
1528
+ const zz = Fp.mul(Z, iz);
1338
1529
  if (is0)
1339
1530
  return { x: Fp.ZERO, y: Fp.ZERO };
1340
1531
  if (!Fp.eql(zz, Fp.ONE))
1341
1532
  throw new Error('invZ was invalid');
1342
- return { x: ax, y: ay };
1533
+ return { x, y };
1343
1534
  });
1344
1535
  // NOTE: on exception this will crash 'cached' and no value will be set.
1345
1536
  // Otherwise true will be return
@@ -1348,55 +1539,62 @@ function weierstrassPoints(opts) {
1348
1539
  // (0, 1, 0) aka ZERO is invalid in most contexts.
1349
1540
  // In BLS, ZERO can be serialized, so we allow it.
1350
1541
  // (0, 0, 0) is invalid representation of ZERO.
1351
- if (CURVE.allowInfinityPoint && !Fp.is0(p.py))
1542
+ if (extraOpts.allowInfinityPoint && !Fp.is0(p.Y))
1352
1543
  return;
1353
1544
  throw new Error('bad point: ZERO');
1354
1545
  }
1355
1546
  // Some 3rd-party test vectors require different wording between here & `fromCompressedHex`
1356
1547
  const { x, y } = p.toAffine();
1357
- // Check if x, y are valid field elements
1358
1548
  if (!Fp.isValid(x) || !Fp.isValid(y))
1359
- throw new Error('bad point: x or y not FE');
1360
- const left = Fp.sqr(y); // y²
1361
- const right = weierstrassEquation(x); // x³ + ax + b
1362
- if (!Fp.eql(left, right))
1549
+ throw new Error('bad point: x or y not field elements');
1550
+ if (!isValidXY(x, y))
1363
1551
  throw new Error('bad point: equation left != right');
1364
1552
  if (!p.isTorsionFree())
1365
1553
  throw new Error('bad point: not in prime-order subgroup');
1366
1554
  return true;
1367
1555
  });
1556
+ function finishEndo(endoBeta, k1p, k2p, k1neg, k2neg) {
1557
+ k2p = new Point(Fp.mul(k2p.X, endoBeta), k2p.Y, k2p.Z);
1558
+ k1p = negateCt(k1neg, k1p);
1559
+ k2p = negateCt(k2neg, k2p);
1560
+ return k1p.add(k2p);
1561
+ }
1368
1562
  /**
1369
- * Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z)
1370
- * Default Point works in 2d / affine coordinates: (x, y)
1563
+ * Projective Point works in 3d / projective (homogeneous) coordinates:(X, Y, Z) ∋ (x=X/Z, y=Y/Z).
1564
+ * Default Point works in 2d / affine coordinates: (x, y).
1371
1565
  * We're doing calculations in projective, because its operations don't require costly inversion.
1372
1566
  */
1373
1567
  class Point {
1374
- constructor(px, py, pz) {
1375
- this.px = px;
1376
- this.py = py;
1377
- this.pz = pz;
1378
- if (px == null || !Fp.isValid(px))
1379
- throw new Error('x required');
1380
- if (py == null || !Fp.isValid(py))
1381
- throw new Error('y required');
1382
- if (pz == null || !Fp.isValid(pz))
1383
- throw new Error('z required');
1568
+ /** Does NOT validate if the point is valid. Use `.assertValidity()`. */
1569
+ constructor(X, Y, Z) {
1570
+ this.X = acoord('x', X);
1571
+ this.Y = acoord('y', Y, true);
1572
+ this.Z = acoord('z', Z);
1384
1573
  Object.freeze(this);
1385
1574
  }
1386
- // Does not validate if the point is on-curve.
1387
- // Use fromHex instead, or call assertValidity() later.
1575
+ static CURVE() {
1576
+ return CURVE;
1577
+ }
1578
+ /** Does NOT validate if the point is valid. Use `.assertValidity()`. */
1388
1579
  static fromAffine(p) {
1389
1580
  const { x, y } = p || {};
1390
1581
  if (!p || !Fp.isValid(x) || !Fp.isValid(y))
1391
1582
  throw new Error('invalid affine point');
1392
1583
  if (p instanceof Point)
1393
1584
  throw new Error('projective point not allowed');
1394
- const is0 = (i) => Fp.eql(i, Fp.ZERO);
1395
- // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0)
1396
- if (is0(x) && is0(y))
1585
+ // (0, 0) would've produced (0, 0, 1) - instead, we need (0, 1, 0)
1586
+ if (Fp.is0(x) && Fp.is0(y))
1397
1587
  return Point.ZERO;
1398
1588
  return new Point(x, y, Fp.ONE);
1399
1589
  }
1590
+ static fromBytes(bytes) {
1591
+ const P = Point.fromAffine(decodePoint(_abytes2(bytes, undefined, 'point')));
1592
+ P.assertValidity();
1593
+ return P;
1594
+ }
1595
+ static fromHex(hex) {
1596
+ return Point.fromBytes(ensureBytes('pointHex', hex));
1597
+ }
1400
1598
  get x() {
1401
1599
  return this.toAffine().x;
1402
1600
  }
@@ -1404,62 +1602,40 @@ function weierstrassPoints(opts) {
1404
1602
  return this.toAffine().y;
1405
1603
  }
1406
1604
  /**
1407
- * Takes a bunch of Projective Points but executes only one
1408
- * inversion on all of them. Inversion is very slow operation,
1409
- * so this improves performance massively.
1410
- * Optimization: converts a list of projective points to a list of identical points with Z=1.
1411
- */
1412
- static normalizeZ(points) {
1413
- const toInv = Fp.invertBatch(points.map((p) => p.pz));
1414
- return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);
1415
- }
1416
- /**
1417
- * Converts hash string or Uint8Array to Point.
1418
- * @param hex short/long ECDSA hex
1605
+ *
1606
+ * @param windowSize
1607
+ * @param isLazy true will defer table computation until the first multiplication
1608
+ * @returns
1419
1609
  */
1420
- static fromHex(hex) {
1421
- const P = Point.fromAffine(fromBytes(ensureBytes('pointHex', hex)));
1422
- P.assertValidity();
1423
- return P;
1424
- }
1425
- // Multiplies generator point by privateKey.
1426
- static fromPrivateKey(privateKey) {
1427
- return Point.BASE.multiply(normPrivateKeyToScalar(privateKey));
1428
- }
1429
- // Multiscalar Multiplication
1430
- static msm(points, scalars) {
1431
- return pippenger(Point, Fn, points, scalars);
1432
- }
1433
- // "Private method", don't use it directly
1434
- _setWindowSize(windowSize) {
1435
- wnaf.setWindowSize(this, windowSize);
1436
- }
1437
- // A point on curve is valid if it conforms to equation.
1610
+ precompute(windowSize = 8, isLazy = true) {
1611
+ wnaf.createCache(this, windowSize);
1612
+ if (!isLazy)
1613
+ this.multiply(_3n$1); // random number
1614
+ return this;
1615
+ }
1616
+ // TODO: return `this`
1617
+ /** A point on curve is valid if it conforms to equation. */
1438
1618
  assertValidity() {
1439
1619
  assertValidMemo(this);
1440
1620
  }
1441
1621
  hasEvenY() {
1442
1622
  const { y } = this.toAffine();
1443
- if (Fp.isOdd)
1444
- return !Fp.isOdd(y);
1445
- throw new Error("Field doesn't support isOdd");
1623
+ if (!Fp.isOdd)
1624
+ throw new Error("Field doesn't support isOdd");
1625
+ return !Fp.isOdd(y);
1446
1626
  }
1447
- /**
1448
- * Compare one point to another.
1449
- */
1627
+ /** Compare one point to another. */
1450
1628
  equals(other) {
1451
- assertPrjPoint(other);
1452
- const { px: X1, py: Y1, pz: Z1 } = this;
1453
- const { px: X2, py: Y2, pz: Z2 } = other;
1629
+ aprjpoint(other);
1630
+ const { X: X1, Y: Y1, Z: Z1 } = this;
1631
+ const { X: X2, Y: Y2, Z: Z2 } = other;
1454
1632
  const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1));
1455
1633
  const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1));
1456
1634
  return U1 && U2;
1457
1635
  }
1458
- /**
1459
- * Flips point to one corresponding to (x, -y) in Affine coordinates.
1460
- */
1636
+ /** Flips point to one corresponding to (x, -y) in Affine coordinates. */
1461
1637
  negate() {
1462
- return new Point(this.px, Fp.neg(this.py), this.pz);
1638
+ return new Point(this.X, Fp.neg(this.Y), this.Z);
1463
1639
  }
1464
1640
  // Renes-Costello-Batina exception-free doubling formula.
1465
1641
  // There is 30% faster Jacobian formula, but it is not complete.
@@ -1468,7 +1644,7 @@ function weierstrassPoints(opts) {
1468
1644
  double() {
1469
1645
  const { a, b } = CURVE;
1470
1646
  const b3 = Fp.mul(b, _3n$1);
1471
- const { px: X1, py: Y1, pz: Z1 } = this;
1647
+ const { X: X1, Y: Y1, Z: Z1 } = this;
1472
1648
  let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
1473
1649
  let t0 = Fp.mul(X1, X1); // step 1
1474
1650
  let t1 = Fp.mul(Y1, Y1);
@@ -1508,9 +1684,9 @@ function weierstrassPoints(opts) {
1508
1684
  // https://eprint.iacr.org/2015/1060, algorithm 1
1509
1685
  // Cost: 12M + 0S + 3*a + 3*b3 + 23add.
1510
1686
  add(other) {
1511
- assertPrjPoint(other);
1512
- const { px: X1, py: Y1, pz: Z1 } = this;
1513
- const { px: X2, py: Y2, pz: Z2 } = other;
1687
+ aprjpoint(other);
1688
+ const { X: X1, Y: Y1, Z: Z1 } = this;
1689
+ const { X: X2, Y: Y2, Z: Z2 } = other;
1514
1690
  let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
1515
1691
  const a = CURVE.a;
1516
1692
  const b3 = Fp.mul(CURVE.b, _3n$1);
@@ -1562,46 +1738,6 @@ function weierstrassPoints(opts) {
1562
1738
  is0() {
1563
1739
  return this.equals(Point.ZERO);
1564
1740
  }
1565
- wNAF(n) {
1566
- return wnaf.wNAFCached(this, n, Point.normalizeZ);
1567
- }
1568
- /**
1569
- * Non-constant-time multiplication. Uses double-and-add algorithm.
1570
- * It's faster, but should only be used when you don't care about
1571
- * an exposed private key e.g. sig verification, which works over *public* keys.
1572
- */
1573
- multiplyUnsafe(sc) {
1574
- const { endo, n: N } = CURVE;
1575
- aInRange('scalar', sc, _0n$2, N);
1576
- const I = Point.ZERO;
1577
- if (sc === _0n$2)
1578
- return I;
1579
- if (this.is0() || sc === _1n$4)
1580
- return this;
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
1585
- let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc);
1586
- let k1p = I;
1587
- let k2p = I;
1588
- let d = this;
1589
- while (k1 > _0n$2 || k2 > _0n$2) {
1590
- if (k1 & _1n$4)
1591
- k1p = k1p.add(d);
1592
- if (k2 & _1n$4)
1593
- k2p = k2p.add(d);
1594
- d = d.double();
1595
- k1 >>= _1n$4;
1596
- k2 >>= _1n$4;
1597
- }
1598
- if (k1neg)
1599
- k1p = k1p.negate();
1600
- if (k2neg)
1601
- k2p = k2p.negate();
1602
- k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
1603
- return k1p.add(k2p);
1604
- }
1605
1741
  /**
1606
1742
  * Constant time multiplication.
1607
1743
  * Uses wNAF method. Windowed method may be 10% faster,
@@ -1612,222 +1748,360 @@ function weierstrassPoints(opts) {
1612
1748
  * @returns New point
1613
1749
  */
1614
1750
  multiply(scalar) {
1615
- const { endo, n: N } = CURVE;
1616
- aInRange('scalar', scalar, _1n$4, N);
1751
+ const { endo } = extraOpts;
1752
+ if (!Fn.isValidNot0(scalar))
1753
+ throw new Error('invalid scalar: out of range'); // 0 is invalid
1617
1754
  let point, fake; // Fake point is used to const-time mult
1755
+ const mul = (n) => wnaf.cached(this, n, (p) => normalizeZ(Point, p));
1756
+ /** See docs for {@link EndomorphismOpts} */
1618
1757
  if (endo) {
1619
- const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar);
1620
- let { p: k1p, f: f1p } = this.wNAF(k1);
1621
- let { p: k2p, f: f2p } = this.wNAF(k2);
1622
- k1p = wnaf.constTimeNegate(k1neg, k1p);
1623
- k2p = wnaf.constTimeNegate(k2neg, k2p);
1624
- k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
1625
- point = k1p.add(k2p);
1626
- fake = f1p.add(f2p);
1758
+ const { k1neg, k1, k2neg, k2 } = splitEndoScalarN(scalar);
1759
+ const { p: k1p, f: k1f } = mul(k1);
1760
+ const { p: k2p, f: k2f } = mul(k2);
1761
+ fake = k1f.add(k2f);
1762
+ point = finishEndo(endo.beta, k1p, k2p, k1neg, k2neg);
1627
1763
  }
1628
1764
  else {
1629
- const { p, f } = this.wNAF(scalar);
1765
+ const { p, f } = mul(scalar);
1630
1766
  point = p;
1631
1767
  fake = f;
1632
1768
  }
1633
1769
  // Normalize `z` for both points, but return only real one
1634
- return Point.normalizeZ([point, fake])[0];
1770
+ return normalizeZ(Point, [point, fake])[0];
1635
1771
  }
1636
1772
  /**
1637
- * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly.
1638
- * Not using Strauss-Shamir trick: precomputation tables are faster.
1639
- * The trick could be useful if both P and Q are not G (not in our case).
1640
- * @returns non-zero affine point
1773
+ * Non-constant-time multiplication. Uses double-and-add algorithm.
1774
+ * It's faster, but should only be used when you don't care about
1775
+ * an exposed secret key e.g. sig verification, which works over *public* keys.
1641
1776
  */
1777
+ multiplyUnsafe(sc) {
1778
+ const { endo } = extraOpts;
1779
+ const p = this;
1780
+ if (!Fn.isValid(sc))
1781
+ throw new Error('invalid scalar: out of range'); // 0 is valid
1782
+ if (sc === _0n$2 || p.is0())
1783
+ return Point.ZERO;
1784
+ if (sc === _1n$3)
1785
+ return p; // fast-path
1786
+ if (wnaf.hasCache(this))
1787
+ return this.multiply(sc);
1788
+ if (endo) {
1789
+ const { k1neg, k1, k2neg, k2 } = splitEndoScalarN(sc);
1790
+ const { p1, p2 } = mulEndoUnsafe(Point, p, k1, k2); // 30% faster vs wnaf.unsafe
1791
+ return finishEndo(endo.beta, p1, p2, k1neg, k2neg);
1792
+ }
1793
+ else {
1794
+ return wnaf.unsafe(p, sc);
1795
+ }
1796
+ }
1642
1797
  multiplyAndAddUnsafe(Q, a, b) {
1643
- const G = Point.BASE; // No Strauss-Shamir trick: we have 10% faster G precomputes
1644
- const mul = (P, a // Select faster multiply() method
1645
- ) => (a === _0n$2 || a === _1n$4 || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a));
1646
- const sum = mul(this, a).add(mul(Q, b));
1798
+ const sum = this.multiplyUnsafe(a).add(Q.multiplyUnsafe(b));
1647
1799
  return sum.is0() ? undefined : sum;
1648
1800
  }
1649
- // Converts Projective point to affine (x, y) coordinates.
1650
- // Can accept precomputed Z^-1 - for example, from invertBatch.
1651
- // (x, y, z) (x=x/z, y=y/z)
1652
- toAffine(iz) {
1653
- return toAffineMemo(this, iz);
1801
+ /**
1802
+ * Converts Projective point to affine (x, y) coordinates.
1803
+ * @param invertedZ Z^-1 (inverted zero) - optional, precomputation is useful for invertBatch
1804
+ */
1805
+ toAffine(invertedZ) {
1806
+ return toAffineMemo(this, invertedZ);
1654
1807
  }
1808
+ /**
1809
+ * Checks whether Point is free of torsion elements (is in prime subgroup).
1810
+ * Always torsion-free for cofactor=1 curves.
1811
+ */
1655
1812
  isTorsionFree() {
1656
- const { h: cofactor, isTorsionFree } = CURVE;
1657
- if (cofactor === _1n$4)
1658
- return true; // No subgroups, always torsion-free
1813
+ const { isTorsionFree } = extraOpts;
1814
+ if (cofactor === _1n$3)
1815
+ return true;
1659
1816
  if (isTorsionFree)
1660
1817
  return isTorsionFree(Point, this);
1661
- throw new Error('isTorsionFree() has not been declared for the elliptic curve');
1818
+ return wnaf.unsafe(this, CURVE_ORDER).is0();
1662
1819
  }
1663
1820
  clearCofactor() {
1664
- const { h: cofactor, clearCofactor } = CURVE;
1665
- if (cofactor === _1n$4)
1821
+ const { clearCofactor } = extraOpts;
1822
+ if (cofactor === _1n$3)
1666
1823
  return this; // Fast-path
1667
1824
  if (clearCofactor)
1668
1825
  return clearCofactor(Point, this);
1669
- return this.multiplyUnsafe(CURVE.h);
1826
+ return this.multiplyUnsafe(cofactor);
1670
1827
  }
1671
- toRawBytes(isCompressed = true) {
1672
- abool('isCompressed', isCompressed);
1828
+ isSmallOrder() {
1829
+ // can we use this.clearCofactor()?
1830
+ return this.multiplyUnsafe(cofactor).is0();
1831
+ }
1832
+ toBytes(isCompressed = true) {
1833
+ _abool2(isCompressed, 'isCompressed');
1673
1834
  this.assertValidity();
1674
- return toBytes(Point, this, isCompressed);
1835
+ return encodePoint(Point, this, isCompressed);
1675
1836
  }
1676
1837
  toHex(isCompressed = true) {
1677
- abool('isCompressed', isCompressed);
1678
- return bytesToHex(this.toRawBytes(isCompressed));
1838
+ return bytesToHex(this.toBytes(isCompressed));
1839
+ }
1840
+ toString() {
1841
+ return `<Point ${this.is0() ? 'ZERO' : this.toHex()}>`;
1842
+ }
1843
+ // TODO: remove
1844
+ get px() {
1845
+ return this.X;
1846
+ }
1847
+ get py() {
1848
+ return this.X;
1849
+ }
1850
+ get pz() {
1851
+ return this.Z;
1852
+ }
1853
+ toRawBytes(isCompressed = true) {
1854
+ return this.toBytes(isCompressed);
1855
+ }
1856
+ _setWindowSize(windowSize) {
1857
+ this.precompute(windowSize);
1858
+ }
1859
+ static normalizeZ(points) {
1860
+ return normalizeZ(Point, points);
1861
+ }
1862
+ static msm(points, scalars) {
1863
+ return pippenger(Point, Fn, points, scalars);
1864
+ }
1865
+ static fromPrivateKey(privateKey) {
1866
+ return Point.BASE.multiply(_normFnElement(Fn, privateKey));
1679
1867
  }
1680
1868
  }
1869
+ // base / generator point
1681
1870
  Point.BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE);
1682
- Point.ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO);
1683
- const _bits = CURVE.nBitLength;
1684
- const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits);
1685
- // Validate if generator point is on curve
1871
+ // zero / infinity / identity point
1872
+ Point.ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO); // 0, 1, 0
1873
+ // math field
1874
+ Point.Fp = Fp;
1875
+ // scalar field
1876
+ Point.Fn = Fn;
1877
+ const bits = Fn.BITS;
1878
+ const wnaf = new wNAF(Point, extraOpts.endo ? Math.ceil(bits / 2) : bits);
1879
+ Point.BASE.precompute(8); // Enable precomputes. Slows down first publicKey computation by 20ms.
1880
+ return Point;
1881
+ }
1882
+ // Points start with byte 0x02 when y is even; otherwise 0x03
1883
+ function pprefix(hasEvenY) {
1884
+ return Uint8Array.of(hasEvenY ? 0x02 : 0x03);
1885
+ }
1886
+ function getWLengths(Fp, Fn) {
1686
1887
  return {
1687
- CURVE,
1688
- ProjectivePoint: Point,
1689
- normPrivateKeyToScalar,
1690
- weierstrassEquation,
1691
- isWithinCurveOrder,
1888
+ secretKey: Fn.BYTES,
1889
+ publicKey: 1 + Fp.BYTES,
1890
+ publicKeyUncompressed: 1 + 2 * Fp.BYTES,
1891
+ publicKeyHasPrefix: true,
1892
+ signature: 2 * Fn.BYTES,
1692
1893
  };
1693
1894
  }
1694
- function validateOpts$2(curve) {
1695
- const opts = validateBasic(curve);
1696
- validateObject(opts, {
1697
- hash: 'hash',
1698
- hmac: 'function',
1699
- randomBytes: 'function',
1700
- }, {
1701
- bits2int: 'function',
1702
- bits2int_modN: 'function',
1703
- lowS: 'boolean',
1704
- });
1705
- return Object.freeze({ lowS: true, ...opts });
1895
+ /**
1896
+ * Sometimes users only need getPublicKey, getSharedSecret, and secret key handling.
1897
+ * This helper ensures no signature functionality is present. Less code, smaller bundle size.
1898
+ */
1899
+ function ecdh(Point, ecdhOpts = {}) {
1900
+ const { Fn } = Point;
1901
+ const randomBytes_ = ecdhOpts.randomBytes || randomBytes;
1902
+ const lengths = Object.assign(getWLengths(Point.Fp, Fn), { seed: getMinHashLength(Fn.ORDER) });
1903
+ function isValidSecretKey(secretKey) {
1904
+ try {
1905
+ return !!_normFnElement(Fn, secretKey);
1906
+ }
1907
+ catch (error) {
1908
+ return false;
1909
+ }
1910
+ }
1911
+ function isValidPublicKey(publicKey, isCompressed) {
1912
+ const { publicKey: comp, publicKeyUncompressed } = lengths;
1913
+ try {
1914
+ const l = publicKey.length;
1915
+ if (isCompressed === true && l !== comp)
1916
+ return false;
1917
+ if (isCompressed === false && l !== publicKeyUncompressed)
1918
+ return false;
1919
+ return !!Point.fromBytes(publicKey);
1920
+ }
1921
+ catch (error) {
1922
+ return false;
1923
+ }
1924
+ }
1925
+ /**
1926
+ * Produces cryptographically secure secret key from random of size
1927
+ * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.
1928
+ */
1929
+ function randomSecretKey(seed = randomBytes_(lengths.seed)) {
1930
+ return mapHashToField(_abytes2(seed, lengths.seed, 'seed'), Fn.ORDER);
1931
+ }
1932
+ /**
1933
+ * Computes public key for a secret key. Checks for validity of the secret key.
1934
+ * @param isCompressed whether to return compact (default), or full key
1935
+ * @returns Public key, full when isCompressed=false; short when isCompressed=true
1936
+ */
1937
+ function getPublicKey(secretKey, isCompressed = true) {
1938
+ return Point.BASE.multiply(_normFnElement(Fn, secretKey)).toBytes(isCompressed);
1939
+ }
1940
+ function keygen(seed) {
1941
+ const secretKey = randomSecretKey(seed);
1942
+ return { secretKey, publicKey: getPublicKey(secretKey) };
1943
+ }
1944
+ /**
1945
+ * Quick and dirty check for item being public key. Does not validate hex, or being on-curve.
1946
+ */
1947
+ function isProbPub(item) {
1948
+ if (typeof item === 'bigint')
1949
+ return false;
1950
+ if (item instanceof Point)
1951
+ return true;
1952
+ const { secretKey, publicKey, publicKeyUncompressed } = lengths;
1953
+ if (Fn.allowedLengths || secretKey === publicKey)
1954
+ return undefined;
1955
+ const l = ensureBytes('key', item).length;
1956
+ return l === publicKey || l === publicKeyUncompressed;
1957
+ }
1958
+ /**
1959
+ * ECDH (Elliptic Curve Diffie Hellman).
1960
+ * Computes shared public key from secret key A and public key B.
1961
+ * Checks: 1) secret key validity 2) shared key is on-curve.
1962
+ * Does NOT hash the result.
1963
+ * @param isCompressed whether to return compact (default), or full key
1964
+ * @returns shared public key
1965
+ */
1966
+ function getSharedSecret(secretKeyA, publicKeyB, isCompressed = true) {
1967
+ if (isProbPub(secretKeyA) === true)
1968
+ throw new Error('first arg must be private key');
1969
+ if (isProbPub(publicKeyB) === false)
1970
+ throw new Error('second arg must be public key');
1971
+ const s = _normFnElement(Fn, secretKeyA);
1972
+ const b = Point.fromHex(publicKeyB); // checks for being on-curve
1973
+ return b.multiply(s).toBytes(isCompressed);
1974
+ }
1975
+ const utils = {
1976
+ isValidSecretKey,
1977
+ isValidPublicKey,
1978
+ randomSecretKey,
1979
+ // TODO: remove
1980
+ isValidPrivateKey: isValidSecretKey,
1981
+ randomPrivateKey: randomSecretKey,
1982
+ normPrivateKeyToScalar: (key) => _normFnElement(Fn, key),
1983
+ precompute(windowSize = 8, point = Point.BASE) {
1984
+ return point.precompute(windowSize, false);
1985
+ },
1986
+ };
1987
+ return Object.freeze({ getPublicKey, getSharedSecret, keygen, Point, utils, lengths });
1706
1988
  }
1707
1989
  /**
1708
- * Creates short weierstrass curve and ECDSA signature methods for it.
1990
+ * Creates ECDSA signing interface for given elliptic curve `Point` and `hash` function.
1991
+ * We need `hash` for 2 features:
1992
+ * 1. Message prehash-ing. NOT used if `sign` / `verify` are called with `prehash: false`
1993
+ * 2. k generation in `sign`, using HMAC-drbg(hash)
1994
+ *
1995
+ * ECDSAOpts are only rarely needed.
1996
+ *
1709
1997
  * @example
1710
- * import { Field } from '@noble/curves/abstract/modular';
1711
- * // Before that, define BigInt-s: a, b, p, n, Gx, Gy
1712
- * const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n })
1998
+ * ```js
1999
+ * const p256_Point = weierstrass(...);
2000
+ * const p256_sha256 = ecdsa(p256_Point, sha256);
2001
+ * const p256_sha224 = ecdsa(p256_Point, sha224);
2002
+ * const p256_sha224_r = ecdsa(p256_Point, sha224, { randomBytes: (length) => { ... } });
2003
+ * ```
1713
2004
  */
1714
- function weierstrass(curveDef) {
1715
- const CURVE = validateOpts$2(curveDef);
1716
- const { Fp, n: CURVE_ORDER } = CURVE;
1717
- const compressedLen = Fp.BYTES + 1; // e.g. 33 for 32
1718
- const uncompressedLen = 2 * Fp.BYTES + 1; // e.g. 65 for 32
1719
- function modN(a) {
1720
- return mod(a, CURVE_ORDER);
1721
- }
1722
- function invN(a) {
1723
- return invert(a, CURVE_ORDER);
1724
- }
1725
- const { ProjectivePoint: Point, normPrivateKeyToScalar, weierstrassEquation, isWithinCurveOrder, } = weierstrassPoints({
1726
- ...CURVE,
1727
- toBytes(_c, point, isCompressed) {
1728
- const a = point.toAffine();
1729
- const x = Fp.toBytes(a.x);
1730
- const cat = concatBytes;
1731
- abool('isCompressed', isCompressed);
1732
- if (isCompressed) {
1733
- return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x);
1734
- }
1735
- else {
1736
- return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y));
1737
- }
1738
- },
1739
- fromBytes(bytes) {
1740
- const len = bytes.length;
1741
- const head = bytes[0];
1742
- const tail = bytes.subarray(1);
1743
- // this.assertValidity() is done inside of fromHex
1744
- if (len === compressedLen && (head === 0x02 || head === 0x03)) {
1745
- const x = bytesToNumberBE(tail);
1746
- if (!inRange(x, _1n$4, Fp.ORDER))
1747
- throw new Error('Point is not on curve');
1748
- const y2 = weierstrassEquation(x); // y² = x³ + ax + b
1749
- let y;
1750
- try {
1751
- y = Fp.sqrt(y2); // y = y² ^ (p+1)/4
1752
- }
1753
- catch (sqrtError) {
1754
- const suffix = sqrtError instanceof Error ? ': ' + sqrtError.message : '';
1755
- throw new Error('Point is not on curve' + suffix);
1756
- }
1757
- const isYOdd = (y & _1n$4) === _1n$4;
1758
- // ECDSA
1759
- const isHeadOdd = (head & 1) === 1;
1760
- if (isHeadOdd !== isYOdd)
1761
- y = Fp.neg(y);
1762
- return { x, y };
1763
- }
1764
- else if (len === uncompressedLen && head === 0x04) {
1765
- const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));
1766
- const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));
1767
- return { x, y };
1768
- }
1769
- else {
1770
- const cl = compressedLen;
1771
- const ul = uncompressedLen;
1772
- throw new Error('invalid Point, expected length of ' + cl + ', or uncompressed ' + ul + ', got ' + len);
1773
- }
1774
- },
2005
+ function ecdsa(Point, hash, ecdsaOpts = {}) {
2006
+ ahash(hash);
2007
+ _validateObject(ecdsaOpts, {}, {
2008
+ hmac: 'function',
2009
+ lowS: 'boolean',
2010
+ randomBytes: 'function',
2011
+ bits2int: 'function',
2012
+ bits2int_modN: 'function',
1775
2013
  });
1776
- const numToNByteStr = (num) => bytesToHex(numberToBytesBE(num, CURVE.nByteLength));
2014
+ const randomBytes$1 = ecdsaOpts.randomBytes || randomBytes;
2015
+ const hmac$1 = ecdsaOpts.hmac ||
2016
+ ((key, ...msgs) => hmac(hash, key, concatBytes(...msgs)));
2017
+ const { Fp, Fn } = Point;
2018
+ const { ORDER: CURVE_ORDER, BITS: fnBits } = Fn;
2019
+ const { keygen, getPublicKey, getSharedSecret, utils, lengths } = ecdh(Point, ecdsaOpts);
2020
+ const defaultSigOpts = {
2021
+ prehash: false,
2022
+ lowS: typeof ecdsaOpts.lowS === 'boolean' ? ecdsaOpts.lowS : false,
2023
+ format: undefined, //'compact' as ECDSASigFormat,
2024
+ extraEntropy: false,
2025
+ };
2026
+ const defaultSigOpts_format = 'compact';
1777
2027
  function isBiggerThanHalfOrder(number) {
1778
- const HALF = CURVE_ORDER >> _1n$4;
2028
+ const HALF = CURVE_ORDER >> _1n$3;
1779
2029
  return number > HALF;
1780
2030
  }
1781
- function normalizeS(s) {
1782
- return isBiggerThanHalfOrder(s) ? modN(-s) : s;
2031
+ function validateRS(title, num) {
2032
+ if (!Fn.isValidNot0(num))
2033
+ throw new Error(`invalid signature ${title}: out of range 1..Point.Fn.ORDER`);
2034
+ return num;
2035
+ }
2036
+ function validateSigLength(bytes, format) {
2037
+ validateSigFormat(format);
2038
+ const size = lengths.signature;
2039
+ const sizer = format === 'compact' ? size : format === 'recovered' ? size + 1 : undefined;
2040
+ return _abytes2(bytes, sizer, `${format} signature`);
1783
2041
  }
1784
- // slice bytes num
1785
- const slcNum = (b, from, to) => bytesToNumberBE(b.slice(from, to));
1786
2042
  /**
1787
- * ECDSA signature with its (r, s) properties. Supports DER & compact representations.
2043
+ * ECDSA signature with its (r, s) properties. Supports compact, recovered & DER representations.
1788
2044
  */
1789
2045
  class Signature {
1790
2046
  constructor(r, s, recovery) {
1791
- this.r = r;
1792
- this.s = s;
1793
- this.recovery = recovery;
1794
- this.assertValidity();
1795
- }
1796
- // pair (bytes of r, bytes of s)
1797
- static fromCompact(hex) {
1798
- const l = CURVE.nByteLength;
1799
- hex = ensureBytes('compactSignature', hex, l * 2);
1800
- return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l));
2047
+ this.r = validateRS('r', r); // r in [1..N-1];
2048
+ this.s = validateRS('s', s); // s in [1..N-1];
2049
+ if (recovery != null)
2050
+ this.recovery = recovery;
2051
+ Object.freeze(this);
1801
2052
  }
1802
- // DER encoded ECDSA signature
1803
- // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script
1804
- static fromDER(hex) {
1805
- const { r, s } = DER.toSig(ensureBytes('DER', hex));
1806
- return new Signature(r, s);
2053
+ static fromBytes(bytes, format = defaultSigOpts_format) {
2054
+ validateSigLength(bytes, format);
2055
+ let recid;
2056
+ if (format === 'der') {
2057
+ const { r, s } = DER.toSig(_abytes2(bytes));
2058
+ return new Signature(r, s);
2059
+ }
2060
+ if (format === 'recovered') {
2061
+ recid = bytes[0];
2062
+ format = 'compact';
2063
+ bytes = bytes.subarray(1);
2064
+ }
2065
+ const L = Fn.BYTES;
2066
+ const r = bytes.subarray(0, L);
2067
+ const s = bytes.subarray(L, L * 2);
2068
+ return new Signature(Fn.fromBytes(r), Fn.fromBytes(s), recid);
1807
2069
  }
1808
- assertValidity() {
1809
- aInRange('r', this.r, _1n$4, CURVE_ORDER); // r in [1..N]
1810
- aInRange('s', this.s, _1n$4, CURVE_ORDER); // s in [1..N]
2070
+ static fromHex(hex, format) {
2071
+ return this.fromBytes(hexToBytes(hex), format);
1811
2072
  }
1812
2073
  addRecoveryBit(recovery) {
1813
2074
  return new Signature(this.r, this.s, recovery);
1814
2075
  }
1815
- recoverPublicKey(msgHash) {
2076
+ recoverPublicKey(messageHash) {
2077
+ const FIELD_ORDER = Fp.ORDER;
1816
2078
  const { r, s, recovery: rec } = this;
1817
- const h = bits2int_modN(ensureBytes('msgHash', msgHash)); // Truncate hash
1818
2079
  if (rec == null || ![0, 1, 2, 3].includes(rec))
1819
2080
  throw new Error('recovery id invalid');
1820
- const radj = rec === 2 || rec === 3 ? r + CURVE.n : r;
1821
- if (radj >= Fp.ORDER)
2081
+ // ECDSA recovery is hard for cofactor > 1 curves.
2082
+ // In sign, `r = q.x mod n`, and here we recover q.x from r.
2083
+ // While recovering q.x >= n, we need to add r+n for cofactor=1 curves.
2084
+ // However, for cofactor>1, r+n may not get q.x:
2085
+ // r+n*i would need to be done instead where i is unknown.
2086
+ // To easily get i, we either need to:
2087
+ // a. increase amount of valid recid values (4, 5...); OR
2088
+ // b. prohibit non-prime-order signatures (recid > 1).
2089
+ const hasCofactor = CURVE_ORDER * _2n$4 < FIELD_ORDER;
2090
+ if (hasCofactor && rec > 1)
2091
+ throw new Error('recovery id is ambiguous for h>1 curve');
2092
+ const radj = rec === 2 || rec === 3 ? r + CURVE_ORDER : r;
2093
+ if (!Fp.isValid(radj))
1822
2094
  throw new Error('recovery id 2 or 3 invalid');
1823
- const prefix = (rec & 1) === 0 ? '02' : '03';
1824
- const R = Point.fromHex(prefix + numToNByteStr(radj));
1825
- const ir = invN(radj); // r^-1
1826
- const u1 = modN(-h * ir); // -hr^-1
1827
- const u2 = modN(s * ir); // sr^-1
1828
- const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1)
1829
- if (!Q)
1830
- throw new Error('point at infinify'); // unsafe is fine: no priv data leaked
2095
+ const x = Fp.toBytes(radj);
2096
+ const R = Point.fromBytes(concatBytes(pprefix((rec & 1) === 0), x));
2097
+ const ir = Fn.inv(radj); // r^-1
2098
+ const h = bits2int_modN(ensureBytes('msgHash', messageHash)); // Truncate hash
2099
+ const u1 = Fn.create(-h * ir); // -hr^-1
2100
+ const u2 = Fn.create(s * ir); // sr^-1
2101
+ // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1). unsafe is fine: there is no private data.
2102
+ const Q = Point.BASE.multiplyUnsafe(u1).add(R.multiplyUnsafe(u2));
2103
+ if (Q.is0())
2104
+ throw new Error('point at infinify');
1831
2105
  Q.assertValidity();
1832
2106
  return Q;
1833
2107
  }
@@ -1835,466 +2109,484 @@ function weierstrass(curveDef) {
1835
2109
  hasHighS() {
1836
2110
  return isBiggerThanHalfOrder(this.s);
1837
2111
  }
2112
+ toBytes(format = defaultSigOpts_format) {
2113
+ validateSigFormat(format);
2114
+ if (format === 'der')
2115
+ return hexToBytes(DER.hexFromSig(this));
2116
+ const r = Fn.toBytes(this.r);
2117
+ const s = Fn.toBytes(this.s);
2118
+ if (format === 'recovered') {
2119
+ if (this.recovery == null)
2120
+ throw new Error('recovery bit must be present');
2121
+ return concatBytes(Uint8Array.of(this.recovery), r, s);
2122
+ }
2123
+ return concatBytes(r, s);
2124
+ }
2125
+ toHex(format) {
2126
+ return bytesToHex(this.toBytes(format));
2127
+ }
2128
+ // TODO: remove
2129
+ assertValidity() { }
2130
+ static fromCompact(hex) {
2131
+ return Signature.fromBytes(ensureBytes('sig', hex), 'compact');
2132
+ }
2133
+ static fromDER(hex) {
2134
+ return Signature.fromBytes(ensureBytes('sig', hex), 'der');
2135
+ }
1838
2136
  normalizeS() {
1839
- return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this;
2137
+ return this.hasHighS() ? new Signature(this.r, Fn.neg(this.s), this.recovery) : this;
1840
2138
  }
1841
- // DER-encoded
1842
2139
  toDERRawBytes() {
1843
- return hexToBytes(this.toDERHex());
2140
+ return this.toBytes('der');
1844
2141
  }
1845
2142
  toDERHex() {
1846
- return DER.hexFromSig({ r: this.r, s: this.s });
2143
+ return bytesToHex(this.toBytes('der'));
1847
2144
  }
1848
- // padded bytes of r, then padded bytes of s
1849
2145
  toCompactRawBytes() {
1850
- return hexToBytes(this.toCompactHex());
2146
+ return this.toBytes('compact');
1851
2147
  }
1852
2148
  toCompactHex() {
1853
- return numToNByteStr(this.r) + numToNByteStr(this.s);
2149
+ return bytesToHex(this.toBytes('compact'));
1854
2150
  }
1855
2151
  }
1856
- const utils = {
1857
- isValidPrivateKey(privateKey) {
1858
- try {
1859
- normPrivateKeyToScalar(privateKey);
1860
- return true;
1861
- }
1862
- catch (error) {
1863
- return false;
1864
- }
1865
- },
1866
- normPrivateKeyToScalar: normPrivateKeyToScalar,
1867
- /**
1868
- * Produces cryptographically secure private key from random of size
1869
- * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.
1870
- */
1871
- randomPrivateKey: () => {
1872
- const length = getMinHashLength(CURVE.n);
1873
- return mapHashToField(CURVE.randomBytes(length), CURVE.n);
1874
- },
1875
- /**
1876
- * Creates precompute table for an arbitrary EC point. Makes point "cached".
1877
- * Allows to massively speed-up `point.multiply(scalar)`.
1878
- * @returns cached point
1879
- * @example
1880
- * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey));
1881
- * fast.multiply(privKey); // much faster ECDH now
1882
- */
1883
- precompute(windowSize = 8, point = Point.BASE) {
1884
- point._setWindowSize(windowSize);
1885
- point.multiply(BigInt(3)); // 3 is arbitrary, just need any number here
1886
- return point;
1887
- },
1888
- };
1889
- /**
1890
- * Computes public key for a private key. Checks for validity of the private key.
1891
- * @param privateKey private key
1892
- * @param isCompressed whether to return compact (default), or full key
1893
- * @returns Public key, full when isCompressed=false; short when isCompressed=true
1894
- */
1895
- function getPublicKey(privateKey, isCompressed = true) {
1896
- return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed);
1897
- }
1898
- /**
1899
- * Quick and dirty check for item being public key. Does not validate hex, or being on-curve.
1900
- */
1901
- function isProbPub(item) {
1902
- const arr = isBytes(item);
1903
- const str = typeof item === 'string';
1904
- const len = (arr || str) && item.length;
1905
- if (arr)
1906
- return len === compressedLen || len === uncompressedLen;
1907
- if (str)
1908
- return len === 2 * compressedLen || len === 2 * uncompressedLen;
1909
- if (item instanceof Point)
1910
- return true;
1911
- return false;
1912
- }
1913
- /**
1914
- * ECDH (Elliptic Curve Diffie Hellman).
1915
- * Computes shared public key from private key and public key.
1916
- * Checks: 1) private key validity 2) shared key is on-curve.
1917
- * Does NOT hash the result.
1918
- * @param privateA private key
1919
- * @param publicB different public key
1920
- * @param isCompressed whether to return compact (default), or full key
1921
- * @returns shared public key
1922
- */
1923
- function getSharedSecret(privateA, publicB, isCompressed = true) {
1924
- if (isProbPub(privateA))
1925
- throw new Error('first arg must be private key');
1926
- if (!isProbPub(publicB))
1927
- throw new Error('second arg must be public key');
1928
- const b = Point.fromHex(publicB); // check for being on-curve
1929
- return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed);
1930
- }
1931
2152
  // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets.
1932
2153
  // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int.
1933
2154
  // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same.
1934
2155
  // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors
1935
- const bits2int = CURVE.bits2int ||
1936
- function (bytes) {
1937
- // Our custom check "just in case"
2156
+ const bits2int = ecdsaOpts.bits2int ||
2157
+ function bits2int_def(bytes) {
2158
+ // Our custom check "just in case", for protection against DoS
1938
2159
  if (bytes.length > 8192)
1939
2160
  throw new Error('input is too large');
1940
2161
  // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)
1941
2162
  // for some cases, since bytes.length * 8 is not actual bitLength.
1942
2163
  const num = bytesToNumberBE(bytes); // check for == u8 done here
1943
- const delta = bytes.length * 8 - CURVE.nBitLength; // truncate to nBitLength leftmost bits
2164
+ const delta = bytes.length * 8 - fnBits; // truncate to nBitLength leftmost bits
1944
2165
  return delta > 0 ? num >> BigInt(delta) : num;
1945
2166
  };
1946
- const bits2int_modN = CURVE.bits2int_modN ||
1947
- function (bytes) {
1948
- return modN(bits2int(bytes)); // can't use bytesToNumberBE here
2167
+ const bits2int_modN = ecdsaOpts.bits2int_modN ||
2168
+ function bits2int_modN_def(bytes) {
2169
+ return Fn.create(bits2int(bytes)); // can't use bytesToNumberBE here
1949
2170
  };
1950
- // NOTE: pads output with zero as per spec
1951
- const ORDER_MASK = bitMask(CURVE.nBitLength);
2171
+ // Pads output with zero as per spec
2172
+ const ORDER_MASK = bitMask(fnBits);
2173
+ /** Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`. */
2174
+ function int2octets(num) {
2175
+ // IMPORTANT: the check ensures working for case `Fn.BYTES != Fn.BITS * 8`
2176
+ aInRange('num < 2^' + fnBits, num, _0n$2, ORDER_MASK);
2177
+ return Fn.toBytes(num);
2178
+ }
2179
+ function validateMsgAndHash(message, prehash) {
2180
+ _abytes2(message, undefined, 'message');
2181
+ return prehash ? _abytes2(hash(message), undefined, 'prehashed message') : message;
2182
+ }
1952
2183
  /**
1953
- * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.
2184
+ * Steps A, D of RFC6979 3.2.
2185
+ * Creates RFC6979 seed; converts msg/privKey to numbers.
2186
+ * Used only in sign, not in verify.
2187
+ *
2188
+ * Warning: we cannot assume here that message has same amount of bytes as curve order,
2189
+ * this will be invalid at least for P521. Also it can be bigger for P224 + SHA256.
1954
2190
  */
1955
- function int2octets(num) {
1956
- aInRange('num < 2^' + CURVE.nBitLength, num, _0n$2, ORDER_MASK);
1957
- // works with order, can have different size than numToField!
1958
- return numberToBytesBE(num, CURVE.nByteLength);
1959
- }
1960
- // Steps A, D of RFC6979 3.2
1961
- // Creates RFC6979 seed; converts msg/privKey to numbers.
1962
- // Used only in sign, not in verify.
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
1965
- function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
2191
+ function prepSig(message, privateKey, opts) {
1966
2192
  if (['recovered', 'canonical'].some((k) => k in opts))
1967
2193
  throw new Error('sign() legacy options not supported');
1968
- const { hash, randomBytes } = CURVE;
1969
- let { lowS, prehash, extraEntropy: ent } = opts; // generates low-s sigs by default
1970
- if (lowS == null)
1971
- lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash
1972
- msgHash = ensureBytes('msgHash', msgHash);
1973
- validateSigVerOpts(opts);
1974
- if (prehash)
1975
- msgHash = ensureBytes('prehashed msgHash', hash(msgHash));
2194
+ const { lowS, prehash, extraEntropy } = validateSigOpts(opts, defaultSigOpts);
2195
+ message = validateMsgAndHash(message, prehash); // RFC6979 3.2 A: h1 = H(m)
1976
2196
  // We can't later call bits2octets, since nested bits2int is broken for curves
1977
- // with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call.
2197
+ // with fnBits % 8 !== 0. Because of that, we unwrap it here as int2octets call.
1978
2198
  // const bits2octets = (bits) => int2octets(bits2int_modN(bits))
1979
- const h1int = bits2int_modN(msgHash);
1980
- const d = normPrivateKeyToScalar(privateKey); // validate private key, convert to bigint
2199
+ const h1int = bits2int_modN(message);
2200
+ const d = _normFnElement(Fn, privateKey); // validate secret key, convert to bigint
1981
2201
  const seedArgs = [int2octets(d), int2octets(h1int)];
1982
2202
  // extraEntropy. RFC6979 3.6: additional k' (optional).
1983
- if (ent != null && ent !== false) {
2203
+ if (extraEntropy != null && extraEntropy !== false) {
1984
2204
  // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
1985
- const e = ent === true ? randomBytes(Fp.BYTES) : ent; // generate random bytes OR pass as-is
2205
+ // gen random bytes OR pass as-is
2206
+ const e = extraEntropy === true ? randomBytes$1(lengths.secretKey) : extraEntropy;
1986
2207
  seedArgs.push(ensureBytes('extraEntropy', e)); // check for being bytes
1987
2208
  }
1988
2209
  const seed = concatBytes(...seedArgs); // Step D of RFC6979 3.2
1989
2210
  const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!
1990
2211
  // Converts signature params into point w r/s, checks result for validity.
2212
+ // To transform k => Signature:
2213
+ // q = k⋅G
2214
+ // r = q.x mod n
2215
+ // s = k^-1(m + rd) mod n
2216
+ // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to
2217
+ // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it:
2218
+ // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT
1991
2219
  function k2sig(kBytes) {
1992
2220
  // RFC 6979 Section 3.2, step 3: k = bits2int(T)
1993
- const k = bits2int(kBytes); // Cannot use fields methods, since it is group element
1994
- if (!isWithinCurveOrder(k))
1995
- return; // Important: all mod() calls here must be done over N
1996
- const ik = invN(k); // k^-1 mod n
1997
- const q = Point.BASE.multiply(k).toAffine(); // q = Gk
1998
- const r = modN(q.x); // r = q.x mod n
2221
+ // Important: all mod() calls here must be done over N
2222
+ const k = bits2int(kBytes); // mod n, not mod p
2223
+ if (!Fn.isValidNot0(k))
2224
+ return; // Valid scalars (including k) must be in 1..N-1
2225
+ const ik = Fn.inv(k); // k^-1 mod n
2226
+ const q = Point.BASE.multiply(k).toAffine(); // q = k⋅G
2227
+ const r = Fn.create(q.x); // r = q.x mod n
1999
2228
  if (r === _0n$2)
2000
2229
  return;
2001
- // Can use scalar blinding b^-1(bm + bdr) where b [1,q−1] according to
2002
- // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it:
2003
- // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT
2004
- const s = modN(ik * modN(m + r * d)); // Not using blinding here
2230
+ const s = Fn.create(ik * Fn.create(m + r * d)); // Not using blinding here, see comment above
2005
2231
  if (s === _0n$2)
2006
2232
  return;
2007
- let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n$4); // recovery bit (2 or 3, when q.x > n)
2233
+ let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n$3); // recovery bit (2 or 3, when q.x > n)
2008
2234
  let normS = s;
2009
2235
  if (lowS && isBiggerThanHalfOrder(s)) {
2010
- normS = normalizeS(s); // if lowS was passed, ensure s is always
2236
+ normS = Fn.neg(s); // if lowS was passed, ensure s is always
2011
2237
  recovery ^= 1; // // in the bottom half of N
2012
2238
  }
2013
2239
  return new Signature(r, normS, recovery); // use normS, not s
2014
2240
  }
2015
2241
  return { seed, k2sig };
2016
2242
  }
2017
- const defaultSigOpts = { lowS: CURVE.lowS, prehash: false };
2018
- const defaultVerOpts = { lowS: CURVE.lowS, prehash: false };
2019
2243
  /**
2020
- * Signs message hash with a private key.
2244
+ * Signs message hash with a secret key.
2245
+ *
2021
2246
  * ```
2022
- * sign(m, d, k) where
2247
+ * sign(m, d) where
2248
+ * k = rfc6979_hmac_drbg(m, d)
2023
2249
  * (x, y) = G × k
2024
2250
  * r = x mod n
2025
- * s = (m + dr)/k mod n
2251
+ * s = (m + dr) / k mod n
2026
2252
  * ```
2027
- * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`.
2028
- * @param privKey private key
2029
- * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg.
2030
- * @returns signature with recovery param
2031
2253
  */
2032
- function sign(msgHash, privKey, opts = defaultSigOpts) {
2033
- const { seed, k2sig } = prepSig(msgHash, privKey, opts); // Steps A, D of RFC6979 3.2.
2034
- const C = CURVE;
2035
- const drbg = createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac);
2036
- return drbg(seed, k2sig); // Steps B, C, D, E, F, G
2037
- }
2038
- // Enable precomputes. Slows down first publicKey computation by 20ms.
2039
- Point.BASE._setWindowSize(8);
2040
- // utils.precompute(8, ProjectivePoint.BASE)
2041
- /**
2042
- * Verifies a signature against message hash and public key.
2043
- * Rejects lowS signatures by default: to override,
2044
- * specify option `{lowS: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf:
2045
- *
2046
- * ```
2047
- * verify(r, s, h, P) where
2048
- * U1 = hs^-1 mod n
2049
- * U2 = rs^-1 mod n
2050
- * R = U1⋅G - U2⋅P
2051
- * mod(R.x, n) == r
2052
- * ```
2053
- */
2054
- function verify(signature, msgHash, publicKey, opts = defaultVerOpts) {
2055
- const sg = signature;
2056
- msgHash = ensureBytes('msgHash', msgHash);
2057
- publicKey = ensureBytes('publicKey', publicKey);
2058
- const { lowS, prehash, format } = opts;
2059
- // Verify opts, deduce signature format
2060
- validateSigVerOpts(opts);
2061
- if ('strict' in opts)
2062
- throw new Error('options.strict was renamed to lowS');
2063
- if (format !== undefined && format !== 'compact' && format !== 'der')
2064
- throw new Error('format must be compact or der');
2254
+ function sign(message, secretKey, opts = {}) {
2255
+ message = ensureBytes('message', message);
2256
+ const { seed, k2sig } = prepSig(message, secretKey, opts); // Steps A, D of RFC6979 3.2.
2257
+ const drbg = createHmacDrbg(hash.outputLen, Fn.BYTES, hmac$1);
2258
+ const sig = drbg(seed, k2sig); // Steps B, C, D, E, F, G
2259
+ return sig;
2260
+ }
2261
+ function tryParsingSig(sg) {
2262
+ // Try to deduce format
2263
+ let sig = undefined;
2065
2264
  const isHex = typeof sg === 'string' || isBytes(sg);
2066
2265
  const isObj = !isHex &&
2067
- !format &&
2068
- typeof sg === 'object' &&
2069
2266
  sg !== null &&
2267
+ typeof sg === 'object' &&
2070
2268
  typeof sg.r === 'bigint' &&
2071
2269
  typeof sg.s === 'bigint';
2072
2270
  if (!isHex && !isObj)
2073
2271
  throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance');
2074
- let _sig = undefined;
2075
- let P;
2076
- try {
2077
- if (isObj)
2078
- _sig = new Signature(sg.r, sg.s);
2079
- if (isHex) {
2080
- // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length).
2081
- // Since DER can also be 2*nByteLength bytes, we check for it first.
2272
+ if (isObj) {
2273
+ sig = new Signature(sg.r, sg.s);
2274
+ }
2275
+ else if (isHex) {
2276
+ try {
2277
+ sig = Signature.fromBytes(ensureBytes('sig', sg), 'der');
2278
+ }
2279
+ catch (derError) {
2280
+ if (!(derError instanceof DER.Err))
2281
+ throw derError;
2282
+ }
2283
+ if (!sig) {
2082
2284
  try {
2083
- if (format !== 'compact')
2084
- _sig = Signature.fromDER(sg);
2285
+ sig = Signature.fromBytes(ensureBytes('sig', sg), 'compact');
2085
2286
  }
2086
- catch (derError) {
2087
- if (!(derError instanceof DER.Err))
2088
- throw derError;
2287
+ catch (error) {
2288
+ return false;
2089
2289
  }
2090
- if (!_sig && format !== 'der')
2091
- _sig = Signature.fromCompact(sg);
2092
2290
  }
2093
- P = Point.fromHex(publicKey);
2094
- }
2095
- catch (error) {
2096
- return false;
2097
2291
  }
2098
- if (!_sig)
2292
+ if (!sig)
2099
2293
  return false;
2100
- if (lowS && _sig.hasHighS())
2294
+ return sig;
2295
+ }
2296
+ /**
2297
+ * Verifies a signature against message and public key.
2298
+ * Rejects lowS signatures by default: see {@link ECDSAVerifyOpts}.
2299
+ * Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf:
2300
+ *
2301
+ * ```
2302
+ * verify(r, s, h, P) where
2303
+ * u1 = hs^-1 mod n
2304
+ * u2 = rs^-1 mod n
2305
+ * R = u1⋅G + u2⋅P
2306
+ * mod(R.x, n) == r
2307
+ * ```
2308
+ */
2309
+ function verify(signature, message, publicKey, opts = {}) {
2310
+ const { lowS, prehash, format } = validateSigOpts(opts, defaultSigOpts);
2311
+ publicKey = ensureBytes('publicKey', publicKey);
2312
+ message = validateMsgAndHash(ensureBytes('message', message), prehash);
2313
+ if ('strict' in opts)
2314
+ throw new Error('options.strict was renamed to lowS');
2315
+ const sig = format === undefined
2316
+ ? tryParsingSig(signature)
2317
+ : Signature.fromBytes(ensureBytes('sig', signature), format);
2318
+ if (sig === false)
2101
2319
  return false;
2102
- if (prehash)
2103
- msgHash = CURVE.hash(msgHash);
2104
- const { r, s } = _sig;
2105
- const h = bits2int_modN(msgHash); // Cannot use fields methods, since it is group element
2106
- const is = invN(s); // s^-1
2107
- const u1 = modN(h * is); // u1 = hs^-1 mod n
2108
- const u2 = modN(r * is); // u2 = rs^-1 mod n
2109
- const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine(); // R = u1⋅G + u2⋅P
2110
- if (!R)
2320
+ try {
2321
+ const P = Point.fromBytes(publicKey);
2322
+ if (lowS && sig.hasHighS())
2323
+ return false;
2324
+ const { r, s } = sig;
2325
+ const h = bits2int_modN(message); // mod n, not mod p
2326
+ const is = Fn.inv(s); // s^-1 mod n
2327
+ const u1 = Fn.create(h * is); // u1 = hs^-1 mod n
2328
+ const u2 = Fn.create(r * is); // u2 = rs^-1 mod n
2329
+ const R = Point.BASE.multiplyUnsafe(u1).add(P.multiplyUnsafe(u2)); // u1⋅G + u2⋅P
2330
+ if (R.is0())
2331
+ return false;
2332
+ const v = Fn.create(R.x); // v = r.x mod n
2333
+ return v === r;
2334
+ }
2335
+ catch (e) {
2111
2336
  return false;
2112
- const v = modN(R.x);
2113
- return v === r;
2337
+ }
2114
2338
  }
2115
- return {
2116
- CURVE,
2339
+ function recoverPublicKey(signature, message, opts = {}) {
2340
+ const { prehash } = validateSigOpts(opts, defaultSigOpts);
2341
+ message = validateMsgAndHash(message, prehash);
2342
+ return Signature.fromBytes(signature, 'recovered').recoverPublicKey(message).toBytes();
2343
+ }
2344
+ return Object.freeze({
2345
+ keygen,
2117
2346
  getPublicKey,
2118
2347
  getSharedSecret,
2348
+ utils,
2349
+ lengths,
2350
+ Point,
2119
2351
  sign,
2120
2352
  verify,
2121
- ProjectivePoint: Point,
2353
+ recoverPublicKey,
2122
2354
  Signature,
2123
- utils,
2355
+ hash,
2356
+ });
2357
+ }
2358
+ function _weierstrass_legacy_opts_to_new(c) {
2359
+ const CURVE = {
2360
+ a: c.a,
2361
+ b: c.b,
2362
+ p: c.Fp.ORDER,
2363
+ n: c.n,
2364
+ h: c.h,
2365
+ Gx: c.Gx,
2366
+ Gy: c.Gy,
2367
+ };
2368
+ const Fp = c.Fp;
2369
+ let allowedLengths = c.allowedPrivateKeyLengths
2370
+ ? Array.from(new Set(c.allowedPrivateKeyLengths.map((l) => Math.ceil(l / 2))))
2371
+ : undefined;
2372
+ const Fn = Field(CURVE.n, {
2373
+ BITS: c.nBitLength,
2374
+ allowedLengths: allowedLengths,
2375
+ modFromBytes: c.wrapPrivateKey,
2376
+ });
2377
+ const curveOpts = {
2378
+ Fp,
2379
+ Fn,
2380
+ allowInfinityPoint: c.allowInfinityPoint,
2381
+ endo: c.endo,
2382
+ isTorsionFree: c.isTorsionFree,
2383
+ clearCofactor: c.clearCofactor,
2384
+ fromBytes: c.fromBytes,
2385
+ toBytes: c.toBytes,
2386
+ };
2387
+ return { CURVE, curveOpts };
2388
+ }
2389
+ function _ecdsa_legacy_opts_to_new(c) {
2390
+ const { CURVE, curveOpts } = _weierstrass_legacy_opts_to_new(c);
2391
+ const ecdsaOpts = {
2392
+ hmac: c.hmac,
2393
+ randomBytes: c.randomBytes,
2394
+ lowS: c.lowS,
2395
+ bits2int: c.bits2int,
2396
+ bits2int_modN: c.bits2int_modN,
2124
2397
  };
2398
+ return { CURVE, curveOpts, hash: c.hash, ecdsaOpts };
2399
+ }
2400
+ function _ecdsa_new_output_to_legacy(c, _ecdsa) {
2401
+ const Point = _ecdsa.Point;
2402
+ return Object.assign({}, _ecdsa, {
2403
+ ProjectivePoint: Point,
2404
+ CURVE: Object.assign({}, c, nLength(Point.Fn.ORDER, Point.Fn.BITS)),
2405
+ });
2406
+ }
2407
+ // _ecdsa_legacy
2408
+ function weierstrass(c) {
2409
+ const { CURVE, curveOpts, hash, ecdsaOpts } = _ecdsa_legacy_opts_to_new(c);
2410
+ const Point = weierstrassN(CURVE, curveOpts);
2411
+ const signs = ecdsa(Point, hash, ecdsaOpts);
2412
+ return _ecdsa_new_output_to_legacy(c, signs);
2125
2413
  }
2126
2414
 
2415
+ /**
2416
+ * Utilities for short weierstrass curves, combined with noble-hashes.
2417
+ * @module
2418
+ */
2127
2419
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2128
- // connects noble-curves to noble-hashes
2129
- function getHash(hash) {
2130
- return {
2131
- hash,
2132
- hmac: (key, ...msgs) => hmac(hash, key, concatBytes$1(...msgs)),
2133
- randomBytes,
2134
- };
2135
- }
2420
+ /** @deprecated use new `weierstrass()` and `ecdsa()` methods */
2136
2421
  function createCurve(curveDef, defHash) {
2137
- const create = (hash) => weierstrass({ ...curveDef, ...getHash(hash) });
2138
- return Object.freeze({ ...create(defHash), create });
2422
+ const create = (hash) => weierstrass({ ...curveDef, hash: hash });
2423
+ return { ...create(defHash), create };
2139
2424
  }
2140
2425
 
2426
+ /**
2427
+ * Internal module for NIST P256, P384, P521 curves.
2428
+ * Do not use for now.
2429
+ * @module
2430
+ */
2141
2431
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2142
- // NIST secp256r1 aka p256
2143
- // https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256
2144
- const Fp256 = Field(BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'));
2145
- const CURVE_A$4 = Fp256.create(BigInt('-3'));
2146
- const CURVE_B$4 = BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b');
2147
- // prettier-ignore
2148
- const p256 = createCurve({
2149
- a: CURVE_A$4, // Equation params: a, b
2150
- b: CURVE_B$4,
2151
- Fp: Fp256, // Field: 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n
2152
- // Curve order, total count of valid points in the field
2432
+ // p = 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n - 1n
2433
+ // a = Fp256.create(BigInt('-3'));
2434
+ const p256_CURVE = {
2435
+ p: BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'),
2153
2436
  n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),
2154
- // Base (generator) point (x, y)
2437
+ h: BigInt(1),
2438
+ a: BigInt('0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc'),
2439
+ b: BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b'),
2155
2440
  Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'),
2156
2441
  Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'),
2157
- h: BigInt(1),
2158
- lowS: false,
2159
- }, sha256);
2160
-
2161
- /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2162
- // NIST secp384r1 aka p384
2163
- // https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-384
2164
- // Field over which we'll do calculations.
2165
- // prettier-ignore
2166
- const P$1 = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff');
2167
- const Fp384 = Field(P$1);
2168
- const CURVE_A$3 = Fp384.create(BigInt('-3'));
2169
- // prettier-ignore
2170
- const CURVE_B$3 = BigInt('0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef');
2171
- // prettier-ignore
2172
- const p384 = createCurve({
2173
- a: CURVE_A$3, // Equation params: a, b
2174
- b: CURVE_B$3,
2175
- Fp: Fp384, // Field: 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
2176
- // Curve order, total count of valid points in the field.
2442
+ };
2443
+ // p = 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
2444
+ const p384_CURVE = {
2445
+ p: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff'),
2177
2446
  n: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'),
2178
- // Base (generator) point (x, y)
2447
+ h: BigInt(1),
2448
+ a: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc'),
2449
+ b: BigInt('0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef'),
2179
2450
  Gx: BigInt('0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7'),
2180
2451
  Gy: BigInt('0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f'),
2452
+ };
2453
+ // p = 2n**521n - 1n
2454
+ const p521_CURVE = {
2455
+ p: BigInt('0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'),
2456
+ n: BigInt('0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409'),
2181
2457
  h: BigInt(1),
2182
- lowS: false,
2183
- }, sha384);
2184
-
2185
- /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2186
- // NIST secp521r1 aka p521
2187
- // Note that it's 521, which differs from 512 of its hash function.
2188
- // https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-521
2189
- // Field over which we'll do calculations.
2190
- // prettier-ignore
2191
- const P = BigInt('0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
2192
- const Fp521 = Field(P);
2193
- const CURVE = {
2194
- a: Fp521.create(BigInt('-3')),
2458
+ a: BigInt('0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc'),
2195
2459
  b: BigInt('0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00'),
2196
- Fp: Fp521,
2197
- n: BigInt('0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409'),
2198
2460
  Gx: BigInt('0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66'),
2199
2461
  Gy: BigInt('0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'),
2200
- h: BigInt(1),
2201
2462
  };
2202
- // prettier-ignore
2203
- const p521 = createCurve({
2204
- a: CURVE.a, // Equation params: a, b
2205
- b: CURVE.b,
2206
- Fp: Fp521, // Field: 2n**521n - 1n
2207
- // Curve order, total count of valid points in the field
2208
- n: CURVE.n,
2209
- Gx: CURVE.Gx, // Base point (x, y) aka generator point
2210
- Gy: CURVE.Gy,
2211
- h: CURVE.h,
2212
- lowS: false,
2213
- allowedPrivateKeyLengths: [130, 131, 132] // P521 keys are variable-length. Normalize to 132b
2214
- }, sha512);
2463
+ const Fp256 = Field(p256_CURVE.p);
2464
+ const Fp384 = Field(p384_CURVE.p);
2465
+ const Fp521 = Field(p521_CURVE.p);
2466
+ /** NIST P256 (aka secp256r1, prime256v1) curve, ECDSA and ECDH methods. */
2467
+ const p256$1 = createCurve({ ...p256_CURVE, Fp: Fp256, lowS: false }, sha256);
2468
+ // export const p256_oprf: OPRF = createORPF({
2469
+ // name: 'P256-SHA256',
2470
+ // Point: p256.Point,
2471
+ // hash: sha256,
2472
+ // hashToGroup: p256_hasher.hashToCurve,
2473
+ // hashToScalar: p256_hasher.hashToScalar,
2474
+ // });
2475
+ /** NIST P384 (aka secp384r1) curve, ECDSA and ECDH methods. */
2476
+ const p384$1 = createCurve({ ...p384_CURVE, Fp: Fp384, lowS: false }, sha384);
2477
+ // export const p384_oprf: OPRF = createORPF({
2478
+ // name: 'P384-SHA384',
2479
+ // Point: p384.Point,
2480
+ // hash: sha384,
2481
+ // hashToGroup: p384_hasher.hashToCurve,
2482
+ // hashToScalar: p384_hasher.hashToScalar,
2483
+ // });
2484
+ // const Fn521 = Field(p521_CURVE.n, { allowedScalarLengths: [65, 66] });
2485
+ /** NIST P521 (aka secp521r1) curve, ECDSA and ECDH methods. */
2486
+ const p521$1 = createCurve({ ...p521_CURVE, Fp: Fp521, lowS: false, allowedPrivateKeyLengths: [130, 131, 132] }, sha512);
2487
+ // export const p521_oprf: OPRF = createORPF({
2488
+ // name: 'P521-SHA512',
2489
+ // Point: p521.Point,
2490
+ // hash: sha512,
2491
+ // hashToGroup: p521_hasher.hashToCurve,
2492
+ // hashToScalar: p521_hasher.hashToScalar, // produces L=98 just like in RFC
2493
+ // });
2494
+
2495
+ /**
2496
+ * NIST secp256r1 aka p256.
2497
+ * @module
2498
+ */
2499
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2500
+ /** @deprecated use `import { p256 } from '@noble/curves/nist.js';` */
2501
+ const p256 = p256$1;
2215
2502
 
2503
+ /**
2504
+ * NIST secp384r1 aka p384.
2505
+ * @module
2506
+ */
2216
2507
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2217
- // Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y²
2218
- // Be friendly to bad ECMAScript parsers by not using bigint literals
2219
- // prettier-ignore
2220
- const _0n$1 = BigInt(0), _1n$3 = BigInt(1), _2n$2 = BigInt(2), _8n = BigInt(8);
2221
- // verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex:
2222
- const VERIFY_DEFAULT = { zip215: true };
2223
- function validateOpts$1(curve) {
2224
- const opts = validateBasic(curve);
2225
- validateObject(curve, {
2226
- hash: 'function',
2227
- a: 'bigint',
2228
- d: 'bigint',
2229
- randomBytes: 'function',
2230
- }, {
2231
- adjustScalarBytes: 'function',
2232
- domain: 'function',
2233
- uvRatio: 'function',
2234
- mapToCurve: 'function',
2235
- });
2236
- // Set defaults
2237
- return Object.freeze({ ...opts });
2238
- }
2508
+ /** @deprecated use `import { p384 } from '@noble/curves/nist.js';` */
2509
+ const p384 = p384$1;
2510
+
2239
2511
  /**
2240
- * Creates Twisted Edwards curve with EdDSA signatures.
2241
- * @example
2242
- * import { Field } from '@noble/curves/abstract/modular';
2243
- * // Before that, define BigInt-s: a, d, p, n, Gx, Gy, h
2244
- * const curve = twistedEdwards({ a, d, Fp: Field(p), n, Gx, Gy, h })
2512
+ * NIST secp521r1 aka p521.
2513
+ * @module
2514
+ */
2515
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2516
+ /** @deprecated use `import { p521 } from '@noble/curves/nist.js';` */
2517
+ const p521 = p521$1;
2518
+
2519
+ /**
2520
+ * Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y².
2521
+ * For design rationale of types / exports, see weierstrass module documentation.
2522
+ * Untwisted Edwards curves exist, but they aren't used in real-world protocols.
2523
+ * @module
2245
2524
  */
2246
- function twistedEdwards(curveDef) {
2247
- const CURVE = validateOpts$1(curveDef);
2248
- const { Fp, n: CURVE_ORDER, prehash: prehash, hash: cHash, randomBytes, nByteLength, h: cofactor, } = CURVE;
2525
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2526
+ // Be friendly to bad ECMAScript parsers by not using bigint literals
2527
+ // prettier-ignore
2528
+ const _0n$1 = BigInt(0), _1n$2 = BigInt(1), _2n$3 = BigInt(2), _8n = BigInt(8);
2529
+ function isEdValidXY(Fp, CURVE, x, y) {
2530
+ const x2 = Fp.sqr(x);
2531
+ const y2 = Fp.sqr(y);
2532
+ const left = Fp.add(Fp.mul(CURVE.a, x2), y2);
2533
+ const right = Fp.add(Fp.ONE, Fp.mul(CURVE.d, Fp.mul(x2, y2)));
2534
+ return Fp.eql(left, right);
2535
+ }
2536
+ function edwards(params, extraOpts = {}) {
2537
+ const validated = _createCurveFields('edwards', params, extraOpts, extraOpts.FpFnLE);
2538
+ const { Fp, Fn } = validated;
2539
+ let CURVE = validated.CURVE;
2540
+ const { h: cofactor } = CURVE;
2541
+ _validateObject(extraOpts, {}, { uvRatio: 'function' });
2249
2542
  // Important:
2250
2543
  // There are some places where Fp.BYTES is used instead of nByteLength.
2251
2544
  // So far, everything has been tested with curves of Fp.BYTES == nByteLength.
2252
2545
  // TODO: test and find curves which behave otherwise.
2253
- const MASK = _2n$2 << (BigInt(nByteLength * 8) - _1n$3);
2254
- const modP = Fp.create; // Function overrides
2255
- const Fn = Field(CURVE.n, CURVE.nBitLength);
2546
+ const MASK = _2n$3 << (BigInt(Fn.BYTES * 8) - _1n$2);
2547
+ const modP = (n) => Fp.create(n); // Function overrides
2256
2548
  // sqrt(u/v)
2257
- const uvRatio = CURVE.uvRatio ||
2549
+ const uvRatio = extraOpts.uvRatio ||
2258
2550
  ((u, v) => {
2259
2551
  try {
2260
- return { isValid: true, value: Fp.sqrt(u * Fp.inv(v)) };
2552
+ return { isValid: true, value: Fp.sqrt(Fp.div(u, v)) };
2261
2553
  }
2262
2554
  catch (e) {
2263
2555
  return { isValid: false, value: _0n$1 };
2264
2556
  }
2265
2557
  });
2266
- const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes) => bytes); // NOOP
2267
- const domain = CURVE.domain ||
2268
- ((data, ctx, phflag) => {
2269
- abool('phflag', phflag);
2270
- if (ctx.length || phflag)
2271
- throw new Error('Contexts/pre-hash are not supported');
2272
- return data;
2273
- }); // NOOP
2274
- // 0 <= n < MASK
2275
- // Coordinates larger than Fp.ORDER are allowed for zip215
2276
- function aCoordinate(title, n) {
2277
- aInRange('coordinate ' + title, n, _0n$1, MASK);
2558
+ // Validate whether the passed curve params are valid.
2559
+ // equation ax² + y² = 1 + dx²y² should work for generator point.
2560
+ if (!isEdValidXY(Fp, CURVE, CURVE.Gx, CURVE.Gy))
2561
+ throw new Error('bad curve params: generator point');
2562
+ /**
2563
+ * Asserts coordinate is valid: 0 <= n < MASK.
2564
+ * Coordinates >= Fp.ORDER are allowed for zip215.
2565
+ */
2566
+ function acoord(title, n, banZero = false) {
2567
+ const min = banZero ? _1n$2 : _0n$1;
2568
+ aInRange('coordinate ' + title, n, min, MASK);
2569
+ return n;
2278
2570
  }
2279
- function assertPoint(other) {
2571
+ function aextpoint(other) {
2280
2572
  if (!(other instanceof Point))
2281
2573
  throw new Error('ExtendedPoint expected');
2282
2574
  }
2283
2575
  // Converts Extended point to default (x, y) coordinates.
2284
2576
  // Can accept precomputed Z^-1 - for example, from invertBatch.
2285
2577
  const toAffineMemo = memoized((p, iz) => {
2286
- const { ex: x, ey: y, ez: z } = p;
2578
+ const { X, Y, Z } = p;
2287
2579
  const is0 = p.is0();
2288
2580
  if (iz == null)
2289
- iz = is0 ? _8n : Fp.inv(z); // 8 was chosen arbitrarily
2290
- const ax = modP(x * iz);
2291
- const ay = modP(y * iz);
2292
- const zz = modP(z * iz);
2581
+ iz = is0 ? _8n : Fp.inv(Z); // 8 was chosen arbitrarily
2582
+ const x = modP(X * iz);
2583
+ const y = modP(Y * iz);
2584
+ const zz = Fp.mul(Z, iz);
2293
2585
  if (is0)
2294
- return { x: _0n$1, y: _1n$3 };
2295
- if (zz !== _1n$3)
2586
+ return { x: _0n$1, y: _1n$2 };
2587
+ if (zz !== _1n$2)
2296
2588
  throw new Error('invZ was invalid');
2297
- return { x: ax, y: ay };
2589
+ return { x, y };
2298
2590
  });
2299
2591
  const assertValidMemo = memoized((p) => {
2300
2592
  const { a, d } = CURVE;
@@ -2302,7 +2594,7 @@ function twistedEdwards(curveDef) {
2302
2594
  throw new Error('bad point: ZERO'); // TODO: optimize, with vars below?
2303
2595
  // Equation in affine coordinates: ax² + y² = 1 + dx²y²
2304
2596
  // Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y²
2305
- const { ex: X, ey: Y, ez: Z, et: T } = p;
2597
+ const { X, Y, Z, T } = p;
2306
2598
  const X2 = modP(X * X); // X²
2307
2599
  const Y2 = modP(Y * Y); // Y²
2308
2600
  const Z2 = modP(Z * Z); // Z²
@@ -2319,56 +2611,84 @@ function twistedEdwards(curveDef) {
2319
2611
  throw new Error('bad point: equation left != right (2)');
2320
2612
  return true;
2321
2613
  });
2322
- // Extended Point works in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z, t=xy).
2614
+ // Extended Point works in extended coordinates: (X, Y, Z, T) ∋ (x=X/Z, y=Y/Z, T=xy).
2323
2615
  // https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Extended_coordinates
2324
2616
  class Point {
2325
- constructor(ex, ey, ez, et) {
2326
- this.ex = ex;
2327
- this.ey = ey;
2328
- this.ez = ez;
2329
- this.et = et;
2330
- aCoordinate('x', ex);
2331
- aCoordinate('y', ey);
2332
- aCoordinate('z', ez);
2333
- aCoordinate('t', et);
2617
+ constructor(X, Y, Z, T) {
2618
+ this.X = acoord('x', X);
2619
+ this.Y = acoord('y', Y);
2620
+ this.Z = acoord('z', Z, true);
2621
+ this.T = acoord('t', T);
2334
2622
  Object.freeze(this);
2335
2623
  }
2336
- get x() {
2337
- return this.toAffine().x;
2338
- }
2339
- get y() {
2340
- return this.toAffine().y;
2624
+ static CURVE() {
2625
+ return CURVE;
2341
2626
  }
2342
2627
  static fromAffine(p) {
2343
2628
  if (p instanceof Point)
2344
2629
  throw new Error('extended point not allowed');
2345
2630
  const { x, y } = p || {};
2346
- aCoordinate('x', x);
2347
- aCoordinate('y', y);
2348
- return new Point(x, y, _1n$3, modP(x * y));
2631
+ acoord('x', x);
2632
+ acoord('y', y);
2633
+ return new Point(x, y, _1n$2, modP(x * y));
2349
2634
  }
2350
- static normalizeZ(points) {
2351
- const toInv = Fp.invertBatch(points.map((p) => p.ez));
2352
- return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);
2635
+ // Uses algo from RFC8032 5.1.3.
2636
+ static fromBytes(bytes, zip215 = false) {
2637
+ const len = Fp.BYTES;
2638
+ const { a, d } = CURVE;
2639
+ bytes = copyBytes(_abytes2(bytes, len, 'point'));
2640
+ _abool2(zip215, 'zip215');
2641
+ const normed = copyBytes(bytes); // copy again, we'll manipulate it
2642
+ const lastByte = bytes[len - 1]; // select last byte
2643
+ normed[len - 1] = lastByte & -129; // clear last bit
2644
+ const y = bytesToNumberLE(normed);
2645
+ // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5.
2646
+ // RFC8032 prohibits >= p, but ZIP215 doesn't
2647
+ // zip215=true: 0 <= y < MASK (2^256 for ed25519)
2648
+ // zip215=false: 0 <= y < P (2^255-19 for ed25519)
2649
+ const max = zip215 ? MASK : Fp.ORDER;
2650
+ aInRange('point.y', y, _0n$1, max);
2651
+ // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case:
2652
+ // ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a)
2653
+ const y2 = modP(y * y); // denominator is always non-0 mod p.
2654
+ const u = modP(y2 - _1n$2); // u = y² - 1
2655
+ const v = modP(d * y2 - a); // v = d y² + 1.
2656
+ let { isValid, value: x } = uvRatio(u, v); // √(u/v)
2657
+ if (!isValid)
2658
+ throw new Error('bad point: invalid y coordinate');
2659
+ const isXOdd = (x & _1n$2) === _1n$2; // There are 2 square roots. Use x_0 bit to select proper
2660
+ const isLastByteOdd = (lastByte & 0x80) !== 0; // x_0, last bit
2661
+ if (!zip215 && x === _0n$1 && isLastByteOdd)
2662
+ // if x=0 and x_0 = 1, fail
2663
+ throw new Error('bad point: x=0 and x_0=1');
2664
+ if (isLastByteOdd !== isXOdd)
2665
+ x = modP(-x); // if x_0 != x mod 2, set x = p-x
2666
+ return Point.fromAffine({ x, y });
2353
2667
  }
2354
- // Multiscalar Multiplication
2355
- static msm(points, scalars) {
2356
- return pippenger(Point, Fn, points, scalars);
2668
+ static fromHex(bytes, zip215 = false) {
2669
+ return Point.fromBytes(ensureBytes('point', bytes), zip215);
2357
2670
  }
2358
- // "Private method", don't use it directly
2359
- _setWindowSize(windowSize) {
2360
- wnaf.setWindowSize(this, windowSize);
2671
+ get x() {
2672
+ return this.toAffine().x;
2673
+ }
2674
+ get y() {
2675
+ return this.toAffine().y;
2361
2676
  }
2362
- // Not required for fromHex(), which always creates valid points.
2363
- // Could be useful for fromAffine().
2677
+ precompute(windowSize = 8, isLazy = true) {
2678
+ wnaf.createCache(this, windowSize);
2679
+ if (!isLazy)
2680
+ this.multiply(_2n$3); // random number
2681
+ return this;
2682
+ }
2683
+ // Useful in fromAffine() - not for fromBytes(), which always created valid points.
2364
2684
  assertValidity() {
2365
2685
  assertValidMemo(this);
2366
2686
  }
2367
2687
  // Compare one point to another.
2368
2688
  equals(other) {
2369
- assertPoint(other);
2370
- const { ex: X1, ey: Y1, ez: Z1 } = this;
2371
- const { ex: X2, ey: Y2, ez: Z2 } = other;
2689
+ aextpoint(other);
2690
+ const { X: X1, Y: Y1, Z: Z1 } = this;
2691
+ const { X: X2, Y: Y2, Z: Z2 } = other;
2372
2692
  const X1Z2 = modP(X1 * Z2);
2373
2693
  const X2Z1 = modP(X2 * Z1);
2374
2694
  const Y1Z2 = modP(Y1 * Z2);
@@ -2380,17 +2700,17 @@ function twistedEdwards(curveDef) {
2380
2700
  }
2381
2701
  negate() {
2382
2702
  // Flips point sign to a negative one (-x, y in affine coords)
2383
- return new Point(modP(-this.ex), this.ey, this.ez, modP(-this.et));
2703
+ return new Point(modP(-this.X), this.Y, this.Z, modP(-this.T));
2384
2704
  }
2385
2705
  // Fast algo for doubling Extended Point.
2386
2706
  // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd
2387
2707
  // Cost: 4M + 4S + 1*a + 6add + 1*2.
2388
2708
  double() {
2389
2709
  const { a } = CURVE;
2390
- const { ex: X1, ey: Y1, ez: Z1 } = this;
2710
+ const { X: X1, Y: Y1, Z: Z1 } = this;
2391
2711
  const A = modP(X1 * X1); // A = X12
2392
2712
  const B = modP(Y1 * Y1); // B = Y12
2393
- const C = modP(_2n$2 * modP(Z1 * Z1)); // C = 2*Z12
2713
+ const C = modP(_2n$3 * modP(Z1 * Z1)); // C = 2*Z12
2394
2714
  const D = modP(a * A); // D = a*A
2395
2715
  const x1y1 = X1 + Y1;
2396
2716
  const E = modP(modP(x1y1 * x1y1) - A - B); // E = (X1+Y1)2-A-B
@@ -2407,31 +2727,10 @@ function twistedEdwards(curveDef) {
2407
2727
  // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
2408
2728
  // Cost: 9M + 1*a + 1*d + 7add.
2409
2729
  add(other) {
2410
- assertPoint(other);
2730
+ aextpoint(other);
2411
2731
  const { a, d } = CURVE;
2412
- const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this;
2413
- const { ex: X2, ey: Y2, ez: Z2, et: T2 } = other;
2414
- // Faster algo for adding 2 Extended Points when curve's a=-1.
2415
- // http://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-4
2416
- // Cost: 8M + 8add + 2*2.
2417
- // Note: It does not check whether the `other` point is valid.
2418
- if (a === BigInt(-1)) {
2419
- const A = modP((Y1 - X1) * (Y2 + X2));
2420
- const B = modP((Y1 + X1) * (Y2 - X2));
2421
- const F = modP(B - A);
2422
- if (F === _0n$1)
2423
- return this.double(); // Same point. Tests say it doesn't affect timing
2424
- const C = modP(Z1 * _2n$2 * T2);
2425
- const D = modP(T1 * _2n$2 * Z2);
2426
- const E = D + C;
2427
- const G = B + A;
2428
- const H = D - C;
2429
- const X3 = modP(E * F);
2430
- const Y3 = modP(G * H);
2431
- const T3 = modP(E * H);
2432
- const Z3 = modP(F * G);
2433
- return new Point(X3, Y3, Z3, T3);
2434
- }
2732
+ const { X: X1, Y: Y1, Z: Z1, T: T1 } = this;
2733
+ const { X: X2, Y: Y2, Z: Z2, T: T2 } = other;
2435
2734
  const A = modP(X1 * X2); // A = X1*X2
2436
2735
  const B = modP(Y1 * Y2); // B = Y1*Y2
2437
2736
  const C = modP(T1 * d * T2); // C = T1*d*T2
@@ -2449,15 +2748,13 @@ function twistedEdwards(curveDef) {
2449
2748
  subtract(other) {
2450
2749
  return this.add(other.negate());
2451
2750
  }
2452
- wNAF(n) {
2453
- return wnaf.wNAFCached(this, n, Point.normalizeZ);
2454
- }
2455
2751
  // Constant-time multiplication.
2456
2752
  multiply(scalar) {
2457
- const n = scalar;
2458
- aInRange('scalar', n, _1n$3, CURVE_ORDER); // 1 <= scalar < L
2459
- const { p, f } = this.wNAF(n);
2460
- return Point.normalizeZ([p, f])[0];
2753
+ // 1 <= scalar < L
2754
+ if (!Fn.isValidNot0(scalar))
2755
+ throw new Error('invalid scalar: expected 1 <= sc < curve.n');
2756
+ const { p, f } = wnaf.cached(this, scalar, (p) => normalizeZ(Point, p));
2757
+ return normalizeZ(Point, [p, f])[0];
2461
2758
  }
2462
2759
  // Non-constant-time multiplication. Uses double-and-add algorithm.
2463
2760
  // It's faster, but should only be used when you don't care about
@@ -2465,13 +2762,14 @@ function twistedEdwards(curveDef) {
2465
2762
  // Does NOT allow scalars higher than CURVE.n.
2466
2763
  // Accepts optional accumulator to merge with multiply (important for sparse scalars)
2467
2764
  multiplyUnsafe(scalar, acc = Point.ZERO) {
2468
- const n = scalar;
2469
- aInRange('scalar', n, _0n$1, CURVE_ORDER); // 0 <= scalar < L
2470
- if (n === _0n$1)
2471
- return I;
2472
- if (this.is0() || n === _1n$3)
2765
+ // 0 <= scalar < L
2766
+ if (!Fn.isValid(scalar))
2767
+ throw new Error('invalid scalar: expected 0 <= sc < curve.n');
2768
+ if (scalar === _0n$1)
2769
+ return Point.ZERO;
2770
+ if (this.is0() || scalar === _1n$2)
2473
2771
  return this;
2474
- return wnaf.wNAFCachedUnsafe(this, n, Point.normalizeZ, acc);
2772
+ return wnaf.unsafe(this, scalar, (p) => normalizeZ(Point, p), acc);
2475
2773
  }
2476
2774
  // Checks if point is of small order.
2477
2775
  // If you add something to small order point, you will have "dirty"
@@ -2483,80 +2781,102 @@ function twistedEdwards(curveDef) {
2483
2781
  // Multiplies point by curve order and checks if the result is 0.
2484
2782
  // Returns `false` is the point is dirty.
2485
2783
  isTorsionFree() {
2486
- return wnaf.unsafeLadder(this, CURVE_ORDER).is0();
2784
+ return wnaf.unsafe(this, CURVE.n).is0();
2487
2785
  }
2488
2786
  // Converts Extended point to default (x, y) coordinates.
2489
2787
  // Can accept precomputed Z^-1 - for example, from invertBatch.
2490
- toAffine(iz) {
2491
- return toAffineMemo(this, iz);
2788
+ toAffine(invertedZ) {
2789
+ return toAffineMemo(this, invertedZ);
2492
2790
  }
2493
2791
  clearCofactor() {
2494
- const { h: cofactor } = CURVE;
2495
- if (cofactor === _1n$3)
2792
+ if (cofactor === _1n$2)
2496
2793
  return this;
2497
2794
  return this.multiplyUnsafe(cofactor);
2498
2795
  }
2499
- // Converts hash string or Uint8Array to Point.
2500
- // Uses algo from RFC8032 5.1.3.
2501
- static fromHex(hex, zip215 = false) {
2502
- const { d, a } = CURVE;
2503
- const len = Fp.BYTES;
2504
- hex = ensureBytes('pointHex', hex, len); // copy hex to a new array
2505
- abool('zip215', zip215);
2506
- const normed = hex.slice(); // copy again, we'll manipulate it
2507
- const lastByte = hex[len - 1]; // select last byte
2508
- normed[len - 1] = lastByte & ~0x80; // clear last bit
2509
- const y = bytesToNumberLE(normed);
2510
- // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5.
2511
- // RFC8032 prohibits >= p, but ZIP215 doesn't
2512
- // zip215=true: 0 <= y < MASK (2^256 for ed25519)
2513
- // zip215=false: 0 <= y < P (2^255-19 for ed25519)
2514
- const max = zip215 ? MASK : Fp.ORDER;
2515
- aInRange('pointHex.y', y, _0n$1, max);
2516
- // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case:
2517
- // ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a)
2518
- const y2 = modP(y * y); // denominator is always non-0 mod p.
2519
- const u = modP(y2 - _1n$3); // u = y² - 1
2520
- const v = modP(d * y2 - a); // v = d y² + 1.
2521
- let { isValid, value: x } = uvRatio(u, v); // √(u/v)
2522
- if (!isValid)
2523
- throw new Error('Point.fromHex: invalid y coordinate');
2524
- const isXOdd = (x & _1n$3) === _1n$3; // There are 2 square roots. Use x_0 bit to select proper
2525
- const isLastByteOdd = (lastByte & 0x80) !== 0; // x_0, last bit
2526
- if (!zip215 && x === _0n$1 && isLastByteOdd)
2527
- // if x=0 and x_0 = 1, fail
2528
- throw new Error('Point.fromHex: x=0 and x_0=1');
2529
- if (isLastByteOdd !== isXOdd)
2530
- x = modP(-x); // if x_0 != x mod 2, set x = p-x
2531
- return Point.fromAffine({ x, y });
2532
- }
2533
- static fromPrivateKey(privKey) {
2534
- return getExtendedPublicKey(privKey).point;
2535
- }
2536
- toRawBytes() {
2796
+ toBytes() {
2537
2797
  const { x, y } = this.toAffine();
2538
- const bytes = numberToBytesLE(y, Fp.BYTES); // each y has 2 x values (x, -y)
2539
- bytes[bytes.length - 1] |= x & _1n$3 ? 0x80 : 0; // when compressing, it's enough to store y
2540
- return bytes; // and use the last byte to encode sign of x
2798
+ // Fp.toBytes() allows non-canonical encoding of y (>= p).
2799
+ const bytes = Fp.toBytes(y);
2800
+ // Each y has 2 valid points: (x, y), (x,-y).
2801
+ // When compressing, it's enough to store y and use the last byte to encode sign of x
2802
+ bytes[bytes.length - 1] |= x & _1n$2 ? 0x80 : 0;
2803
+ return bytes;
2541
2804
  }
2542
2805
  toHex() {
2543
- return bytesToHex(this.toRawBytes()); // Same as toRawBytes, but returns string.
2806
+ return bytesToHex(this.toBytes());
2807
+ }
2808
+ toString() {
2809
+ return `<Point ${this.is0() ? 'ZERO' : this.toHex()}>`;
2810
+ }
2811
+ // TODO: remove
2812
+ get ex() {
2813
+ return this.X;
2814
+ }
2815
+ get ey() {
2816
+ return this.Y;
2817
+ }
2818
+ get ez() {
2819
+ return this.Z;
2820
+ }
2821
+ get et() {
2822
+ return this.T;
2823
+ }
2824
+ static normalizeZ(points) {
2825
+ return normalizeZ(Point, points);
2826
+ }
2827
+ static msm(points, scalars) {
2828
+ return pippenger(Point, Fn, points, scalars);
2829
+ }
2830
+ _setWindowSize(windowSize) {
2831
+ this.precompute(windowSize);
2832
+ }
2833
+ toRawBytes() {
2834
+ return this.toBytes();
2544
2835
  }
2545
2836
  }
2546
- Point.BASE = new Point(CURVE.Gx, CURVE.Gy, _1n$3, modP(CURVE.Gx * CURVE.Gy));
2547
- Point.ZERO = new Point(_0n$1, _1n$3, _1n$3, _0n$1); // 0, 1, 1, 0
2548
- const { BASE: G, ZERO: I } = Point;
2549
- const wnaf = wNAF(Point, nByteLength * 8);
2550
- function modN(a) {
2551
- return mod(a, CURVE_ORDER);
2552
- }
2837
+ // base / generator point
2838
+ Point.BASE = new Point(CURVE.Gx, CURVE.Gy, _1n$2, modP(CURVE.Gx * CURVE.Gy));
2839
+ // zero / infinity / identity point
2840
+ Point.ZERO = new Point(_0n$1, _1n$2, _1n$2, _0n$1); // 0, 1, 1, 0
2841
+ // math field
2842
+ Point.Fp = Fp;
2843
+ // scalar field
2844
+ Point.Fn = Fn;
2845
+ const wnaf = new wNAF(Point, Fn.BITS);
2846
+ Point.BASE.precompute(8); // Enable precomputes. Slows down first publicKey computation by 20ms.
2847
+ return Point;
2848
+ }
2849
+ /**
2850
+ * Initializes EdDSA signatures over given Edwards curve.
2851
+ */
2852
+ function eddsa(Point, cHash, eddsaOpts = {}) {
2853
+ if (typeof cHash !== 'function')
2854
+ throw new Error('"hash" function param is required');
2855
+ _validateObject(eddsaOpts, {}, {
2856
+ adjustScalarBytes: 'function',
2857
+ randomBytes: 'function',
2858
+ domain: 'function',
2859
+ prehash: 'function',
2860
+ mapToCurve: 'function',
2861
+ });
2862
+ const { prehash } = eddsaOpts;
2863
+ const { BASE, Fp, Fn } = Point;
2864
+ const randomBytes$1 = eddsaOpts.randomBytes || randomBytes;
2865
+ const adjustScalarBytes = eddsaOpts.adjustScalarBytes || ((bytes) => bytes);
2866
+ const domain = eddsaOpts.domain ||
2867
+ ((data, ctx, phflag) => {
2868
+ _abool2(phflag, 'phflag');
2869
+ if (ctx.length || phflag)
2870
+ throw new Error('Contexts/pre-hash are not supported');
2871
+ return data;
2872
+ }); // NOOP
2553
2873
  // Little-endian SHA512 with modulo n
2554
2874
  function modN_LE(hash) {
2555
- return modN(bytesToNumberLE(hash));
2875
+ return Fn.create(bytesToNumberLE(hash)); // Not Fn.fromBytes: it has length limit
2556
2876
  }
2557
- /** Convenience method that creates public key and other stuff. RFC8032 5.1.5 */
2558
- function getExtendedPublicKey(key) {
2559
- const len = Fp.BYTES;
2877
+ // Get the hashed private scalar per RFC8032 5.1.5
2878
+ function getPrivateScalar(key) {
2879
+ const len = lengths.secretKey;
2560
2880
  key = ensureBytes('private key', key, len);
2561
2881
  // Hash private key with curve's hash function to produce uniformingly random input
2562
2882
  // Check byte lengths: ensure(64, h(ensure(32, key)))
@@ -2564,171 +2884,293 @@ function twistedEdwards(curveDef) {
2564
2884
  const head = adjustScalarBytes(hashed.slice(0, len)); // clear first half bits, produce FE
2565
2885
  const prefix = hashed.slice(len, 2 * len); // second half is called key prefix (5.1.6)
2566
2886
  const scalar = modN_LE(head); // The actual private scalar
2567
- const point = G.multiply(scalar); // Point on Edwards curve aka public key
2568
- const pointBytes = point.toRawBytes(); // Uint8Array representation
2887
+ return { head, prefix, scalar };
2888
+ }
2889
+ /** Convenience method that creates public key from scalar. RFC8032 5.1.5 */
2890
+ function getExtendedPublicKey(secretKey) {
2891
+ const { head, prefix, scalar } = getPrivateScalar(secretKey);
2892
+ const point = BASE.multiply(scalar); // Point on Edwards curve aka public key
2893
+ const pointBytes = point.toBytes();
2569
2894
  return { head, prefix, scalar, point, pointBytes };
2570
2895
  }
2571
- // Calculates EdDSA pub key. RFC8032 5.1.5. Privkey is hashed. Use first half with 3 bits cleared
2572
- function getPublicKey(privKey) {
2573
- return getExtendedPublicKey(privKey).pointBytes;
2896
+ /** Calculates EdDSA pub key. RFC8032 5.1.5. */
2897
+ function getPublicKey(secretKey) {
2898
+ return getExtendedPublicKey(secretKey).pointBytes;
2574
2899
  }
2575
2900
  // int('LE', SHA512(dom2(F, C) || msgs)) mod N
2576
- function hashDomainToScalar(context = new Uint8Array(), ...msgs) {
2901
+ function hashDomainToScalar(context = Uint8Array.of(), ...msgs) {
2577
2902
  const msg = concatBytes(...msgs);
2578
2903
  return modN_LE(cHash(domain(msg, ensureBytes('context', context), !!prehash)));
2579
2904
  }
2580
2905
  /** Signs message with privateKey. RFC8032 5.1.6 */
2581
- function sign(msg, privKey, options = {}) {
2906
+ function sign(msg, secretKey, options = {}) {
2582
2907
  msg = ensureBytes('message', msg);
2583
2908
  if (prehash)
2584
2909
  msg = prehash(msg); // for ed25519ph etc.
2585
- const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey);
2910
+ const { prefix, scalar, pointBytes } = getExtendedPublicKey(secretKey);
2586
2911
  const r = hashDomainToScalar(options.context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)
2587
- const R = G.multiply(r).toRawBytes(); // R = rG
2912
+ const R = BASE.multiply(r).toBytes(); // R = rG
2588
2913
  const k = hashDomainToScalar(options.context, R, pointBytes, msg); // R || A || PH(M)
2589
- const s = modN(r + k * scalar); // S = (r + k * s) mod L
2590
- aInRange('signature.s', s, _0n$1, CURVE_ORDER); // 0 <= s < l
2591
- const res = concatBytes(R, numberToBytesLE(s, Fp.BYTES));
2592
- return ensureBytes('result', res, Fp.BYTES * 2); // 64-byte signature
2914
+ const s = Fn.create(r + k * scalar); // S = (r + k * s) mod L
2915
+ if (!Fn.isValid(s))
2916
+ throw new Error('sign failed: invalid s'); // 0 <= s < L
2917
+ const rs = concatBytes(R, Fn.toBytes(s));
2918
+ return _abytes2(rs, lengths.signature, 'result');
2593
2919
  }
2594
- const verifyOpts = VERIFY_DEFAULT;
2920
+ // verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex:
2921
+ const verifyOpts = { zip215: true };
2595
2922
  /**
2596
2923
  * Verifies EdDSA signature against message and public key. RFC8032 5.1.7.
2597
2924
  * An extended group equation is checked.
2598
2925
  */
2599
2926
  function verify(sig, msg, publicKey, options = verifyOpts) {
2600
2927
  const { context, zip215 } = options;
2601
- const len = Fp.BYTES; // Verifies EdDSA signature against message and public key. RFC8032 5.1.7.
2602
- sig = ensureBytes('signature', sig, 2 * len); // An extended group equation is checked.
2928
+ const len = lengths.signature;
2929
+ sig = ensureBytes('signature', sig, len);
2603
2930
  msg = ensureBytes('message', msg);
2604
- publicKey = ensureBytes('publicKey', publicKey, len);
2931
+ publicKey = ensureBytes('publicKey', publicKey, lengths.publicKey);
2605
2932
  if (zip215 !== undefined)
2606
- abool('zip215', zip215);
2933
+ _abool2(zip215, 'zip215');
2607
2934
  if (prehash)
2608
2935
  msg = prehash(msg); // for ed25519ph, etc
2609
- const s = bytesToNumberLE(sig.slice(len, 2 * len));
2936
+ const mid = len / 2;
2937
+ const r = sig.subarray(0, mid);
2938
+ const s = bytesToNumberLE(sig.subarray(mid, len));
2610
2939
  let A, R, SB;
2611
2940
  try {
2612
2941
  // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5.
2613
2942
  // zip215=true: 0 <= y < MASK (2^256 for ed25519)
2614
2943
  // zip215=false: 0 <= y < P (2^255-19 for ed25519)
2615
- A = Point.fromHex(publicKey, zip215);
2616
- R = Point.fromHex(sig.slice(0, len), zip215);
2617
- SB = G.multiplyUnsafe(s); // 0 <= s < l is done inside
2944
+ A = Point.fromBytes(publicKey, zip215);
2945
+ R = Point.fromBytes(r, zip215);
2946
+ SB = BASE.multiplyUnsafe(s); // 0 <= s < l is done inside
2618
2947
  }
2619
2948
  catch (error) {
2620
2949
  return false;
2621
2950
  }
2622
2951
  if (!zip215 && A.isSmallOrder())
2623
- return false;
2624
- const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg);
2952
+ return false; // zip215 allows public keys of small order
2953
+ const k = hashDomainToScalar(context, R.toBytes(), A.toBytes(), msg);
2625
2954
  const RkA = R.add(A.multiplyUnsafe(k));
2626
2955
  // Extended group equation
2627
2956
  // [8][S]B = [8]R + [8][k]A'
2628
- return RkA.subtract(SB).clearCofactor().equals(Point.ZERO);
2957
+ return RkA.subtract(SB).clearCofactor().is0();
2958
+ }
2959
+ const _size = Fp.BYTES; // 32 for ed25519, 57 for ed448
2960
+ const lengths = {
2961
+ secretKey: _size,
2962
+ publicKey: _size,
2963
+ signature: 2 * _size,
2964
+ seed: _size,
2965
+ };
2966
+ function randomSecretKey(seed = randomBytes$1(lengths.seed)) {
2967
+ return _abytes2(seed, lengths.seed, 'seed');
2968
+ }
2969
+ function keygen(seed) {
2970
+ const secretKey = utils.randomSecretKey(seed);
2971
+ return { secretKey, publicKey: getPublicKey(secretKey) };
2972
+ }
2973
+ function isValidSecretKey(key) {
2974
+ return isBytes(key) && key.length === Fn.BYTES;
2975
+ }
2976
+ function isValidPublicKey(key, zip215) {
2977
+ try {
2978
+ return !!Point.fromBytes(key, zip215);
2979
+ }
2980
+ catch (error) {
2981
+ return false;
2982
+ }
2629
2983
  }
2630
- G._setWindowSize(8); // Enable precomputes. Slows down first publicKey computation by 20ms.
2631
2984
  const utils = {
2632
2985
  getExtendedPublicKey,
2633
- // ed25519 private keys are uniform 32b. No need to check for modulo bias, like in secp256k1.
2634
- randomPrivateKey: () => randomBytes(Fp.BYTES),
2986
+ randomSecretKey,
2987
+ isValidSecretKey,
2988
+ isValidPublicKey,
2635
2989
  /**
2636
- * We're doing scalar multiplication (used in getPublicKey etc) with precomputed BASE_POINT
2637
- * values. This slows down first getPublicKey() by milliseconds (see Speed section),
2638
- * but allows to speed-up subsequent getPublicKey() calls up to 20x.
2639
- * @param windowSize 2, 4, 8, 16
2990
+ * Converts ed public key to x public key. Uses formula:
2991
+ * - ed25519:
2992
+ * - `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)`
2993
+ * - `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))`
2994
+ * - ed448:
2995
+ * - `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)`
2996
+ * - `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))`
2640
2997
  */
2998
+ toMontgomery(publicKey) {
2999
+ const { y } = Point.fromBytes(publicKey);
3000
+ const size = lengths.publicKey;
3001
+ const is25519 = size === 32;
3002
+ if (!is25519 && size !== 57)
3003
+ throw new Error('only defined for 25519 and 448');
3004
+ const u = is25519 ? Fp.div(_1n$2 + y, _1n$2 - y) : Fp.div(y - _1n$2, y + _1n$2);
3005
+ return Fp.toBytes(u);
3006
+ },
3007
+ toMontgomeryPriv(secretKey) {
3008
+ const size = lengths.secretKey;
3009
+ _abytes2(secretKey, size);
3010
+ const hashed = cHash(secretKey.subarray(0, size));
3011
+ return adjustScalarBytes(hashed).subarray(0, size);
3012
+ },
3013
+ /** @deprecated */
3014
+ randomPrivateKey: randomSecretKey,
3015
+ /** @deprecated */
2641
3016
  precompute(windowSize = 8, point = Point.BASE) {
2642
- point._setWindowSize(windowSize);
2643
- point.multiply(BigInt(3));
2644
- return point;
3017
+ return point.precompute(windowSize, false);
2645
3018
  },
2646
3019
  };
2647
- return {
2648
- CURVE,
3020
+ return Object.freeze({
3021
+ keygen,
2649
3022
  getPublicKey,
2650
3023
  sign,
2651
3024
  verify,
2652
- ExtendedPoint: Point,
2653
3025
  utils,
3026
+ Point,
3027
+ lengths,
3028
+ });
3029
+ }
3030
+ function _eddsa_legacy_opts_to_new(c) {
3031
+ const CURVE = {
3032
+ a: c.a,
3033
+ d: c.d,
3034
+ p: c.Fp.ORDER,
3035
+ n: c.n,
3036
+ h: c.h,
3037
+ Gx: c.Gx,
3038
+ Gy: c.Gy,
3039
+ };
3040
+ const Fp = c.Fp;
3041
+ const Fn = Field(CURVE.n, c.nBitLength, true);
3042
+ const curveOpts = { Fp, Fn, uvRatio: c.uvRatio };
3043
+ const eddsaOpts = {
3044
+ randomBytes: c.randomBytes,
3045
+ adjustScalarBytes: c.adjustScalarBytes,
3046
+ domain: c.domain,
3047
+ prehash: c.prehash,
3048
+ mapToCurve: c.mapToCurve,
2654
3049
  };
3050
+ return { CURVE, curveOpts, hash: c.hash, eddsaOpts };
3051
+ }
3052
+ function _eddsa_new_output_to_legacy(c, eddsa) {
3053
+ const Point = eddsa.Point;
3054
+ const legacy = Object.assign({}, eddsa, {
3055
+ ExtendedPoint: Point,
3056
+ CURVE: c,
3057
+ nBitLength: Point.Fn.BITS,
3058
+ nByteLength: Point.Fn.BYTES,
3059
+ });
3060
+ return legacy;
3061
+ }
3062
+ // TODO: remove. Use eddsa
3063
+ function twistedEdwards(c) {
3064
+ const { CURVE, curveOpts, hash, eddsaOpts } = _eddsa_legacy_opts_to_new(c);
3065
+ const Point = edwards(CURVE, curveOpts);
3066
+ const EDDSA = eddsa(Point, hash, eddsaOpts);
3067
+ return _eddsa_new_output_to_legacy(c, EDDSA);
2655
3068
  }
2656
3069
 
3070
+ /**
3071
+ * Montgomery curve methods. It's not really whole montgomery curve,
3072
+ * just bunch of very specific methods for X25519 / X448 from
3073
+ * [RFC 7748](https://www.rfc-editor.org/rfc/rfc7748)
3074
+ * @module
3075
+ */
2657
3076
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2658
3077
  const _0n = BigInt(0);
2659
- const _1n$2 = BigInt(1);
3078
+ const _1n$1 = BigInt(1);
3079
+ const _2n$2 = BigInt(2);
2660
3080
  function validateOpts(curve) {
2661
- validateObject(curve, {
2662
- a: 'bigint',
2663
- }, {
2664
- montgomeryBits: 'isSafeInteger',
2665
- nByteLength: 'isSafeInteger',
3081
+ _validateObject(curve, {
2666
3082
  adjustScalarBytes: 'function',
2667
- domain: 'function',
2668
3083
  powPminus2: 'function',
2669
- Gu: 'bigint',
2670
3084
  });
2671
- // Set defaults
2672
3085
  return Object.freeze({ ...curve });
2673
3086
  }
2674
- // NOTE: not really montgomery curve, just bunch of very specific methods for X25519/X448 (RFC 7748, https://www.rfc-editor.org/rfc/rfc7748)
2675
- // Uses only one coordinate instead of two
2676
3087
  function montgomery(curveDef) {
2677
3088
  const CURVE = validateOpts(curveDef);
2678
- const { P } = CURVE;
3089
+ const { P, type, adjustScalarBytes, powPminus2, randomBytes: rand } = CURVE;
3090
+ const is25519 = type === 'x25519';
3091
+ if (!is25519 && type !== 'x448')
3092
+ throw new Error('invalid type');
3093
+ const randomBytes_ = rand || randomBytes;
3094
+ const montgomeryBits = is25519 ? 255 : 448;
3095
+ const fieldLen = is25519 ? 32 : 56;
3096
+ const Gu = is25519 ? BigInt(9) : BigInt(5);
3097
+ // RFC 7748 #5:
3098
+ // The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519 and
3099
+ // (156326 - 2) / 4 = 39081 for curve448/X448
3100
+ // const a = is25519 ? 156326n : 486662n;
3101
+ const a24 = is25519 ? BigInt(121665) : BigInt(39081);
3102
+ // RFC: x25519 "the resulting integer is of the form 2^254 plus
3103
+ // eight times a value between 0 and 2^251 - 1 (inclusive)"
3104
+ // x448: "2^447 plus four times a value between 0 and 2^445 - 1 (inclusive)"
3105
+ const minScalar = is25519 ? _2n$2 ** BigInt(254) : _2n$2 ** BigInt(447);
3106
+ const maxAdded = is25519
3107
+ ? BigInt(8) * _2n$2 ** BigInt(251) - _1n$1
3108
+ : BigInt(4) * _2n$2 ** BigInt(445) - _1n$1;
3109
+ const maxScalar = minScalar + maxAdded + _1n$1; // (inclusive)
2679
3110
  const modP = (n) => mod(n, P);
2680
- const montgomeryBits = CURVE.montgomeryBits;
2681
- const montgomeryBytes = Math.ceil(montgomeryBits / 8);
2682
- const fieldLen = CURVE.nByteLength;
2683
- const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes) => bytes);
2684
- const powPminus2 = CURVE.powPminus2 || ((x) => pow(x, P - BigInt(2), P));
2685
- // cswap from RFC7748. But it is not from RFC7748!
2686
- /*
2687
- cswap(swap, x_2, x_3):
2688
- dummy = mask(swap) AND (x_2 XOR x_3)
2689
- x_2 = x_2 XOR dummy
2690
- x_3 = x_3 XOR dummy
2691
- Return (x_2, x_3)
2692
- Where mask(swap) is the all-1 or all-0 word of the same length as x_2
2693
- and x_3, computed, e.g., as mask(swap) = 0 - swap.
2694
- */
3111
+ const GuBytes = encodeU(Gu);
3112
+ function encodeU(u) {
3113
+ return numberToBytesLE(modP(u), fieldLen);
3114
+ }
3115
+ function decodeU(u) {
3116
+ const _u = ensureBytes('u coordinate', u, fieldLen);
3117
+ // RFC: When receiving such an array, implementations of X25519
3118
+ // (but not X448) MUST mask the most significant bit in the final byte.
3119
+ if (is25519)
3120
+ _u[31] &= 127; // 0b0111_1111
3121
+ // RFC: Implementations MUST accept non-canonical values and process them as
3122
+ // if they had been reduced modulo the field prime. The non-canonical
3123
+ // values are 2^255 - 19 through 2^255 - 1 for X25519 and 2^448 - 2^224
3124
+ // - 1 through 2^448 - 1 for X448.
3125
+ return modP(bytesToNumberLE(_u));
3126
+ }
3127
+ function decodeScalar(scalar) {
3128
+ return bytesToNumberLE(adjustScalarBytes(ensureBytes('scalar', scalar, fieldLen)));
3129
+ }
3130
+ function scalarMult(scalar, u) {
3131
+ const pu = montgomeryLadder(decodeU(u), decodeScalar(scalar));
3132
+ // Some public keys are useless, of low-order. Curve author doesn't think
3133
+ // it needs to be validated, but we do it nonetheless.
3134
+ // https://cr.yp.to/ecdh.html#validate
3135
+ if (pu === _0n)
3136
+ throw new Error('invalid private or public key received');
3137
+ return encodeU(pu);
3138
+ }
3139
+ // Computes public key from private. By doing scalar multiplication of base point.
3140
+ function scalarMultBase(scalar) {
3141
+ return scalarMult(scalar, GuBytes);
3142
+ }
3143
+ // cswap from RFC7748 "example code"
2695
3144
  function cswap(swap, x_2, x_3) {
3145
+ // dummy = mask(swap) AND (x_2 XOR x_3)
3146
+ // Where mask(swap) is the all-1 or all-0 word of the same length as x_2
3147
+ // and x_3, computed, e.g., as mask(swap) = 0 - swap.
2696
3148
  const dummy = modP(swap * (x_2 - x_3));
2697
- x_2 = modP(x_2 - dummy);
2698
- x_3 = modP(x_3 + dummy);
2699
- return [x_2, x_3];
3149
+ x_2 = modP(x_2 - dummy); // x_2 = x_2 XOR dummy
3150
+ x_3 = modP(x_3 + dummy); // x_3 = x_3 XOR dummy
3151
+ return { x_2, x_3 };
2700
3152
  }
2701
- // x25519 from 4
2702
- // The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519
2703
- const a24 = (CURVE.a - BigInt(2)) / BigInt(4);
2704
3153
  /**
2705
- *
3154
+ * Montgomery x-only multiplication ladder.
2706
3155
  * @param pointU u coordinate (x) on Montgomery Curve 25519
2707
3156
  * @param scalar by which the point would be multiplied
2708
3157
  * @returns new Point on Montgomery curve
2709
3158
  */
2710
3159
  function montgomeryLadder(u, scalar) {
2711
3160
  aInRange('u', u, _0n, P);
2712
- aInRange('scalar', scalar, _0n, P);
2713
- // Section 5: Implementations MUST accept non-canonical values and process them as
2714
- // if they had been reduced modulo the field prime.
3161
+ aInRange('scalar', scalar, minScalar, maxScalar);
2715
3162
  const k = scalar;
2716
3163
  const x_1 = u;
2717
- let x_2 = _1n$2;
3164
+ let x_2 = _1n$1;
2718
3165
  let z_2 = _0n;
2719
3166
  let x_3 = u;
2720
- let z_3 = _1n$2;
3167
+ let z_3 = _1n$1;
2721
3168
  let swap = _0n;
2722
- let sw;
2723
3169
  for (let t = BigInt(montgomeryBits - 1); t >= _0n; t--) {
2724
- const k_t = (k >> t) & _1n$2;
3170
+ const k_t = (k >> t) & _1n$1;
2725
3171
  swap ^= k_t;
2726
- sw = cswap(swap, x_2, x_3);
2727
- x_2 = sw[0];
2728
- x_3 = sw[1];
2729
- sw = cswap(swap, z_2, z_3);
2730
- z_2 = sw[0];
2731
- z_3 = sw[1];
3172
+ ({ x_2, x_3 } = cswap(swap, x_2, x_3));
3173
+ ({ x_2: z_2, x_3: z_3 } = cswap(swap, z_2, z_3));
2732
3174
  swap = k_t;
2733
3175
  const A = x_2 + z_2;
2734
3176
  const AA = modP(A * A);
@@ -2746,84 +3188,82 @@ function montgomery(curveDef) {
2746
3188
  x_2 = modP(AA * BB);
2747
3189
  z_2 = modP(E * (AA + modP(a24 * E)));
2748
3190
  }
2749
- // (x_2, x_3) = cswap(swap, x_2, x_3)
2750
- sw = cswap(swap, x_2, x_3);
2751
- x_2 = sw[0];
2752
- x_3 = sw[1];
2753
- // (z_2, z_3) = cswap(swap, z_2, z_3)
2754
- sw = cswap(swap, z_2, z_3);
2755
- z_2 = sw[0];
2756
- z_3 = sw[1];
2757
- // z_2^(p - 2)
2758
- const z2 = powPminus2(z_2);
2759
- // Return x_2 * (z_2^(p - 2))
2760
- return modP(x_2 * z2);
2761
- }
2762
- function encodeUCoordinate(u) {
2763
- return numberToBytesLE(modP(u), montgomeryBytes);
2764
- }
2765
- function decodeUCoordinate(uEnc) {
2766
- // Section 5: When receiving such an array, implementations of X25519
2767
- // MUST mask the most significant bit in the final byte.
2768
- const u = ensureBytes('u coordinate', uEnc, montgomeryBytes);
2769
- if (fieldLen === 32)
2770
- u[31] &= 127; // 0b0111_1111
2771
- return bytesToNumberLE(u);
2772
- }
2773
- function decodeScalar(n) {
2774
- const bytes = ensureBytes('scalar', n);
2775
- const len = bytes.length;
2776
- if (len !== montgomeryBytes && len !== fieldLen) {
2777
- let valid = '' + montgomeryBytes + ' or ' + fieldLen;
2778
- throw new Error('invalid scalar, expected ' + valid + ' bytes, got ' + len);
2779
- }
2780
- return bytesToNumberLE(adjustScalarBytes(bytes));
3191
+ ({ x_2, x_3 } = cswap(swap, x_2, x_3));
3192
+ ({ x_2: z_2, x_3: z_3 } = cswap(swap, z_2, z_3));
3193
+ const z2 = powPminus2(z_2); // `Fp.pow(x, P - _2n)` is much slower equivalent
3194
+ return modP(x_2 * z2); // Return x_2 * (z_2^(p - 2))
2781
3195
  }
2782
- function scalarMult(scalar, u) {
2783
- const pointU = decodeUCoordinate(u);
2784
- const _scalar = decodeScalar(scalar);
2785
- const pu = montgomeryLadder(pointU, _scalar);
2786
- // The result was not contributory
2787
- // https://cr.yp.to/ecdh.html#validate
2788
- if (pu === _0n)
2789
- throw new Error('invalid private or public key received');
2790
- return encodeUCoordinate(pu);
2791
- }
2792
- // Computes public key from private. By doing scalar multiplication of base point.
2793
- const GuBytes = encodeUCoordinate(CURVE.Gu);
2794
- function scalarMultBase(scalar) {
2795
- return scalarMult(scalar, GuBytes);
3196
+ const lengths = {
3197
+ secretKey: fieldLen,
3198
+ publicKey: fieldLen,
3199
+ seed: fieldLen,
3200
+ };
3201
+ const randomSecretKey = (seed = randomBytes_(fieldLen)) => {
3202
+ abytes(seed, lengths.seed);
3203
+ return seed;
3204
+ };
3205
+ function keygen(seed) {
3206
+ const secretKey = randomSecretKey(seed);
3207
+ return { secretKey, publicKey: scalarMultBase(secretKey) };
2796
3208
  }
3209
+ const utils = {
3210
+ randomSecretKey,
3211
+ randomPrivateKey: randomSecretKey,
3212
+ };
2797
3213
  return {
3214
+ keygen,
3215
+ getSharedSecret: (secretKey, publicKey) => scalarMult(secretKey, publicKey),
3216
+ getPublicKey: (secretKey) => scalarMultBase(secretKey),
2798
3217
  scalarMult,
2799
3218
  scalarMultBase,
2800
- getSharedSecret: (privateKey, publicKey) => scalarMult(privateKey, publicKey),
2801
- getPublicKey: (privateKey) => scalarMultBase(privateKey),
2802
- utils: { randomPrivateKey: () => CURVE.randomBytes(CURVE.nByteLength) },
2803
- GuBytes: GuBytes,
3219
+ utils,
3220
+ GuBytes: GuBytes.slice(),
3221
+ lengths,
2804
3222
  };
2805
3223
  }
2806
3224
 
2807
- /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2808
3225
  /**
2809
3226
  * Edwards448 (not Ed448-Goldilocks) curve with following addons:
2810
3227
  * - X448 ECDH
2811
3228
  * - Decaf cofactor elimination
2812
3229
  * - Elligator hash-to-group / point indistinguishability
2813
3230
  * Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2
3231
+ * @module
2814
3232
  */
2815
- const shake256_114 = wrapConstructor(() => shake256.create({ dkLen: 114 }));
2816
- const shake256_64 = wrapConstructor(() => shake256.create({ dkLen: 64 }));
2817
- const ed448P = BigInt('726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439');
3233
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
3234
+ // edwards448 curve
3235
+ // a = 1n
3236
+ // d = Fp.neg(39081n)
3237
+ // Finite field 2n**448n - 2n**224n - 1n
3238
+ // Subgroup order
3239
+ // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n
3240
+ const ed448_CURVE = {
3241
+ p: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffff'),
3242
+ n: BigInt('0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffff7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3'),
3243
+ h: BigInt(4),
3244
+ a: BigInt(1),
3245
+ d: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffff6756'),
3246
+ Gx: BigInt('0x4f1970c66bed0ded221d15a622bf36da9e146570470f1767ea6de324a3d3a46412ae1af72ab66511433b80e18b00938e2626a82bc70cc05e'),
3247
+ Gy: BigInt('0x693f46716eb6bc248876203756c9c7624bea73736ca3984087789c1e05a0c2d73ad3ff1ce67c39c4fdbd132c4ed7c8ad9808795bf230fa14'),
3248
+ };
3249
+ // E448 NIST curve is identical to edwards448, except for:
3250
+ // d = 39082/39081
3251
+ // Gx = 3/2
3252
+ const E448_CURVE = Object.assign({}, ed448_CURVE, {
3253
+ d: BigInt('0xd78b4bdc7f0daf19f24f38c29373a2ccad46157242a50f37809b1da3412a12e79ccc9c81264cfe9ad080997058fb61c4243cc32dbaa156b9'),
3254
+ Gx: BigInt('0x79a70b2b70400553ae7c9df416c792c61128751ac92969240c25a07d728bdc93e21f7787ed6972249de732f38496cd11698713093e9c04fc'),
3255
+ Gy: BigInt('0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000000000000000000001'),
3256
+ });
3257
+ const shake256_114 = /* @__PURE__ */ createHasher(() => shake256.create({ dkLen: 114 }));
2818
3258
  // prettier-ignore
2819
- const _1n$1 = BigInt(1), _2n$1 = BigInt(2), _3n = BigInt(3); BigInt(4); const _11n = BigInt(11);
3259
+ const _1n = BigInt(1), _2n$1 = BigInt(2), _3n = BigInt(3); BigInt(4); const _11n = BigInt(11);
2820
3260
  // prettier-ignore
2821
3261
  const _22n = BigInt(22), _44n = BigInt(44), _88n = BigInt(88), _223n = BigInt(223);
2822
3262
  // powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4.
2823
3263
  // Used for efficient square root calculation.
2824
3264
  // ((P-3)/4).toString(2) would produce bits [223x 1, 0, 222x 1]
2825
3265
  function ed448_pow_Pminus3div4(x) {
2826
- const P = ed448P;
3266
+ const P = ed448_CURVE.p;
2827
3267
  const b2 = (x * x * x) % P;
2828
3268
  const b3 = (b2 * b2 * x) % P;
2829
3269
  const b6 = (pow2(b3, _3n, P) * b3) % P;
@@ -2835,23 +3275,22 @@ function ed448_pow_Pminus3div4(x) {
2835
3275
  const b176 = (pow2(b88, _88n, P) * b88) % P;
2836
3276
  const b220 = (pow2(b176, _44n, P) * b44) % P;
2837
3277
  const b222 = (pow2(b220, _2n$1, P) * b2) % P;
2838
- const b223 = (pow2(b222, _1n$1, P) * x) % P;
3278
+ const b223 = (pow2(b222, _1n, P) * x) % P;
2839
3279
  return (pow2(b223, _223n, P) * b222) % P;
2840
3280
  }
2841
3281
  function adjustScalarBytes(bytes) {
2842
- // Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0, and the most
2843
- // significant bit of the last byte to 1.
3282
+ // Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0,
2844
3283
  bytes[0] &= 252; // 0b11111100
2845
3284
  // and the most significant bit of the last byte to 1.
2846
3285
  bytes[55] |= 128; // 0b10000000
2847
- // NOTE: is is NOOP for 56 bytes scalars (X25519/X448)
3286
+ // NOTE: is NOOP for 56 bytes scalars (X25519/X448)
2848
3287
  bytes[56] = 0; // Byte outside of group (456 buts vs 448 bits)
2849
3288
  return bytes;
2850
3289
  }
2851
3290
  // Constant-time ratio of u to v. Allows to combine inversion and square root u/√v.
2852
3291
  // Uses algo from RFC8032 5.1.3.
2853
3292
  function uvRatio(u, v) {
2854
- const P = ed448P;
3293
+ const P = ed448_CURVE.p;
2855
3294
  // https://www.rfc-editor.org/rfc/rfc8032#section-5.2.3
2856
3295
  // To compute the square root of (u/v), the first step is to compute the
2857
3296
  // candidate root x = (u/v)^((p+1)/4). This can be done using the
@@ -2869,81 +3308,99 @@ function uvRatio(u, v) {
2869
3308
  // square root exists, and the decoding fails.
2870
3309
  return { isValid: mod(x2 * v, P) === u, value: x };
2871
3310
  }
2872
- const Fp$3 = Field(ed448P, 456, true);
2873
- const ED448_DEF = {
2874
- // Param: a
2875
- a: BigInt(1),
2876
- // -39081. Negative number is P - number
2877
- d: BigInt('726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358'),
2878
- // Finite field 𝔽p over which we'll do calculations; 2n**448n - 2n**224n - 1n
3311
+ // Finite field 2n**448n - 2n**224n - 1n
3312
+ // The value fits in 448 bits, but we use 456-bit (57-byte) elements because of bitflags.
3313
+ // - ed25519 fits in 255 bits, allowing using last 1 byte for specifying bit flag of point negation.
3314
+ // - ed448 fits in 448 bits. We can't use last 1 byte: we can only use a bit 224 in the middle.
3315
+ const Fp$3 = /* @__PURE__ */ (() => Field(ed448_CURVE.p, { BITS: 456, isLE: true }))();
3316
+ const Fn = /* @__PURE__ */ (() => Field(ed448_CURVE.n, { BITS: 456, isLE: true }))();
3317
+ // SHAKE256(dom4(phflag,context)||x, 114)
3318
+ function dom4(data, ctx, phflag) {
3319
+ if (ctx.length > 255)
3320
+ throw new Error('context must be smaller than 255, got: ' + ctx.length);
3321
+ return concatBytes(asciiToBytes('SigEd448'), new Uint8Array([phflag ? 1 : 0, ctx.length]), ctx, data);
3322
+ }
3323
+ // const ed448_eddsa_opts = { adjustScalarBytes, domain: dom4 };
3324
+ // const ed448_Point = edwards(ed448_CURVE, { Fp, Fn, uvRatio });
3325
+ const ED448_DEF = /* @__PURE__ */ (() => ({
3326
+ ...ed448_CURVE,
2879
3327
  Fp: Fp$3,
2880
- // Subgroup order: how many points curve has;
2881
- // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n
2882
- n: BigInt('181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779'),
2883
- // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys
2884
- nBitLength: 456,
2885
- // Cofactor
2886
- h: BigInt(4),
2887
- // Base point (x, y) aka generator point
2888
- Gx: BigInt('224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710'),
2889
- Gy: BigInt('298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660'),
2890
- // SHAKE256(dom4(phflag,context)||x, 114)
3328
+ Fn,
3329
+ nBitLength: Fn.BITS,
2891
3330
  hash: shake256_114,
2892
- randomBytes,
2893
3331
  adjustScalarBytes,
2894
- // dom4
2895
- domain: (data, ctx, phflag) => {
2896
- if (ctx.length > 255)
2897
- throw new Error('context must be smaller than 255, got: ' + ctx.length);
2898
- return concatBytes$1(utf8ToBytes$1('SigEd448'), new Uint8Array([phflag ? 1 : 0, ctx.length]), ctx, data);
2899
- },
3332
+ domain: dom4,
2900
3333
  uvRatio,
2901
- };
2902
- const ed448 = /* @__PURE__ */ twistedEdwards(ED448_DEF);
2903
- // NOTE: there is no ed448ctx, since ed448 supports ctx by default
2904
- /* @__PURE__ */ twistedEdwards({ ...ED448_DEF, prehash: shake256_64 });
2905
- const x448 = /* @__PURE__ */ (() => montgomery({
2906
- a: BigInt(156326),
2907
- // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys
2908
- montgomeryBits: 448,
2909
- nByteLength: 56,
2910
- P: ed448P,
2911
- Gu: BigInt(5),
2912
- powPminus2: (x) => {
2913
- const P = ed448P;
2914
- const Pminus3div4 = ed448_pow_Pminus3div4(x);
2915
- const Pminus3 = pow2(Pminus3div4, BigInt(2), P);
2916
- return mod(Pminus3 * x, P); // Pminus3 * x = Pminus2
2917
- },
2918
- adjustScalarBytes,
2919
- randomBytes,
2920
3334
  }))();
2921
- // TODO: add edwardsToMontgomeryPriv, similar to ed25519 version
2922
- // Hash To Curve Elligator2 Map
2923
- (Fp$3.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic
2924
- BigInt(156326);
2925
- // 1-d
2926
- BigInt('39082');
2927
- // 1-2d
2928
- BigInt('78163');
2929
- // √(-d)
2930
- BigInt('98944233647732219769177004876929019128417576295529901074099889598043702116001257856802131563896515373927712232092845883226922417596214');
2931
- // 1 / √(-d)
2932
- BigInt('315019913931389607337177038330951043522456072897266928557328499619017160722351061360252776265186336876723201881398623946864393857820716');
2933
- BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
3335
+ /**
3336
+ * ed448 EdDSA curve and methods.
3337
+ * @example
3338
+ * import { ed448 } from '@noble/curves/ed448';
3339
+ * const { secretKey, publicKey } = ed448.keygen();
3340
+ * const msg = new TextEncoder().encode('hello');
3341
+ * const sig = ed448.sign(msg, secretKey);
3342
+ * const isValid = ed448.verify(sig, msg, publicKey);
3343
+ */
3344
+ const ed448 = twistedEdwards(ED448_DEF);
3345
+ /**
3346
+ * E448 curve, defined by NIST.
3347
+ * E448 != edwards448 used in ed448.
3348
+ * E448 is birationally equivalent to edwards448.
3349
+ */
3350
+ edwards(E448_CURVE);
3351
+ /**
3352
+ * ECDH using curve448 aka x448.
3353
+ * x448 has 56-byte keys as per RFC 7748, while
3354
+ * ed448 has 57-byte keys as per RFC 8032.
3355
+ */
3356
+ const x448 = /* @__PURE__ */ (() => {
3357
+ const P = ed448_CURVE.p;
3358
+ return montgomery({
3359
+ P,
3360
+ type: 'x448',
3361
+ powPminus2: (x) => {
3362
+ const Pminus3div4 = ed448_pow_Pminus3div4(x);
3363
+ const Pminus3 = pow2(Pminus3div4, _2n$1, P);
3364
+ return mod(Pminus3 * x, P); // Pminus3 * x = Pminus2
3365
+ },
3366
+ adjustScalarBytes,
3367
+ });
3368
+ })();
2934
3369
 
3370
+ /**
3371
+ * SECG secp256k1. See [pdf](https://www.secg.org/sec2-v2.pdf).
3372
+ *
3373
+ * Belongs to Koblitz curves: it has efficiently-computable GLV endomorphism ψ,
3374
+ * check out {@link EndomorphismOpts}. Seems to be rigid (not backdoored).
3375
+ * @module
3376
+ */
2935
3377
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2936
- const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f');
2937
- const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141');
2938
- const _1n = BigInt(1);
2939
- const _2n = BigInt(2);
2940
- const divNearest = (a, b) => (a + b / _2n) / b;
3378
+ // Seems like generator was produced from some seed:
3379
+ // `Point.BASE.multiply(Point.Fn.inv(2n, N)).toAffine().x`
3380
+ // // gives short x 0x3b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63n
3381
+ const secp256k1_CURVE = {
3382
+ p: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'),
3383
+ n: BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'),
3384
+ h: BigInt(1),
3385
+ a: BigInt(0),
3386
+ b: BigInt(7),
3387
+ Gx: BigInt('0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'),
3388
+ Gy: BigInt('0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'),
3389
+ };
3390
+ const secp256k1_ENDO = {
3391
+ beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
3392
+ basises: [
3393
+ [BigInt('0x3086d221a7d46bcde86c90e49284eb15'), -BigInt('0xe4437ed6010e88286f547fa90abfe4c3')],
3394
+ [BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8'), BigInt('0x3086d221a7d46bcde86c90e49284eb15')],
3395
+ ],
3396
+ };
3397
+ const _2n = /* @__PURE__ */ BigInt(2);
2941
3398
  /**
2942
3399
  * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit.
2943
3400
  * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00]
2944
3401
  */
2945
3402
  function sqrtMod(y) {
2946
- const P = secp256k1P;
3403
+ const P = secp256k1_CURVE.p;
2947
3404
  // prettier-ignore
2948
3405
  const _3n = BigInt(3), _6n = BigInt(6), _11n = BigInt(11), _22n = BigInt(22);
2949
3406
  // prettier-ignore
@@ -2966,56 +3423,22 @@ function sqrtMod(y) {
2966
3423
  throw new Error('Cannot find square root');
2967
3424
  return root;
2968
3425
  }
2969
- const Fpk1 = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod });
3426
+ const Fpk1 = Field(secp256k1_CURVE.p, { sqrt: sqrtMod });
2970
3427
  /**
2971
- * secp256k1 short weierstrass curve and ECDSA signatures over it.
3428
+ * secp256k1 curve, ECDSA and ECDH methods.
3429
+ *
3430
+ * Field: `2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n`
3431
+ *
3432
+ * @example
3433
+ * ```js
3434
+ * import { secp256k1 } from '@noble/curves/secp256k1';
3435
+ * const { secretKey, publicKey } = secp256k1.keygen();
3436
+ * const msg = new TextEncoder().encode('hello');
3437
+ * const sig = secp256k1.sign(msg, secretKey);
3438
+ * const isValid = secp256k1.verify(sig, msg, publicKey) === true;
3439
+ * ```
2972
3440
  */
2973
- const secp256k1 = createCurve({
2974
- a: BigInt(0), // equation params: a, b
2975
- b: BigInt(7), // Seem to be rigid: bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975
2976
- Fp: Fpk1, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n
2977
- n: secp256k1N, // Curve order, total count of valid points in the field
2978
- // Base point (x, y) aka generator point
2979
- Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),
2980
- Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),
2981
- h: BigInt(1), // Cofactor
2982
- lowS: true, // Allow only low-S signatures by default in sign() and verify()
2983
- /**
2984
- * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism.
2985
- * Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%.
2986
- * For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit.
2987
- * Explanation: https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066
2988
- */
2989
- endo: {
2990
- beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
2991
- splitScalar: (k) => {
2992
- const n = secp256k1N;
2993
- const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15');
2994
- const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3');
2995
- const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8');
2996
- const b2 = a1;
2997
- const POW_2_128 = BigInt('0x100000000000000000000000000000000'); // (2n**128n).toString(16)
2998
- const c1 = divNearest(b2 * k, n);
2999
- const c2 = divNearest(-b1 * k, n);
3000
- let k1 = mod(k - c1 * a1 - c2 * a2, n);
3001
- let k2 = mod(-c1 * b1 - c2 * b2, n);
3002
- const k1neg = k1 > POW_2_128;
3003
- const k2neg = k2 > POW_2_128;
3004
- if (k1neg)
3005
- k1 = n - k1;
3006
- if (k2neg)
3007
- k2 = n - k2;
3008
- if (k1 > POW_2_128 || k2 > POW_2_128) {
3009
- throw new Error('splitScalar: Endomorphism failed, k=' + k);
3010
- }
3011
- return { k1neg, k1, k2neg, k2 };
3012
- },
3013
- },
3014
- }, sha256);
3015
- // Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code.
3016
- // https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
3017
- BigInt(0);
3018
- secp256k1.ProjectivePoint;
3441
+ const secp256k1 = createCurve({ ...secp256k1_CURVE, Fp: Fpk1, lowS: true, endo: secp256k1_ENDO }, sha256);
3019
3442
 
3020
3443
  // brainpoolP256r1: https://datatracker.ietf.org/doc/html/rfc5639#section-3.4
3021
3444
  // eslint-disable-next-line new-cap
@@ -3034,7 +3457,7 @@ const brainpoolP256r1 = createCurve({
3034
3457
  Gy: BigInt('0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997'),
3035
3458
  h: BigInt(1),
3036
3459
  lowS: false
3037
- }, sha256);
3460
+ }, sha256$1);
3038
3461
 
3039
3462
  // brainpoolP384 r1: https://datatracker.ietf.org/doc/html/rfc5639#section-3.6
3040
3463
  // eslint-disable-next-line new-cap
@@ -3053,7 +3476,7 @@ const brainpoolP384r1 = createCurve({
3053
3476
  Gy: BigInt('0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff99129280e4646217791811142820341263c5315'),
3054
3477
  h: BigInt(1),
3055
3478
  lowS: false
3056
- }, sha384);
3479
+ }, sha384$1);
3057
3480
 
3058
3481
  // brainpoolP512r1: https://datatracker.ietf.org/doc/html/rfc5639#section-3.7
3059
3482
  // eslint-disable-next-line new-cap
@@ -3072,7 +3495,7 @@ const brainpoolP512r1 = createCurve({
3072
3495
  Gy: BigInt('0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892'),
3073
3496
  h: BigInt(1),
3074
3497
  lowS: false
3075
- }, sha512);
3498
+ }, sha512$1);
3076
3499
 
3077
3500
  /**
3078
3501
  * This file is needed to dynamic import the noble-curves.