{"version":3,"file":"aes-cmac.mjs","sources":["../src/BufferTools.ts","../src/AesCmac.ts"],"sourcesContent":["export class BufferTools {\n  public static bitShiftLeft(input: Uint8Array): Uint8Array<ArrayBuffer> {\n    const output = new Uint8Array(input.length);\n    let overflow = 0;\n    for (let i = input.length - 1; i >= 0; i--) {\n      const byte = input[i]!;\n      output[i] = (byte << 1) | overflow;\n      overflow = byte & 0x80 ? 1 : 0;\n    }\n    return output;\n  }\n\n  public static xor(a: Uint8Array, b: Uint8Array): Uint8Array<ArrayBuffer> {\n    const length = Math.min(a.length, b.length);\n    const output = new Uint8Array(length);\n    for (let i = 0; i < length; i++) {\n      output[i] = a[i]! ^ b[i]!;\n    }\n    return output;\n  }\n\n  public static toBinaryString(input: Uint8Array): string {\n    let binary = \"\";\n    for (let i = 0; i < input.length; i++) {\n      for (let b = 7; b >= 0; b--) {\n        const byte = input[i]!;\n        binary += byte & (1 << b) ? \"1\" : \"0\";\n      }\n    }\n    return binary;\n  }\n}\n","import type { webcrypto } from \"node:crypto\";\nimport { BufferTools } from \"./BufferTools\";\n\nexport class AesCmac {\n  private readonly blockSize = 16;\n  private readonly supportedLengths = [16, 24, 32];\n\n  private subkeys?: { key1: Uint8Array; key2: Uint8Array };\n  private key: webcrypto.CryptoKey | PromiseLike<webcrypto.CryptoKey>;\n\n  public constructor(key: Uint8Array) {\n    if (key instanceof Uint8Array === false) {\n      throw new Error(\"The key must be provided as a Uint8Array.\");\n    }\n\n    if (this.supportedLengths.includes(key.length) === false) {\n      throw new Error(\"Key size must be 128, 192, or 256 bits.\");\n    }\n\n    // note that this is a Promise<CryptoKey> at this point, which we await in aes()\n    this.key = crypto.subtle.importKey(\"raw\", key, \"AES-CBC\", false, [\"encrypt\"]);\n  }\n\n  private async generateSubkeys(): Promise<{\n    key1: Uint8Array;\n    key2: Uint8Array;\n  }> {\n    const rb = Uint8Array.from([\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n      0x87,\n    ]);\n\n    const z = new Uint8Array(this.blockSize);\n    const l = await this.aes(z);\n\n    let key1 = BufferTools.bitShiftLeft(l);\n    if (l[0]! & 0x80) {\n      key1 = BufferTools.xor(key1, rb);\n    }\n\n    let key2 = BufferTools.bitShiftLeft(key1);\n    if (key1[0]! & 0x80) {\n      key2 = BufferTools.xor(key2, rb);\n    }\n\n    return { key1, key2 };\n  }\n\n  public async getSubKeys(): Promise<{ key1: Uint8Array; key2: Uint8Array }> {\n    // subkeys are generated lazily because we cannot await in a constructor\n    if (!this.subkeys) {\n      this.subkeys = await this.generateSubkeys();\n    }\n\n    const key1 = new Uint8Array(this.blockSize);\n    key1.set(this.subkeys.key1);\n\n    const key2 = new Uint8Array(this.blockSize);\n    key2.set(this.subkeys.key2);\n\n    return { key1, key2 };\n  }\n\n  public async calculate(message: Uint8Array): Promise<Uint8Array> {\n    if (message instanceof Uint8Array === false) {\n      throw new Error(\"The message must be provided as a Uint8Array.\");\n    }\n\n    const blockCount = this.getBlockCount(message);\n\n    let x = new Uint8Array(this.blockSize);\n    let y = new Uint8Array(0);\n\n    for (let i = 0; i < blockCount - 1; i++) {\n      const from = i * this.blockSize;\n      const block = message.slice(from, from + this.blockSize);\n      y = BufferTools.xor(x, block);\n      x = await this.aes(y);\n    }\n\n    y = BufferTools.xor(x, await this.getLastBlock(message));\n    x = await this.aes(y);\n\n    return x;\n  }\n\n  private getBlockCount(message: Uint8Array): number {\n    const blockCount = Math.ceil(message.length / this.blockSize);\n    return blockCount === 0 ? 1 : blockCount;\n  }\n\n  private async aes(message: Uint8Array): Promise<Uint8Array<ArrayBuffer>> {\n    const iv = new Uint8Array(this.blockSize);\n\n    /// because constructors cannot be async, we await the key import here\n    if (\"then\" in this.key) {\n      this.key = await this.key;\n    }\n\n    const aesCiphertext = (await crypto.subtle.encrypt(\n      { name: \"AES-CBC\", iv },\n      this.key,\n      message,\n    )) as ArrayBuffer;\n\n    return new Uint8Array(aesCiphertext.slice(0, 16));\n  }\n\n  private async getLastBlock(message: Uint8Array): Promise<Uint8Array> {\n    if (!this.subkeys) {\n      this.subkeys = await this.generateSubkeys();\n    }\n\n    const blockCount = this.getBlockCount(message);\n    const paddedBlock = this.padding(message, blockCount - 1);\n\n    let complete = false;\n    if (message.length > 0) {\n      complete = message.length % this.blockSize === 0;\n    }\n\n    const key = complete ? this.subkeys.key1 : this.subkeys.key2;\n    return BufferTools.xor(paddedBlock, key);\n  }\n\n  private padding(message: Uint8Array, blockIndex: number): Uint8Array {\n    const block = new Uint8Array(this.blockSize);\n\n    const from = blockIndex * this.blockSize;\n\n    const slice = message.slice(from, from + this.blockSize);\n    block.set(slice);\n\n    if (slice.length !== this.blockSize) {\n      block[slice.length] = 0x80;\n    }\n\n    return block;\n  }\n}\n"],"names":[],"mappings":"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"}