1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-18 18:33:50 +00:00

[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
This commit is contained in:
Bernd Schoolmann
2026-01-19 14:02:36 +01:00
committed by jaasen-livefront
parent fa23288ce5
commit 9216d54e97
3 changed files with 16 additions and 13 deletions

View File

@@ -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<UserPrivateKey | null>;

View File

@@ -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 () => {

View File

@@ -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,
});
}),
);
}),
);