diff --git a/libs/common/src/vault/models/domain/cipher.spec.ts b/libs/common/src/vault/models/domain/cipher.spec.ts index 1b97ad06bc3..ba83cf38ae4 100644 --- a/libs/common/src/vault/models/domain/cipher.spec.ts +++ b/libs/common/src/vault/models/domain/cipher.spec.ts @@ -68,6 +68,68 @@ describe("Cipher DTO", () => { }); }); + it("Decrypt should handle cipher key error", 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"); + cipher.permissions = new CipherPermissionsApi(); + + 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.unwrapSymmetricKey.mockRejectedValue(new Error("Failed to unwrap key")); + + (window as any).bitwardenContainerService = new ContainerService(keyService, encryptService); + + const cipherView = await cipher.decrypt( + await cipherService.getKeyForCipherKeyDecryption(cipher, mockUserId), + ); + + expect(cipherView).toMatchObject({ + id: "id", + organizationId: "orgId", + folderId: "folderId", + name: "[error: cannot decrypt]", + type: 1, + favorite: false, + organizationUseTotp: true, + edit: true, + viewPassword: true, + decryptionFailure: true, + collectionIds: undefined, + revisionDate: new Date("2022-01-31T12:00:00.000Z"), + creationDate: new Date("2022-01-01T12:00:00.000Z"), + deletedDate: null, + reprompt: 0, + localData: undefined, + permissions: new CipherPermissionsApi(), + }); + + expect(login.decrypt).not.toHaveBeenCalled(); + }); + 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 d816ebb24ce..e6d11a82b69 100644 --- a/libs/common/src/vault/models/domain/cipher.ts +++ b/libs/common/src/vault/models/domain/cipher.ts @@ -145,14 +145,15 @@ export class Cipher extends Domain implements Decryptable { if (this.key != null) { const encryptService = Utils.getContainerService().getEncryptService(); - const cipherKey = await encryptService.unwrapSymmetricKey(this.key, encKey); - if (cipherKey == null) { + try { + const cipherKey = await encryptService.unwrapSymmetricKey(this.key, encKey); + encKey = cipherKey; + bypassValidation = false; + } catch { model.name = "[error: cannot decrypt]"; model.decryptionFailure = true; return model; } - encKey = cipherKey; - bypassValidation = false; } await this.decryptObj( diff --git a/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.ts b/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.ts index 096e9236a30..dbdac6bfc99 100644 --- a/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.ts +++ b/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.ts @@ -162,17 +162,26 @@ export class DefaultUserAsymmetricKeysRegenerationService const ciphers = await this.cipherService.getAll(userId); const cipher = ciphers.find((cipher) => cipher.organizationId == null); - if (cipher != null) { - try { - await cipher.decrypt(userKey); - return true; - } catch (error) { + if (!cipher) { + return false; + } + + try { + const cipherView = await cipher.decrypt(userKey); + + if (cipherView.decryptionFailure) { this.logService.error( - "[UserAsymmetricKeyRegeneration] User Symmetric Key validation error: " + error, + "[UserAsymmetricKeyRegeneration] User Symmetric Key validation error: Cipher decryption failed", ); return false; } + + return true; + } catch (error) { + this.logService.error( + "[UserAsymmetricKeyRegeneration] User Symmetric Key validation error: " + error, + ); + return false; } - return false; } }