mirror of
https://github.com/bitwarden/browser
synced 2026-02-22 12:24:01 +00:00
Created cipher encryption abstraction and service
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import { CipherListView } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { UserId } from "../../types/guid";
|
||||
import { Cipher } from "../models/domain/cipher";
|
||||
import { CipherView } from "../models/view/cipher.view";
|
||||
|
||||
/**
|
||||
* Service responsible for encrypting and decrypting ciphers.
|
||||
*/
|
||||
export abstract class CipherEncryptionService {
|
||||
/**
|
||||
* Decrypts a cipher using the SDK for the given userId.
|
||||
*
|
||||
* @param userId The user ID whose key will be used for decryption
|
||||
* @param cipher The encrypted cipher object
|
||||
*
|
||||
* @returns A promise that resolves to the decrypted cipher view
|
||||
*/
|
||||
abstract decrypt(userId: UserId, cipher: Cipher): Promise<CipherView>;
|
||||
/**
|
||||
* Decrypts a list of ciphers using the SDK for the given userId.
|
||||
*
|
||||
* @param userId The user ID whose key will be used for decryption
|
||||
* @param ciphers The encrypted cipher objects
|
||||
*
|
||||
* @returns A promise that resolves to an array of decrypted cipher list views
|
||||
*/
|
||||
abstract decryptCipherList(userId: UserId, ciphers: Cipher[]): Promise<CipherListView[]>;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
import { EMPTY, catchError, firstValueFrom, map } from "rxjs";
|
||||
|
||||
import { CipherListView } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { LogService } from "../../platform/abstractions/log.service";
|
||||
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 { Cipher } from "../models/domain/cipher";
|
||||
import { CipherView } from "../models/view/cipher.view";
|
||||
import { Fido2CredentialView } from "../models/view/fido2-credential.view";
|
||||
|
||||
export class DefaultCipherEncryptionService implements CipherEncryptionService {
|
||||
constructor(
|
||||
private sdkService: SdkService,
|
||||
private logService: LogService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
async decrypt(userId: UserId, cipher: Cipher): Promise<CipherView> {
|
||||
return firstValueFrom(
|
||||
this.sdkService.userClient$(userId).pipe(
|
||||
map((sdk) => {
|
||||
if (!sdk) {
|
||||
throw new Error("SDK not available");
|
||||
}
|
||||
|
||||
using ref = sdk.take();
|
||||
const sdkCipherView = ref.value.vault().ciphers().decrypt(cipher.toSdkCipher());
|
||||
// The SDK returns a cipherView or throws an error if decryption fails.
|
||||
const clientCipherView = CipherView.fromSdkCipherView(sdkCipherView)!;
|
||||
|
||||
// Decrypt Fido2 credentials if available
|
||||
if (
|
||||
clientCipherView.type === CipherType.Login &&
|
||||
sdkCipherView.login?.fido2Credentials?.length
|
||||
) {
|
||||
const fido2CredentialViews = ref.value
|
||||
.vault()
|
||||
.ciphers()
|
||||
.decrypt_fido2_credentials(sdkCipherView);
|
||||
|
||||
clientCipherView.login.fido2Credentials = fido2CredentialViews
|
||||
.map((f) => Fido2CredentialView.fromSdkFido2CredentialView(f))
|
||||
.filter((view): view is Fido2CredentialView => view !== undefined);
|
||||
}
|
||||
|
||||
return clientCipherView;
|
||||
}),
|
||||
catchError((error: unknown) => {
|
||||
this.logService.error(`Failed to decrypt cipher ${cipher.id}: ${error}`);
|
||||
return EMPTY;
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
async decryptCipherList(userId: UserId, ciphers: Cipher[]): Promise<CipherListView[]> {
|
||||
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()
|
||||
.ciphers()
|
||||
.decrypt_list(ciphers.map((cipher) => cipher.toSdkCipher()));
|
||||
}),
|
||||
catchError((error: unknown) => {
|
||||
this.logService.error(`Failed to decrypt cipher list: ${error}`);
|
||||
return EMPTY;
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user