{"ast":null,"code":"import { createView, toBytes, u32 } from './utils.js';\nimport { bytes as abytes, exists as aexists, output as aoutput } from './_assert.js';\n// GHash from AES-GCM and its little-endian \"mirror image\" Polyval from AES-SIV.\n// Implemented in terms of GHash with conversion function for keys\n// GCM GHASH from NIST SP800-38d, SIV from RFC 8452.\n// https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf\n// GHASH   modulo: x^128 + x^7   + x^2   + x     + 1\n// POLYVAL modulo: x^128 + x^127 + x^126 + x^121 + 1\nconst BLOCK_SIZE = 16;\n// TODO: rewrite\n// temporary padding buffer\nconst ZEROS16 = /* @__PURE__ */new Uint8Array(16);\nconst ZEROS32 = u32(ZEROS16);\nconst POLY = 0xe1; // v = 2*v % POLY\n// v = 2*v % POLY\n// NOTE: because x + x = 0 (add/sub is same), mul2(x) != x+x\n// We can multiply any number using montgomery ladder and this function (works as double, add is simple xor)\nconst mul2 = (s0, s1, s2, s3) => {\n  const hiBit = s3 & 1;\n  return {\n    s3: s2 << 31 | s3 >>> 1,\n    s2: s1 << 31 | s2 >>> 1,\n    s1: s0 << 31 | s1 >>> 1,\n    s0: s0 >>> 1 ^ POLY << 24 & -(hiBit & 1) // reduce % poly\n  };\n};\nconst swapLE = n => (n >>> 0 & 0xff) << 24 | (n >>> 8 & 0xff) << 16 | (n >>> 16 & 0xff) << 8 | n >>> 24 & 0xff | 0;\n/**\n * `mulX_POLYVAL(ByteReverse(H))` from spec\n * @param k mutated in place\n */\nexport function _toGHASHKey(k) {\n  k.reverse();\n  const hiBit = k[15] & 1;\n  // k >>= 1\n  let carry = 0;\n  for (let i = 0; i < k.length; i++) {\n    const t = k[i];\n    k[i] = t >>> 1 | carry;\n    carry = (t & 1) << 7;\n  }\n  k[0] ^= -hiBit & 0xe1; // if (hiBit) n ^= 0xe1000000000000000000000000000000;\n  return k;\n}\nconst estimateWindow = bytes => {\n  if (bytes > 64 * 1024) return 8;\n  if (bytes > 1024) return 4;\n  return 2;\n};\nclass GHASH {\n  // We select bits per window adaptively based on expectedLength\n  constructor(key, expectedLength) {\n    this.blockLen = BLOCK_SIZE;\n    this.outputLen = BLOCK_SIZE;\n    this.s0 = 0;\n    this.s1 = 0;\n    this.s2 = 0;\n    this.s3 = 0;\n    this.finished = false;\n    key = toBytes(key);\n    abytes(key, 16);\n    const kView = createView(key);\n    let k0 = kView.getUint32(0, false);\n    let k1 = kView.getUint32(4, false);\n    let k2 = kView.getUint32(8, false);\n    let k3 = kView.getUint32(12, false);\n    // generate table of doubled keys (half of montgomery ladder)\n    const doubles = [];\n    for (let i = 0; i < 128; i++) {\n      doubles.push({\n        s0: swapLE(k0),\n        s1: swapLE(k1),\n        s2: swapLE(k2),\n        s3: swapLE(k3)\n      });\n      ({\n        s0: k0,\n        s1: k1,\n        s2: k2,\n        s3: k3\n      } = mul2(k0, k1, k2, k3));\n    }\n    const W = estimateWindow(expectedLength || 1024);\n    if (![1, 2, 4, 8].includes(W)) throw new Error(`ghash: wrong window size=${W}, should be 2, 4 or 8`);\n    this.W = W;\n    const bits = 128; // always 128 bits;\n    const windows = bits / W;\n    const windowSize = this.windowSize = 2 ** W;\n    const items = [];\n    // Create precompute table for window of W bits\n    for (let w = 0; w < windows; w++) {\n      // truth table: 00, 01, 10, 11\n      for (let byte = 0; byte < windowSize; byte++) {\n        // prettier-ignore\n        let s0 = 0,\n          s1 = 0,\n          s2 = 0,\n          s3 = 0;\n        for (let j = 0; j < W; j++) {\n          const bit = byte >>> W - j - 1 & 1;\n          if (!bit) continue;\n          const {\n            s0: d0,\n            s1: d1,\n            s2: d2,\n            s3: d3\n          } = doubles[W * w + j];\n          s0 ^= d0, s1 ^= d1, s2 ^= d2, s3 ^= d3;\n        }\n        items.push({\n          s0,\n          s1,\n          s2,\n          s3\n        });\n      }\n    }\n    this.t = items;\n  }\n  _updateBlock(s0, s1, s2, s3) {\n    s0 ^= this.s0, s1 ^= this.s1, s2 ^= this.s2, s3 ^= this.s3;\n    const {\n      W,\n      t,\n      windowSize\n    } = this;\n    // prettier-ignore\n    let o0 = 0,\n      o1 = 0,\n      o2 = 0,\n      o3 = 0;\n    const mask = (1 << W) - 1; // 2**W will kill performance.\n    let w = 0;\n    for (const num of [s0, s1, s2, s3]) {\n      for (let bytePos = 0; bytePos < 4; bytePos++) {\n        const byte = num >>> 8 * bytePos & 0xff;\n        for (let bitPos = 8 / W - 1; bitPos >= 0; bitPos--) {\n          const bit = byte >>> W * bitPos & mask;\n          const {\n            s0: e0,\n            s1: e1,\n            s2: e2,\n            s3: e3\n          } = t[w * windowSize + bit];\n          o0 ^= e0, o1 ^= e1, o2 ^= e2, o3 ^= e3;\n          w += 1;\n        }\n      }\n    }\n    this.s0 = o0;\n    this.s1 = o1;\n    this.s2 = o2;\n    this.s3 = o3;\n  }\n  update(data) {\n    data = toBytes(data);\n    aexists(this);\n    const b32 = u32(data);\n    const blocks = Math.floor(data.length / BLOCK_SIZE);\n    const left = data.length % BLOCK_SIZE;\n    for (let i = 0; i < blocks; i++) {\n      this._updateBlock(b32[i * 4 + 0], b32[i * 4 + 1], b32[i * 4 + 2], b32[i * 4 + 3]);\n    }\n    if (left) {\n      ZEROS16.set(data.subarray(blocks * BLOCK_SIZE));\n      this._updateBlock(ZEROS32[0], ZEROS32[1], ZEROS32[2], ZEROS32[3]);\n      ZEROS32.fill(0); // clean tmp buffer\n    }\n    return this;\n  }\n  destroy() {\n    const {\n      t\n    } = this;\n    // clean precompute table\n    for (const elm of t) {\n      elm.s0 = 0, elm.s1 = 0, elm.s2 = 0, elm.s3 = 0;\n    }\n  }\n  digestInto(out) {\n    aexists(this);\n    aoutput(out, this);\n    this.finished = true;\n    const {\n      s0,\n      s1,\n      s2,\n      s3\n    } = this;\n    const o32 = u32(out);\n    o32[0] = s0;\n    o32[1] = s1;\n    o32[2] = s2;\n    o32[3] = s3;\n    return out;\n  }\n  digest() {\n    const res = new Uint8Array(BLOCK_SIZE);\n    this.digestInto(res);\n    this.destroy();\n    return res;\n  }\n}\nclass Polyval extends GHASH {\n  constructor(key, expectedLength) {\n    key = toBytes(key);\n    const ghKey = _toGHASHKey(key.slice());\n    super(ghKey, expectedLength);\n    ghKey.fill(0);\n  }\n  update(data) {\n    data = toBytes(data);\n    aexists(this);\n    const b32 = u32(data);\n    const left = data.length % BLOCK_SIZE;\n    const blocks = Math.floor(data.length / BLOCK_SIZE);\n    for (let i = 0; i < blocks; i++) {\n      this._updateBlock(swapLE(b32[i * 4 + 3]), swapLE(b32[i * 4 + 2]), swapLE(b32[i * 4 + 1]), swapLE(b32[i * 4 + 0]));\n    }\n    if (left) {\n      ZEROS16.set(data.subarray(blocks * BLOCK_SIZE));\n      this._updateBlock(swapLE(ZEROS32[3]), swapLE(ZEROS32[2]), swapLE(ZEROS32[1]), swapLE(ZEROS32[0]));\n      ZEROS32.fill(0); // clean tmp buffer\n    }\n    return this;\n  }\n  digestInto(out) {\n    aexists(this);\n    aoutput(out, this);\n    this.finished = true;\n    // tmp ugly hack\n    const {\n      s0,\n      s1,\n      s2,\n      s3\n    } = this;\n    const o32 = u32(out);\n    o32[0] = s0;\n    o32[1] = s1;\n    o32[2] = s2;\n    o32[3] = s3;\n    return out.reverse();\n  }\n}\nfunction wrapConstructorWithKey(hashCons) {\n  const hashC = (msg, key) => hashCons(key, msg.length).update(toBytes(msg)).digest();\n  const tmp = hashCons(new Uint8Array(16), 0);\n  hashC.outputLen = tmp.outputLen;\n  hashC.blockLen = tmp.blockLen;\n  hashC.create = (key, expectedLength) => hashCons(key, expectedLength);\n  return hashC;\n}\nexport const ghash = wrapConstructorWithKey((key, expectedLength) => new GHASH(key, expectedLength));\nexport const polyval = wrapConstructorWithKey((key, expectedLength) => new Polyval(key, expectedLength));\n//# sourceMappingURL=_polyval.js.map","map":null,"metadata":{},"sourceType":"module","externalDependencies":[]}