aes-cmac
Version:
AES-CMAC implementation in typescript
1 lines • 10.5 kB
Source Map (JSON)
{"version":3,"file":"aes-cmac.cjs","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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"}