node-rsa
Version:
RSA library for Node.js and browsers
2,041 lines (2,034 loc) • 116 kB
JavaScript
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