diff --git a/libs/common/src/vault/models/domain/cipher.spec.ts b/libs/common/src/vault/models/domain/cipher.spec.ts index 509a17a8a0e..9529cf67f74 100644 --- a/libs/common/src/vault/models/domain/cipher.spec.ts +++ b/libs/common/src/vault/models/domain/cipher.spec.ts @@ -57,6 +57,47 @@ describe("Cipher DTO", () => { }); }); + describe("Cipher", () => { + it("Throws error with invalid cipher key", async () => { + const cipher = new Cipher(); + cipher.id = "id"; + cipher.organizationId = "orgId"; + cipher.folderId = "folderId"; + cipher.edit = true; + cipher.viewPassword = true; + cipher.organizationUseTotp = true; + cipher.favorite = false; + cipher.revisionDate = new Date("2022-01-31T12:00:00.000Z"); + cipher.type = CipherType.Login; + cipher.name = mockEnc("EncryptedString"); + cipher.notes = mockEnc("EncryptedString"); + cipher.creationDate = new Date("2022-01-01T12:00:00.000Z"); + cipher.deletedDate = null; + cipher.reprompt = CipherRepromptType.None; + cipher.key = mockEnc("EncKey"); + + const loginView = new LoginView(); + loginView.username = "username"; + loginView.password = "password"; + + const login = mock(); + login.decrypt.mockResolvedValue(loginView); + cipher.login = login; + + const keyService = mock(); + const encryptService = mock(); + const cipherService = mock(); + + encryptService.decryptToBytes.mockResolvedValue(null); + + (window as any).bitwardenContainerService = new ContainerService(keyService, encryptService); + + await cipher.decrypt(await cipherService.getKeyForCipherKeyDecryption(cipher, mockUserId)); + + expect.toThrow("Failed to decrypt cipher key."); + }); + }); + describe("LoginCipher", () => { let cipherData: CipherData; diff --git a/libs/common/src/vault/models/domain/cipher.ts b/libs/common/src/vault/models/domain/cipher.ts index 79536f5379a..348cd54706a 100644 --- a/libs/common/src/vault/models/domain/cipher.ts +++ b/libs/common/src/vault/models/domain/cipher.ts @@ -132,10 +132,17 @@ export class Cipher extends Domain implements Decryptable { const model = new CipherView(this); let bypassValidation = true; + // If the cipher has a key, we'll attempt to decrypt it with the user/org encryption key + // and use that as the key to decrypt the cipher data. if (this.key != null) { const encryptService = Utils.getContainerService().getEncryptService(); - encKey = new SymmetricCryptoKey(await encryptService.decryptToBytes(this.key, encKey)); - bypassValidation = false; + const cipherKey = await encryptService.decryptToBytes(this.key, encKey); + if (cipherKey !== null) { + encKey = new SymmetricCryptoKey(cipherKey); + bypassValidation = false; + } else { + throw new Error("Failed to decrypt cipher key."); + } } await this.decryptObj(