{"ast":null,"code":"// prettier-ignore\nimport { wrapCipher, createView, equalBytes, setBigUint64 } from './utils.js';\nimport { poly1305 } from './_poly1305.js';\nimport { createCipher, rotl } from './_arx.js';\nimport { bytes as abytes } from './_assert.js';\n// ChaCha20 stream cipher was released in 2008. ChaCha aims to increase\n// the diffusion per round, but had slightly less cryptanalysis.\n// https://cr.yp.to/chacha.html, http://cr.yp.to/chacha/chacha-20080128.pdf\n/**\n * ChaCha core function.\n */\n// prettier-ignore\nfunction chachaCore(s, k, n, out, cnt, rounds = 20) {\n  let y00 = s[0],\n    y01 = s[1],\n    y02 = s[2],\n    y03 = s[3],\n    // \"expa\"   \"nd 3\"  \"2-by\"  \"te k\"\n    y04 = k[0],\n    y05 = k[1],\n    y06 = k[2],\n    y07 = k[3],\n    // Key      Key     Key     Key\n    y08 = k[4],\n    y09 = k[5],\n    y10 = k[6],\n    y11 = k[7],\n    // Key      Key     Key     Key\n    y12 = cnt,\n    y13 = n[0],\n    y14 = n[1],\n    y15 = n[2]; // Counter  Counter\tNonce   Nonce\n  // Save state to temporary variables\n  let x00 = y00,\n    x01 = y01,\n    x02 = y02,\n    x03 = y03,\n    x04 = y04,\n    x05 = y05,\n    x06 = y06,\n    x07 = y07,\n    x08 = y08,\n    x09 = y09,\n    x10 = y10,\n    x11 = y11,\n    x12 = y12,\n    x13 = y13,\n    x14 = y14,\n    x15 = y15;\n  for (let r = 0; r < rounds; r += 2) {\n    x00 = x00 + x04 | 0;\n    x12 = rotl(x12 ^ x00, 16);\n    x08 = x08 + x12 | 0;\n    x04 = rotl(x04 ^ x08, 12);\n    x00 = x00 + x04 | 0;\n    x12 = rotl(x12 ^ x00, 8);\n    x08 = x08 + x12 | 0;\n    x04 = rotl(x04 ^ x08, 7);\n    x01 = x01 + x05 | 0;\n    x13 = rotl(x13 ^ x01, 16);\n    x09 = x09 + x13 | 0;\n    x05 = rotl(x05 ^ x09, 12);\n    x01 = x01 + x05 | 0;\n    x13 = rotl(x13 ^ x01, 8);\n    x09 = x09 + x13 | 0;\n    x05 = rotl(x05 ^ x09, 7);\n    x02 = x02 + x06 | 0;\n    x14 = rotl(x14 ^ x02, 16);\n    x10 = x10 + x14 | 0;\n    x06 = rotl(x06 ^ x10, 12);\n    x02 = x02 + x06 | 0;\n    x14 = rotl(x14 ^ x02, 8);\n    x10 = x10 + x14 | 0;\n    x06 = rotl(x06 ^ x10, 7);\n    x03 = x03 + x07 | 0;\n    x15 = rotl(x15 ^ x03, 16);\n    x11 = x11 + x15 | 0;\n    x07 = rotl(x07 ^ x11, 12);\n    x03 = x03 + x07 | 0;\n    x15 = rotl(x15 ^ x03, 8);\n    x11 = x11 + x15 | 0;\n    x07 = rotl(x07 ^ x11, 7);\n    x00 = x00 + x05 | 0;\n    x15 = rotl(x15 ^ x00, 16);\n    x10 = x10 + x15 | 0;\n    x05 = rotl(x05 ^ x10, 12);\n    x00 = x00 + x05 | 0;\n    x15 = rotl(x15 ^ x00, 8);\n    x10 = x10 + x15 | 0;\n    x05 = rotl(x05 ^ x10, 7);\n    x01 = x01 + x06 | 0;\n    x12 = rotl(x12 ^ x01, 16);\n    x11 = x11 + x12 | 0;\n    x06 = rotl(x06 ^ x11, 12);\n    x01 = x01 + x06 | 0;\n    x12 = rotl(x12 ^ x01, 8);\n    x11 = x11 + x12 | 0;\n    x06 = rotl(x06 ^ x11, 7);\n    x02 = x02 + x07 | 0;\n    x13 = rotl(x13 ^ x02, 16);\n    x08 = x08 + x13 | 0;\n    x07 = rotl(x07 ^ x08, 12);\n    x02 = x02 + x07 | 0;\n    x13 = rotl(x13 ^ x02, 8);\n    x08 = x08 + x13 | 0;\n    x07 = rotl(x07 ^ x08, 7);\n    x03 = x03 + x04 | 0;\n    x14 = rotl(x14 ^ x03, 16);\n    x09 = x09 + x14 | 0;\n    x04 = rotl(x04 ^ x09, 12);\n    x03 = x03 + x04 | 0;\n    x14 = rotl(x14 ^ x03, 8);\n    x09 = x09 + x14 | 0;\n    x04 = rotl(x04 ^ x09, 7);\n  }\n  // Write output\n  let oi = 0;\n  out[oi++] = y00 + x00 | 0;\n  out[oi++] = y01 + x01 | 0;\n  out[oi++] = y02 + x02 | 0;\n  out[oi++] = y03 + x03 | 0;\n  out[oi++] = y04 + x04 | 0;\n  out[oi++] = y05 + x05 | 0;\n  out[oi++] = y06 + x06 | 0;\n  out[oi++] = y07 + x07 | 0;\n  out[oi++] = y08 + x08 | 0;\n  out[oi++] = y09 + x09 | 0;\n  out[oi++] = y10 + x10 | 0;\n  out[oi++] = y11 + x11 | 0;\n  out[oi++] = y12 + x12 | 0;\n  out[oi++] = y13 + x13 | 0;\n  out[oi++] = y14 + x14 | 0;\n  out[oi++] = y15 + x15 | 0;\n}\n/**\n * hchacha helper method, used primarily in xchacha, to hash\n * key and nonce into key' and nonce'.\n * Same as chachaCore, but there doesn't seem to be a way to move the block\n * out without 25% performance hit.\n */\n// prettier-ignore\nexport function hchacha(s, k, i, o32) {\n  let x00 = s[0],\n    x01 = s[1],\n    x02 = s[2],\n    x03 = s[3],\n    x04 = k[0],\n    x05 = k[1],\n    x06 = k[2],\n    x07 = k[3],\n    x08 = k[4],\n    x09 = k[5],\n    x10 = k[6],\n    x11 = k[7],\n    x12 = i[0],\n    x13 = i[1],\n    x14 = i[2],\n    x15 = i[3];\n  for (let r = 0; r < 20; r += 2) {\n    x00 = x00 + x04 | 0;\n    x12 = rotl(x12 ^ x00, 16);\n    x08 = x08 + x12 | 0;\n    x04 = rotl(x04 ^ x08, 12);\n    x00 = x00 + x04 | 0;\n    x12 = rotl(x12 ^ x00, 8);\n    x08 = x08 + x12 | 0;\n    x04 = rotl(x04 ^ x08, 7);\n    x01 = x01 + x05 | 0;\n    x13 = rotl(x13 ^ x01, 16);\n    x09 = x09 + x13 | 0;\n    x05 = rotl(x05 ^ x09, 12);\n    x01 = x01 + x05 | 0;\n    x13 = rotl(x13 ^ x01, 8);\n    x09 = x09 + x13 | 0;\n    x05 = rotl(x05 ^ x09, 7);\n    x02 = x02 + x06 | 0;\n    x14 = rotl(x14 ^ x02, 16);\n    x10 = x10 + x14 | 0;\n    x06 = rotl(x06 ^ x10, 12);\n    x02 = x02 + x06 | 0;\n    x14 = rotl(x14 ^ x02, 8);\n    x10 = x10 + x14 | 0;\n    x06 = rotl(x06 ^ x10, 7);\n    x03 = x03 + x07 | 0;\n    x15 = rotl(x15 ^ x03, 16);\n    x11 = x11 + x15 | 0;\n    x07 = rotl(x07 ^ x11, 12);\n    x03 = x03 + x07 | 0;\n    x15 = rotl(x15 ^ x03, 8);\n    x11 = x11 + x15 | 0;\n    x07 = rotl(x07 ^ x11, 7);\n    x00 = x00 + x05 | 0;\n    x15 = rotl(x15 ^ x00, 16);\n    x10 = x10 + x15 | 0;\n    x05 = rotl(x05 ^ x10, 12);\n    x00 = x00 + x05 | 0;\n    x15 = rotl(x15 ^ x00, 8);\n    x10 = x10 + x15 | 0;\n    x05 = rotl(x05 ^ x10, 7);\n    x01 = x01 + x06 | 0;\n    x12 = rotl(x12 ^ x01, 16);\n    x11 = x11 + x12 | 0;\n    x06 = rotl(x06 ^ x11, 12);\n    x01 = x01 + x06 | 0;\n    x12 = rotl(x12 ^ x01, 8);\n    x11 = x11 + x12 | 0;\n    x06 = rotl(x06 ^ x11, 7);\n    x02 = x02 + x07 | 0;\n    x13 = rotl(x13 ^ x02, 16);\n    x08 = x08 + x13 | 0;\n    x07 = rotl(x07 ^ x08, 12);\n    x02 = x02 + x07 | 0;\n    x13 = rotl(x13 ^ x02, 8);\n    x08 = x08 + x13 | 0;\n    x07 = rotl(x07 ^ x08, 7);\n    x03 = x03 + x04 | 0;\n    x14 = rotl(x14 ^ x03, 16);\n    x09 = x09 + x14 | 0;\n    x04 = rotl(x04 ^ x09, 12);\n    x03 = x03 + x04 | 0;\n    x14 = rotl(x14 ^ x03, 8);\n    x09 = x09 + x14 | 0;\n    x04 = rotl(x04 ^ x09, 7);\n  }\n  let oi = 0;\n  o32[oi++] = x00;\n  o32[oi++] = x01;\n  o32[oi++] = x02;\n  o32[oi++] = x03;\n  o32[oi++] = x12;\n  o32[oi++] = x13;\n  o32[oi++] = x14;\n  o32[oi++] = x15;\n}\n/**\n * Original, non-RFC chacha20 from DJB. 8-byte nonce, 8-byte counter.\n */\nexport const chacha20orig = /* @__PURE__ */createCipher(chachaCore, {\n  counterRight: false,\n  counterLength: 8,\n  allowShortKeys: true\n});\n/**\n * ChaCha stream cipher. Conforms to RFC 8439 (IETF, TLS). 12-byte nonce, 4-byte counter.\n * With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance.\n */\nexport const chacha20 = /* @__PURE__ */createCipher(chachaCore, {\n  counterRight: false,\n  counterLength: 4,\n  allowShortKeys: false\n});\n/**\n * XChaCha eXtended-nonce ChaCha. 24-byte nonce.\n * With 24-byte nonce, it's safe to use fill it with random (CSPRNG).\n * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha\n */\nexport const xchacha20 = /* @__PURE__ */createCipher(chachaCore, {\n  counterRight: false,\n  counterLength: 8,\n  extendNonceFn: hchacha,\n  allowShortKeys: false\n});\n/**\n * Reduced 8-round chacha, described in original paper.\n */\nexport const chacha8 = /* @__PURE__ */createCipher(chachaCore, {\n  counterRight: false,\n  counterLength: 4,\n  rounds: 8\n});\n/**\n * Reduced 12-round chacha, described in original paper.\n */\nexport const chacha12 = /* @__PURE__ */createCipher(chachaCore, {\n  counterRight: false,\n  counterLength: 4,\n  rounds: 12\n});\nconst ZEROS16 = /* @__PURE__ */new Uint8Array(16);\n// Pad to digest size with zeros\nconst updatePadded = (h, msg) => {\n  h.update(msg);\n  const left = msg.length % 16;\n  if (left) h.update(ZEROS16.subarray(left));\n};\nconst ZEROS32 = /* @__PURE__ */new Uint8Array(32);\nfunction computeTag(fn, key, nonce, data, AAD) {\n  const authKey = fn(key, nonce, ZEROS32);\n  const h = poly1305.create(authKey);\n  if (AAD) updatePadded(h, AAD);\n  updatePadded(h, data);\n  const num = new Uint8Array(16);\n  const view = createView(num);\n  setBigUint64(view, 0, BigInt(AAD ? AAD.length : 0), true);\n  setBigUint64(view, 8, BigInt(data.length), true);\n  h.update(num);\n  const res = h.digest();\n  authKey.fill(0);\n  return res;\n}\n/**\n * AEAD algorithm from RFC 8439.\n * Salsa20 and chacha (RFC 8439) use poly1305 differently.\n * We could have composed them similar to:\n * https://github.com/paulmillr/scure-base/blob/b266c73dde977b1dd7ef40ef7a23cc15aab526b3/index.ts#L250\n * But it's hard because of authKey:\n * In salsa20, authKey changes position in salsa stream.\n * In chacha, authKey can't be computed inside computeTag, it modifies the counter.\n */\nexport const _poly1305_aead = xorStream => (key, nonce, AAD) => {\n  const tagLength = 16;\n  abytes(key, 32);\n  abytes(nonce);\n  return {\n    encrypt: (plaintext, output) => {\n      const plength = plaintext.length;\n      const clength = plength + tagLength;\n      if (output) {\n        abytes(output, clength);\n      } else {\n        output = new Uint8Array(clength);\n      }\n      xorStream(key, nonce, plaintext, output, 1);\n      const tag = computeTag(xorStream, key, nonce, output.subarray(0, -tagLength), AAD);\n      output.set(tag, plength); // append tag\n      return output;\n    },\n    decrypt: (ciphertext, output) => {\n      const clength = ciphertext.length;\n      const plength = clength - tagLength;\n      if (clength < tagLength) throw new Error(`encrypted data must be at least ${tagLength} bytes`);\n      if (output) {\n        abytes(output, plength);\n      } else {\n        output = new Uint8Array(plength);\n      }\n      const data = ciphertext.subarray(0, -tagLength);\n      const passedTag = ciphertext.subarray(-tagLength);\n      const tag = computeTag(xorStream, key, nonce, data, AAD);\n      if (!equalBytes(passedTag, tag)) throw new Error('invalid tag');\n      xorStream(key, nonce, data, output, 1);\n      return output;\n    }\n  };\n};\n/**\n * ChaCha20-Poly1305 from RFC 8439.\n * With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance.\n */\nexport const chacha20poly1305 = /* @__PURE__ */wrapCipher({\n  blockSize: 64,\n  nonceLength: 12,\n  tagLength: 16\n}, _poly1305_aead(chacha20));\n/**\n * XChaCha20-Poly1305 extended-nonce chacha.\n * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha\n * With 24-byte nonce, it's safe to use fill it with random (CSPRNG).\n */\nexport const xchacha20poly1305 = /* @__PURE__ */wrapCipher({\n  blockSize: 64,\n  nonceLength: 24,\n  tagLength: 16\n}, _poly1305_aead(xchacha20));\n//# sourceMappingURL=chacha.js.map","map":null,"metadata":{},"sourceType":"module","externalDependencies":[]}