From 44d22af1047afe32c30ee3a2c8be012cc9497fe5 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Sat, 13 Jul 2024 13:48:36 +0100 Subject: [PATCH] Use webcrypto for aes and sha256 --- src/checksum.ts | 15 ++++++++++++++- src/cipher.ts | 40 ++++++++++++++++++++++++++++++++++++++++ src/kdf.ts | 4 ++-- 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/checksum.ts b/src/checksum.ts index 09899fa..05d3047 100644 --- a/src/checksum.ts +++ b/src/checksum.ts @@ -27,7 +27,20 @@ export function checksum(mod: IChecksumModule, key: Uint8Array, ciphertext: Uint export async function verifyChecksum(mod: IChecksumModule, key: Uint8Array, ciphertext: Uint8Array): Promise { if (mod.function === "sha256") { - return equalsBytes(hexToBytes(mod.message), sha256(checksumData(key, ciphertext))); + if (globalThis?.crypto?.subtle) { + return verifyChecksumWebCrypto(mod, key, ciphertext); + } + return equalsBytes(hexToBytes(mod.message), sha256(checksumData(key as Uint8Array, ciphertext))); + } else { + throw new Error("Invalid checksum type"); + } +} + +async function verifyChecksumWebCrypto(mod: IChecksumModule, key: Uint8Array, ciphertext: Uint8Array) { + if (mod.function === "sha256") { + const data = checksumData(key, ciphertext); + const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", data)); + return equalsBytes(hexToBytes(mod.message), digest); } else { throw new Error("Invalid checksum type"); } diff --git a/src/cipher.ts b/src/cipher.ts index 0da99d4..d32d06f 100644 --- a/src/cipher.ts +++ b/src/cipher.ts @@ -16,6 +16,9 @@ export function defaultAes128CtrModule(): Pick { if (mod.function === "aes-128-ctr") { try { + if (globalThis?.crypto?.subtle) { + return await cipherEncryptWebCrypto(mod, key, data); + } return await aesEncrypt( data, key, @@ -31,9 +34,27 @@ export async function cipherEncrypt(mod: ICipherModule, key: Uint8Array, data: U } } +export async function cipherEncryptWebCrypto( + mod: ICipherModule, + key: Uint8Array, + data: Uint8Array +): Promise { + const cryptoKey = await crypto.subtle.importKey( + "raw", + key, + {name: "AES-CTR"}, + false, + ["encrypt"] + ); + return new Uint8Array(await crypto.subtle.encrypt(pickAlgorithm(mod), cryptoKey, data)); +} + export async function cipherDecrypt(mod: ICipherModule, key: Uint8Array): Promise { if (mod.function === "aes-128-ctr") { try { + if (globalThis?.crypto?.subtle) { + return await cipherDecryptWebCrypto(mod, key); + } return await aesDecrypt( hexToBytes(mod.message), key, @@ -48,3 +69,22 @@ export async function cipherDecrypt(mod: ICipherModule, key: Uint8Array): Promis throw new Error("Invalid cipher type"); } } + +async function cipherDecryptWebCrypto(mod: ICipherModule, key: Uint8Array): Promise { + const cryptoKey = await crypto.subtle.importKey( + "raw", + key, + {name: "AES-CTR"}, + false, + ["decrypt"] + ); + return new Uint8Array(await crypto.subtle.decrypt(pickAlgorithm(mod), cryptoKey, hexToBytes(mod.message))); +} + +function pickAlgorithm(mod: ICipherModule): AesCtrParams { + if (mod.function === "aes-128-ctr") { + return { name: "AES-CTR", counter: hexToBytes(mod.params.iv), length: 128 }; + } else { + throw new Error("Invalid cipher type"); + } +} diff --git a/src/kdf.ts b/src/kdf.ts index 05dd3b9..893191b 100644 --- a/src/kdf.ts +++ b/src/kdf.ts @@ -60,7 +60,7 @@ async function doPbkdf2WebCrypto(params: IPbkdf2KdfModule["params"], password: U const passwordKey = await crypto.subtle.importKey( "raw", password, - "PBKDF2", + {name: "PBKDF2"}, false, ["deriveKey"], ); @@ -72,7 +72,7 @@ async function doPbkdf2WebCrypto(params: IPbkdf2KdfModule["params"], password: U hash: pickHash(params.prf.slice(5)), }, passwordKey, - { name: "AES-GCM", length: params.dklen * 8 }, + {name: "AES-CTR", length: params.dklen * 8}, true, ["encrypt", "decrypt"] );