'use strict'; var oneWebcrypto = require('one-webcrypto'); class BufferTools { static bitShiftLeft(input) { const output = new Uint8Array(input.length); let overflow = 0; for (let i = input.length - 1; i >= 0; i--) { output[i] = input[i] << 1 | overflow; overflow = input[i] & 128 ? 1 : 0; } return output; } static xor(a, b) { const length = Math.min(a.length, b.length); const output = new Uint8Array(length); for (let i = 0; i < length; i++) { output[i] = a[i] ^ b[i]; } return output; } static toBinaryString(buffer) { let binary = ""; for (let i = 0; i < buffer.length; i++) { for (let b = 7; b >= 0; b--) { binary += buffer[i] & 1 << b ? "1" : "0"; } } return binary; } } var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => { __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); return value; }; class AesCmac { constructor(key) { __publicField(this, "blockSize", 16); __publicField(this, "supportedLengths", [16, 24, 32]); __publicField(this, "subkeys"); __publicField(this, "key"); if (key instanceof Uint8Array === false) { throw new Error("The key must be provided as a Uint8Array."); } if (this.supportedLengths.includes(key.length) === false) { throw new Error("Key size must be 128, 192, or 256 bits."); } this.key = oneWebcrypto.webcrypto.subtle.importKey("raw", key, "AES-CBC", false, ["encrypt"]); } async generateSubkeys() { const rb = Uint8Array.from([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135 ]); const z = new Uint8Array(this.blockSize); const l = await this.aes(z); let key1 = BufferTools.bitShiftLeft(l); if (l[0] & 128) { key1 = BufferTools.xor(key1, rb); } let key2 = BufferTools.bitShiftLeft(key1); if (key1[0] & 128) { key2 = BufferTools.xor(key2, rb); } return { key1, key2 }; } async getSubKeys() { if (!this.subkeys) { this.subkeys = await this.generateSubkeys(); } const key1 = new Uint8Array(this.blockSize); key1.set(this.subkeys.key1); const key2 = new Uint8Array(this.blockSize); key2.set(this.subkeys.key2); return { key1, key2 }; } async calculate(message) { if (message instanceof Uint8Array === false) { throw new Error("The message must be provided as a Uint8Array."); } const blockCount = this.getBlockCount(message); let x = new Uint8Array(this.blockSize); let y = new Uint8Array(0); for (let i = 0; i < blockCount - 1; i++) { const from = i * this.blockSize; const block = message.slice(from, from + this.blockSize); y = BufferTools.xor(x, block); x = await this.aes(y); } y = BufferTools.xor(x, await this.getLastBlock(message)); x = await this.aes(y); return x; } getBlockCount(message) { const blockCount = Math.ceil(message.length / this.blockSize); return blockCount === 0 ? 1 : blockCount; } async aes(message) { const iv = new Uint8Array(this.blockSize); if ("then" in this.key) { this.key = await this.key; } const aesCiphertext = await oneWebcrypto.webcrypto.subtle.encrypt({ name: "AES-CBC", iv }, this.key, message); return new Uint8Array(aesCiphertext.slice(0, 16)); } async getLastBlock(message) { if (!this.subkeys) { this.subkeys = await this.generateSubkeys(); } const blockCount = this.getBlockCount(message); const paddedBlock = this.padding(message, blockCount - 1); let complete = false; if (message.length > 0) { complete = message.length % this.blockSize === 0; } const key = complete ? this.subkeys.key1 : this.subkeys.key2; return BufferTools.xor(paddedBlock, key); } padding(message, blockIndex) { const block = new Uint8Array(this.blockSize); const from = blockIndex * this.blockSize; const slice = message.slice(from, from + this.blockSize); block.set(slice); if (slice.length !== this.blockSize) { block[slice.length] = 128; } return block; } } exports.AesCmac = AesCmac; //# sourceMappingURL=aes-cmac.cjs.map