mirror of
https://github.com/bitwarden/browser
synced 2025-12-06 00:13:28 +00:00
[PM-22516] Fix cipher key decryption to handle new error-based API instead of null returns (#15124)
* Replace null check in cipher key decryption * Handle decryption error properly in user asymmetric key regeneration service
This commit is contained in:
@@ -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>();
|
||||
login.decrypt.mockResolvedValue(loginView);
|
||||
cipher.login = login;
|
||||
|
||||
const keyService = mock<KeyService>();
|
||||
const encryptService = mock<EncryptService>();
|
||||
const cipherService = mock<CipherService>();
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -145,14 +145,15 @@ export class Cipher extends Domain implements Decryptable<CipherView> {
|
||||
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<Cipher, CipherView>(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user