noble-secp256k1.js (44938B)
1 (function (global, factory) { 2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 3 typeof define === 'function' && define.amd ? define(['exports'], factory) : 4 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.nobleSecp256k1 = {})); 5 })(this, (function (exports) { 'use strict'; 6 7 const _nodeResolve_empty = {}; 8 9 const nodeCrypto = /*#__PURE__*/Object.freeze({ 10 __proto__: null, 11 'default': _nodeResolve_empty 12 }); 13 14 /*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */ 15 const _0n = BigInt(0); 16 const _1n = BigInt(1); 17 const _2n = BigInt(2); 18 const _3n = BigInt(3); 19 const _8n = BigInt(8); 20 const CURVE = Object.freeze({ 21 a: _0n, 22 b: BigInt(7), 23 P: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'), 24 n: BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'), 25 h: _1n, 26 Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'), 27 Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'), 28 beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), 29 }); 30 function weistrass(x) { 31 const { a, b } = CURVE; 32 const x2 = mod(x * x); 33 const x3 = mod(x2 * x); 34 return mod(x3 + a * x + b); 35 } 36 const USE_ENDOMORPHISM = CURVE.a === _0n; 37 class ShaError extends Error { 38 constructor(message) { 39 super(message); 40 } 41 } 42 class JacobianPoint { 43 constructor(x, y, z) { 44 this.x = x; 45 this.y = y; 46 this.z = z; 47 } 48 static fromAffine(p) { 49 if (!(p instanceof Point)) { 50 throw new TypeError('JacobianPoint#fromAffine: expected Point'); 51 } 52 return new JacobianPoint(p.x, p.y, _1n); 53 } 54 static toAffineBatch(points) { 55 const toInv = invertBatch(points.map((p) => p.z)); 56 return points.map((p, i) => p.toAffine(toInv[i])); 57 } 58 static normalizeZ(points) { 59 return JacobianPoint.toAffineBatch(points).map(JacobianPoint.fromAffine); 60 } 61 equals(other) { 62 if (!(other instanceof JacobianPoint)) 63 throw new TypeError('JacobianPoint expected'); 64 const { x: X1, y: Y1, z: Z1 } = this; 65 const { x: X2, y: Y2, z: Z2 } = other; 66 const Z1Z1 = mod(Z1 * Z1); 67 const Z2Z2 = mod(Z2 * Z2); 68 const U1 = mod(X1 * Z2Z2); 69 const U2 = mod(X2 * Z1Z1); 70 const S1 = mod(mod(Y1 * Z2) * Z2Z2); 71 const S2 = mod(mod(Y2 * Z1) * Z1Z1); 72 return U1 === U2 && S1 === S2; 73 } 74 negate() { 75 return new JacobianPoint(this.x, mod(-this.y), this.z); 76 } 77 double() { 78 const { x: X1, y: Y1, z: Z1 } = this; 79 const A = mod(X1 * X1); 80 const B = mod(Y1 * Y1); 81 const C = mod(B * B); 82 const x1b = X1 + B; 83 const D = mod(_2n * (mod(x1b * x1b) - A - C)); 84 const E = mod(_3n * A); 85 const F = mod(E * E); 86 const X3 = mod(F - _2n * D); 87 const Y3 = mod(E * (D - X3) - _8n * C); 88 const Z3 = mod(_2n * Y1 * Z1); 89 return new JacobianPoint(X3, Y3, Z3); 90 } 91 add(other) { 92 if (!(other instanceof JacobianPoint)) 93 throw new TypeError('JacobianPoint expected'); 94 const { x: X1, y: Y1, z: Z1 } = this; 95 const { x: X2, y: Y2, z: Z2 } = other; 96 if (X2 === _0n || Y2 === _0n) 97 return this; 98 if (X1 === _0n || Y1 === _0n) 99 return other; 100 const Z1Z1 = mod(Z1 * Z1); 101 const Z2Z2 = mod(Z2 * Z2); 102 const U1 = mod(X1 * Z2Z2); 103 const U2 = mod(X2 * Z1Z1); 104 const S1 = mod(mod(Y1 * Z2) * Z2Z2); 105 const S2 = mod(mod(Y2 * Z1) * Z1Z1); 106 const H = mod(U2 - U1); 107 const r = mod(S2 - S1); 108 if (H === _0n) { 109 if (r === _0n) { 110 return this.double(); 111 } 112 else { 113 return JacobianPoint.ZERO; 114 } 115 } 116 const HH = mod(H * H); 117 const HHH = mod(H * HH); 118 const V = mod(U1 * HH); 119 const X3 = mod(r * r - HHH - _2n * V); 120 const Y3 = mod(r * (V - X3) - S1 * HHH); 121 const Z3 = mod(Z1 * Z2 * H); 122 return new JacobianPoint(X3, Y3, Z3); 123 } 124 subtract(other) { 125 return this.add(other.negate()); 126 } 127 multiplyUnsafe(scalar) { 128 const P0 = JacobianPoint.ZERO; 129 if (typeof scalar === 'bigint' && scalar === _0n) 130 return P0; 131 let n = normalizeScalar(scalar); 132 if (n === _1n) 133 return this; 134 if (!USE_ENDOMORPHISM) { 135 let p = P0; 136 let d = this; 137 while (n > _0n) { 138 if (n & _1n) 139 p = p.add(d); 140 d = d.double(); 141 n >>= _1n; 142 } 143 return p; 144 } 145 let { k1neg, k1, k2neg, k2 } = splitScalarEndo(n); 146 let k1p = P0; 147 let k2p = P0; 148 let d = this; 149 while (k1 > _0n || k2 > _0n) { 150 if (k1 & _1n) 151 k1p = k1p.add(d); 152 if (k2 & _1n) 153 k2p = k2p.add(d); 154 d = d.double(); 155 k1 >>= _1n; 156 k2 >>= _1n; 157 } 158 if (k1neg) 159 k1p = k1p.negate(); 160 if (k2neg) 161 k2p = k2p.negate(); 162 k2p = new JacobianPoint(mod(k2p.x * CURVE.beta), k2p.y, k2p.z); 163 return k1p.add(k2p); 164 } 165 precomputeWindow(W) { 166 const windows = USE_ENDOMORPHISM ? 128 / W + 1 : 256 / W + 1; 167 const points = []; 168 let p = this; 169 let base = p; 170 for (let window = 0; window < windows; window++) { 171 base = p; 172 points.push(base); 173 for (let i = 1; i < 2 ** (W - 1); i++) { 174 base = base.add(p); 175 points.push(base); 176 } 177 p = base.double(); 178 } 179 return points; 180 } 181 wNAF(n, affinePoint) { 182 if (!affinePoint && this.equals(JacobianPoint.BASE)) 183 affinePoint = Point.BASE; 184 const W = (affinePoint && affinePoint._WINDOW_SIZE) || 1; 185 if (256 % W) { 186 throw new Error('Point#wNAF: Invalid precomputation window, must be power of 2'); 187 } 188 let precomputes = affinePoint && pointPrecomputes.get(affinePoint); 189 if (!precomputes) { 190 precomputes = this.precomputeWindow(W); 191 if (affinePoint && W !== 1) { 192 precomputes = JacobianPoint.normalizeZ(precomputes); 193 pointPrecomputes.set(affinePoint, precomputes); 194 } 195 } 196 let p = JacobianPoint.ZERO; 197 let f = JacobianPoint.ZERO; 198 const windows = 1 + (USE_ENDOMORPHISM ? 128 / W : 256 / W); 199 const windowSize = 2 ** (W - 1); 200 const mask = BigInt(2 ** W - 1); 201 const maxNumber = 2 ** W; 202 const shiftBy = BigInt(W); 203 for (let window = 0; window < windows; window++) { 204 const offset = window * windowSize; 205 let wbits = Number(n & mask); 206 n >>= shiftBy; 207 if (wbits > windowSize) { 208 wbits -= maxNumber; 209 n += _1n; 210 } 211 if (wbits === 0) { 212 let pr = precomputes[offset]; 213 if (window % 2) 214 pr = pr.negate(); 215 f = f.add(pr); 216 } 217 else { 218 let cached = precomputes[offset + Math.abs(wbits) - 1]; 219 if (wbits < 0) 220 cached = cached.negate(); 221 p = p.add(cached); 222 } 223 } 224 return { p, f }; 225 } 226 multiply(scalar, affinePoint) { 227 let n = normalizeScalar(scalar); 228 let point; 229 let fake; 230 if (USE_ENDOMORPHISM) { 231 const { k1neg, k1, k2neg, k2 } = splitScalarEndo(n); 232 let { p: k1p, f: f1p } = this.wNAF(k1, affinePoint); 233 let { p: k2p, f: f2p } = this.wNAF(k2, affinePoint); 234 if (k1neg) 235 k1p = k1p.negate(); 236 if (k2neg) 237 k2p = k2p.negate(); 238 k2p = new JacobianPoint(mod(k2p.x * CURVE.beta), k2p.y, k2p.z); 239 point = k1p.add(k2p); 240 fake = f1p.add(f2p); 241 } 242 else { 243 const { p, f } = this.wNAF(n, affinePoint); 244 point = p; 245 fake = f; 246 } 247 return JacobianPoint.normalizeZ([point, fake])[0]; 248 } 249 toAffine(invZ = invert(this.z)) { 250 const { x, y, z } = this; 251 const iz1 = invZ; 252 const iz2 = mod(iz1 * iz1); 253 const iz3 = mod(iz2 * iz1); 254 const ax = mod(x * iz2); 255 const ay = mod(y * iz3); 256 const zz = mod(z * iz1); 257 if (zz !== _1n) 258 throw new Error('invZ was invalid'); 259 return new Point(ax, ay); 260 } 261 } 262 JacobianPoint.BASE = new JacobianPoint(CURVE.Gx, CURVE.Gy, _1n); 263 JacobianPoint.ZERO = new JacobianPoint(_0n, _1n, _0n); 264 const pointPrecomputes = new WeakMap(); 265 class Point { 266 constructor(x, y) { 267 this.x = x; 268 this.y = y; 269 } 270 _setWindowSize(windowSize) { 271 this._WINDOW_SIZE = windowSize; 272 pointPrecomputes.delete(this); 273 } 274 hasEvenY() { 275 return this.y % _2n === _0n; 276 } 277 static fromCompressedHex(bytes) { 278 const isShort = bytes.length === 32; 279 const x = bytesToNumber(isShort ? bytes : bytes.subarray(1)); 280 if (!isValidFieldElement(x)) 281 throw new Error('Point is not on curve'); 282 const y2 = weistrass(x); 283 let y = sqrtMod(y2); 284 const isYOdd = (y & _1n) === _1n; 285 if (isShort) { 286 if (isYOdd) 287 y = mod(-y); 288 } 289 else { 290 const isFirstByteOdd = (bytes[0] & 1) === 1; 291 if (isFirstByteOdd !== isYOdd) 292 y = mod(-y); 293 } 294 const point = new Point(x, y); 295 point.assertValidity(); 296 return point; 297 } 298 static fromUncompressedHex(bytes) { 299 const x = bytesToNumber(bytes.subarray(1, 33)); 300 const y = bytesToNumber(bytes.subarray(33, 65)); 301 const point = new Point(x, y); 302 point.assertValidity(); 303 return point; 304 } 305 static fromHex(hex) { 306 const bytes = ensureBytes(hex); 307 const len = bytes.length; 308 const header = bytes[0]; 309 if (len === 32 || (len === 33 && (header === 0x02 || header === 0x03))) { 310 return this.fromCompressedHex(bytes); 311 } 312 if (len === 65 && header === 0x04) 313 return this.fromUncompressedHex(bytes); 314 throw new Error(`Point.fromHex: received invalid point. Expected 32-33 compressed bytes or 65 uncompressed bytes, not ${len}`); 315 } 316 static fromPrivateKey(privateKey) { 317 return Point.BASE.multiply(normalizePrivateKey(privateKey)); 318 } 319 static fromSignature(msgHash, signature, recovery) { 320 msgHash = ensureBytes(msgHash); 321 const h = truncateHash(msgHash); 322 const { r, s } = normalizeSignature(signature); 323 if (recovery !== 0 && recovery !== 1) { 324 throw new Error('Cannot recover signature: invalid recovery bit'); 325 } 326 const prefix = recovery & 1 ? '03' : '02'; 327 const R = Point.fromHex(prefix + numTo32bStr(r)); 328 const { n } = CURVE; 329 const rinv = invert(r, n); 330 const u1 = mod(-h * rinv, n); 331 const u2 = mod(s * rinv, n); 332 const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); 333 if (!Q) 334 throw new Error('Cannot recover signature: point at infinify'); 335 Q.assertValidity(); 336 return Q; 337 } 338 toRawBytes(isCompressed = false) { 339 return hexToBytes(this.toHex(isCompressed)); 340 } 341 toHex(isCompressed = false) { 342 const x = numTo32bStr(this.x); 343 if (isCompressed) { 344 const prefix = this.hasEvenY() ? '02' : '03'; 345 return `${prefix}${x}`; 346 } 347 else { 348 return `04${x}${numTo32bStr(this.y)}`; 349 } 350 } 351 toHexX() { 352 return this.toHex(true).slice(2); 353 } 354 toRawX() { 355 return this.toRawBytes(true).slice(1); 356 } 357 assertValidity() { 358 const msg = 'Point is not on elliptic curve'; 359 const { x, y } = this; 360 if (!isValidFieldElement(x) || !isValidFieldElement(y)) 361 throw new Error(msg); 362 const left = mod(y * y); 363 const right = weistrass(x); 364 if (mod(left - right) !== _0n) 365 throw new Error(msg); 366 } 367 equals(other) { 368 return this.x === other.x && this.y === other.y; 369 } 370 negate() { 371 return new Point(this.x, mod(-this.y)); 372 } 373 double() { 374 return JacobianPoint.fromAffine(this).double().toAffine(); 375 } 376 add(other) { 377 return JacobianPoint.fromAffine(this).add(JacobianPoint.fromAffine(other)).toAffine(); 378 } 379 subtract(other) { 380 return this.add(other.negate()); 381 } 382 multiply(scalar) { 383 return JacobianPoint.fromAffine(this).multiply(scalar, this).toAffine(); 384 } 385 multiplyAndAddUnsafe(Q, a, b) { 386 const P = JacobianPoint.fromAffine(this); 387 const aP = a === _0n || a === _1n || this !== Point.BASE ? P.multiplyUnsafe(a) : P.multiply(a); 388 const bQ = JacobianPoint.fromAffine(Q).multiplyUnsafe(b); 389 const sum = aP.add(bQ); 390 return sum.equals(JacobianPoint.ZERO) ? undefined : sum.toAffine(); 391 } 392 } 393 Point.BASE = new Point(CURVE.Gx, CURVE.Gy); 394 Point.ZERO = new Point(_0n, _0n); 395 function sliceDER(s) { 396 return Number.parseInt(s[0], 16) >= 8 ? '00' + s : s; 397 } 398 function parseDERInt(data) { 399 if (data.length < 2 || data[0] !== 0x02) { 400 throw new Error(`Invalid signature integer tag: ${bytesToHex(data)}`); 401 } 402 const len = data[1]; 403 const res = data.subarray(2, len + 2); 404 if (!len || res.length !== len) { 405 throw new Error(`Invalid signature integer: wrong length`); 406 } 407 if (res[0] === 0x00 && res[1] <= 0x7f) { 408 throw new Error('Invalid signature integer: trailing length'); 409 } 410 return { data: bytesToNumber(res), left: data.subarray(len + 2) }; 411 } 412 function parseDERSignature(data) { 413 if (data.length < 2 || data[0] != 0x30) { 414 throw new Error(`Invalid signature tag: ${bytesToHex(data)}`); 415 } 416 if (data[1] !== data.length - 2) { 417 throw new Error('Invalid signature: incorrect length'); 418 } 419 const { data: r, left: sBytes } = parseDERInt(data.subarray(2)); 420 const { data: s, left: rBytesLeft } = parseDERInt(sBytes); 421 if (rBytesLeft.length) { 422 throw new Error(`Invalid signature: left bytes after parsing: ${bytesToHex(rBytesLeft)}`); 423 } 424 return { r, s }; 425 } 426 class Signature { 427 constructor(r, s) { 428 this.r = r; 429 this.s = s; 430 this.assertValidity(); 431 } 432 static fromCompact(hex) { 433 const arr = hex instanceof Uint8Array; 434 const name = 'Signature.fromCompact'; 435 if (typeof hex !== 'string' && !arr) 436 throw new TypeError(`${name}: Expected string or Uint8Array`); 437 const str = arr ? bytesToHex(hex) : hex; 438 if (str.length !== 128) 439 throw new Error(`${name}: Expected 64-byte hex`); 440 return new Signature(hexToNumber(str.slice(0, 64)), hexToNumber(str.slice(64, 128))); 441 } 442 static fromDER(hex) { 443 const arr = hex instanceof Uint8Array; 444 if (typeof hex !== 'string' && !arr) 445 throw new TypeError(`Signature.fromDER: Expected string or Uint8Array`); 446 const { r, s } = parseDERSignature(arr ? hex : hexToBytes(hex)); 447 return new Signature(r, s); 448 } 449 static fromHex(hex) { 450 return this.fromDER(hex); 451 } 452 assertValidity() { 453 const { r, s } = this; 454 if (!isWithinCurveOrder(r)) 455 throw new Error('Invalid Signature: r must be 0 < r < n'); 456 if (!isWithinCurveOrder(s)) 457 throw new Error('Invalid Signature: s must be 0 < s < n'); 458 } 459 hasHighS() { 460 const HALF = CURVE.n >> _1n; 461 return this.s > HALF; 462 } 463 normalizeS() { 464 return this.hasHighS() ? new Signature(this.r, CURVE.n - this.s) : this; 465 } 466 toDERRawBytes(isCompressed = false) { 467 return hexToBytes(this.toDERHex(isCompressed)); 468 } 469 toDERHex(isCompressed = false) { 470 const sHex = sliceDER(numberToHexUnpadded(this.s)); 471 if (isCompressed) 472 return sHex; 473 const rHex = sliceDER(numberToHexUnpadded(this.r)); 474 const rLen = numberToHexUnpadded(rHex.length / 2); 475 const sLen = numberToHexUnpadded(sHex.length / 2); 476 const length = numberToHexUnpadded(rHex.length / 2 + sHex.length / 2 + 4); 477 return `30${length}02${rLen}${rHex}02${sLen}${sHex}`; 478 } 479 toRawBytes() { 480 return this.toDERRawBytes(); 481 } 482 toHex() { 483 return this.toDERHex(); 484 } 485 toCompactRawBytes() { 486 return hexToBytes(this.toCompactHex()); 487 } 488 toCompactHex() { 489 return numTo32bStr(this.r) + numTo32bStr(this.s); 490 } 491 } 492 function concatBytes(...arrays) { 493 if (!arrays.every((b) => b instanceof Uint8Array)) 494 throw new Error('Uint8Array list expected'); 495 if (arrays.length === 1) 496 return arrays[0]; 497 const length = arrays.reduce((a, arr) => a + arr.length, 0); 498 const result = new Uint8Array(length); 499 for (let i = 0, pad = 0; i < arrays.length; i++) { 500 const arr = arrays[i]; 501 result.set(arr, pad); 502 pad += arr.length; 503 } 504 return result; 505 } 506 const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0')); 507 function bytesToHex(uint8a) { 508 if (!(uint8a instanceof Uint8Array)) 509 throw new Error('Expected Uint8Array'); 510 let hex = ''; 511 for (let i = 0; i < uint8a.length; i++) { 512 hex += hexes[uint8a[i]]; 513 } 514 return hex; 515 } 516 const POW_2_256 = BigInt('0x10000000000000000000000000000000000000000000000000000000000000000'); 517 function numTo32bStr(num) { 518 if (typeof num !== 'bigint') 519 throw new Error('Expected bigint'); 520 if (!(_0n <= num && num < POW_2_256)) 521 throw new Error('Expected number < 2^256'); 522 return num.toString(16).padStart(64, '0'); 523 } 524 function numTo32b(num) { 525 const b = hexToBytes(numTo32bStr(num)); 526 if (b.length !== 32) 527 throw new Error('Error: expected 32 bytes'); 528 return b; 529 } 530 function numberToHexUnpadded(num) { 531 const hex = num.toString(16); 532 return hex.length & 1 ? `0${hex}` : hex; 533 } 534 function hexToNumber(hex) { 535 if (typeof hex !== 'string') { 536 throw new TypeError('hexToNumber: expected string, got ' + typeof hex); 537 } 538 return BigInt(`0x${hex}`); 539 } 540 function hexToBytes(hex) { 541 if (typeof hex !== 'string') { 542 throw new TypeError('hexToBytes: expected string, got ' + typeof hex); 543 } 544 if (hex.length % 2) 545 throw new Error('hexToBytes: received invalid unpadded hex' + hex.length); 546 const array = new Uint8Array(hex.length / 2); 547 for (let i = 0; i < array.length; i++) { 548 const j = i * 2; 549 const hexByte = hex.slice(j, j + 2); 550 const byte = Number.parseInt(hexByte, 16); 551 if (Number.isNaN(byte) || byte < 0) 552 throw new Error('Invalid byte sequence'); 553 array[i] = byte; 554 } 555 return array; 556 } 557 function bytesToNumber(bytes) { 558 return hexToNumber(bytesToHex(bytes)); 559 } 560 function ensureBytes(hex) { 561 return hex instanceof Uint8Array ? Uint8Array.from(hex) : hexToBytes(hex); 562 } 563 function normalizeScalar(num) { 564 if (typeof num === 'number' && Number.isSafeInteger(num) && num > 0) 565 return BigInt(num); 566 if (typeof num === 'bigint' && isWithinCurveOrder(num)) 567 return num; 568 throw new TypeError('Expected valid private scalar: 0 < scalar < curve.n'); 569 } 570 function mod(a, b = CURVE.P) { 571 const result = a % b; 572 return result >= _0n ? result : b + result; 573 } 574 function pow2(x, power) { 575 const { P } = CURVE; 576 let res = x; 577 while (power-- > _0n) { 578 res *= res; 579 res %= P; 580 } 581 return res; 582 } 583 function sqrtMod(x) { 584 const { P } = CURVE; 585 const _6n = BigInt(6); 586 const _11n = BigInt(11); 587 const _22n = BigInt(22); 588 const _23n = BigInt(23); 589 const _44n = BigInt(44); 590 const _88n = BigInt(88); 591 const b2 = (x * x * x) % P; 592 const b3 = (b2 * b2 * x) % P; 593 const b6 = (pow2(b3, _3n) * b3) % P; 594 const b9 = (pow2(b6, _3n) * b3) % P; 595 const b11 = (pow2(b9, _2n) * b2) % P; 596 const b22 = (pow2(b11, _11n) * b11) % P; 597 const b44 = (pow2(b22, _22n) * b22) % P; 598 const b88 = (pow2(b44, _44n) * b44) % P; 599 const b176 = (pow2(b88, _88n) * b88) % P; 600 const b220 = (pow2(b176, _44n) * b44) % P; 601 const b223 = (pow2(b220, _3n) * b3) % P; 602 const t1 = (pow2(b223, _23n) * b22) % P; 603 const t2 = (pow2(t1, _6n) * b2) % P; 604 return pow2(t2, _2n); 605 } 606 function invert(number, modulo = CURVE.P) { 607 if (number === _0n || modulo <= _0n) { 608 throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`); 609 } 610 let a = mod(number, modulo); 611 let b = modulo; 612 let x = _0n, u = _1n; 613 while (a !== _0n) { 614 const q = b / a; 615 const r = b % a; 616 const m = x - u * q; 617 b = a, a = r, x = u, u = m; 618 } 619 const gcd = b; 620 if (gcd !== _1n) 621 throw new Error('invert: does not exist'); 622 return mod(x, modulo); 623 } 624 function invertBatch(nums, p = CURVE.P) { 625 const scratch = new Array(nums.length); 626 const lastMultiplied = nums.reduce((acc, num, i) => { 627 if (num === _0n) 628 return acc; 629 scratch[i] = acc; 630 return mod(acc * num, p); 631 }, _1n); 632 const inverted = invert(lastMultiplied, p); 633 nums.reduceRight((acc, num, i) => { 634 if (num === _0n) 635 return acc; 636 scratch[i] = mod(acc * scratch[i], p); 637 return mod(acc * num, p); 638 }, inverted); 639 return scratch; 640 } 641 const divNearest = (a, b) => (a + b / _2n) / b; 642 const ENDO = { 643 a1: BigInt('0x3086d221a7d46bcde86c90e49284eb15'), 644 b1: -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3'), 645 a2: BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8'), 646 b2: BigInt('0x3086d221a7d46bcde86c90e49284eb15'), 647 POW_2_128: BigInt('0x100000000000000000000000000000000'), 648 }; 649 function splitScalarEndo(k) { 650 const { n } = CURVE; 651 const { a1, b1, a2, b2, POW_2_128 } = ENDO; 652 const c1 = divNearest(b2 * k, n); 653 const c2 = divNearest(-b1 * k, n); 654 let k1 = mod(k - c1 * a1 - c2 * a2, n); 655 let k2 = mod(-c1 * b1 - c2 * b2, n); 656 const k1neg = k1 > POW_2_128; 657 const k2neg = k2 > POW_2_128; 658 if (k1neg) 659 k1 = n - k1; 660 if (k2neg) 661 k2 = n - k2; 662 if (k1 > POW_2_128 || k2 > POW_2_128) { 663 throw new Error('splitScalarEndo: Endomorphism failed, k=' + k); 664 } 665 return { k1neg, k1, k2neg, k2 }; 666 } 667 function truncateHash(hash) { 668 const { n } = CURVE; 669 const byteLength = hash.length; 670 const delta = byteLength * 8 - 256; 671 let h = bytesToNumber(hash); 672 if (delta > 0) 673 h = h >> BigInt(delta); 674 if (h >= n) 675 h -= n; 676 return h; 677 } 678 let _sha256Sync; 679 let _hmacSha256Sync; 680 class HmacDrbg { 681 constructor() { 682 this.v = new Uint8Array(32).fill(1); 683 this.k = new Uint8Array(32).fill(0); 684 this.counter = 0; 685 } 686 hmac(...values) { 687 return utils.hmacSha256(this.k, ...values); 688 } 689 hmacSync(...values) { 690 return _hmacSha256Sync(this.k, ...values); 691 } 692 checkSync() { 693 if (typeof _hmacSha256Sync !== 'function') 694 throw new ShaError('hmacSha256Sync needs to be set'); 695 } 696 incr() { 697 if (this.counter >= 1000) 698 throw new Error('Tried 1,000 k values for sign(), all were invalid'); 699 this.counter += 1; 700 } 701 async reseed(seed = new Uint8Array()) { 702 this.k = await this.hmac(this.v, Uint8Array.from([0x00]), seed); 703 this.v = await this.hmac(this.v); 704 if (seed.length === 0) 705 return; 706 this.k = await this.hmac(this.v, Uint8Array.from([0x01]), seed); 707 this.v = await this.hmac(this.v); 708 } 709 reseedSync(seed = new Uint8Array()) { 710 this.checkSync(); 711 this.k = this.hmacSync(this.v, Uint8Array.from([0x00]), seed); 712 this.v = this.hmacSync(this.v); 713 if (seed.length === 0) 714 return; 715 this.k = this.hmacSync(this.v, Uint8Array.from([0x01]), seed); 716 this.v = this.hmacSync(this.v); 717 } 718 async generate() { 719 this.incr(); 720 this.v = await this.hmac(this.v); 721 return this.v; 722 } 723 generateSync() { 724 this.checkSync(); 725 this.incr(); 726 this.v = this.hmacSync(this.v); 727 return this.v; 728 } 729 } 730 function isWithinCurveOrder(num) { 731 return _0n < num && num < CURVE.n; 732 } 733 function isValidFieldElement(num) { 734 return _0n < num && num < CURVE.P; 735 } 736 function kmdToSig(kBytes, m, d) { 737 const k = bytesToNumber(kBytes); 738 if (!isWithinCurveOrder(k)) 739 return; 740 const { n } = CURVE; 741 const q = Point.BASE.multiply(k); 742 const r = mod(q.x, n); 743 if (r === _0n) 744 return; 745 const s = mod(invert(k, n) * mod(m + d * r, n), n); 746 if (s === _0n) 747 return; 748 const sig = new Signature(r, s); 749 const recovery = (q.x === sig.r ? 0 : 2) | Number(q.y & _1n); 750 return { sig, recovery }; 751 } 752 function normalizePrivateKey(key) { 753 let num; 754 if (typeof key === 'bigint') { 755 num = key; 756 } 757 else if (typeof key === 'number' && Number.isSafeInteger(key) && key > 0) { 758 num = BigInt(key); 759 } 760 else if (typeof key === 'string') { 761 if (key.length !== 64) 762 throw new Error('Expected 32 bytes of private key'); 763 num = hexToNumber(key); 764 } 765 else if (key instanceof Uint8Array) { 766 if (key.length !== 32) 767 throw new Error('Expected 32 bytes of private key'); 768 num = bytesToNumber(key); 769 } 770 else { 771 throw new TypeError('Expected valid private key'); 772 } 773 if (!isWithinCurveOrder(num)) 774 throw new Error('Expected private key: 0 < key < n'); 775 return num; 776 } 777 function normalizePublicKey(publicKey) { 778 if (publicKey instanceof Point) { 779 publicKey.assertValidity(); 780 return publicKey; 781 } 782 else { 783 return Point.fromHex(publicKey); 784 } 785 } 786 function normalizeSignature(signature) { 787 if (signature instanceof Signature) { 788 signature.assertValidity(); 789 return signature; 790 } 791 try { 792 return Signature.fromDER(signature); 793 } 794 catch (error) { 795 return Signature.fromCompact(signature); 796 } 797 } 798 function getPublicKey(privateKey, isCompressed = false) { 799 return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed); 800 } 801 function recoverPublicKey(msgHash, signature, recovery, isCompressed = false) { 802 return Point.fromSignature(msgHash, signature, recovery).toRawBytes(isCompressed); 803 } 804 function isProbPub(item) { 805 const arr = item instanceof Uint8Array; 806 const str = typeof item === 'string'; 807 const len = (arr || str) && item.length; 808 if (arr) 809 return len === 33 || len === 65; 810 if (str) 811 return len === 66 || len === 130; 812 if (item instanceof Point) 813 return true; 814 return false; 815 } 816 function getSharedSecret(privateA, publicB, isCompressed = false) { 817 if (isProbPub(privateA)) 818 throw new TypeError('getSharedSecret: first arg must be private key'); 819 if (!isProbPub(publicB)) 820 throw new TypeError('getSharedSecret: second arg must be public key'); 821 const b = normalizePublicKey(publicB); 822 b.assertValidity(); 823 return b.multiply(normalizePrivateKey(privateA)).toRawBytes(isCompressed); 824 } 825 function bits2int(bytes) { 826 const slice = bytes.length > 32 ? bytes.slice(0, 32) : bytes; 827 return bytesToNumber(slice); 828 } 829 function bits2octets(bytes) { 830 const z1 = bits2int(bytes); 831 const z2 = mod(z1, CURVE.n); 832 return int2octets(z2 < _0n ? z1 : z2); 833 } 834 function int2octets(num) { 835 return numTo32b(num); 836 } 837 function initSigArgs(msgHash, privateKey, extraEntropy) { 838 if (msgHash == null) 839 throw new Error(`sign: expected valid message hash, not "${msgHash}"`); 840 const h1 = ensureBytes(msgHash); 841 const d = normalizePrivateKey(privateKey); 842 const seedArgs = [int2octets(d), bits2octets(h1)]; 843 if (extraEntropy != null) { 844 if (extraEntropy === true) 845 extraEntropy = utils.randomBytes(32); 846 const e = ensureBytes(extraEntropy); 847 if (e.length !== 32) 848 throw new Error('sign: Expected 32 bytes of extra data'); 849 seedArgs.push(e); 850 } 851 const seed = concatBytes(...seedArgs); 852 const m = bits2int(h1); 853 return { seed, m, d }; 854 } 855 function finalizeSig(recSig, opts) { 856 let { sig, recovery } = recSig; 857 const { canonical, der, recovered } = Object.assign({ canonical: true, der: true }, opts); 858 if (canonical && sig.hasHighS()) { 859 sig = sig.normalizeS(); 860 recovery ^= 1; 861 } 862 const hashed = der ? sig.toDERRawBytes() : sig.toCompactRawBytes(); 863 return recovered ? [hashed, recovery] : hashed; 864 } 865 async function sign(msgHash, privKey, opts = {}) { 866 const { seed, m, d } = initSigArgs(msgHash, privKey, opts.extraEntropy); 867 let sig; 868 const drbg = new HmacDrbg(); 869 await drbg.reseed(seed); 870 while (!(sig = kmdToSig(await drbg.generate(), m, d))) 871 await drbg.reseed(); 872 return finalizeSig(sig, opts); 873 } 874 function signSync(msgHash, privKey, opts = {}) { 875 const { seed, m, d } = initSigArgs(msgHash, privKey, opts.extraEntropy); 876 let sig; 877 const drbg = new HmacDrbg(); 878 drbg.reseedSync(seed); 879 while (!(sig = kmdToSig(drbg.generateSync(), m, d))) 880 drbg.reseedSync(); 881 return finalizeSig(sig, opts); 882 } 883 const vopts = { strict: true }; 884 function verify(signature, msgHash, publicKey, opts = vopts) { 885 let sig; 886 try { 887 sig = normalizeSignature(signature); 888 msgHash = ensureBytes(msgHash); 889 } 890 catch (error) { 891 return false; 892 } 893 const { r, s } = sig; 894 if (opts.strict && sig.hasHighS()) 895 return false; 896 const h = truncateHash(msgHash); 897 let P; 898 try { 899 P = normalizePublicKey(publicKey); 900 } 901 catch (error) { 902 return false; 903 } 904 const { n } = CURVE; 905 const sinv = invert(s, n); 906 const u1 = mod(h * sinv, n); 907 const u2 = mod(r * sinv, n); 908 const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2); 909 if (!R) 910 return false; 911 const v = mod(R.x, n); 912 return v === r; 913 } 914 function schnorrChallengeFinalize(ch) { 915 return mod(bytesToNumber(ch), CURVE.n); 916 } 917 class SchnorrSignature { 918 constructor(r, s) { 919 this.r = r; 920 this.s = s; 921 this.assertValidity(); 922 } 923 static fromHex(hex) { 924 const bytes = ensureBytes(hex); 925 if (bytes.length !== 64) 926 throw new TypeError(`SchnorrSignature.fromHex: expected 64 bytes, not ${bytes.length}`); 927 const r = bytesToNumber(bytes.subarray(0, 32)); 928 const s = bytesToNumber(bytes.subarray(32, 64)); 929 return new SchnorrSignature(r, s); 930 } 931 assertValidity() { 932 const { r, s } = this; 933 if (!isValidFieldElement(r) || !isWithinCurveOrder(s)) 934 throw new Error('Invalid signature'); 935 } 936 toHex() { 937 return numTo32bStr(this.r) + numTo32bStr(this.s); 938 } 939 toRawBytes() { 940 return hexToBytes(this.toHex()); 941 } 942 } 943 function schnorrGetPublicKey(privateKey) { 944 return Point.fromPrivateKey(privateKey).toRawX(); 945 } 946 class InternalSchnorrSignature { 947 constructor(message, privateKey, auxRand = utils.randomBytes()) { 948 if (message == null) 949 throw new TypeError(`sign: Expected valid message, not "${message}"`); 950 this.m = ensureBytes(message); 951 const { x, scalar } = this.getScalar(normalizePrivateKey(privateKey)); 952 this.px = x; 953 this.d = scalar; 954 this.rand = ensureBytes(auxRand); 955 if (this.rand.length !== 32) 956 throw new TypeError('sign: Expected 32 bytes of aux randomness'); 957 } 958 getScalar(priv) { 959 const point = Point.fromPrivateKey(priv); 960 const scalar = point.hasEvenY() ? priv : CURVE.n - priv; 961 return { point, scalar, x: point.toRawX() }; 962 } 963 initNonce(d, t0h) { 964 return numTo32b(d ^ bytesToNumber(t0h)); 965 } 966 finalizeNonce(k0h) { 967 const k0 = mod(bytesToNumber(k0h), CURVE.n); 968 if (k0 === _0n) 969 throw new Error('sign: Creation of signature failed. k is zero'); 970 const { point: R, x: rx, scalar: k } = this.getScalar(k0); 971 return { R, rx, k }; 972 } 973 finalizeSig(R, k, e, d) { 974 return new SchnorrSignature(R.x, mod(k + e * d, CURVE.n)).toRawBytes(); 975 } 976 error() { 977 throw new Error('sign: Invalid signature produced'); 978 } 979 async calc() { 980 const { m, d, px, rand } = this; 981 const tag = utils.taggedHash; 982 const t = this.initNonce(d, await tag(TAGS.aux, rand)); 983 const { R, rx, k } = this.finalizeNonce(await tag(TAGS.nonce, t, px, m)); 984 const e = schnorrChallengeFinalize(await tag(TAGS.challenge, rx, px, m)); 985 const sig = this.finalizeSig(R, k, e, d); 986 if (!(await schnorrVerify(sig, m, px))) 987 this.error(); 988 return sig; 989 } 990 calcSync() { 991 const { m, d, px, rand } = this; 992 const tag = utils.taggedHashSync; 993 const t = this.initNonce(d, tag(TAGS.aux, rand)); 994 const { R, rx, k } = this.finalizeNonce(tag(TAGS.nonce, t, px, m)); 995 const e = schnorrChallengeFinalize(tag(TAGS.challenge, rx, px, m)); 996 const sig = this.finalizeSig(R, k, e, d); 997 if (!schnorrVerifySync(sig, m, px)) 998 this.error(); 999 return sig; 1000 } 1001 } 1002 async function schnorrSign(msg, privKey, auxRand) { 1003 return new InternalSchnorrSignature(msg, privKey, auxRand).calc(); 1004 } 1005 function schnorrSignSync(msg, privKey, auxRand) { 1006 return new InternalSchnorrSignature(msg, privKey, auxRand).calcSync(); 1007 } 1008 function initSchnorrVerify(signature, message, publicKey) { 1009 const raw = signature instanceof SchnorrSignature; 1010 const sig = raw ? signature : SchnorrSignature.fromHex(signature); 1011 if (raw) 1012 sig.assertValidity(); 1013 return { 1014 ...sig, 1015 m: ensureBytes(message), 1016 P: normalizePublicKey(publicKey), 1017 }; 1018 } 1019 function finalizeSchnorrVerify(r, P, s, e) { 1020 const R = Point.BASE.multiplyAndAddUnsafe(P, normalizePrivateKey(s), mod(-e, CURVE.n)); 1021 if (!R || !R.hasEvenY() || R.x !== r) 1022 return false; 1023 return true; 1024 } 1025 async function schnorrVerify(signature, message, publicKey) { 1026 try { 1027 const { r, s, m, P } = initSchnorrVerify(signature, message, publicKey); 1028 const e = schnorrChallengeFinalize(await utils.taggedHash(TAGS.challenge, numTo32b(r), P.toRawX(), m)); 1029 return finalizeSchnorrVerify(r, P, s, e); 1030 } 1031 catch (error) { 1032 return false; 1033 } 1034 } 1035 function schnorrVerifySync(signature, message, publicKey) { 1036 try { 1037 const { r, s, m, P } = initSchnorrVerify(signature, message, publicKey); 1038 const e = schnorrChallengeFinalize(utils.taggedHashSync(TAGS.challenge, numTo32b(r), P.toRawX(), m)); 1039 return finalizeSchnorrVerify(r, P, s, e); 1040 } 1041 catch (error) { 1042 if (error instanceof ShaError) 1043 throw error; 1044 return false; 1045 } 1046 } 1047 const schnorr = { 1048 Signature: SchnorrSignature, 1049 getPublicKey: schnorrGetPublicKey, 1050 sign: schnorrSign, 1051 verify: schnorrVerify, 1052 signSync: schnorrSignSync, 1053 verifySync: schnorrVerifySync, 1054 }; 1055 Point.BASE._setWindowSize(8); 1056 const crypto = { 1057 node: nodeCrypto, 1058 web: typeof self === 'object' && 'crypto' in self ? self.crypto : undefined, 1059 }; 1060 const TAGS = { 1061 challenge: 'BIP0340/challenge', 1062 aux: 'BIP0340/aux', 1063 nonce: 'BIP0340/nonce', 1064 }; 1065 const TAGGED_HASH_PREFIXES = {}; 1066 const utils = { 1067 bytesToHex, 1068 hexToBytes, 1069 concatBytes, 1070 mod, 1071 invert, 1072 isValidPrivateKey(privateKey) { 1073 try { 1074 normalizePrivateKey(privateKey); 1075 return true; 1076 } 1077 catch (error) { 1078 return false; 1079 } 1080 }, 1081 _bigintTo32Bytes: numTo32b, 1082 _normalizePrivateKey: normalizePrivateKey, 1083 hashToPrivateKey: (hash) => { 1084 hash = ensureBytes(hash); 1085 if (hash.length < 40 || hash.length > 1024) 1086 throw new Error('Expected 40-1024 bytes of private key as per FIPS 186'); 1087 const num = mod(bytesToNumber(hash), CURVE.n - _1n) + _1n; 1088 return numTo32b(num); 1089 }, 1090 randomBytes: (bytesLength = 32) => { 1091 if (crypto.web) { 1092 return crypto.web.getRandomValues(new Uint8Array(bytesLength)); 1093 } 1094 else if (crypto.node) { 1095 const { randomBytes } = crypto.node; 1096 return Uint8Array.from(randomBytes(bytesLength)); 1097 } 1098 else { 1099 throw new Error("The environment doesn't have randomBytes function"); 1100 } 1101 }, 1102 randomPrivateKey: () => { 1103 return utils.hashToPrivateKey(utils.randomBytes(40)); 1104 }, 1105 sha256: async (...messages) => { 1106 if (crypto.web) { 1107 const buffer = await crypto.web.subtle.digest('SHA-256', concatBytes(...messages)); 1108 return new Uint8Array(buffer); 1109 } 1110 else if (crypto.node) { 1111 const { createHash } = crypto.node; 1112 const hash = createHash('sha256'); 1113 messages.forEach((m) => hash.update(m)); 1114 return Uint8Array.from(hash.digest()); 1115 } 1116 else { 1117 throw new Error("The environment doesn't have sha256 function"); 1118 } 1119 }, 1120 hmacSha256: async (key, ...messages) => { 1121 if (crypto.web) { 1122 const ckey = await crypto.web.subtle.importKey('raw', key, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']); 1123 const message = concatBytes(...messages); 1124 const buffer = await crypto.web.subtle.sign('HMAC', ckey, message); 1125 return new Uint8Array(buffer); 1126 } 1127 else if (crypto.node) { 1128 const { createHmac } = crypto.node; 1129 const hash = createHmac('sha256', key); 1130 messages.forEach((m) => hash.update(m)); 1131 return Uint8Array.from(hash.digest()); 1132 } 1133 else { 1134 throw new Error("The environment doesn't have hmac-sha256 function"); 1135 } 1136 }, 1137 sha256Sync: undefined, 1138 hmacSha256Sync: undefined, 1139 taggedHash: async (tag, ...messages) => { 1140 let tagP = TAGGED_HASH_PREFIXES[tag]; 1141 if (tagP === undefined) { 1142 const tagH = await utils.sha256(Uint8Array.from(tag, (c) => c.charCodeAt(0))); 1143 tagP = concatBytes(tagH, tagH); 1144 TAGGED_HASH_PREFIXES[tag] = tagP; 1145 } 1146 return utils.sha256(tagP, ...messages); 1147 }, 1148 taggedHashSync: (tag, ...messages) => { 1149 if (typeof _sha256Sync !== 'function') 1150 throw new ShaError('sha256Sync is undefined, you need to set it'); 1151 let tagP = TAGGED_HASH_PREFIXES[tag]; 1152 if (tagP === undefined) { 1153 const tagH = _sha256Sync(Uint8Array.from(tag, (c) => c.charCodeAt(0))); 1154 tagP = concatBytes(tagH, tagH); 1155 TAGGED_HASH_PREFIXES[tag] = tagP; 1156 } 1157 return _sha256Sync(tagP, ...messages); 1158 }, 1159 precompute(windowSize = 8, point = Point.BASE) { 1160 const cached = point === Point.BASE ? point : new Point(point.x, point.y); 1161 cached._setWindowSize(windowSize); 1162 cached.multiply(_3n); 1163 return cached; 1164 }, 1165 }; 1166 Object.defineProperties(utils, { 1167 sha256Sync: { 1168 configurable: false, 1169 get() { 1170 return _sha256Sync; 1171 }, 1172 set(val) { 1173 if (!_sha256Sync) 1174 _sha256Sync = val; 1175 }, 1176 }, 1177 hmacSha256Sync: { 1178 configurable: false, 1179 get() { 1180 return _hmacSha256Sync; 1181 }, 1182 set(val) { 1183 if (!_hmacSha256Sync) 1184 _hmacSha256Sync = val; 1185 }, 1186 }, 1187 }); 1188 1189 exports.CURVE = CURVE; 1190 exports.Point = Point; 1191 exports.Signature = Signature; 1192 exports.getPublicKey = getPublicKey; 1193 exports.getSharedSecret = getSharedSecret; 1194 exports.recoverPublicKey = recoverPublicKey; 1195 exports.schnorr = schnorr; 1196 exports.sign = sign; 1197 exports.signSync = signSync; 1198 exports.utils = utils; 1199 exports.verify = verify; 1200 1201 Object.defineProperty(exports, '__esModule', { value: true }); 1202 1203 }));