diff --git a/src/mechs/aes/key.ts b/src/mechs/aes/key.ts index 2da5be6..fb8ca50 100644 --- a/src/mechs/aes/key.ts +++ b/src/mechs/aes/key.ts @@ -20,6 +20,8 @@ export class AesCryptoKey extends SymmetricKey { return `A${this.algorithm.length}GCM`; case "AES-KW": return `A${this.algorithm.length}KW`; + case "AES-CMAC": + return `A${this.algorithm.length}CMAC`; default: throw new core.AlgorithmError("Unsupported algorithm name"); } diff --git a/src/subtle.ts b/src/subtle.ts index 28f317e..53428ee 100644 --- a/src/subtle.ts +++ b/src/subtle.ts @@ -1,9 +1,10 @@ import * as core from "webcrypto-core"; import { - AesCbcProvider, AesCtrProvider, AesGcmProvider, AesKwProvider, - DesCbcProvider, DesEde3CbcProvider, - EcdhProvider, EcdsaProvider, - HkdfProvider, HmacProvider, + AesCbcProvider, AesCmacProvider, AesCtrProvider, AesGcmProvider, + AesKwProvider, DesCbcProvider, + DesEde3CbcProvider, EcdhProvider, + EcdsaProvider, HkdfProvider, + HmacProvider, Pbkdf2Provider, RsaOaepProvider, RsaPssProvider, RsaSsaProvider, Sha1Provider, Sha256Provider, Sha384Provider, Sha512Provider, @@ -17,6 +18,7 @@ export class SubtleCrypto extends core.SubtleCrypto { this.providers.set(new AesCbcProvider()); this.providers.set(new AesCtrProvider()); this.providers.set(new AesGcmProvider()); + this.providers.set(new AesCmacProvider()); this.providers.set(new AesKwProvider()); //#endregion diff --git a/test/aes.ts b/test/aes.ts index 0e50692..98f1291 100644 --- a/test/aes.ts +++ b/test/aes.ts @@ -367,6 +367,117 @@ context("AES", () => { }, //#endregion + //#region AES-CMAC + { + name: "AES-128-CMAC", + only: true, + actions: { + generateKey: [ + { + algorithm: { name: "AES-CMAC", length: 128 } as AesKeyGenParams, + extractable: true, + keyUsages: ["sign", "verify"], + }, + ], + sign: [ + { + algorithm: { + name: "AES-CMAC", + length: 256, + } as AesCmacParams, + data: Buffer.from("test message"), + signature: Buffer.from("98038e3ad7500d11005b6789c6cf9672", "hex"), + key: { + format: "raw", + data: Buffer.from("1234567890abcdef"), + algorithm: { name: "AES-CMAC" }, + extractable: true, + keyUsages: ["sign", "verify"], + }, + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("1234567890abcdef"), + algorithm: "AES-CMAC", + extractable: true, + keyUsages: ["sign", "verify"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A128CMAC", + k: "MTIzNDU2Nzg5MGFiY2RlZg", + ext: true, + key_ops: ["sign", "verify"], + }, + algorithm: "AES-CMAC", + extractable: true, + keyUsages: ["sign", "verify"], + }, + ], + }, + }, + { + name: "AES-192-CMAC", + only: true, + actions: { + generateKey: [ + { + algorithm: { name: "AES-CMAC", length: 192 } as AesKeyGenParams, + extractable: true, + keyUsages: ["sign", "verify"], + }, + ], + sign: [ + { + algorithm: { + name: "AES-CMAC", + length: 192, + } as AesCmacParams, + data: Buffer.from("test message"), + signature: Buffer.from("fe5c107cbcafd8a0a47a83c7bf55f1d0", "hex"), + key: { + format: "raw", + data: Buffer.from("1234567890abcdef12345678"), + algorithm: { name: "AES-CMAC" }, + extractable: true, + keyUsages: ["sign", "verify"], + }, + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("1234567890abcdef12345678"), + algorithm: "AES-CMAC", + extractable: true, + keyUsages: ["sign", "verify"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A192CMAC", + k: "MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4", + ext: true, + key_ops: ["sign", "verify"], + }, + algorithm: "AES-CMAC", + extractable: true, + keyUsages: ["sign", "verify"], + }, + ], + }, + }, + //#endregion + //#region AES-GCM { name: "AES-128-GCM",