UNPKG

node-rsa

Version:

RSA library for Node.js and browsers

2,041 lines (2,034 loc) 116 kB
import { sha1, ripemd160, md5 } from '@noble/hashes/legacy.js'; import { sha512, sha384, sha256, sha224 } from '@noble/hashes/sha2.js'; // src/bigint/big-integer-jsbn.ts var _backend; function setBigIntegerBackend(backend) { _backend = backend; } function getBackend() { if (!_backend) { throw new Error( "BigInteger crypto backend not initialized. Did you import from src/index.node.ts or src/index.browser.ts?" ); } return _backend; } var DB = 28; var DM = (1 << DB) - 1; var DV = 1 << DB; var BI_FP = 52; var FV = 2 ** BI_FP; var F1 = BI_FP - DB; var F2 = 2 * DB - BI_FP; var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz"; var BI_RC = []; { let rr = "0".charCodeAt(0); for (let vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv; rr = "a".charCodeAt(0); for (let vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv; rr = "A".charCodeAt(0); for (let vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv; } function int2char(n) { return BI_RM.charAt(n); } function intAt(s, i) { const c = BI_RC[s.charCodeAt(i)]; return c == null ? -1 : c; } function nbits(x) { let r = 1; let t; if ((t = x >>> 16) !== 0) { x = t; r += 16; } if ((t = x >> 8) !== 0) { x = t; r += 8; } if ((t = x >> 4) !== 0) { x = t; r += 4; } if ((t = x >> 2) !== 0) { x = t; r += 2; } if ((t = x >> 1) !== 0) { r += 1; } return r; } function lbit(x) { if (x === 0) return -1; let r = 0; if ((x & 65535) === 0) { x >>= 16; r += 16; } if ((x & 255) === 0) { x >>= 8; r += 8; } if ((x & 15) === 0) { x >>= 4; r += 4; } if ((x & 3) === 0) { x >>= 2; r += 2; } if ((x & 1) === 0) ++r; return r; } function cbit(x) { let r = 0; while (x !== 0) { x &= x - 1; ++r; } return r; } var BigInteger = class _BigInteger { /** @internal */ t = 0; /** @internal */ s = 0; // Mirror legacy `this.DB`/`this.DM`/etc. access patterns /** @internal */ DB = DB; /** @internal */ DM = DM; /** @internal */ DV = DV; /** @internal */ FV = FV; /** @internal */ F1 = F1; /** @internal */ F2 = F2; static ZERO; static ONE; /** @internal */ static int2char = int2char; constructor(a, b, unsigned) { if (a == null) return; if (typeof a === "number") { this.fromNumber(a, b); } else if (a instanceof Uint8Array) { this.fromBuffer(a); } else if (typeof a === "string") { this.fromString(a, b, unsigned); } else if (Array.isArray(a)) { this.fromByteArray(a, unsigned); } } // am3: multiply-accumulate (digit-base 2^28) /** @internal */ am(i, x, w, j, c, n) { const xl = x & 16383; const xh = x >> 14; while (--n >= 0) { let l = this[i] & 16383; const h = this[i++] >> 14; const m = xh * l + h * xl; l = xl * l + ((m & 16383) << 14) + w[j] + c; c = (l >> 28) + (m >> 14) + xh * h; w[j++] = l & 268435455; } return c; } // protected: digit/byte initialisation /** @internal */ copyTo(r) { for (let i = this.t - 1; i >= 0; --i) r[i] = this[i]; r.t = this.t; r.s = this.s; } /** @internal */ fromInt(x) { this.t = 1; this.s = x < 0 ? -1 : 0; if (x > 0) this[0] = x; else if (x < -1) this[0] = x + DV; else this.t = 0; } /** @internal */ fromString(data, radix, unsigned) { let k; switch (radix) { case 2: k = 1; break; case 4: k = 2; break; case 8: k = 3; break; case 16: k = 4; break; case 32: k = 5; break; case 256: k = 8; break; default: this.fromRadix(data, radix); return; } this.t = 0; this.s = 0; const dataAny = data; let i = dataAny.length; let mi = false; let sh = 0; while (--i >= 0) { const x = k === 8 ? dataAny[i] & 255 : intAt(data, i); if (x < 0) { if (dataAny.charAt && dataAny.charAt(i) === "-") mi = true; continue; } mi = false; if (sh === 0) this[this.t++] = x; else if (sh + k > this.DB) { this[this.t - 1] = (this[this.t - 1] | (x & (1 << this.DB - sh) - 1) << sh) >>> 0; this[this.t++] = x >> this.DB - sh; } else { this[this.t - 1] = (this[this.t - 1] | x << sh) >>> 0; } sh += k; if (sh >= this.DB) sh -= this.DB; } if (!unsigned && k === 8 && (dataAny[0] & 128) !== 0) { this.s = -1; if (sh > 0) this[this.t - 1] = (this[this.t - 1] | (1 << this.DB - sh) - 1 << sh) >>> 0; } this.clamp(); if (mi) _BigInteger.ZERO.subTo(this, this); } /** @internal */ fromByteArray(a, unsigned) { this.fromString(a, 256, unsigned); } /** @internal */ fromBuffer(a) { this.fromString(a, 256, true); } /** @internal */ clamp() { const c = this.s & this.DM; while (this.t > 0 && this[this.t - 1] === c) --this.t; } // arithmetic on internal digits /** @internal */ dlShiftTo(n, r) { let i; for (i = this.t - 1; i >= 0; --i) r[i + n] = this[i]; for (i = n - 1; i >= 0; --i) r[i] = 0; r.t = this.t + n; r.s = this.s; } /** @internal */ drShiftTo(n, r) { for (let i = n; i < this.t; ++i) r[i - n] = this[i]; r.t = Math.max(this.t - n, 0); r.s = this.s; } /** @internal */ lShiftTo(n, r) { const bs = n % this.DB; const cbs = this.DB - bs; const bm = (1 << cbs) - 1; const ds = Math.floor(n / this.DB); let c = this.s << bs & this.DM; let i; for (i = this.t - 1; i >= 0; --i) { r[i + ds + 1] = this[i] >> cbs | c; c = (this[i] & bm) << bs; } for (i = ds - 1; i >= 0; --i) r[i] = 0; r[ds] = c; r.t = this.t + ds + 1; r.s = this.s; r.clamp(); } /** @internal */ rShiftTo(n, r) { r.s = this.s; const ds = Math.floor(n / this.DB); if (ds >= this.t) { r.t = 0; return; } const bs = n % this.DB; const cbs = this.DB - bs; const bm = (1 << bs) - 1; r[0] = this[ds] >> bs; for (let i = ds + 1; i < this.t; ++i) { r[i - ds - 1] = (r[i - ds - 1] ?? 0) | (this[i] & bm) << cbs; r[i - ds] = this[i] >> bs; } if (bs > 0) r[this.t - ds - 1] = (r[this.t - ds - 1] ?? 0) | (this.s & bm) << cbs; r.t = this.t - ds; r.clamp(); } /** @internal */ subTo(a, r) { let i = 0; let c = 0; const m = Math.min(a.t, this.t); while (i < m) { c += this[i] - a[i]; r[i++] = c & this.DM; c >>= this.DB; } if (a.t < this.t) { c -= a.s; while (i < this.t) { c += this[i]; r[i++] = c & this.DM; c >>= this.DB; } c += this.s; } else { c += this.s; while (i < a.t) { c -= a[i]; r[i++] = c & this.DM; c >>= this.DB; } c -= a.s; } r.s = c < 0 ? -1 : 0; if (c < -1) r[i++] = this.DV + c; else if (c > 0) r[i++] = c; r.t = i; r.clamp(); } /** @internal */ multiplyTo(a, r) { const x = this.abs(); const y = a.abs(); let i = x.t; r.t = i + y.t; while (--i >= 0) r[i] = 0; for (i = 0; i < y.t; ++i) r[i + x.t] = x.am(0, y[i], r, i, 0, x.t); r.s = 0; r.clamp(); if (this.s !== a.s) _BigInteger.ZERO.subTo(r, r); } /** @internal */ squareTo(r) { const x = this.abs(); let i = r.t = 2 * x.t; while (--i >= 0) r[i] = 0; for (i = 0; i < x.t - 1; ++i) { const c = x.am(i, x[i], r, 2 * i, 0, 1); if ((r[i + x.t] = (r[i + x.t] ?? 0) + x.am(i + 1, 2 * x[i], r, 2 * i + 1, c, x.t - i - 1)) >= x.DV) { r[i + x.t] = r[i + x.t] - x.DV; r[i + x.t + 1] = 1; } } if (r.t > 0) r[r.t - 1] = (r[r.t - 1] ?? 0) + x.am(i, x[i], r, 2 * i, 0, 1); r.s = 0; r.clamp(); } /** @internal */ divRemTo(m, q, r) { const pm = m.abs(); if (pm.t <= 0) return; const pt = this.abs(); if (pt.t < pm.t) { if (q != null) q.fromInt(0); if (r != null) this.copyTo(r); return; } if (r == null) r = nbi(); const y = nbi(); const ts = this.s; const ms = m.s; const nsh = this.DB - nbits(pm[pm.t - 1]); if (nsh > 0) { pm.lShiftTo(nsh, y); pt.lShiftTo(nsh, r); } else { pm.copyTo(y); pt.copyTo(r); } const ys = y.t; const y0 = y[ys - 1]; if (y0 === 0) return; const yt = y0 * (1 << this.F1) + (ys > 1 ? y[ys - 2] >> this.F2 : 0); const d1 = this.FV / yt; const d2 = (1 << this.F1) / yt; const e = 1 << this.F2; let i = r.t; let j = i - ys; const t = q == null ? nbi() : q; y.dlShiftTo(j, t); if (r.compareTo(t) >= 0) { r[r.t++] = 1; r.subTo(t, r); } _BigInteger.ONE.dlShiftTo(ys, t); t.subTo(y, y); while (y.t < ys) y[y.t++] = 0; while (--j >= 0) { let qd = r[--i] === y0 ? this.DM : Math.floor(r[i] * d1 + (r[i - 1] + e) * d2); if ((r[i] = r[i] + y.am(0, qd, r, j, 0, ys)) < qd) { y.dlShiftTo(j, t); r.subTo(t, r); while (r[i] < --qd) r.subTo(t, r); } } if (q != null) { r.drShiftTo(ys, q); if (ts !== ms) _BigInteger.ZERO.subTo(q, q); } r.t = ys; r.clamp(); if (nsh > 0) r.rShiftTo(nsh, r); if (ts < 0) _BigInteger.ZERO.subTo(r, r); } /** @internal */ invDigit() { if (this.t < 1) return 0; const x = this[0]; if ((x & 1) === 0) return 0; let y = x & 3; y = y * (2 - (x & 15) * y) & 15; y = y * (2 - (x & 255) * y) & 255; y = y * (2 - ((x & 65535) * y & 65535)) & 65535; y = y * (2 - x * y % this.DV) % this.DV; return y > 0 ? this.DV - y : -y; } isEven() { return ((this.t > 0 ? this[0] & 1 : this.s) & 1) === 0; } /** @internal */ exp(e, z) { if (e > 4294967295 || e < 1) return _BigInteger.ONE; let r = nbi(); let r2 = nbi(); const g = z.convert(this); let i = nbits(e) - 1; g.copyTo(r); while (--i >= 0) { z.sqrTo(r, r2); if ((e & 1 << i) > 0) z.mulTo(r2, g, r); else { const tmp = r; r = r2; r2 = tmp; } } return z.revert(r); } // public arithmetic & comparisons toString(b) { if (this.s < 0) return `-${this.negate().toString(b)}`; let k; if (b === 16) k = 4; else if (b === 8) k = 3; else if (b === 2) k = 1; else if (b === 32) k = 5; else if (b === 4) k = 2; else return this.toRadix(b); const km = (1 << k) - 1; let d; let m = false; let r = ""; let i = this.t; let p = this.DB - i * this.DB % k; if (i-- > 0) { if (p < this.DB && (d = this[i] >> p) > 0) { m = true; r = int2char(d); } while (i >= 0) { if (p < k) { d = (this[i] & (1 << p) - 1) << k - p; d |= this[--i] >> (p += this.DB - k); } else { d = this[i] >> (p -= k) & km; if (p <= 0) { p += this.DB; --i; } } if (d > 0) m = true; if (m) r += int2char(d); } } return m ? r : "0"; } /** @internal */ negate() { const r = nbi(); _BigInteger.ZERO.subTo(this, r); return r; } abs() { return this.s < 0 ? this.negate() : this; } compareTo(a) { let r = this.s - a.s; if (r !== 0) return r; let i = this.t; r = i - a.t; if (r !== 0) return this.s < 0 ? -r : r; while (--i >= 0) if ((r = this[i] - a[i]) !== 0) return r; return 0; } bitLength() { if (this.t <= 0) return 0; return this.DB * (this.t - 1) + nbits(this[this.t - 1] ^ this.s & this.DM); } mod(a) { const r = nbi(); this.abs().divRemTo(a, null, r); if (this.s < 0 && r.compareTo(_BigInteger.ZERO) > 0) a.subTo(r, r); return r; } modPowInt(e, m) { const z = e < 256 || m.isEven() ? new Classic(m) : new Montgomery(m); return this.exp(e, z); } // extended functions /** @internal */ clone() { const r = nbi(); this.copyTo(r); return r; } /** @internal */ intValue() { if (this.s < 0) { if (this.t === 1) return this[0] - this.DV; if (this.t === 0) return -1; } else if (this.t === 1) return this[0]; else if (this.t === 0) return 0; return (this[1] & (1 << 32 - this.DB) - 1) << this.DB | this[0]; } /** @internal */ byteValue() { return this.t === 0 ? this.s : this[0] << 24 >> 24; } /** @internal */ shortValue() { return this.t === 0 ? this.s : this[0] << 16 >> 16; } /** @internal */ chunkSize(r) { return Math.floor(Math.LN2 * this.DB / Math.log(r)); } signum() { if (this.s < 0) return -1; if (this.t <= 0 || this.t === 1 && this[0] <= 0) return 0; return 1; } /** @internal */ toRadix(b) { const base = b ?? 10; if (this.signum() === 0 || base < 2 || base > 36) return "0"; const cs = this.chunkSize(base); const a = base ** cs; const d = nbv(a); const y = nbi(); const z = nbi(); let r = ""; this.divRemTo(d, y, z); while (y.signum() > 0) { r = (a + z.intValue()).toString(base).slice(1) + r; y.divRemTo(d, y, z); } return z.intValue().toString(base) + r; } /** @internal */ fromRadix(s, b) { this.fromInt(0); const base = b ?? 10; const cs = this.chunkSize(base); const d = base ** cs; let mi = false; let j = 0; let w = 0; for (let i = 0; i < s.length; ++i) { const x = intAt(s, i); if (x < 0) { if (s.charAt(i) === "-" && this.signum() === 0) mi = true; continue; } w = base * w + x; if (++j >= cs) { this.dMultiply(d); this.dAddOffset(w, 0); j = 0; w = 0; } } if (j > 0) { this.dMultiply(base ** j); this.dAddOffset(w, 0); } if (mi) _BigInteger.ZERO.subTo(this, this); } /** @internal */ fromNumber(a, b) { if (typeof b === "number") { if (a < 2) this.fromInt(1); else { this.fromNumber(a); if (!this.testBit(a - 1)) { this.bitwiseTo(_BigInteger.ONE.shiftLeft(a - 1), op_or, this); } if (this.isEven()) this.dAddOffset(1, 0); while (!this.isProbablePrime(b)) { this.dAddOffset(2, 0); if (this.bitLength() > a) this.subTo(_BigInteger.ONE.shiftLeft(a - 1), this); } } } else { const x = getBackend().randomBytes((a >> 3) + 1); const t = a & 7; const bytes = new Uint8Array(x); if (t > 0) bytes[0] = bytes[0] & (1 << t) - 1; else bytes[0] = 0; this.fromByteArray(Array.from(bytes)); } } /** @internal */ toByteArray() { let i = this.t; const r = []; r[0] = this.s; let p = this.DB - i * this.DB % 8; let d; let k = 0; if (i-- > 0) { if (p < this.DB && (d = this[i] >> p) !== (this.s & this.DM) >> p) { r[k++] = d | this.s << this.DB - p; } while (i >= 0) { if (p < 8) { d = (this[i] & (1 << p) - 1) << 8 - p; d |= this[--i] >> (p += this.DB - 8); } else { d = this[i] >> (p -= 8) & 255; if (p <= 0) { p += this.DB; --i; } } if ((d & 128) !== 0) d |= -256; if (k === 0 && (this.s & 128) !== (d & 128)) ++k; if (k > 0 || d !== this.s) r[k++] = d; } } return r; } /** * Return a Uint8Array of this integer in big-endian unsigned form. * * - `trimOrSize === true`: drop a leading 0x00 sign byte if present. * - `trimOrSize` is a positive integer: left-pad or trim leading zeros to * produce exactly `trimOrSize` bytes. Returns null if trimming would * discard a non-zero byte (i.e., the value doesn't fit). * - Otherwise: return the raw two's-complement byte array with possible * leading 0x00 sign byte. */ toBuffer(trimOrSize) { let res = Uint8Array.from(this.toByteArray().map((b) => b & 255)); if (trimOrSize === true && res.length > 0 && res[0] === 0) { res = res.subarray(1); } else if (typeof trimOrSize === "number") { if (res.length > trimOrSize) { const excess = res.length - trimOrSize; for (let i = 0; i < excess; i++) { if (res[i] !== 0) return null; } return res.subarray(excess).slice(); } if (res.length < trimOrSize) { const padded = new Uint8Array(trimOrSize); padded.set(res, trimOrSize - res.length); return padded; } } return res.slice(); } /** @internal */ equals(a) { return this.compareTo(a) === 0; } /** @internal */ min(a) { return this.compareTo(a) < 0 ? this : a; } /** @internal */ max(a) { return this.compareTo(a) > 0 ? this : a; } /** @internal */ bitwiseTo(a, op, r) { let i; let f; const m = Math.min(a.t, this.t); for (i = 0; i < m; ++i) r[i] = op(this[i], a[i]); if (a.t < this.t) { f = a.s & this.DM; for (i = m; i < this.t; ++i) r[i] = op(this[i], f); r.t = this.t; } else { f = this.s & this.DM; for (i = m; i < a.t; ++i) r[i] = op(f, a[i]); r.t = a.t; } r.s = op(this.s, a.s); r.clamp(); } /** @internal */ and(a) { const r = nbi(); this.bitwiseTo(a, op_and, r); return r; } /** @internal */ or(a) { const r = nbi(); this.bitwiseTo(a, op_or, r); return r; } /** @internal */ xor(a) { const r = nbi(); this.bitwiseTo(a, op_xor, r); return r; } /** @internal */ andNot(a) { const r = nbi(); this.bitwiseTo(a, op_andnot, r); return r; } /** @internal */ not() { const r = nbi(); for (let i = 0; i < this.t; ++i) r[i] = this.DM & ~this[i]; r.t = this.t; r.s = ~this.s; return r; } shiftLeft(n) { const r = nbi(); if (n < 0) this.rShiftTo(-n, r); else this.lShiftTo(n, r); return r; } shiftRight(n) { const r = nbi(); if (n < 0) this.lShiftTo(-n, r); else this.rShiftTo(n, r); return r; } /** @internal */ getLowestSetBit() { for (let i = 0; i < this.t; ++i) if (this[i] !== 0) return i * this.DB + lbit(this[i]); if (this.s < 0) return this.t * this.DB; return -1; } /** @internal */ bitCount() { let r = 0; const x = this.s & this.DM; for (let i = 0; i < this.t; ++i) r += cbit(this[i] ^ x); return r; } testBit(n) { const j = Math.floor(n / this.DB); if (j >= this.t) return this.s !== 0; return (this[j] & 1 << n % this.DB) !== 0; } /** @internal */ changeBit(n, op) { const r = _BigInteger.ONE.shiftLeft(n); this.bitwiseTo(r, op, r); return r; } /** @internal */ setBit(n) { return this.changeBit(n, op_or); } /** @internal */ clearBit(n) { return this.changeBit(n, op_andnot); } /** @internal */ flipBit(n) { return this.changeBit(n, op_xor); } /** @internal */ addTo(a, r) { let i = 0; let c = 0; const m = Math.min(a.t, this.t); while (i < m) { c += this[i] + a[i]; r[i++] = c & this.DM; c >>= this.DB; } if (a.t < this.t) { c += a.s; while (i < this.t) { c += this[i]; r[i++] = c & this.DM; c >>= this.DB; } c += this.s; } else { c += this.s; while (i < a.t) { c += a[i]; r[i++] = c & this.DM; c >>= this.DB; } c += a.s; } r.s = c < 0 ? -1 : 0; if (c > 0) r[i++] = c; else if (c < -1) r[i++] = this.DV + c; r.t = i; r.clamp(); } add(a) { const r = nbi(); this.addTo(a, r); return r; } subtract(a) { const r = nbi(); this.subTo(a, r); return r; } multiply(a) { const r = nbi(); this.multiplyTo(a, r); return r; } square() { const r = nbi(); this.squareTo(r); return r; } /** @internal */ divide(a) { const r = nbi(); this.divRemTo(a, r, null); return r; } /** @internal */ remainder(a) { const r = nbi(); this.divRemTo(a, null, r); return r; } divideAndRemainder(a) { const q = nbi(); const r = nbi(); this.divRemTo(a, q, r); return [q, r]; } /** @internal */ dMultiply(n) { this[this.t] = this.am(0, n - 1, this, 0, 0, this.t); ++this.t; this.clamp(); } /** @internal */ dAddOffset(n, w) { if (n === 0) return; while (this.t <= w) this[this.t++] = 0; this[w] = this[w] + n; while (this[w] >= this.DV) { this[w] = this[w] - this.DV; if (++w >= this.t) this[this.t++] = 0; this[w] = (this[w] ?? 0) + 1; } } /** @internal */ pow(e) { return this.exp(e, new NullExp()); } /** @internal */ multiplyLowerTo(a, n, r) { let i = Math.min(this.t + a.t, n); r.s = 0; r.t = i; while (i > 0) r[--i] = 0; let j; for (j = r.t - this.t; i < j; ++i) r[i + this.t] = this.am(0, a[i], r, i, 0, this.t); for (j = Math.min(a.t, n); i < j; ++i) this.am(0, a[i], r, i, 0, n - i); r.clamp(); } /** @internal */ multiplyUpperTo(a, n, r) { --n; let i = r.t = this.t + a.t - n; r.s = 0; while (--i >= 0) r[i] = 0; for (i = Math.max(n - this.t, 0); i < a.t; ++i) { r[this.t + i - n] = this.am(n - i, a[i], r, 0, 0, this.t + i - n); } r.clamp(); r.drShiftTo(1, r); } modPow(e, m) { let i = e.bitLength(); let k; let r = nbv(1); let z; if (i <= 0) return r; if (i < 18) k = 1; else if (i < 48) k = 3; else if (i < 144) k = 4; else if (i < 768) k = 5; else k = 6; if (i < 8) z = new Classic(m); else if (m.isEven()) z = new Barrett(m); else z = new Montgomery(m); const g = []; let n = 3; const k1 = k - 1; const km = (1 << k) - 1; g[1] = z.convert(this); if (k > 1) { const g2 = nbi(); z.sqrTo(g[1], g2); while (n <= km) { g[n] = nbi(); z.mulTo(g2, g[n - 2], g[n]); n += 2; } } let j = e.t - 1; let w; let is1 = true; let r2 = nbi(); let t; i = nbits(e[j]) - 1; while (j >= 0) { if (i >= k1) w = e[j] >> i - k1 & km; else { w = (e[j] & (1 << i + 1) - 1) << k1 - i; if (j > 0) w |= e[j - 1] >> this.DB + i - k1; } n = k; while ((w & 1) === 0) { w >>= 1; --n; } if ((i -= n) < 0) { i += this.DB; --j; } if (is1) { g[w].copyTo(r); is1 = false; } else { while (n > 1) { z.sqrTo(r, r2); z.sqrTo(r2, r); n -= 2; } if (n > 0) z.sqrTo(r, r2); else { t = r; r = r2; r2 = t; } z.mulTo(r2, g[w], r); } while (j >= 0 && (e[j] & 1 << i) === 0) { z.sqrTo(r, r2); t = r; r = r2; r2 = t; if (--i < 0) { i = this.DB - 1; --j; } } } return z.revert(r); } gcd(a) { let x = this.s < 0 ? this.negate() : this.clone(); let y = a.s < 0 ? a.negate() : a.clone(); if (x.compareTo(y) < 0) { [x, y] = [y, x]; } let i = x.getLowestSetBit(); let g = y.getLowestSetBit(); if (g < 0) return x; if (i < g) g = i; if (g > 0) { x.rShiftTo(g, x); y.rShiftTo(g, y); } while (x.signum() > 0) { if ((i = x.getLowestSetBit()) > 0) x.rShiftTo(i, x); if ((i = y.getLowestSetBit()) > 0) y.rShiftTo(i, y); if (x.compareTo(y) >= 0) { x.subTo(y, x); x.rShiftTo(1, x); } else { y.subTo(x, y); y.rShiftTo(1, y); } } if (g > 0) y.lShiftTo(g, y); return y; } /** @internal */ modInt(n) { if (n <= 0) return 0; const d = this.DV % n; let r = this.s < 0 ? n - 1 : 0; if (this.t > 0) { if (d === 0) r = this[0] % n; else for (let i = this.t - 1; i >= 0; --i) r = (d * r + this[i]) % n; } return r; } modInverse(m) { const ac = m.isEven(); if (this.isEven() && ac || m.signum() === 0) return _BigInteger.ZERO; const u = m.clone(); const v = this.clone(); const a = nbv(1); const b = nbv(0); const c = nbv(0); const d = nbv(1); while (u.signum() !== 0) { while (u.isEven()) { u.rShiftTo(1, u); if (ac) { if (!a.isEven() || !b.isEven()) { a.addTo(this, a); b.subTo(m, b); } a.rShiftTo(1, a); } else if (!b.isEven()) b.subTo(m, b); b.rShiftTo(1, b); } while (v.isEven()) { v.rShiftTo(1, v); if (ac) { if (!c.isEven() || !d.isEven()) { c.addTo(this, c); d.subTo(m, d); } c.rShiftTo(1, c); } else if (!d.isEven()) d.subTo(m, d); d.rShiftTo(1, d); } if (u.compareTo(v) >= 0) { u.subTo(v, u); if (ac) a.subTo(c, a); b.subTo(d, b); } else { v.subTo(u, v); if (ac) c.subTo(a, c); d.subTo(b, d); } } if (v.compareTo(_BigInteger.ONE) !== 0) return _BigInteger.ZERO; if (d.compareTo(m) >= 0) return d.subtract(m); if (d.signum() < 0) d.addTo(m, d); else return d; if (d.signum() < 0) return d.add(m); return d; } isProbablePrime(t) { let i; const x = this.abs(); if (x.t === 1 && x[0] <= lowprimes[lowprimes.length - 1]) { for (i = 0; i < lowprimes.length; ++i) if (x[0] === lowprimes[i]) return true; return false; } if (x.isEven()) return false; i = 1; while (i < lowprimes.length) { let m = lowprimes[i]; let j = i + 1; while (j < lowprimes.length && m < lplim) m *= lowprimes[j++]; m = x.modInt(m); while (i < j) if (m % lowprimes[i++] === 0) return false; } return x.millerRabin(t); } /** @internal */ millerRabin(t) { const n1 = this.subtract(_BigInteger.ONE); const k = n1.getLowestSetBit(); if (k <= 0) return false; const r = n1.shiftRight(k); const two = nbv(2); const nMinus3 = n1.subtract(two); const byteLen = (this.bitLength() + 7 >> 3) + 1; for (let i = 0; i < t; ++i) { const rb = getBackend().randomBytes(byteLen); const a = new _BigInteger(rb).mod(nMinus3).add(two); let y = a.modPow(r, this); if (y.compareTo(_BigInteger.ONE) !== 0 && y.compareTo(n1) !== 0) { let j = 1; while (j++ < k && y.compareTo(n1) !== 0) { y = y.modPowInt(2, this); if (y.compareTo(_BigInteger.ONE) === 0) return false; } if (y.compareTo(n1) !== 0) return false; } } return true; } }; function nbi() { return new BigInteger(null); } function nbv(i) { const r = nbi(); r.fromInt(i); return r; } function op_and(x, y) { return x & y; } function op_or(x, y) { return x | y; } function op_xor(x, y) { return x ^ y; } function op_andnot(x, y) { return x & ~y; } var Classic = class { constructor(m) { this.m = m; } m; convert(x) { if (x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); return x; } revert(x) { return x; } reduce(x) { x.divRemTo(this.m, null, x); } mulTo(x, y, r) { x.multiplyTo(y, r); this.reduce(r); } sqrTo(x, r) { x.squareTo(r); this.reduce(r); } }; var Montgomery = class { m; mp; mpl; mph; um; mt2; constructor(m) { this.m = m; this.mp = m.invDigit(); this.mpl = this.mp & 32767; this.mph = this.mp >> 15; this.um = (1 << m.DB - 15) - 1; this.mt2 = 2 * m.t; } convert(x) { const r = nbi(); x.abs().dlShiftTo(this.m.t, r); r.divRemTo(this.m, null, r); if (x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r, r); return r; } revert(x) { const r = nbi(); x.copyTo(r); this.reduce(r); return r; } reduce(x) { while (x.t <= this.mt2) x[x.t++] = 0; for (let i = 0; i < this.m.t; ++i) { let j = x[i] & 32767; const u0 = j * this.mpl + ((j * this.mph + (x[i] >> 15) * this.mpl & this.um) << 15) & x.DM; j = i + this.m.t; x[j] = (x[j] ?? 0) + this.m.am(0, u0, x, i, 0, this.m.t); while (x[j] >= x.DV) { x[j] = x[j] - x.DV; x[++j] = (x[j] ?? 0) + 1; } } x.clamp(); x.drShiftTo(this.m.t, x); if (x.compareTo(this.m) >= 0) x.subTo(this.m, x); } mulTo(x, y, r) { x.multiplyTo(y, r); this.reduce(r); } sqrTo(x, r) { x.squareTo(r); this.reduce(r); } }; var Barrett = class { r2; q3; mu; m; constructor(m) { this.r2 = nbi(); this.q3 = nbi(); BigInteger.ONE.dlShiftTo(2 * m.t, this.r2); this.mu = this.r2.divide(m); this.m = m; } convert(x) { if (x.s < 0 || x.t > 2 * this.m.t) return x.mod(this.m); if (x.compareTo(this.m) < 0) return x; const r = nbi(); x.copyTo(r); this.reduce(r); return r; } revert(x) { return x; } reduce(x) { x.drShiftTo(this.m.t - 1, this.r2); if (x.t > this.m.t + 1) { x.t = this.m.t + 1; x.clamp(); } this.mu.multiplyUpperTo(this.r2, this.m.t + 1, this.q3); this.m.multiplyLowerTo(this.q3, this.m.t + 1, this.r2); while (x.compareTo(this.r2) < 0) x.dAddOffset(1, this.m.t + 1); x.subTo(this.r2, x); while (x.compareTo(this.m) >= 0) x.subTo(this.m, x); } mulTo(x, y, r) { x.multiplyTo(y, r); this.reduce(r); } sqrTo(x, r) { x.squareTo(r); this.reduce(r); } }; var NullExp = class { convert(x) { return x; } revert(x) { return x; } reduce(_x) { } mulTo(x, y, r) { x.multiplyTo(y, r); } sqrTo(x, r) { x.squareTo(r); } }; var lowprimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]; var lplim = (1 << 26) / lowprimes[lowprimes.length - 1]; BigInteger.ZERO = nbv(0); BigInteger.ONE = nbv(1); // src/bigint/big-integer-native.ts var _backend2; function setBigIntegerBackend2(backend) { _backend2 = backend; } function getBackend2() { if (!_backend2) { throw new Error( "BigInteger (native): backend not set. Did you import the package via its main entry?" ); } return _backend2; } var ZERO_BI = 0n; var ONE_BI = 1n; var TWO_BI = 2n; function bytesToBigInt(bytes, unsigned) { if (bytes.length === 0) return ZERO_BI; if (!unsigned && (bytes[0] & 128) !== 0) { let inv = ZERO_BI; for (let i = 0; i < bytes.length; i++) { inv = inv << 8n | BigInt(bytes[i] ^ 255); } return -(inv + ONE_BI); } let v = ZERO_BI; for (let i = 0; i < bytes.length; i++) { v = v << 8n | BigInt(bytes[i]); } return v; } function bigIntToBytes(v, length) { if (v < ZERO_BI) throw new Error("BigInteger.toBuffer: negative value"); if (v === ZERO_BI) return new Uint8Array(length ?? 1); let hex = v.toString(16); if (hex.length & 1) hex = `0${hex}`; const raw = new Uint8Array(hex.length / 2); for (let i = 0; i < raw.length; i++) { raw[i] = Number.parseInt(hex.substring(i * 2, i * 2 + 2), 16); } if (length === void 0) { if (raw[0] & 128) { const padded = new Uint8Array(raw.length + 1); padded.set(raw, 1); return padded; } return raw; } if (length === raw.length) return raw; if (length < raw.length) { let cut = 0; while (cut < raw.length - length && raw[cut] === 0) cut++; if (raw.length - cut === length) return raw.slice(cut); return raw.slice(raw.length - length); } const out = new Uint8Array(length); out.set(raw, length - raw.length); return out; } function bitLengthOf(v) { if (v === ZERO_BI) return 0; const x = v < ZERO_BI ? -v : v; return x.toString(2).length; } function modPowBI(base, exp, mod) { if (mod === ONE_BI) return ZERO_BI; if (exp < ZERO_BI) { return modPowBI(modInverseBI(base, mod), -exp, mod); } let b = base % mod; if (b < ZERO_BI) b += mod; let result = ONE_BI; let e = exp; while (e > ZERO_BI) { if (e & ONE_BI) result = result * b % mod; e >>= ONE_BI; b = b * b % mod; } return result; } function modInverseBI(a, m) { if (m <= ZERO_BI) throw new Error("BigInteger.modInverse: modulus must be positive"); let aNorm = a % m; if (aNorm < ZERO_BI) aNorm += m; let oldR = aNorm; let r = m; let oldS = ONE_BI; let s = ZERO_BI; while (r !== ZERO_BI) { const q = oldR / r; [oldR, r] = [r, oldR - q * r]; [oldS, s] = [s, oldS - q * s]; } if (oldR !== ONE_BI) return ZERO_BI; return oldS < ZERO_BI ? oldS + m : oldS; } function gcdBI(a, b) { let x = a < ZERO_BI ? -a : a; let y = b < ZERO_BI ? -b : b; while (y !== ZERO_BI) { [x, y] = [y, x % y]; } return x; } var SMALL_PRIMES = [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997 ]; var SMALL_PRIMES_BI = SMALL_PRIMES.map((p) => BigInt(p)); function millerRabin(n, rounds) { if (n < TWO_BI) return false; if (n === TWO_BI || n === 3n) return true; if ((n & ONE_BI) === ZERO_BI) return false; const nMinus1 = n - ONE_BI; let s = 0; let d = nMinus1; while ((d & ONE_BI) === ZERO_BI) { d >>= ONE_BI; s++; } const byteLen = (bitLengthOf(n) + 7 >> 3) + 1; const backend = getBackend2(); const nMinus3 = n - 3n; witnessLoop: for (let i = 0; i < rounds; i++) { let a; for (; ; ) { a = bytesToBigInt(backend.randomBytes(byteLen), true) % nMinus3; a += TWO_BI; if (a >= TWO_BI && a <= nMinus1 - ONE_BI) break; } let x = modPowBI(a, d, n); if (x === ONE_BI || x === nMinus1) continue; for (let r = 1; r < s; r++) { x = x * x % n; if (x === nMinus1) continue witnessLoop; } return false; } return true; } function probablePrime(v, rounds) { if (v < TWO_BI) return false; for (const p of SMALL_PRIMES_BI) { if (v === p) return true; if (v % p === ZERO_BI) return false; } return millerRabin(v, rounds); } function generateProbablePrime(bits) { if (bits < 2) throw new Error("BigInteger: cannot generate prime with < 2 bits"); const byteLen = bits + 7 >> 3; const backend = getBackend2(); while (true) { const x = backend.randomBytes(byteLen); const tailBits = bits & 7; if (tailBits > 0) x[0] = x[0] & (1 << tailBits) - 1; let v = bytesToBigInt(x, true); v |= ONE_BI << BigInt(bits - 1); v |= ONE_BI; for (let step = 0; step < 1 << 15; step += 2) { if (bitLengthOf(v) > bits) break; if (probablePrime(v, 1)) return v; v += TWO_BI; } } } function parseFromString(s, radix) { if (s.length === 0) return ZERO_BI; let str = s; let neg = false; if (str[0] === "-") { neg = true; str = str.substring(1); } if (str.length === 0) return ZERO_BI; let v; if (radix === 10) { v = BigInt(str); } else if (radix === 16) { v = BigInt(`0x${str}`); } else { const r = BigInt(radix); v = ZERO_BI; for (let i = 0; i < str.length; i++) { const code = str.charCodeAt(i); let d; if (code >= 48 && code <= 57) d = code - 48; else if (code >= 65 && code <= 90) d = code - 55; else if (code >= 97 && code <= 122) d = code - 87; else continue; if (d < 0 || d >= radix) continue; v = v * r + BigInt(d); } } return neg ? -v : v; } var BigInteger2 = class _BigInteger { static ONE = new _BigInteger(1); static ZERO = new _BigInteger(0); _v; constructor(a, b, unsigned) { if (a == null) { this._v = ZERO_BI; } else if (typeof a === "bigint") { this._v = a; } else if (typeof a === "number") { if (b === 1) { this._v = generateProbablePrime(a); } else { this._v = BigInt(a); } } else if (typeof a === "string") { this._v = parseFromString(a, b ?? 10); } else if (a instanceof Uint8Array) { this._v = bytesToBigInt(a, unsigned ?? true); } else { throw new Error(`BigInteger: unsupported input type ${typeof a}`); } } signum() { return this._v === ZERO_BI ? 0 : this._v > ZERO_BI ? 1 : -1; } compareTo(o) { if (this._v === o._v) return 0; return this._v > o._v ? 1 : -1; } bitLength() { return bitLengthOf(this._v); } testBit(n) { return (this._v >> BigInt(n) & ONE_BI) === ONE_BI; } isEven() { return (this._v & ONE_BI) === ZERO_BI; } /** @internal */ negate() { return new _BigInteger(-this._v); } abs() { return new _BigInteger(this._v < ZERO_BI ? -this._v : this._v); } add(o) { return new _BigInteger(this._v + o._v); } subtract(o) { return new _BigInteger(this._v - o._v); } multiply(o) { return new _BigInteger(this._v * o._v); } square() { return new _BigInteger(this._v * this._v); } /** @internal */ divide(o) { return new _BigInteger(this._v / o._v); } /** Returns [quotient, remainder]. Matches jsbn divideAndRemainder. */ divideAndRemainder(o) { return [new _BigInteger(this._v / o._v), new _BigInteger(this._v % o._v)]; } /** Always non-negative result for positive modulus (Java/jsbn semantics). */ mod(o) { const m = o._v; if (m === ZERO_BI) throw new Error("BigInteger.mod: divide by zero"); let r = this._v % m; const absM = m < ZERO_BI ? -m : m; if (r < ZERO_BI) r += absM; return new _BigInteger(r); } modPow(e, m) { return new _BigInteger(modPowBI(this._v, e._v, m._v)); } modPowInt(e, m) { return new _BigInteger(modPowBI(this._v, BigInt(e), m._v)); } modInverse(m) { return new _BigInteger(modInverseBI(this._v, m._v)); } gcd(o) { return new _BigInteger(gcdBI(this._v, o._v)); } shiftLeft(n) { return new _BigInteger(n >= 0 ? this._v << BigInt(n) : this._v >> BigInt(-n)); } shiftRight(n) { return new _BigInteger(n >= 0 ? this._v >> BigInt(n) : this._v << BigInt(-n)); } isProbablePrime(rounds) { return probablePrime(this._v, rounds); } toString(radix) { return this._v.toString(radix ?? 10); } /** Unsigned big-endian bytes; pads/truncates to `length` if given (jsbn parity). */ toBuffer(length) { if (this._v < ZERO_BI) { return null; } return bigIntToBytes(this._v, length); } }; // src/bigint/big-integer.ts var BigInteger3 = BigInteger; var _currentImpl = "jsbn"; var _currentBackend; function setBigIntegerImpl(impl) { if (impl === "native" && typeof BigInt === "function") { BigInteger3 = BigInteger2; _currentImpl = "native"; } else { BigInteger3 = BigInteger; _currentImpl = "jsbn"; } if (_currentBackend) { setBigIntegerBackend(_currentBackend); setBigIntegerBackend2(_currentBackend); } return _currentImpl; } function setBigIntegerBackend3(backend) { _currentBackend = backend; setBigIntegerBackend(backend); setBigIntegerBackend2(backend); } var HASHES = { md5: (d) => md5(d), ripemd160: (d) => ripemd160(d), sha1: (d) => sha1(d), sha224: (d) => sha224(d), sha256: (d) => sha256(d), sha384: (d) => sha384(d), sha512: (d) => sha512(d) }; function getWebCrypto() { const c = globalThis.crypto; if (!c || typeof c.getRandomValues !== "function") { throw new Error( "Web Crypto getRandomValues unavailable. Are you running in an environment without secure RNG?" ); } return c; } var webBackend = { name: "web", randomBytes(n) { const out = new Uint8Array(n); let off = 0; const c = getWebCrypto(); while (off < n) { const chunk = Math.min(n - off, 65536); c.getRandomValues(out.subarray(off, off + chunk)); off += chunk; } return out; }, digest(alg, data) { if (alg === "md4") { throw new Error("MD4 is not supported in the browser backend (Node-only)"); } const fn = HASHES[alg]; if (!fn) throw new Error(`Unsupported hash algorithm: ${alg}`); return fn(data); }, supportsHash(alg) { return alg !== "md4" && alg in HASHES; } }; // src/crypto/bytes.ts var HEX_CHARS = "0123456789abcdef"; var utf8Encoder = new TextEncoder(); var utf8Decoder = new TextDecoder("utf-8", { fatal: false }); function concat(...arrays) { let total = 0; for (const a of arrays) total += a.length; const out = new Uint8Array(total); let off = 0; for (const a of arrays) { out.set(a, off); off += a.length; } return out; } function constantTimeEqual(a, b) { if (a.length !== b.length) return false; let diff = 0; for (let i = 0; i < a.length; i++) { diff |= a[i] ^ b[i]; } return diff === 0; } function toHex(bytes) { let out = ""; for (let i = 0; i < bytes.length; i++) { const b = bytes[i]; out += HEX_CHARS[b >>> 4]; out += HEX_CHARS[b & 15]; } return out; } function fromHex(hex) { const clean = hex.startsWith("0x") ? hex.slice(2) : hex; if (clean.length % 2 !== 0) { throw new Error(`Invalid hex: odd length ${clean.length}`); } const out = new Uint8Array(clean.length / 2); for (let i = 0; i < out.length; i++) { const hi = parseHexNibble(clean.charCodeAt(i * 2)); const lo = parseHexNibble(clean.charCodeAt(i * 2 + 1)); out[i] = hi << 4 | lo; } return out; } function parseHexNibble(c) { if (c >= 48 && c <= 57) return c - 48; if (c >= 97 && c <= 102) return c - 97 + 10; if (c >= 65 && c <= 70) return c - 65 + 10; throw new Error(`Invalid hex character: 0x${c.toString(16).padStart(2, "0")}`); } function toBase64(bytes) { let binary = ""; const chunk = 32768; for (let i = 0; i < bytes.length; i += chunk) { const slice = bytes.subarray(i, Math.min(i + chunk, bytes.length)); binary += String.fromCharCode(...slice); } return btoa(binary); } function fromBase64(b64) { const binary = atob(b64); const out = new Uint8Array(binary.length); for (let i = 0; i < binary.length; i++) { out[i] = binary.charCodeAt(i); } return out; } function fromUtf8(s) { return utf8Encoder.encode(s); } function toUtf8(bytes) { return utf8Decoder.decode(bytes); } function fromLatin1(s) { const out = new Uint8Array(s.length); for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i) & 255; return out; } function toLatin1(bytes) { let out = ""; const chunk = 32768; for (let i = 0; i < bytes.length; i += chunk) { const slice = bytes.subarray(i, Math.min(i + chunk, bytes.length)); out += String.fromCharCode(...slice); } return out; } function readUInt32BE(bytes, offset = 0) { if (offset + 4 > bytes.length) { throw new RangeError(`readUInt32BE: out of range (offset=${offset}, length=${bytes.length})`); } return (bytes[offset] << 24 | bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]) >>> 0; } function writeUInt32BE(value, target, offset = 0) { if (offset + 4 > target.length) { throw new RangeError(`writeUInt32BE: out of range (offset=${offset}, length=${target.length})`); } target[offset] = value >>> 24 & 255; target[offset + 1] = value >>> 16 & 255; target[offset + 2] = value >>> 8 & 255; target[offset + 3] = value & 255; } // src/formats/components.ts var componentsFormat = { privateExport(key, _options = {}) { if (!key.n || !key.d || !key.p || !key.q || !key.dmp1 || !key.dmq1 || !key.coeff) { throw new Error("components export: incomplete private key"); } return { n: key.n.toBuffer(), e: key.e, d: key.d.toBuffer(), p: key.p.toBuffer(), q: key.q.toBuffer(), dmp1: key.dmp1.toBuffer(), dmq1: key.dmq1.toBuffer(), coeff: key.coeff.toBuffer() }; }, privateImport(key, data, _options = {}) { const d = data; if (!d.n || !d.e || !d.d || !d.p || !d.q || !d.dmp1 || !d.dmq1 || !d.coeff) { throw new Error("Invalid key data"); } key.setPrivate(d.n, d.e, d.d, d.p, d.q, d.dmp1, d.dmq1, d.coeff); }, publicExport(key, _options = {}) { if (!key.n) throw new Error("components export: missing modulus"); return { n: key.n.toBuffer(), e: key.e }; }, publicImport(key, data, _options = {}) { const d = data; if (!d.n || d.e == null) throw new Error("Invalid key data"); key.setPublic(d.n, d.e); }, autoImport(key, data) { if (typeof data !== "object" || data === null) return false; const d = data; if (!d.n || d.e == null) return false; if (d.d && d.p && d.q && d.dmp1 && d.dmq1 && d.coeff) { componentsFormat.privateImport?.(key, data); return true; } componentsFormat.publicImport?.(key, data); return true; } }; // src/utils/text-utils.ts function linebrk(str, maxLen) { let out = ""; let i = 0; while (i + maxLen < str.length) { out += `${str.substring(i, i + maxLen)} `; i += maxLen; } return out + str.substring(i); } function trimSurroundingText(data, opening, closing) { let start = 0; let end = data.length; const openIdx = data.indexOf(opening); const closeIdx = openIdx >= 0 ? data.indexOf(closing, openIdx) : -1; if (openIdx >= 0 && closeIdx >= 0) { const secondOpen = data.indexOf(opening, closeIdx + closing.length); if (secondOpen >= 0) { throw new Error(`multiple ${opening} blocks \u2014 refusing ambiguous input`); } } if (openIdx >= 0) start = openIdx + opening.length; if (closeIdx >= 0) end = closeIdx; return data.substring(start, end); } // src/formats/openssh.ts var PRIVATE_OPENING = "-----BEGIN OPENSSH PRIVATE KEY-----"; var PRIVATE_CLOSING = "-----END OPENSSH PRIVATE KEY-----"; var opensshFormat = { /** OpenSSH private-key export. The two checkint placeholders are left as zero (no integrity field is written). */ privateExport(key, options = {}) { if (!key.n || !key.d || !key.p || !key.q || !key.coeff) { throw new Error("OpenSSH export: incomplete private key"); } const nbuf = key.n.toBuffer(); let ebuf = new Uint8Array(4); writeUInt32BE(key.e, ebuf, 0); while (ebuf.length > 0 && ebuf[0] === 0) ebuf = ebuf.subarray(1); const dbuf = key.d.toBuffer(); const coeffbuf = key.coeff.toBuffer(); const pbuf = key.p.toBuffer(); const qbuf = key.q.toBuffer(); const commentbuf = key.sshcomment ? fromUtf8(key.sshcomment) : new Uint8Array(0); const pubkeyLength = 11 + // length-prefixed 'ssh-rsa' (4-byte uint32 length + 7 chars) 4 + ebuf.byteLength + // 4 = length prefix for e 4 + nbuf.byteLength; const privateKeyLength = 8 + // two uint32 checkints (file-corruption / wrong-passphrase detector) 11 + // length-prefixed 'ssh-rsa' (4 + 7) 4 + nbuf.byteLength + // 4 = length prefix for n 4 + ebuf.byteLength + // 4 = length prefix for e 4 + dbuf.byteLength + // 4 = length prefix for d 4 + coeffbuf.byteLength + // 4 = length prefix for iqmp (coeff) 4 + pbuf.byteLength + // 4 = length prefix for p 4 + qbuf.byteLength + // 4 = length prefix for q 4 + commentbuf.byteLength; const paddingLength = Math.ceil(privateKeyLength / 8) * 8 - privateKeyLength; const totalLength = 15 + // 'openssh-key-v1\0' magic 16 + // two length-prefixed 'none' strings (cipher + kdf), 2*(4+4) 4 + // empty kdfoptions (length prefix only, zero bytes of payload) 4 + // numkeys (uint32 = 1) 4 + // pubkey-blob length prefix pubkeyLength + 4 + // private-section length prefix privateKeyLength + paddingLength; const buf = new Uint8Array(totalLength); const writer = new SshWriter(buf); buf.set(fromUtf8("openssh-key-v1"), 0); buf[14] = 0; writer.off = 15; writer.writeString(fromUtf8("none")); writer.writeString(fromUtf8("none")); writer.writeString(new Uint8Array(0)); writer.writeUInt32(1); writer.writeUInt32(pubkeyLength); writer.writeString(fromUtf8("ssh-rsa")); writer.writeString(ebuf); writer.writeString(nbuf); writer.writeUInt32(privateKeyLength + paddingLength); writer.off += 8; writer.writeString(fromUtf8("ssh-rsa")); writer.writeString(nbuf); writer.writeString(ebuf); writer.writeString(dbuf); writer.writeString(coeffbuf); writer.writeString(pbuf); writer.writeString(qbuf); writer.writeString(commentbuf); let pad = 1; while (writer.off < totalLength) { buf[wr