diff --git a/libs/common/src/vault/services/cipher.service.spec.ts b/libs/common/src/vault/services/cipher.service.spec.ts index 85ce8bd0423..70e615c9eff 100644 --- a/libs/common/src/vault/services/cipher.service.spec.ts +++ b/libs/common/src/vault/services/cipher.service.spec.ts @@ -119,6 +119,8 @@ describe("Cipher Service", () => { beforeEach(() => { encryptService.encryptFileData.mockReturnValue(Promise.resolve(ENCRYPTED_BYTES)); encryptService.encryptString.mockReturnValue(Promise.resolve(new EncString(ENCRYPTED_TEXT))); + keyService.userKey$.mockReturnValue(of(makeSymmetricCryptoKey(64) as UserKey)); + keyService.orgKeys$.mockReturnValue(of({ [orgId]: makeSymmetricCryptoKey(64) as OrgKey })); // Mock i18nService collator i18nService.collator = { @@ -156,9 +158,6 @@ describe("Cipher Service", () => { it("should upload encrypted file contents with save attachments", async () => { const fileName = "filename"; const fileData = new Uint8Array(10); - keyService.getOrgKey.mockReturnValue( - Promise.resolve(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey), - ); keyService.makeDataEncKey.mockReturnValue( Promise.resolve(new SymmetricCryptoKey(new Uint8Array(32))), ); @@ -181,9 +180,6 @@ describe("Cipher Service", () => { const testCipher = new Cipher(cipherData); const expectedRevisionDate = "2022-01-31T12:00:00.000Z"; - keyService.getOrgKey.mockReturnValue( - Promise.resolve(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey), - ); keyService.makeDataEncKey.mockReturnValue( Promise.resolve([ new SymmetricCryptoKey(new Uint8Array(32)), @@ -362,10 +358,6 @@ describe("Cipher Service", () => { }); it("should return the encrypting user id", async () => { - keyService.getOrgKey.mockReturnValue( - Promise.resolve(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey), - ); - const { encryptedFor } = await cipherService.encrypt(cipherView, userId); expect(encryptedFor).toEqual(userId); }); @@ -377,10 +369,6 @@ describe("Cipher Service", () => { { uri: "uri", match: UriMatchStrategy.RegularExpression } as LoginUriView, ]; - keyService.getOrgKey.mockReturnValue( - Promise.resolve(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey), - ); - const { cipher } = await cipherService.encrypt(cipherView, userId); expect(cipher.login.uris).toEqual([ @@ -394,12 +382,6 @@ describe("Cipher Service", () => { }); describe("cipher.key", () => { - beforeEach(() => { - keyService.getOrgKey.mockReturnValue( - Promise.resolve(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey), - ); - }); - it("is null when feature flag is false", async () => { configService.getFeatureFlag .calledWith(FeatureFlag.CipherKeyEncryption) @@ -437,9 +419,6 @@ describe("Cipher Service", () => { describe("encryptCipherForRotation", () => { beforeEach(() => { jest.spyOn(cipherService, "encryptCipherWithCipherKey"); - keyService.getOrgKey.mockReturnValue( - Promise.resolve(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey), - ); }); it("is not called when feature flag is false", async () => { @@ -637,7 +616,7 @@ describe("Cipher Service", () => { const result = await cipherService.decrypt(encryptionContext.cipher, userId); expect(result).toEqual(new CipherView(encryptionContext.cipher)); - expect(encryptionContext.cipher.decrypt).toHaveBeenCalledWith(mockUserKey); + expect(encryptionContext.cipher.decrypt).toHaveBeenCalledWith(mockUserKey, userId); }); }); diff --git a/libs/common/src/vault/services/cipher.service.ts b/libs/common/src/vault/services/cipher.service.ts index 86e285c9120..a97d9f59796 100644 --- a/libs/common/src/vault/services/cipher.service.ts +++ b/libs/common/src/vault/services/cipher.service.ts @@ -726,7 +726,11 @@ export class CipherService implements CipherServiceAbstraction { } const ciphers = response.data.map((cr) => new Cipher(new CipherData(cr))); - const key = await this.keyService.getOrgKey(organizationId); + const key = await firstValueFrom( + this.keyService + .orgKeys$(userId) + .pipe(map((orgKeys) => orgKeys[organizationId as OrganizationId] ?? null)), + ); const decCiphers: CipherView[] = await Promise.all( ciphers.map(async (cipher) => { return await cipher.decrypt(key, userId); @@ -1536,10 +1540,17 @@ export class CipherService implements CipherServiceAbstraction { } async getKeyForCipherKeyDecryption(cipher: Cipher, userId: UserId): Promise { - return ( - (await this.keyService.getOrgKey(cipher.organizationId)) || - ((await this.keyService.getUserKey(userId)) as UserKey) - ); + if (cipher.organizationId) { + const orgKey = await firstValueFrom( + this.keyService + .orgKeys$(userId) + .pipe(map((orgKeys) => orgKeys[cipher.organizationId as OrganizationId] ?? null)), + ); + if (orgKey) { + return orgKey; + } + } + return (await firstValueFrom(this.keyService.userKey$(userId))) as UserKey; } async setAddEditCipherInfo(value: AddEditCipherInfo, userId: UserId) { @@ -1672,7 +1683,7 @@ export class CipherService implements CipherServiceAbstraction { // In the case of a cipher that is being shared with an organization, we want to decrypt the // cipher key with the user's key and then re-encrypt it with the organization's key. private async encryptSharedCipher(model: CipherView, userId: UserId): Promise { - const keyForCipherKeyDecryption = await this.keyService.getUserKey(userId); + const keyForCipherKeyDecryption = await firstValueFrom(this.keyService.userKey$(userId)); return await this.encrypt(model, userId, null, keyForCipherKeyDecryption); } @@ -1749,12 +1760,16 @@ export class CipherService implements CipherServiceAbstraction { } const encBuf = await EncArrayBuffer.fromResponse(attachmentResponse); - const userKey = await this.keyService.getUserKey(activeUserId.id); + const userKey = await firstValueFrom(this.keyService.userKey$(activeUserId.id)); const decBuf = await this.encryptService.decryptFileData(encBuf, userKey); let encKey: UserKey | OrgKey; - encKey = await this.keyService.getOrgKey(organizationId); - encKey ||= (await this.keyService.getUserKey()) as UserKey; + encKey = await firstValueFrom( + this.keyService + .orgKeys$(activeUserId.id) + .pipe(map((orgKeys) => orgKeys[organizationId as OrganizationId] ?? null)), + ); + encKey ||= (await firstValueFrom(this.keyService.userKey$(activeUserId.id))) as UserKey; const dataEncKey = await this.keyService.makeDataEncKey(encKey);