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:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user