{"ast":null,"code":"// prettier-ignore\nimport { wrapCipher, createView, setBigUint64, equalBytes, u32, u8 } from './utils.js';\nimport { ghash, polyval } from './_polyval.js';\nimport { bytes as abytes } from './_assert.js';\n/*\nAES (Advanced Encryption Standard) aka Rijndael block cipher.\n\nData is split into 128-bit blocks. Encrypted in 10/12/14 rounds (128/192/256 bits). In every round:\n1. **S-box**, table substitution\n2. **Shift rows**, cyclic shift left of all rows of data array\n3. **Mix columns**, multiplying every column by fixed polynomial\n4. **Add round key**, round_key xor i-th column of array\n\nResources:\n- FIPS-197 https://csrc.nist.gov/files/pubs/fips/197/final/docs/fips-197.pdf\n- Original proposal: https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/aes-development/rijndael-ammended.pdf\n*/\nconst BLOCK_SIZE = 16;\nconst BLOCK_SIZE32 = 4;\nconst EMPTY_BLOCK = new Uint8Array(BLOCK_SIZE);\nconst POLY = 0x11b; // 1 + x + x**3 + x**4 + x**8\n// TODO: remove multiplication, binary ops only\nfunction mul2(n) {\n  return n << 1 ^ POLY & -(n >> 7);\n}\nfunction mul(a, b) {\n  let res = 0;\n  for (; b > 0; b >>= 1) {\n    // Montgomery ladder\n    res ^= a & -(b & 1); // if (b&1) res ^=a (but const-time).\n    a = mul2(a); // a = 2*a\n  }\n  return res;\n}\n// AES S-box is generated using finite field inversion,\n// an affine transform, and xor of a constant 0x63.\nconst sbox = /* @__PURE__ */(() => {\n  let t = new Uint8Array(256);\n  for (let i = 0, x = 1; i < 256; i++, x ^= mul2(x)) t[i] = x;\n  const box = new Uint8Array(256);\n  box[0] = 0x63; // first elm\n  for (let i = 0; i < 255; i++) {\n    let x = t[255 - i];\n    x |= x << 8;\n    box[t[i]] = (x ^ x >> 4 ^ x >> 5 ^ x >> 6 ^ x >> 7 ^ 0x63) & 0xff;\n  }\n  return box;\n})();\n// Inverted S-box\nconst invSbox = /* @__PURE__ */sbox.map((_, j) => sbox.indexOf(j));\n// Rotate u32 by 8\nconst rotr32_8 = n => n << 24 | n >>> 8;\nconst rotl32_8 = n => n << 8 | n >>> 24;\n// T-table is optimization suggested in 5.2 of original proposal (missed from FIPS-197). Changes:\n// - LE instead of BE\n// - bigger tables: T0 and T1 are merged into T01 table and T2 & T3 into T23;\n//   so index is u16, instead of u8. This speeds up things, unexpectedly\nfunction genTtable(sbox, fn) {\n  if (sbox.length !== 256) throw new Error('Wrong sbox length');\n  const T0 = new Uint32Array(256).map((_, j) => fn(sbox[j]));\n  const T1 = T0.map(rotl32_8);\n  const T2 = T1.map(rotl32_8);\n  const T3 = T2.map(rotl32_8);\n  const T01 = new Uint32Array(256 * 256);\n  const T23 = new Uint32Array(256 * 256);\n  const sbox2 = new Uint16Array(256 * 256);\n  for (let i = 0; i < 256; i++) {\n    for (let j = 0; j < 256; j++) {\n      const idx = i * 256 + j;\n      T01[idx] = T0[i] ^ T1[j];\n      T23[idx] = T2[i] ^ T3[j];\n      sbox2[idx] = sbox[i] << 8 | sbox[j];\n    }\n  }\n  return {\n    sbox,\n    sbox2,\n    T0,\n    T1,\n    T2,\n    T3,\n    T01,\n    T23\n  };\n}\nconst tableEncoding = /* @__PURE__ */genTtable(sbox, s => mul(s, 3) << 24 | s << 16 | s << 8 | mul(s, 2));\nconst tableDecoding = /* @__PURE__ */genTtable(invSbox, s => mul(s, 11) << 24 | mul(s, 13) << 16 | mul(s, 9) << 8 | mul(s, 14));\nconst xPowers = /* @__PURE__ */(() => {\n  const p = new Uint8Array(16);\n  for (let i = 0, x = 1; i < 16; i++, x = mul2(x)) p[i] = x;\n  return p;\n})();\nexport function expandKeyLE(key) {\n  abytes(key);\n  const len = key.length;\n  if (![16, 24, 32].includes(len)) throw new Error(`aes: wrong key size: should be 16, 24 or 32, got: ${len}`);\n  const {\n    sbox2\n  } = tableEncoding;\n  const k32 = u32(key);\n  const Nk = k32.length;\n  const subByte = n => applySbox(sbox2, n, n, n, n);\n  const xk = new Uint32Array(len + 28); // expanded key\n  xk.set(k32);\n  // 4.3.1 Key expansion\n  for (let i = Nk; i < xk.length; i++) {\n    let t = xk[i - 1];\n    if (i % Nk === 0) t = subByte(rotr32_8(t)) ^ xPowers[i / Nk - 1];else if (Nk > 6 && i % Nk === 4) t = subByte(t);\n    xk[i] = xk[i - Nk] ^ t;\n  }\n  return xk;\n}\nexport function expandKeyDecLE(key) {\n  const encKey = expandKeyLE(key);\n  const xk = encKey.slice();\n  const Nk = encKey.length;\n  const {\n    sbox2\n  } = tableEncoding;\n  const {\n    T0,\n    T1,\n    T2,\n    T3\n  } = tableDecoding;\n  // Inverse key by chunks of 4 (rounds)\n  for (let i = 0; i < Nk; i += 4) {\n    for (let j = 0; j < 4; j++) xk[i + j] = encKey[Nk - i - 4 + j];\n  }\n  encKey.fill(0);\n  // apply InvMixColumn except first & last round\n  for (let i = 4; i < Nk - 4; i++) {\n    const x = xk[i];\n    const w = applySbox(sbox2, x, x, x, x);\n    xk[i] = T0[w & 0xff] ^ T1[w >>> 8 & 0xff] ^ T2[w >>> 16 & 0xff] ^ T3[w >>> 24];\n  }\n  return xk;\n}\n// Apply tables\nfunction apply0123(T01, T23, s0, s1, s2, s3) {\n  return T01[s0 << 8 & 0xff00 | s1 >>> 8 & 0xff] ^ T23[s2 >>> 8 & 0xff00 | s3 >>> 24 & 0xff];\n}\nfunction applySbox(sbox2, s0, s1, s2, s3) {\n  return sbox2[s0 & 0xff | s1 & 0xff00] | sbox2[s2 >>> 16 & 0xff | s3 >>> 16 & 0xff00] << 16;\n}\nfunction encrypt(xk, s0, s1, s2, s3) {\n  const {\n    sbox2,\n    T01,\n    T23\n  } = tableEncoding;\n  let k = 0;\n  s0 ^= xk[k++], s1 ^= xk[k++], s2 ^= xk[k++], s3 ^= xk[k++];\n  const rounds = xk.length / 4 - 2;\n  for (let i = 0; i < rounds; i++) {\n    const t0 = xk[k++] ^ apply0123(T01, T23, s0, s1, s2, s3);\n    const t1 = xk[k++] ^ apply0123(T01, T23, s1, s2, s3, s0);\n    const t2 = xk[k++] ^ apply0123(T01, T23, s2, s3, s0, s1);\n    const t3 = xk[k++] ^ apply0123(T01, T23, s3, s0, s1, s2);\n    s0 = t0, s1 = t1, s2 = t2, s3 = t3;\n  }\n  // last round (without mixcolumns, so using SBOX2 table)\n  const t0 = xk[k++] ^ applySbox(sbox2, s0, s1, s2, s3);\n  const t1 = xk[k++] ^ applySbox(sbox2, s1, s2, s3, s0);\n  const t2 = xk[k++] ^ applySbox(sbox2, s2, s3, s0, s1);\n  const t3 = xk[k++] ^ applySbox(sbox2, s3, s0, s1, s2);\n  return {\n    s0: t0,\n    s1: t1,\n    s2: t2,\n    s3: t3\n  };\n}\nfunction decrypt(xk, s0, s1, s2, s3) {\n  const {\n    sbox2,\n    T01,\n    T23\n  } = tableDecoding;\n  let k = 0;\n  s0 ^= xk[k++], s1 ^= xk[k++], s2 ^= xk[k++], s3 ^= xk[k++];\n  const rounds = xk.length / 4 - 2;\n  for (let i = 0; i < rounds; i++) {\n    const t0 = xk[k++] ^ apply0123(T01, T23, s0, s3, s2, s1);\n    const t1 = xk[k++] ^ apply0123(T01, T23, s1, s0, s3, s2);\n    const t2 = xk[k++] ^ apply0123(T01, T23, s2, s1, s0, s3);\n    const t3 = xk[k++] ^ apply0123(T01, T23, s3, s2, s1, s0);\n    s0 = t0, s1 = t1, s2 = t2, s3 = t3;\n  }\n  // Last round\n  const t0 = xk[k++] ^ applySbox(sbox2, s0, s3, s2, s1);\n  const t1 = xk[k++] ^ applySbox(sbox2, s1, s0, s3, s2);\n  const t2 = xk[k++] ^ applySbox(sbox2, s2, s1, s0, s3);\n  const t3 = xk[k++] ^ applySbox(sbox2, s3, s2, s1, s0);\n  return {\n    s0: t0,\n    s1: t1,\n    s2: t2,\n    s3: t3\n  };\n}\nfunction getDst(len, dst) {\n  if (!dst) return new Uint8Array(len);\n  abytes(dst);\n  if (dst.length < len) throw new Error(`aes: wrong destination length, expected at least ${len}, got: ${dst.length}`);\n  return dst;\n}\n// TODO: investigate merging with ctr32\nfunction ctrCounter(xk, nonce, src, dst) {\n  abytes(nonce, BLOCK_SIZE);\n  abytes(src);\n  const srcLen = src.length;\n  dst = getDst(srcLen, dst);\n  const ctr = nonce;\n  const c32 = u32(ctr);\n  // Fill block (empty, ctr=0)\n  let {\n    s0,\n    s1,\n    s2,\n    s3\n  } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]);\n  const src32 = u32(src);\n  const dst32 = u32(dst);\n  // process blocks\n  for (let i = 0; i + 4 <= src32.length; i += 4) {\n    dst32[i + 0] = src32[i + 0] ^ s0;\n    dst32[i + 1] = src32[i + 1] ^ s1;\n    dst32[i + 2] = src32[i + 2] ^ s2;\n    dst32[i + 3] = src32[i + 3] ^ s3;\n    // Full 128 bit counter with wrap around\n    let carry = 1;\n    for (let i = ctr.length - 1; i >= 0; i--) {\n      carry = carry + (ctr[i] & 0xff) | 0;\n      ctr[i] = carry & 0xff;\n      carry >>>= 8;\n    }\n    ({\n      s0,\n      s1,\n      s2,\n      s3\n    } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]));\n  }\n  // leftovers (less than block)\n  // It's possible to handle > u32 fast, but is it worth it?\n  const start = BLOCK_SIZE * Math.floor(src32.length / BLOCK_SIZE32);\n  if (start < srcLen) {\n    const b32 = new Uint32Array([s0, s1, s2, s3]);\n    const buf = u8(b32);\n    for (let i = start, pos = 0; i < srcLen; i++, pos++) dst[i] = src[i] ^ buf[pos];\n  }\n  return dst;\n}\n// AES CTR with overflowing 32 bit counter\n// It's possible to do 32le significantly simpler (and probably faster) by using u32.\n// But, we need both, and perf bottleneck is in ghash anyway.\nfunction ctr32(xk, isLE, nonce, src, dst) {\n  abytes(nonce, BLOCK_SIZE);\n  abytes(src);\n  dst = getDst(src.length, dst);\n  const ctr = nonce; // write new value to nonce, so it can be re-used\n  const c32 = u32(ctr);\n  const view = createView(ctr);\n  const src32 = u32(src);\n  const dst32 = u32(dst);\n  const ctrPos = isLE ? 0 : 12;\n  const srcLen = src.length;\n  // Fill block (empty, ctr=0)\n  let ctrNum = view.getUint32(ctrPos, isLE); // read current counter value\n  let {\n    s0,\n    s1,\n    s2,\n    s3\n  } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]);\n  // process blocks\n  for (let i = 0; i + 4 <= src32.length; i += 4) {\n    dst32[i + 0] = src32[i + 0] ^ s0;\n    dst32[i + 1] = src32[i + 1] ^ s1;\n    dst32[i + 2] = src32[i + 2] ^ s2;\n    dst32[i + 3] = src32[i + 3] ^ s3;\n    ctrNum = ctrNum + 1 >>> 0; // u32 wrap\n    view.setUint32(ctrPos, ctrNum, isLE);\n    ({\n      s0,\n      s1,\n      s2,\n      s3\n    } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]));\n  }\n  // leftovers (less than a block)\n  const start = BLOCK_SIZE * Math.floor(src32.length / BLOCK_SIZE32);\n  if (start < srcLen) {\n    const b32 = new Uint32Array([s0, s1, s2, s3]);\n    const buf = u8(b32);\n    for (let i = start, pos = 0; i < srcLen; i++, pos++) dst[i] = src[i] ^ buf[pos];\n  }\n  return dst;\n}\n/**\n * CTR: counter mode. Creates stream cipher.\n * Requires good IV. Parallelizable. OK, but no MAC.\n */\nexport const ctr = wrapCipher({\n  blockSize: 16,\n  nonceLength: 16\n}, function ctr(key, nonce) {\n  abytes(key);\n  abytes(nonce, BLOCK_SIZE);\n  function processCtr(buf, dst) {\n    const xk = expandKeyLE(key);\n    const n = nonce.slice();\n    const out = ctrCounter(xk, n, buf, dst);\n    xk.fill(0);\n    n.fill(0);\n    return out;\n  }\n  return {\n    encrypt: (plaintext, dst) => processCtr(plaintext, dst),\n    decrypt: (ciphertext, dst) => processCtr(ciphertext, dst)\n  };\n});\nfunction validateBlockDecrypt(data) {\n  abytes(data);\n  if (data.length % BLOCK_SIZE !== 0) {\n    throw new Error(`aes/(cbc-ecb).decrypt ciphertext should consist of blocks with size ${BLOCK_SIZE}`);\n  }\n}\nfunction validateBlockEncrypt(plaintext, pcks5, dst) {\n  let outLen = plaintext.length;\n  const remaining = outLen % BLOCK_SIZE;\n  if (!pcks5 && remaining !== 0) throw new Error('aec/(cbc-ecb): unpadded plaintext with disabled padding');\n  const b = u32(plaintext);\n  if (pcks5) {\n    let left = BLOCK_SIZE - remaining;\n    if (!left) left = BLOCK_SIZE; // if no bytes left, create empty padding block\n    outLen = outLen + left;\n  }\n  const out = getDst(outLen, dst);\n  const o = u32(out);\n  return {\n    b,\n    o,\n    out\n  };\n}\nfunction validatePCKS(data, pcks5) {\n  if (!pcks5) return data;\n  const len = data.length;\n  if (!len) throw new Error(`aes/pcks5: empty ciphertext not allowed`);\n  const lastByte = data[len - 1];\n  if (lastByte <= 0 || lastByte > 16) throw new Error(`aes/pcks5: wrong padding byte: ${lastByte}`);\n  const out = data.subarray(0, -lastByte);\n  for (let i = 0; i < lastByte; i++) if (data[len - i - 1] !== lastByte) throw new Error(`aes/pcks5: wrong padding`);\n  return out;\n}\nfunction padPCKS(left) {\n  const tmp = new Uint8Array(16);\n  const tmp32 = u32(tmp);\n  tmp.set(left);\n  const paddingByte = BLOCK_SIZE - left.length;\n  for (let i = BLOCK_SIZE - paddingByte; i < BLOCK_SIZE; i++) tmp[i] = paddingByte;\n  return tmp32;\n}\n/**\n * ECB: Electronic CodeBook. Simple deterministic replacement.\n * Dangerous: always map x to y. See [AES Penguin](https://words.filippo.io/the-ecb-penguin/).\n */\nexport const ecb = wrapCipher({\n  blockSize: 16\n}, function ecb(key, opts = {}) {\n  abytes(key);\n  const pcks5 = !opts.disablePadding;\n  return {\n    encrypt: (plaintext, dst) => {\n      abytes(plaintext);\n      const {\n        b,\n        o,\n        out: _out\n      } = validateBlockEncrypt(plaintext, pcks5, dst);\n      const xk = expandKeyLE(key);\n      let i = 0;\n      for (; i + 4 <= b.length;) {\n        const {\n          s0,\n          s1,\n          s2,\n          s3\n        } = encrypt(xk, b[i + 0], b[i + 1], b[i + 2], b[i + 3]);\n        o[i++] = s0, o[i++] = s1, o[i++] = s2, o[i++] = s3;\n      }\n      if (pcks5) {\n        const tmp32 = padPCKS(plaintext.subarray(i * 4));\n        const {\n          s0,\n          s1,\n          s2,\n          s3\n        } = encrypt(xk, tmp32[0], tmp32[1], tmp32[2], tmp32[3]);\n        o[i++] = s0, o[i++] = s1, o[i++] = s2, o[i++] = s3;\n      }\n      xk.fill(0);\n      return _out;\n    },\n    decrypt: (ciphertext, dst) => {\n      validateBlockDecrypt(ciphertext);\n      const xk = expandKeyDecLE(key);\n      const out = getDst(ciphertext.length, dst);\n      const b = u32(ciphertext);\n      const o = u32(out);\n      for (let i = 0; i + 4 <= b.length;) {\n        const {\n          s0,\n          s1,\n          s2,\n          s3\n        } = decrypt(xk, b[i + 0], b[i + 1], b[i + 2], b[i + 3]);\n        o[i++] = s0, o[i++] = s1, o[i++] = s2, o[i++] = s3;\n      }\n      xk.fill(0);\n      return validatePCKS(out, pcks5);\n    }\n  };\n});\n/**\n * CBC: Cipher-Block-Chaining. Key is previous round’s block.\n * Fragile: needs proper padding. Unauthenticated: needs MAC.\n */\nexport const cbc = wrapCipher({\n  blockSize: 16,\n  nonceLength: 16\n}, function cbc(key, iv, opts = {}) {\n  abytes(key);\n  abytes(iv, 16);\n  const pcks5 = !opts.disablePadding;\n  return {\n    encrypt: (plaintext, dst) => {\n      const xk = expandKeyLE(key);\n      const {\n        b,\n        o,\n        out: _out\n      } = validateBlockEncrypt(plaintext, pcks5, dst);\n      const n32 = u32(iv);\n      // prettier-ignore\n      let s0 = n32[0],\n        s1 = n32[1],\n        s2 = n32[2],\n        s3 = n32[3];\n      let i = 0;\n      for (; i + 4 <= b.length;) {\n        s0 ^= b[i + 0], s1 ^= b[i + 1], s2 ^= b[i + 2], s3 ^= b[i + 3];\n        ({\n          s0,\n          s1,\n          s2,\n          s3\n        } = encrypt(xk, s0, s1, s2, s3));\n        o[i++] = s0, o[i++] = s1, o[i++] = s2, o[i++] = s3;\n      }\n      if (pcks5) {\n        const tmp32 = padPCKS(plaintext.subarray(i * 4));\n        s0 ^= tmp32[0], s1 ^= tmp32[1], s2 ^= tmp32[2], s3 ^= tmp32[3];\n        ({\n          s0,\n          s1,\n          s2,\n          s3\n        } = encrypt(xk, s0, s1, s2, s3));\n        o[i++] = s0, o[i++] = s1, o[i++] = s2, o[i++] = s3;\n      }\n      xk.fill(0);\n      return _out;\n    },\n    decrypt: (ciphertext, dst) => {\n      validateBlockDecrypt(ciphertext);\n      const xk = expandKeyDecLE(key);\n      const n32 = u32(iv);\n      const out = getDst(ciphertext.length, dst);\n      const b = u32(ciphertext);\n      const o = u32(out);\n      // prettier-ignore\n      let s0 = n32[0],\n        s1 = n32[1],\n        s2 = n32[2],\n        s3 = n32[3];\n      for (let i = 0; i + 4 <= b.length;) {\n        // prettier-ignore\n        const ps0 = s0,\n          ps1 = s1,\n          ps2 = s2,\n          ps3 = s3;\n        s0 = b[i + 0], s1 = b[i + 1], s2 = b[i + 2], s3 = b[i + 3];\n        const {\n          s0: o0,\n          s1: o1,\n          s2: o2,\n          s3: o3\n        } = decrypt(xk, s0, s1, s2, s3);\n        o[i++] = o0 ^ ps0, o[i++] = o1 ^ ps1, o[i++] = o2 ^ ps2, o[i++] = o3 ^ ps3;\n      }\n      xk.fill(0);\n      return validatePCKS(out, pcks5);\n    }\n  };\n});\n/**\n * CFB: Cipher Feedback Mode. The input for the block cipher is the previous cipher output.\n * Unauthenticated: needs MAC.\n */\nexport const cfb = wrapCipher({\n  blockSize: 16,\n  nonceLength: 16\n}, function cfb(key, iv) {\n  abytes(key);\n  abytes(iv, 16);\n  function processCfb(src, isEncrypt, dst) {\n    const xk = expandKeyLE(key);\n    const srcLen = src.length;\n    dst = getDst(srcLen, dst);\n    const src32 = u32(src);\n    const dst32 = u32(dst);\n    const next32 = isEncrypt ? dst32 : src32;\n    const n32 = u32(iv);\n    // prettier-ignore\n    let s0 = n32[0],\n      s1 = n32[1],\n      s2 = n32[2],\n      s3 = n32[3];\n    for (let i = 0; i + 4 <= src32.length;) {\n      const {\n        s0: e0,\n        s1: e1,\n        s2: e2,\n        s3: e3\n      } = encrypt(xk, s0, s1, s2, s3);\n      dst32[i + 0] = src32[i + 0] ^ e0;\n      dst32[i + 1] = src32[i + 1] ^ e1;\n      dst32[i + 2] = src32[i + 2] ^ e2;\n      dst32[i + 3] = src32[i + 3] ^ e3;\n      s0 = next32[i++], s1 = next32[i++], s2 = next32[i++], s3 = next32[i++];\n    }\n    // leftovers (less than block)\n    const start = BLOCK_SIZE * Math.floor(src32.length / BLOCK_SIZE32);\n    if (start < srcLen) {\n      ({\n        s0,\n        s1,\n        s2,\n        s3\n      } = encrypt(xk, s0, s1, s2, s3));\n      const buf = u8(new Uint32Array([s0, s1, s2, s3]));\n      for (let i = start, pos = 0; i < srcLen; i++, pos++) dst[i] = src[i] ^ buf[pos];\n      buf.fill(0);\n    }\n    xk.fill(0);\n    return dst;\n  }\n  return {\n    encrypt: (plaintext, dst) => processCfb(plaintext, true, dst),\n    decrypt: (ciphertext, dst) => processCfb(ciphertext, false, dst)\n  };\n});\n// TODO: merge with chacha, however gcm has bitLen while chacha has byteLen\nfunction computeTag(fn, isLE, key, data, AAD) {\n  const h = fn.create(key, data.length + (AAD?.length || 0));\n  if (AAD) h.update(AAD);\n  h.update(data);\n  const num = new Uint8Array(16);\n  const view = createView(num);\n  if (AAD) setBigUint64(view, 0, BigInt(AAD.length * 8), isLE);\n  setBigUint64(view, 8, BigInt(data.length * 8), isLE);\n  h.update(num);\n  return h.digest();\n}\n/**\n * GCM: Galois/Counter Mode.\n * Good, modern version of CTR, parallel, with MAC.\n * Be careful: MACs can be forged.\n */\nexport const gcm = wrapCipher({\n  blockSize: 16,\n  nonceLength: 12,\n  tagLength: 16\n}, function gcm(key, nonce, AAD) {\n  abytes(nonce);\n  // Nonce can be pretty much anything (even 1 byte). But smaller nonces less secure.\n  if (nonce.length === 0) throw new Error('aes/gcm: empty nonce');\n  const tagLength = 16;\n  function _computeTag(authKey, tagMask, data) {\n    const tag = computeTag(ghash, false, authKey, data, AAD);\n    for (let i = 0; i < tagMask.length; i++) tag[i] ^= tagMask[i];\n    return tag;\n  }\n  function deriveKeys() {\n    const xk = expandKeyLE(key);\n    const authKey = EMPTY_BLOCK.slice();\n    const counter = EMPTY_BLOCK.slice();\n    ctr32(xk, false, counter, counter, authKey);\n    if (nonce.length === 12) {\n      counter.set(nonce);\n    } else {\n      // Spec (NIST 800-38d) supports variable size nonce.\n      // Not supported for now, but can be useful.\n      const nonceLen = EMPTY_BLOCK.slice();\n      const view = createView(nonceLen);\n      setBigUint64(view, 8, BigInt(nonce.length * 8), false);\n      // ghash(nonce || u64be(0) || u64be(nonceLen*8))\n      ghash.create(authKey).update(nonce).update(nonceLen).digestInto(counter);\n    }\n    const tagMask = ctr32(xk, false, counter, EMPTY_BLOCK);\n    return {\n      xk,\n      authKey,\n      counter,\n      tagMask\n    };\n  }\n  return {\n    encrypt: plaintext => {\n      abytes(plaintext);\n      const {\n        xk,\n        authKey,\n        counter,\n        tagMask\n      } = deriveKeys();\n      const out = new Uint8Array(plaintext.length + tagLength);\n      ctr32(xk, false, counter, plaintext, out);\n      const tag = _computeTag(authKey, tagMask, out.subarray(0, out.length - tagLength));\n      out.set(tag, plaintext.length);\n      xk.fill(0);\n      return out;\n    },\n    decrypt: ciphertext => {\n      abytes(ciphertext);\n      if (ciphertext.length < tagLength) throw new Error(`aes/gcm: ciphertext less than tagLen (${tagLength})`);\n      const {\n        xk,\n        authKey,\n        counter,\n        tagMask\n      } = deriveKeys();\n      const data = ciphertext.subarray(0, -tagLength);\n      const passedTag = ciphertext.subarray(-tagLength);\n      const tag = _computeTag(authKey, tagMask, data);\n      if (!equalBytes(tag, passedTag)) throw new Error('aes/gcm: invalid ghash tag');\n      const out = ctr32(xk, false, counter, data);\n      authKey.fill(0);\n      tagMask.fill(0);\n      xk.fill(0);\n      return out;\n    }\n  };\n});\nconst limit = (name, min, max) => value => {\n  if (!Number.isSafeInteger(value) || min > value || value > max) throw new Error(`${name}: invalid value=${value}, must be [${min}..${max}]`);\n};\n/**\n * AES-GCM-SIV: classic AES-GCM with nonce-misuse resistance.\n * Guarantees that, when a nonce is repeated, the only security loss is that identical\n * plaintexts will produce identical ciphertexts.\n * RFC 8452, https://datatracker.ietf.org/doc/html/rfc8452\n */\nexport const siv = wrapCipher({\n  blockSize: 16,\n  nonceLength: 12,\n  tagLength: 16\n}, function siv(key, nonce, AAD) {\n  const tagLength = 16;\n  // From RFC 8452: Section 6\n  const AAD_LIMIT = limit('AAD', 0, 2 ** 36);\n  const PLAIN_LIMIT = limit('plaintext', 0, 2 ** 36);\n  const NONCE_LIMIT = limit('nonce', 12, 12);\n  const CIPHER_LIMIT = limit('ciphertext', 16, 2 ** 36 + 16);\n  abytes(nonce);\n  NONCE_LIMIT(nonce.length);\n  if (AAD) {\n    abytes(AAD);\n    AAD_LIMIT(AAD.length);\n  }\n  function deriveKeys() {\n    const len = key.length;\n    if (len !== 16 && len !== 24 && len !== 32) throw new Error(`key length must be 16, 24 or 32 bytes, got: ${len} bytes`);\n    const xk = expandKeyLE(key);\n    const encKey = new Uint8Array(len);\n    const authKey = new Uint8Array(16);\n    const n32 = u32(nonce);\n    // prettier-ignore\n    let s0 = 0,\n      s1 = n32[0],\n      s2 = n32[1],\n      s3 = n32[2];\n    let counter = 0;\n    for (const derivedKey of [authKey, encKey].map(u32)) {\n      const d32 = u32(derivedKey);\n      for (let i = 0; i < d32.length; i += 2) {\n        // aes(u32le(0) || nonce)[:8] || aes(u32le(1) || nonce)[:8] ...\n        const {\n          s0: o0,\n          s1: o1\n        } = encrypt(xk, s0, s1, s2, s3);\n        d32[i + 0] = o0;\n        d32[i + 1] = o1;\n        s0 = ++counter; // increment counter inside state\n      }\n    }\n    xk.fill(0);\n    return {\n      authKey,\n      encKey: expandKeyLE(encKey)\n    };\n  }\n  function _computeTag(encKey, authKey, data) {\n    const tag = computeTag(polyval, true, authKey, data, AAD);\n    // Compute the expected tag by XORing S_s and the nonce, clearing the\n    // most significant bit of the last byte and encrypting with the\n    // message-encryption key.\n    for (let i = 0; i < 12; i++) tag[i] ^= nonce[i];\n    tag[15] &= 0x7f; // Clear the highest bit\n    // encrypt tag as block\n    const t32 = u32(tag);\n    // prettier-ignore\n    let s0 = t32[0],\n      s1 = t32[1],\n      s2 = t32[2],\n      s3 = t32[3];\n    ({\n      s0,\n      s1,\n      s2,\n      s3\n    } = encrypt(encKey, s0, s1, s2, s3));\n    t32[0] = s0, t32[1] = s1, t32[2] = s2, t32[3] = s3;\n    return tag;\n  }\n  // actual decrypt/encrypt of message.\n  function processSiv(encKey, tag, input) {\n    let block = tag.slice();\n    block[15] |= 0x80; // Force highest bit\n    return ctr32(encKey, true, block, input);\n  }\n  return {\n    encrypt: plaintext => {\n      abytes(plaintext);\n      PLAIN_LIMIT(plaintext.length);\n      const {\n        encKey,\n        authKey\n      } = deriveKeys();\n      const tag = _computeTag(encKey, authKey, plaintext);\n      const out = new Uint8Array(plaintext.length + tagLength);\n      out.set(tag, plaintext.length);\n      out.set(processSiv(encKey, tag, plaintext));\n      encKey.fill(0);\n      authKey.fill(0);\n      return out;\n    },\n    decrypt: ciphertext => {\n      abytes(ciphertext);\n      CIPHER_LIMIT(ciphertext.length);\n      const tag = ciphertext.subarray(-tagLength);\n      const {\n        encKey,\n        authKey\n      } = deriveKeys();\n      const plaintext = processSiv(encKey, tag, ciphertext.subarray(0, -tagLength));\n      const expectedTag = _computeTag(encKey, authKey, plaintext);\n      encKey.fill(0);\n      authKey.fill(0);\n      if (!equalBytes(tag, expectedTag)) throw new Error('invalid polyval tag');\n      return plaintext;\n    }\n  };\n});\nfunction isBytes32(a) {\n  return a != null && typeof a === 'object' && (a instanceof Uint32Array || a.constructor.name === 'Uint32Array');\n}\nfunction encryptBlock(xk, block) {\n  abytes(block, 16);\n  if (!isBytes32(xk)) throw new Error('_encryptBlock accepts result of expandKeyLE');\n  const b32 = u32(block);\n  let {\n    s0,\n    s1,\n    s2,\n    s3\n  } = encrypt(xk, b32[0], b32[1], b32[2], b32[3]);\n  b32[0] = s0, b32[1] = s1, b32[2] = s2, b32[3] = s3;\n  return block;\n}\nfunction decryptBlock(xk, block) {\n  abytes(block, 16);\n  if (!isBytes32(xk)) throw new Error('_decryptBlock accepts result of expandKeyLE');\n  const b32 = u32(block);\n  let {\n    s0,\n    s1,\n    s2,\n    s3\n  } = decrypt(xk, b32[0], b32[1], b32[2], b32[3]);\n  b32[0] = s0, b32[1] = s1, b32[2] = s2, b32[3] = s3;\n  return block;\n}\n// Highly unsafe private functions for implementing new modes or ciphers based on AES\n// Can change at any time, no API guarantees\nexport const unsafe = {\n  expandKeyLE,\n  expandKeyDecLE,\n  encrypt,\n  decrypt,\n  encryptBlock,\n  decryptBlock,\n  ctrCounter,\n  ctr32\n};\n//# sourceMappingURL=aes.js.map","map":null,"metadata":{},"sourceType":"module","externalDependencies":[]}