From 9216d54e977689ecd87056d876cc447e40ef6c2a Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Mon, 19 Jan 2026 14:02:36 +0100 Subject: [PATCH] [PM-30565] Fix corrupt private key making cipher decryption keys not emit (#18357) * Fix corrupt private key making cipher decryption keys not emit * Prettier * Fix tests --- .../src/abstractions/key.service.ts | 3 +-- libs/key-management/src/key.service.spec.ts | 7 +++---- libs/key-management/src/key.service.ts | 19 ++++++++++++------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/libs/key-management/src/abstractions/key.service.ts b/libs/key-management/src/abstractions/key.service.ts index bc065155fdb..db8eacb5fa4 100644 --- a/libs/key-management/src/abstractions/key.service.ts +++ b/libs/key-management/src/abstractions/key.service.ts @@ -280,8 +280,7 @@ export abstract class KeyService { * encrypted private key at all. * * @param userId The user id of the user to get the data for. - * @returns An observable stream of the decrypted private key or null. - * @throws Error when decryption of the encrypted private key fails. + * @returns An observable stream of the decrypted private key or null if the private key is not present or fails to decrypt */ abstract userPrivateKey$(userId: UserId): Observable; diff --git a/libs/key-management/src/key.service.spec.ts b/libs/key-management/src/key.service.spec.ts index c0a0ab62347..9d96d7c09b1 100644 --- a/libs/key-management/src/key.service.spec.ts +++ b/libs/key-management/src/key.service.spec.ts @@ -437,14 +437,13 @@ describe("keyService", () => { ); }); - it("throws an error if unwrapping encrypted private key fails", async () => { + it("emits null if unwrapping encrypted private key fails", async () => { encryptService.unwrapDecapsulationKey.mockImplementationOnce(() => { throw new Error("Unwrapping failed"); }); - await expect(firstValueFrom(keyService.userPrivateKey$(mockUserId))).rejects.toThrow( - "Unwrapping failed", - ); + const result = await firstValueFrom(keyService.userPrivateKey$(mockUserId)); + expect(result).toBeNull(); }); it("returns null if user key is not set", async () => { diff --git a/libs/key-management/src/key.service.ts b/libs/key-management/src/key.service.ts index 752a89e5fcd..4c749e9f6c4 100644 --- a/libs/key-management/src/key.service.ts +++ b/libs/key-management/src/key.service.ts @@ -791,7 +791,10 @@ export class DefaultKeyService implements KeyServiceAbstraction { return this.stateProvider.getUser(userId, USER_ENCRYPTED_PRIVATE_KEY).state$; } - private userPrivateKeyHelper$(userId: UserId) { + private userPrivateKeyHelper$(userId: UserId): Observable<{ + userKey: UserKey; + userPrivateKey: UserPrivateKey | null; + } | null> { const userKey$ = this.userKey$(userId); return userKey$.pipe( switchMap((userKey) => { @@ -801,18 +804,20 @@ export class DefaultKeyService implements KeyServiceAbstraction { return this.stateProvider.getUser(userId, USER_ENCRYPTED_PRIVATE_KEY).state$.pipe( switchMap(async (encryptedPrivateKey) => { - try { - return await this.decryptPrivateKey(encryptedPrivateKey, userKey); - } catch (e) { - this.logService.error("Failed to decrypt private key for user ", userId, e); - throw e; - } + return await this.decryptPrivateKey(encryptedPrivateKey, userKey); }), // Combine outerscope info with user private key map((userPrivateKey) => ({ userKey, userPrivateKey, })), + catchError((err: unknown) => { + this.logService.error(`Failed to decrypt private key for user ${userId}`); + return of({ + userKey, + userPrivateKey: null, + }); + }), ); }), );