1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-10 13:40:06 +00:00

Push decryption to SDK and prep for feature flag control

This commit is contained in:
Matt Gibson
2025-03-05 16:42:04 -08:00
parent 394ed91993
commit 5c4c6cdea1
3 changed files with 54 additions and 15 deletions

View File

@@ -24,6 +24,9 @@ export enum FeatureFlag {
NotificationRefresh = "notification-refresh",
UseTreeWalkerApiForPageDetailsCollection = "use-tree-walker-api-for-page-details-collection",
/* Key Management */
UseSDKForDecryption = "use-sdk-for-decryption",
/* Tools */
ItemShare = "item-share",
CriticalApps = "pm-14466-risk-insights-critical-application",
@@ -81,6 +84,9 @@ export const DefaultFeatureFlagValue = {
[FeatureFlag.NotificationRefresh]: FALSE,
[FeatureFlag.UseTreeWalkerApiForPageDetailsCollection]: FALSE,
/* Key Management */
[FeatureFlag.UseSDKForDecryption]: FALSE,
/* Tools */
[FeatureFlag.ItemShare]: FALSE,
[FeatureFlag.CriticalApps]: FALSE,

View File

@@ -1,3 +1,5 @@
import { OnServerConfigChange } from "@bitwarden/common/platform/abstractions/config/config.service";
import { ServerConfig } from "@bitwarden/common/platform/abstractions/config/server-config";
import { Decryptable } from "@bitwarden/common/platform/interfaces/decryptable.interface";
import { Encrypted } from "@bitwarden/common/platform/interfaces/encrypted";
import { InitializerMetadata } from "@bitwarden/common/platform/interfaces/initializer-metadata.interface";
@@ -5,7 +7,7 @@ import { EncArrayBuffer } from "@bitwarden/common/platform/models/domain/enc-arr
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
export abstract class EncryptService {
export abstract class EncryptService implements OnServerConfigChange {
abstract encrypt(plainValue: string | Uint8Array, key: SymmetricCryptoKey): Promise<EncString>;
abstract encryptToBytes(plainValue: Uint8Array, key: SymmetricCryptoKey): Promise<EncArrayBuffer>;
/**
@@ -55,4 +57,5 @@ export abstract class EncryptService {
value: string | Uint8Array,
algorithm: "sha1" | "sha256" | "sha512",
): Promise<string>;
abstract onServerConfigChange(newConfig: ServerConfig): void;
}

View File

@@ -14,16 +14,31 @@ import { EncArrayBuffer } from "@bitwarden/common/platform/models/domain/enc-arr
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { EncryptedObject } from "@bitwarden/common/platform/models/domain/encrypted-object";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { PureCrypto } from "@bitwarden/sdk-internal";
import {
DefaultFeatureFlagValue,
FeatureFlag,
getFeatureFlagValue,
} from "../../../enums/feature-flag.enum";
import { ServerConfig } from "../../../platform/abstractions/config/server-config";
import { EncryptService } from "../abstractions/encrypt.service";
export class EncryptServiceImplementation implements EncryptService {
private useSDKForDecryption: boolean = DefaultFeatureFlagValue[FeatureFlag.UseSDKForDecryption];
constructor(
protected cryptoFunctionService: CryptoFunctionService,
protected logService: LogService,
protected logMacFailures: boolean,
) {}
onServerConfigChange(newConfig: ServerConfig): void {
const old = this.useSDKForDecryption;
this.useSDKForDecryption = getFeatureFlagValue(newConfig, FeatureFlag.UseSDKForDecryption);
this.logService.debug("updated sdk decryption flag", old, this.useSDKForDecryption);
}
async encrypt(plainValue: string | Uint8Array, key: SymmetricCryptoKey): Promise<EncString> {
if (key == null) {
throw new Error("No encryption key provided.");
@@ -53,20 +68,7 @@ export class EncryptServiceImplementation implements EncryptService {
}
const encValue = await this.aesEncrypt(plainValue, key);
let macLen = 0;
if (encValue.mac != null) {
macLen = encValue.mac.byteLength;
}
const encBytes = new Uint8Array(1 + encValue.iv.byteLength + macLen + encValue.data.byteLength);
encBytes.set([encValue.key.encType]);
encBytes.set(new Uint8Array(encValue.iv), 1);
if (encValue.mac != null) {
encBytes.set(new Uint8Array(encValue.mac), 1 + encValue.iv.byteLength);
}
encBytes.set(new Uint8Array(encValue.data), 1 + encValue.iv.byteLength + macLen);
return new EncArrayBuffer(encBytes);
return EncArrayBuffer.fromParts(encValue.key.encType, encValue.iv, encValue.data, encValue.mac);
}
async decryptToUtf8(
@@ -74,6 +76,15 @@ export class EncryptServiceImplementation implements EncryptService {
key: SymmetricCryptoKey,
decryptContext: string = "no context",
): Promise<string> {
if (this.useSDKForDecryption) {
this.logService.debug("decrypting with SDK");
if (encString == null || encString.encryptedString == null) {
throw new Error("encString is null or undefined");
}
return PureCrypto.symmetric_decrypt(encString.encryptedString, key.keyB64);
}
this.logService.debug("decrypting with javascript");
if (key == null) {
throw new Error("No key provided for decryption.");
}
@@ -137,6 +148,25 @@ export class EncryptServiceImplementation implements EncryptService {
key: SymmetricCryptoKey,
decryptContext: string = "no context",
): Promise<Uint8Array | null> {
if (this.useSDKForDecryption) {
this.logService.debug("decrypting bytes with SDK");
if (
encThing.encryptionType == null ||
encThing.ivBytes == null ||
encThing.dataBytes == null
) {
throw new Error("Cannot decrypt, missing type, IV, or data bytes.");
}
const buffer = EncArrayBuffer.fromParts(
encThing.encryptionType,
encThing.ivBytes,
encThing.dataBytes,
encThing.macBytes,
).buffer;
return PureCrypto.symmetric_decrypt_array_buffer(buffer, key.keyB64);
}
this.logService.debug("decrypting bytes with javascript");
if (key == null) {
throw new Error("No encryption key provided.");
}