mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 00:03:56 +00:00
[PM-16699] Add decrypt trace for decrypt failures (#12749)
* Improve decrypt failure logging * Rename decryptcontext to decrypttrace * Improve docs * Revert changes to decrypt logic * Revert keyservice decryption logic change * Undo one more change to decrypt logic
This commit is contained in:
@@ -101,7 +101,7 @@ describe("Attachment", () => {
|
||||
it("uses the provided key without depending on KeyService", async () => {
|
||||
const providedKey = mock<SymmetricCryptoKey>();
|
||||
|
||||
await attachment.decrypt(null, providedKey);
|
||||
await attachment.decrypt(null, "", providedKey);
|
||||
|
||||
expect(keyService.getUserKeyWithLegacySupport).not.toHaveBeenCalled();
|
||||
expect(encryptService.decryptToBytes).toHaveBeenCalledWith(attachment.key, providedKey);
|
||||
@@ -111,7 +111,7 @@ describe("Attachment", () => {
|
||||
const orgKey = mock<OrgKey>();
|
||||
keyService.getOrgKey.calledWith("orgId").mockResolvedValue(orgKey);
|
||||
|
||||
await attachment.decrypt("orgId", null);
|
||||
await attachment.decrypt("orgId", "", null);
|
||||
|
||||
expect(keyService.getOrgKey).toHaveBeenCalledWith("orgId");
|
||||
expect(encryptService.decryptToBytes).toHaveBeenCalledWith(attachment.key, orgKey);
|
||||
@@ -121,7 +121,7 @@ describe("Attachment", () => {
|
||||
const userKey = mock<UserKey>();
|
||||
keyService.getUserKeyWithLegacySupport.mockResolvedValue(userKey);
|
||||
|
||||
await attachment.decrypt(null, null);
|
||||
await attachment.decrypt(null, "", null);
|
||||
|
||||
expect(keyService.getUserKeyWithLegacySupport).toHaveBeenCalled();
|
||||
expect(encryptService.decryptToBytes).toHaveBeenCalledWith(attachment.key, userKey);
|
||||
|
||||
@@ -38,7 +38,11 @@ export class Attachment extends Domain {
|
||||
);
|
||||
}
|
||||
|
||||
async decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise<AttachmentView> {
|
||||
async decrypt(
|
||||
orgId: string,
|
||||
context = "No Cipher Context",
|
||||
encKey?: SymmetricCryptoKey,
|
||||
): Promise<AttachmentView> {
|
||||
const view = await this.decryptObj(
|
||||
new AttachmentView(this),
|
||||
{
|
||||
@@ -46,6 +50,7 @@ export class Attachment extends Domain {
|
||||
},
|
||||
orgId,
|
||||
encKey,
|
||||
"DomainType: Attachment; " + context,
|
||||
);
|
||||
|
||||
if (this.key != null) {
|
||||
|
||||
@@ -37,7 +37,11 @@ export class Card extends Domain {
|
||||
);
|
||||
}
|
||||
|
||||
decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise<CardView> {
|
||||
async decrypt(
|
||||
orgId: string,
|
||||
context = "No Cipher Context",
|
||||
encKey?: SymmetricCryptoKey,
|
||||
): Promise<CardView> {
|
||||
return this.decryptObj(
|
||||
new CardView(),
|
||||
{
|
||||
@@ -50,6 +54,7 @@ export class Card extends Domain {
|
||||
},
|
||||
orgId,
|
||||
encKey,
|
||||
"DomainType: Card; " + context,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +136,11 @@ export class Cipher extends Domain implements Decryptable<CipherView> {
|
||||
|
||||
if (this.key != null) {
|
||||
const encryptService = Utils.getContainerService().getEncryptService();
|
||||
const keyBytes = await encryptService.decryptToBytes(this.key, encKey);
|
||||
const keyBytes = await encryptService.decryptToBytes(
|
||||
this.key,
|
||||
encKey,
|
||||
`Cipher Id: ${this.id}; Content: CipherKey; IsEncryptedByOrgKey: ${this.organizationId != null}`,
|
||||
);
|
||||
if (keyBytes == null) {
|
||||
model.name = "[error: cannot decrypt]";
|
||||
model.decryptionFailure = true;
|
||||
@@ -158,19 +162,36 @@ export class Cipher extends Domain implements Decryptable<CipherView> {
|
||||
|
||||
switch (this.type) {
|
||||
case CipherType.Login:
|
||||
model.login = await this.login.decrypt(this.organizationId, bypassValidation, encKey);
|
||||
model.login = await this.login.decrypt(
|
||||
this.organizationId,
|
||||
bypassValidation,
|
||||
`Cipher Id: ${this.id}`,
|
||||
encKey,
|
||||
);
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
model.secureNote = await this.secureNote.decrypt(this.organizationId, encKey);
|
||||
model.secureNote = await this.secureNote.decrypt(
|
||||
this.organizationId,
|
||||
`Cipher Id: ${this.id}`,
|
||||
encKey,
|
||||
);
|
||||
break;
|
||||
case CipherType.Card:
|
||||
model.card = await this.card.decrypt(this.organizationId, encKey);
|
||||
model.card = await this.card.decrypt(this.organizationId, `Cipher Id: ${this.id}`, encKey);
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
model.identity = await this.identity.decrypt(this.organizationId, encKey);
|
||||
model.identity = await this.identity.decrypt(
|
||||
this.organizationId,
|
||||
`Cipher Id: ${this.id}`,
|
||||
encKey,
|
||||
);
|
||||
break;
|
||||
case CipherType.SshKey:
|
||||
model.sshKey = await this.sshKey.decrypt(this.organizationId, encKey);
|
||||
model.sshKey = await this.sshKey.decrypt(
|
||||
this.organizationId,
|
||||
`Cipher Id: ${this.id}`,
|
||||
encKey,
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -181,7 +202,7 @@ export class Cipher extends Domain implements Decryptable<CipherView> {
|
||||
await this.attachments.reduce((promise, attachment) => {
|
||||
return promise
|
||||
.then(() => {
|
||||
return attachment.decrypt(this.organizationId, encKey);
|
||||
return attachment.decrypt(this.organizationId, `Cipher Id: ${this.id}`, encKey);
|
||||
})
|
||||
.then((decAttachment) => {
|
||||
attachments.push(decAttachment);
|
||||
|
||||
@@ -61,7 +61,11 @@ export class Identity extends Domain {
|
||||
);
|
||||
}
|
||||
|
||||
decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise<IdentityView> {
|
||||
decrypt(
|
||||
orgId: string,
|
||||
context: string = "No Cipher Context",
|
||||
encKey?: SymmetricCryptoKey,
|
||||
): Promise<IdentityView> {
|
||||
return this.decryptObj(
|
||||
new IdentityView(),
|
||||
{
|
||||
@@ -86,6 +90,7 @@ export class Identity extends Domain {
|
||||
},
|
||||
orgId,
|
||||
encKey,
|
||||
"DomainType: Identity; " + context,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,11 @@ export class LoginUri extends Domain {
|
||||
);
|
||||
}
|
||||
|
||||
decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise<LoginUriView> {
|
||||
decrypt(
|
||||
orgId: string,
|
||||
context: string = "No Cipher Context",
|
||||
encKey?: SymmetricCryptoKey,
|
||||
): Promise<LoginUriView> {
|
||||
return this.decryptObj(
|
||||
new LoginUriView(this),
|
||||
{
|
||||
@@ -41,6 +45,7 @@ export class LoginUri extends Domain {
|
||||
},
|
||||
orgId,
|
||||
encKey,
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ export class Login extends Domain {
|
||||
async decrypt(
|
||||
orgId: string,
|
||||
bypassValidation: boolean,
|
||||
context: string = "No Cipher Context",
|
||||
encKey?: SymmetricCryptoKey,
|
||||
): Promise<LoginView> {
|
||||
const view = await this.decryptObj(
|
||||
@@ -66,6 +67,7 @@ export class Login extends Domain {
|
||||
},
|
||||
orgId,
|
||||
encKey,
|
||||
`DomainType: Login; ${context}`,
|
||||
);
|
||||
|
||||
if (this.uris != null) {
|
||||
@@ -76,7 +78,7 @@ export class Login extends Domain {
|
||||
continue;
|
||||
}
|
||||
|
||||
const uri = await this.uris[i].decrypt(orgId, encKey);
|
||||
const uri = await this.uris[i].decrypt(orgId, context, encKey);
|
||||
// URIs are shared remotely after decryption
|
||||
// we need to validate that the string hasn't been changed by a compromised server
|
||||
// This validation is tied to the existence of cypher.key for backwards compatibility
|
||||
|
||||
@@ -32,6 +32,7 @@ export class Password extends Domain {
|
||||
},
|
||||
orgId,
|
||||
encKey,
|
||||
"DomainType: PasswordHistory",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,12 @@ export class SecureNote extends Domain {
|
||||
this.type = obj.type;
|
||||
}
|
||||
|
||||
decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise<SecureNoteView> {
|
||||
return Promise.resolve(new SecureNoteView(this));
|
||||
async decrypt(
|
||||
orgId: string,
|
||||
context = "No Cipher Context",
|
||||
encKey?: SymmetricCryptoKey,
|
||||
): Promise<SecureNoteView> {
|
||||
return new SecureNoteView(this);
|
||||
}
|
||||
|
||||
toSecureNoteData(): SecureNoteData {
|
||||
|
||||
@@ -32,7 +32,11 @@ export class SshKey extends Domain {
|
||||
);
|
||||
}
|
||||
|
||||
decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise<SshKeyView> {
|
||||
decrypt(
|
||||
orgId: string,
|
||||
context = "No Cipher Context",
|
||||
encKey?: SymmetricCryptoKey,
|
||||
): Promise<SshKeyView> {
|
||||
return this.decryptObj(
|
||||
new SshKeyView(),
|
||||
{
|
||||
@@ -42,6 +46,7 @@ export class SshKey extends Domain {
|
||||
},
|
||||
orgId,
|
||||
encKey,
|
||||
"DomainType: SshKey; " + context,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user