1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-19 17:53:39 +00:00

[EC-272] Web workers using EncryptionService (#3532)

* Add item decryption to encryptService
* Create multithreadEncryptService subclass to handle web workers
* Create encryption web worker
* Refactor cipherService to use new interface
* Update dependencies
This commit is contained in:
Thomas Rittson
2022-10-28 07:38:54 +10:00
committed by GitHub
parent e972e905c8
commit da47992a22
50 changed files with 419 additions and 136 deletions

View File

@@ -6,6 +6,7 @@ import { CipherService as CipherServiceAbstraction } from "@bitwarden/common/abs
import { CollectionService as CollectionServiceAbstraction } from "@bitwarden/common/abstractions/collection.service";
import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/abstractions/crypto.service";
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/abstractions/cryptoFunction.service";
import { EncryptService } from "@bitwarden/common/abstractions/encrypt.service";
import { EventService as EventServiceAbstraction } from "@bitwarden/common/abstractions/event.service";
import { ExportService as ExportServiceAbstraction } from "@bitwarden/common/abstractions/export.service";
import { FileUploadService as FileUploadServiceAbstraction } from "@bitwarden/common/abstractions/fileUpload.service";
@@ -51,7 +52,8 @@ import { CipherService } from "@bitwarden/common/services/cipher.service";
import { CollectionService } from "@bitwarden/common/services/collection.service";
import { ConsoleLogService } from "@bitwarden/common/services/consoleLog.service";
import { ContainerService } from "@bitwarden/common/services/container.service";
import { EncryptService } from "@bitwarden/common/services/encrypt.service";
import { EncryptServiceImplementation } from "@bitwarden/common/services/cryptography/encrypt.service.implementation";
import { MultithreadEncryptServiceImplementation } from "@bitwarden/common/services/cryptography/multithread-encrypt.service.implementation";
import { EventService } from "@bitwarden/common/services/event.service";
import { ExportService } from "@bitwarden/common/services/export.service";
import { FileUploadService } from "@bitwarden/common/services/fileUpload.service";
@@ -82,6 +84,7 @@ import { WebCryptoFunctionService } from "@bitwarden/common/services/webCryptoFu
import { BrowserApi } from "../browser/browserApi";
import { SafariApp } from "../browser/safariApp";
import { flagEnabled } from "../flags";
import { UpdateBadge } from "../listeners/update-badge";
import { Account } from "../models/account";
import { PopupUtilsService } from "../popup/services/popup-utils.service";
@@ -215,7 +218,7 @@ export default class MainBackground {
this.memoryStorageService =
BrowserApi.manifestVersion === 3
? new LocalBackedSessionStorageService(
new EncryptService(this.cryptoFunctionService, this.logService, false),
new EncryptServiceImplementation(this.cryptoFunctionService, this.logService, false),
new KeyGenerationService(this.cryptoFunctionService)
)
: new MemoryStorageService();
@@ -255,7 +258,13 @@ export default class MainBackground {
window
);
this.i18nService = new I18nService(BrowserApi.getUILanguage(window));
this.encryptService = new EncryptService(this.cryptoFunctionService, this.logService, true);
this.encryptService = flagEnabled("multithreadDecryption")
? new MultithreadEncryptServiceImplementation(
this.cryptoFunctionService,
this.logService,
true
)
: new EncryptServiceImplementation(this.cryptoFunctionService, this.logService, true);
this.cryptoService = new BrowserCryptoService(
this.cryptoFunctionService,
this.encryptService,
@@ -283,7 +292,8 @@ export default class MainBackground {
this.i18nService,
() => this.searchService,
this.logService,
this.stateService
this.stateService,
this.encryptService
);
this.folderService = new FolderService(
this.cryptoService,

View File

@@ -4,6 +4,7 @@ import { CipherService } from "@bitwarden/common/services/cipher.service";
import { apiServiceFactory, ApiServiceInitOptions } from "./api-service.factory";
import { cryptoServiceFactory, CryptoServiceInitOptions } from "./crypto-service.factory";
import { encryptServiceFactory, EncryptServiceInitOptions } from "./encrypt-service.factory";
import { CachedServices, factory, FactoryOptions } from "./factory-options";
import {
FileUploadServiceInitOptions,
@@ -27,7 +28,8 @@ export type CipherServiceInitOptions = CipherServiceFactoryOptions &
FileUploadServiceInitOptions &
I18nServiceInitOptions &
LogServiceInitOptions &
StateServiceInitOptions;
StateServiceInitOptions &
EncryptServiceInitOptions;
export function cipherServiceFactory(
cache: { cipherService?: AbstractCipherService } & CachedServices,
@@ -48,7 +50,8 @@ export function cipherServiceFactory(
? () => cache.searchService
: opts.cipherServiceOptions.searchServiceFactory,
await logServiceFactory(cache, opts),
await stateServiceFactory(cache, opts)
await stateServiceFactory(cache, opts),
await encryptServiceFactory(cache, opts)
)
);
}

View File

@@ -1,4 +1,7 @@
import { EncryptService } from "@bitwarden/common/services/encrypt.service";
import { EncryptServiceImplementation } from "@bitwarden/common/services/cryptography/encrypt.service.implementation";
import { MultithreadEncryptServiceImplementation } from "@bitwarden/common/services/cryptography/multithread-encrypt.service.implementation";
import { flagEnabled } from "../../flags";
import {
cryptoFunctionServiceFactory,
@@ -18,18 +21,20 @@ export type EncryptServiceInitOptions = EncryptServiceFactoryOptions &
LogServiceInitOptions;
export function encryptServiceFactory(
cache: { encryptService?: EncryptService } & CachedServices,
cache: { encryptService?: EncryptServiceImplementation } & CachedServices,
opts: EncryptServiceInitOptions
): Promise<EncryptService> {
return factory(
cache,
"encryptService",
opts,
async () =>
new EncryptService(
await cryptoFunctionServiceFactory(cache, opts),
await logServiceFactory(cache, opts),
opts.encryptServiceOptions.logMacFailures
)
): Promise<EncryptServiceImplementation> {
return factory(cache, "encryptService", opts, async () =>
flagEnabled("multithreadDecryption")
? new MultithreadEncryptServiceImplementation(
await cryptoFunctionServiceFactory(cache, opts),
await logServiceFactory(cache, opts),
opts.encryptServiceOptions.logMacFailures
)
: new EncryptServiceImplementation(
await cryptoFunctionServiceFactory(cache, opts),
await logServiceFactory(cache, opts),
opts.encryptServiceOptions.logMacFailures
)
);
}

View File

@@ -1,7 +1,7 @@
import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractEncrypt.service";
import { AuthService } from "@bitwarden/common/abstractions/auth.service";
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/abstractions/encrypt.service";
import { AuthenticationStatus } from "@bitwarden/common/enums/authenticationStatus";
import { StateFactory } from "@bitwarden/common/factories/stateFactory";
import { Utils } from "@bitwarden/common/misc/utils";
@@ -259,7 +259,7 @@ export class UpdateBadge {
if (!self.bitwardenContainerService) {
new ContainerService(
serviceCache.cryptoService as CryptoService,
serviceCache.encryptService as AbstractEncryptService
serviceCache.encryptService as EncryptService
).attachToGlobal(self);
}

View File

@@ -4,7 +4,7 @@ import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
import { Utils } from "@bitwarden/common/misc/utils";
import { EncString } from "@bitwarden/common/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetric-crypto-key";
import { EncryptService } from "@bitwarden/common/src/services/encrypt.service";
import { EncryptServiceImplementation } from "@bitwarden/common/services/cryptography/encrypt.service.implementation";
import BrowserLocalStorageService from "./browserLocalStorage.service";
import BrowserMemoryStorageService from "./browserMemoryStorage.service";
@@ -12,7 +12,7 @@ import { KeyGenerationService } from "./keyGeneration.service";
import { LocalBackedSessionStorageService } from "./localBackedSessionStorage.service";
describe("Browser Session Storage Service", () => {
let encryptService: SubstituteOf<EncryptService>;
let encryptService: SubstituteOf<EncryptServiceImplementation>;
let keyGenerationService: SubstituteOf<KeyGenerationService>;
let cache: Map<string, any>;

View File

@@ -1,6 +1,6 @@
import { Jsonify } from "type-fest";
import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractEncrypt.service";
import { EncryptService } from "@bitwarden/common/abstractions/encrypt.service";
import {
AbstractCachedStorageService,
MemoryStorageServiceInterface,
@@ -30,7 +30,7 @@ export class LocalBackedSessionStorageService
private sessionStorage = new BrowserMemoryStorageService();
constructor(
private encryptService: AbstractEncryptService,
private encryptService: EncryptService,
private keyGenerationService: AbstractKeyGenerationService
) {
super();

View File

@@ -4,7 +4,7 @@
"noImplicitAny": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"module": "es6",
"module": "ES2020",
"target": "ES2016",
"allowJs": true,
"sourceMap": true,
@@ -17,5 +17,5 @@
"angularCompilerOptions": {
"preserveWhitespaces": true
},
"include": ["src"]
"include": ["src", "../../libs/common/src/services/**/*.worker.ts"]
}

View File

@@ -20,7 +20,7 @@ import { CipherService } from "@bitwarden/common/services/cipher.service";
import { CollectionService } from "@bitwarden/common/services/collection.service";
import { ContainerService } from "@bitwarden/common/services/container.service";
import { CryptoService } from "@bitwarden/common/services/crypto.service";
import { EncryptService } from "@bitwarden/common/services/encrypt.service";
import { EncryptServiceImplementation } from "@bitwarden/common/services/cryptography/encrypt.service.implementation";
import { EnvironmentService } from "@bitwarden/common/services/environment.service";
import { ExportService } from "@bitwarden/common/services/export.service";
import { FileUploadService } from "@bitwarden/common/services/fileUpload.service";
@@ -94,7 +94,7 @@ export class Main {
exportService: ExportService;
searchService: SearchService;
cryptoFunctionService: NodeCryptoFunctionService;
encryptService: EncryptService;
encryptService: EncryptServiceImplementation;
authService: AuthService;
policyService: PolicyService;
program: Program;
@@ -140,7 +140,11 @@ export class Main {
(level) => process.env.BITWARDENCLI_DEBUG !== "true" && level <= LogLevelType.Info
);
this.cryptoFunctionService = new NodeCryptoFunctionService();
this.encryptService = new EncryptService(this.cryptoFunctionService, this.logService, true);
this.encryptService = new EncryptServiceImplementation(
this.cryptoFunctionService,
this.logService,
true
);
this.storageService = new LowdbStorageService(this.logService, null, p, false, true);
this.secureStorageService = new NodeEnvSecureStorageService(
this.storageService,
@@ -211,7 +215,8 @@ export class Main {
this.i18nService,
null,
this.logService,
this.stateService
this.stateService,
this.encryptService
);
this.broadcasterService = new BroadcasterService();

View File

@@ -1,4 +1,6 @@
{
"dev_flags": {},
"flags": {}
"flags": {
"multithreadDecryption": false
}
}

View File

@@ -6,7 +6,7 @@ import { Utils } from "@bitwarden/common/misc/utils";
import { EncString } from "@bitwarden/common/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetric-crypto-key";
import { ConsoleLogService } from "@bitwarden/common/services/consoleLog.service";
import { EncryptService } from "@bitwarden/common/services/encrypt.service";
import { EncryptServiceImplementation } from "@bitwarden/common/services/cryptography/encrypt.service.implementation";
import { NodeCryptoFunctionService } from "@bitwarden/node/services/nodeCryptoFunction.service";
import { DecryptedCommandData } from "../../src/models/nativeMessaging/decryptedCommandData";
@@ -32,7 +32,7 @@ const CONFIRMATION_MESSAGE_TIMEOUT = 100 * 1000; // 100 seconds
export default class NativeMessageService {
private ipcService: IPCService;
private nodeCryptoFunctionService: NodeCryptoFunctionService;
private encryptService: EncryptService;
private encryptService: EncryptServiceImplementation;
constructor(private apiVersion: number) {
console.log("Starting native messaging service");
@@ -41,7 +41,7 @@ export default class NativeMessageService {
});
this.nodeCryptoFunctionService = new NodeCryptoFunctionService();
this.encryptService = new EncryptService(
this.encryptService = new EncryptServiceImplementation(
this.nodeCryptoFunctionService,
new ConsoleLogService(false),
false

View File

@@ -2,8 +2,8 @@ import { Inject, Injectable } from "@angular/core";
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction";
import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractEncrypt.service";
import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/abstractions/encrypt.service";
import { EnvironmentService as EnvironmentServiceAbstraction } from "@bitwarden/common/abstractions/environment.service";
import { EventService as EventServiceAbstraction } from "@bitwarden/common/abstractions/event.service";
import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/abstractions/i18n.service";
@@ -36,7 +36,7 @@ export class InitService {
private cryptoService: CryptoServiceAbstraction,
private nativeMessagingService: NativeMessagingService,
private themingService: AbstractThemingService,
private encryptService: AbstractEncryptService
private encryptService: EncryptService
) {}
init() {

View File

@@ -11,12 +11,12 @@ import {
} from "@bitwarden/angular/services/injection-tokens";
import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.module";
import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction";
import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractEncrypt.service";
import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/abstractions/auth.service";
import { BroadcasterService as BroadcasterServiceAbstraction } from "@bitwarden/common/abstractions/broadcaster.service";
import { CipherService as CipherServiceAbstraction } from "@bitwarden/common/abstractions/cipher.service";
import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/abstractions/crypto.service";
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/abstractions/cryptoFunction.service";
import { EncryptService } from "@bitwarden/common/abstractions/encrypt.service";
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/abstractions/i18n.service";
import {
@@ -115,7 +115,7 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
useClass: ElectronCryptoService,
deps: [
CryptoFunctionServiceAbstraction,
AbstractEncryptService,
EncryptService,
PlatformUtilsServiceAbstraction,
LogServiceAbstraction,
StateServiceAbstraction,

View File

@@ -4,7 +4,7 @@
"noImplicitAny": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"module": "es6",
"module": "ES2020",
"target": "ES2016",
"sourceMap": true,
"types": [],
@@ -18,5 +18,5 @@
"angularCompilerOptions": {
"preserveWhitespaces": true
},
"include": ["src"]
"include": ["src", "../../libs/common/src/services/**/*.worker.ts"]
}

View File

@@ -6,7 +6,7 @@ import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { InfiniteScrollModule } from "ngx-infinite-scroll";
import { AppComponent } from "./app.component";
import { CoreModule } from "./core";
import { CoreModule } from "./core/core.module";
import { OssRoutingModule } from "./oss-routing.module";
import { OssModule } from "./oss.module";
import { WildcardRoutingModule } from "./wildcard-routing.module";

View File

@@ -1,4 +1,7 @@
export * from "./core.module";
// Do not export this here or it will import MultithreadEncryptService (via JslibServicesModule) into test code.
// MultithreadEncryptService contains ES2020 features (import.meta) which are not supported in Node and Jest.
// Revisit this when Node & Jest get stable support for ESM.
// export * from "./core.module";
export * from "./event.service";
export * from "./policy-list.service";
export * from "./router.service";

View File

@@ -2,8 +2,8 @@ import { Inject, Injectable } from "@angular/core";
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction";
import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractEncrypt.service";
import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/abstractions/encrypt.service";
import {
EnvironmentService as EnvironmentServiceAbstraction,
Urls,
@@ -33,7 +33,7 @@ export class InitService {
private stateService: StateServiceAbstraction,
private cryptoService: CryptoServiceAbstraction,
private themingService: AbstractThemingService,
private encryptService: AbstractEncryptService
private encryptService: EncryptService
) {}
init() {

View File

@@ -3,7 +3,7 @@ import { APP_INITIALIZER, NgModule } from "@angular/core";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { I18nService as BaseI18nService } from "@bitwarden/common/services/i18n.service";
import * as eng from "../../locales/en/messages.json";
import eng from "../../locales/en/messages.json";
class PreloadedEnglishI18nService extends BaseI18nService {
constructor() {

View File

@@ -15,5 +15,10 @@
"preserveWhitespaces": true
},
"files": ["src/polyfills.ts", "src/main.ts", "../../bitwarden_license/bit-web/src/main.ts"],
"include": ["src/connectors/*.ts", "src/**/*.stories.ts", "src/**/*.spec.ts"]
"include": [
"src/connectors/*.ts",
"src/**/*.stories.ts",
"src/**/*.spec.ts",
"../../libs/common/src/services/**/*.worker.ts"
]
}