mirror of
https://github.com/bitwarden/browser
synced 2026-02-28 02:23:25 +00:00
decrypt attachment content using sdk
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { CipherListView } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { UserId } from "../../types/guid";
|
||||
import { Attachment } from "../models/domain/attachment";
|
||||
import { Cipher } from "../models/domain/cipher";
|
||||
import { CipherView } from "../models/view/cipher.view";
|
||||
|
||||
@@ -26,4 +27,20 @@ export abstract class CipherEncryptionService {
|
||||
* @returns A promise that resolves to an array of decrypted cipher list views
|
||||
*/
|
||||
abstract decryptCipherList(ciphers: Cipher[], userId: UserId): Promise<CipherListView[]>;
|
||||
/**
|
||||
* Decrypts an array buffer using the SDK for the given userId.
|
||||
*
|
||||
* @param cipher The encrypted cipher object that owns the attachment
|
||||
* @param attachment The encrypted attachment object
|
||||
* @param encryptedContent The encrypted content as a Uint8Array
|
||||
* @param userId The user ID whose key will be used for decryption
|
||||
*
|
||||
* @returns A promise that resolves to the decrypted content
|
||||
*/
|
||||
abstract decryptAttachmentContent(
|
||||
cipher: Cipher,
|
||||
attachment: Attachment,
|
||||
encryptedContent: Uint8Array,
|
||||
userId: UserId,
|
||||
): Promise<Uint8Array>;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
Cipher as SdkCipher,
|
||||
CipherType as SdkCipherType,
|
||||
CipherView as SdkCipherView,
|
||||
Attachment as SdkAttachment,
|
||||
} from "@bitwarden/sdk-internal";
|
||||
|
||||
import { mockEnc } from "../../../spec";
|
||||
@@ -16,6 +17,7 @@ import { UserId } from "../../types/guid";
|
||||
import { CipherRepromptType, CipherType } from "../enums";
|
||||
import { CipherPermissionsApi } from "../models/api/cipher-permissions.api";
|
||||
import { CipherData } from "../models/data/cipher.data";
|
||||
import { Attachment } from "../models/domain/attachment";
|
||||
import { Cipher } from "../models/domain/cipher";
|
||||
import { CipherView } from "../models/view/cipher.view";
|
||||
import { Fido2CredentialView } from "../models/view/fido2-credential.view";
|
||||
@@ -82,6 +84,9 @@ describe("DefaultCipherEncryptionService", () => {
|
||||
decrypt: jest.fn(),
|
||||
decrypt_fido2_credentials: jest.fn(),
|
||||
}),
|
||||
attachments: jest.fn().mockReturnValue({
|
||||
decrypt_buffer: jest.fn(),
|
||||
}),
|
||||
}),
|
||||
};
|
||||
const mockRef = {
|
||||
@@ -232,4 +237,34 @@ describe("DefaultCipherEncryptionService", () => {
|
||||
expect(result.name).toBe("[error: cannot decrypt]");
|
||||
});
|
||||
});
|
||||
|
||||
describe("decryptAttachmentContent", () => {
|
||||
it("should decrypt attachment content successfully", async () => {
|
||||
const cipher = new Cipher(cipherData);
|
||||
const attachment = new Attachment(cipherData.attachments![0]);
|
||||
const encryptedContent = new Uint8Array([1, 2, 3, 4]);
|
||||
const expectedDecryptedContent = new Uint8Array([5, 6, 7, 8]);
|
||||
|
||||
jest.spyOn(cipher, "toSdkCipher").mockReturnValue({ id: "id" } as SdkCipher);
|
||||
jest.spyOn(attachment, "toSdkAttachment").mockReturnValue({ id: "a1" } as SdkAttachment);
|
||||
|
||||
mockSdkClient.vault().attachments().decrypt_buffer.mockReturnValue(expectedDecryptedContent);
|
||||
|
||||
const result = await cipherEncryptionService.decryptAttachmentContent(
|
||||
cipher,
|
||||
attachment,
|
||||
encryptedContent,
|
||||
userId,
|
||||
);
|
||||
|
||||
expect(result).toEqual(expectedDecryptedContent);
|
||||
expect(cipher.toSdkCipher).toHaveBeenCalled();
|
||||
expect(attachment.toSdkAttachment).toHaveBeenCalled();
|
||||
expect(mockSdkClient.vault().attachments().decrypt_buffer).toHaveBeenCalledWith(
|
||||
{ id: "id" },
|
||||
{ id: "a1" },
|
||||
encryptedContent,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,6 +7,7 @@ import { SdkService } from "../../platform/abstractions/sdk/sdk.service";
|
||||
import { UserId } from "../../types/guid";
|
||||
import { CipherEncryptionService } from "../abstractions/cipher-encryption.service";
|
||||
import { CipherType } from "../enums";
|
||||
import { Attachment } from "../models/domain/attachment";
|
||||
import { Cipher } from "../models/domain/cipher";
|
||||
import { CipherView } from "../models/view/cipher.view";
|
||||
import { Fido2CredentialView } from "../models/view/fido2-credential.view";
|
||||
@@ -102,4 +103,35 @@ export class DefaultCipherEncryptionService implements CipherEncryptionService {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
async decryptAttachmentContent(
|
||||
cipher: Cipher,
|
||||
attachment: Attachment,
|
||||
encryptedContent: Uint8Array,
|
||||
userId: UserId,
|
||||
): Promise<Uint8Array> {
|
||||
return firstValueFrom(
|
||||
this.sdkService.userClient$(userId).pipe(
|
||||
map((sdk) => {
|
||||
if (!sdk) {
|
||||
throw new Error("SDK is undefined");
|
||||
}
|
||||
|
||||
using ref = sdk.take();
|
||||
|
||||
return ref.value
|
||||
.vault()
|
||||
.attachments()
|
||||
.decrypt_buffer(cipher.toSdkCipher(), attachment.toSdkAttachment(), encryptedContent);
|
||||
}),
|
||||
catchError((error: unknown) => {
|
||||
this.logService.error(`Failed to decrypt cipher buffer: ${error}`);
|
||||
return EMPTY;
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user