diff --git a/libs/common/src/platform/services/key-generation.service.spec.ts b/libs/common/src/platform/services/key-generation.service.spec.ts index f75eaeb25be..0a9e997b428 100644 --- a/libs/common/src/platform/services/key-generation.service.spec.ts +++ b/libs/common/src/platform/services/key-generation.service.spec.ts @@ -5,6 +5,7 @@ import { PBKDF2KdfConfig, Argon2KdfConfig } from "@bitwarden/key-management"; import { CryptoFunctionService } from "../../key-management/crypto/abstractions/crypto-function.service"; import { CsprngArray } from "../../types/csprng"; import { EncryptionType } from "../enums"; +import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key"; import { KeyGenerationService } from "./key-generation.service"; @@ -98,4 +99,23 @@ describe("KeyGenerationService", () => { expect(key.inner().type).toEqual(EncryptionType.AesCbc256_B64); }); }); + + describe("stretchKey", () => { + it("should stretch a key", async () => { + const key = new SymmetricCryptoKey(new Uint8Array(32)); + + cryptoFunctionService.hkdf.mockResolvedValue(new Uint8Array(64)); + + const stretchedKey = await sut.stretchKey(key); + + expect(stretchedKey.inner().type).toEqual(EncryptionType.AesCbc256_HmacSha256_B64); + }); + it("should throw if key is not 32 bytes", async () => { + const key = new SymmetricCryptoKey(new Uint8Array(64)); + + await expect(sut.stretchKey(key)).rejects.toThrow( + "Key passed into stretchKey is not a 256-bit key.", + ); + }); + }); }); diff --git a/libs/common/src/platform/services/key-generation.service.ts b/libs/common/src/platform/services/key-generation.service.ts index 8f9e6856aa0..dcd1f4f95d7 100644 --- a/libs/common/src/platform/services/key-generation.service.ts +++ b/libs/common/src/platform/services/key-generation.service.ts @@ -1,11 +1,11 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { MasterKey, PinKey } from "@bitwarden/common/types/key"; import { KdfConfig, PBKDF2KdfConfig, Argon2KdfConfig, KdfType } from "@bitwarden/key-management"; import { CryptoFunctionService } from "../../key-management/crypto/abstractions/crypto-function.service"; import { CsprngArray } from "../../types/csprng"; import { KeyGenerationService as KeyGenerationServiceAbstraction } from "../abstractions/key-generation.service"; +import { EncryptionType } from "../enums"; import { Utils } from "../misc/utils"; import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key"; @@ -79,7 +79,13 @@ export class KeyGenerationService implements KeyGenerationServiceAbstraction { return new SymmetricCryptoKey(key); } - async stretchKey(key: MasterKey | PinKey): Promise { + async stretchKey(key: SymmetricCryptoKey): Promise { + // The key to be stretched is actually usually the output of a KDF, and not actually meant for AesCbc256_B64 encryption, + // but has the same key length. Only 256-bit key materials should be stretched. + if (key.inner().type != EncryptionType.AesCbc256_B64) { + throw new Error("Key passed into stretchKey is not a 256-bit key."); + } + const newKey = new Uint8Array(64); // Master key and pin key are always 32 bytes const encKey = await this.cryptoFunctionService.hkdfExpand(