diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 5c1d2335750..00de1873462 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -73,10 +73,7 @@ import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-management/abstractions/process-reload.service"; import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service"; import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; -import { BulkEncryptServiceImplementation } from "@bitwarden/common/key-management/crypto/services/bulk-encrypt.service.implementation"; import { EncryptServiceImplementation } from "@bitwarden/common/key-management/crypto/services/encrypt.service.implementation"; -import { FallbackBulkEncryptService } from "@bitwarden/common/key-management/crypto/services/fallback-bulk-encrypt.service"; -import { MultithreadEncryptServiceImplementation } from "@bitwarden/common/key-management/crypto/services/multithread-encrypt.service.implementation"; import { WebCryptoFunctionService } from "@bitwarden/common/key-management/crypto/services/web-crypto-function.service"; import { DeviceTrustServiceAbstraction } from "@bitwarden/common/key-management/device-trust/abstractions/device-trust.service.abstraction"; import { DeviceTrustService } from "@bitwarden/common/key-management/device-trust/services/device-trust.service.implementation"; @@ -363,7 +360,6 @@ export default class MainBackground { vaultFilterService: VaultFilterService; usernameGenerationService: UsernameGenerationServiceAbstraction; encryptService: EncryptService; - bulkEncryptService: FallbackBulkEncryptService; folderApiService: FolderApiServiceAbstraction; policyApiService: PolicyApiServiceAbstraction; sendApiService: SendApiServiceAbstraction; @@ -577,13 +573,11 @@ export default class MainBackground { storageServiceProvider, ); - this.encryptService = BrowserApi.isManifestVersion(2) - ? new MultithreadEncryptServiceImplementation( - this.cryptoFunctionService, - this.logService, - true, - ) - : new EncryptServiceImplementation(this.cryptoFunctionService, this.logService, true); + this.encryptService = new EncryptServiceImplementation( + this.cryptoFunctionService, + this.logService, + true, + ); this.singleUserStateProvider = new DefaultSingleUserStateProvider( storageServiceProvider, @@ -883,8 +877,6 @@ export default class MainBackground { this.themeStateService = new DefaultThemeStateService(this.globalStateProvider); - this.bulkEncryptService = new FallbackBulkEncryptService(this.encryptService); - this.cipherEncryptionService = new DefaultCipherEncryptionService( this.sdkService, this.logService, @@ -899,7 +891,6 @@ export default class MainBackground { this.stateService, this.autofillSettingsService, this.encryptService, - this.bulkEncryptService, this.cipherFileUploadService, this.configService, this.stateProvider, @@ -1400,13 +1391,6 @@ export default class MainBackground { // Only the "true" background should run migrations await this.stateService.init({ runMigrations: true }); - this.configService.serverConfig$.subscribe((newConfig) => { - if (newConfig != null) { - this.encryptService.onServerConfigChange(newConfig); - this.bulkEncryptService.onServerConfigChange(newConfig); - } - }); - // This is here instead of in in the InitService b/c we don't plan for // side effects to run in the Browser InitService. const accounts = await firstValueFrom(this.accountService.accounts$); @@ -1439,15 +1423,6 @@ export default class MainBackground { this.syncServiceListener?.listener$().subscribe(); await this.autoSubmitLoginBackground.init(); - if ( - BrowserApi.isManifestVersion(2) && - (await this.configService.getFeatureFlag(FeatureFlag.PM4154_BulkEncryptionService)) - ) { - await this.bulkEncryptService.setFeatureFlagEncryptService( - new BulkEncryptServiceImplementation(this.cryptoFunctionService, this.logService), - ); - } - // If the user is logged out, switch to the next account const active = await firstValueFrom(this.accountService.activeAccount$); if (active != null) { diff --git a/apps/browser/src/popup/services/init.service.ts b/apps/browser/src/popup/services/init.service.ts index f29745e6f59..9e750ae7341 100644 --- a/apps/browser/src/popup/services/init.service.ts +++ b/apps/browser/src/popup/services/init.service.ts @@ -3,9 +3,6 @@ import { inject, Inject, Injectable } from "@angular/core"; import { AbstractThemingService } from "@bitwarden/angular/platform/services/theming/theming.service.abstraction"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service"; -import { BulkEncryptService } from "@bitwarden/common/key-management/crypto/abstractions/bulk-encrypt.service"; -import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; -import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService as LogServiceAbstraction } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -30,9 +27,6 @@ export class InitService { private themingService: AbstractThemingService, private sdkLoadService: SdkLoadService, private viewCacheService: PopupViewCacheService, - private configService: ConfigService, - private encryptService: EncryptService, - private bulkEncryptService: BulkEncryptService, @Inject(DOCUMENT) private document: Document, ) {} @@ -40,12 +34,6 @@ export class InitService { return async () => { await this.sdkLoadService.loadAndInit(); await this.stateService.init({ runMigrations: false }); // Browser background is responsible for migrations - this.configService.serverConfig$.subscribe((newConfig) => { - if (newConfig != null) { - this.encryptService.onServerConfigChange(newConfig); - this.bulkEncryptService.onServerConfigChange(newConfig); - } - }); await this.i18nService.init(); this.twoFactorService.init(); await this.viewCacheService.init(); diff --git a/apps/browser/tsconfig.json b/apps/browser/tsconfig.json index a554120bd1e..0fd6cac4230 100644 --- a/apps/browser/tsconfig.json +++ b/apps/browser/tsconfig.json @@ -3,7 +3,6 @@ "include": [ "src", "../../libs/common/src/autofill/constants", - "../../libs/common/custom-matchers.d.ts", - "../../libs/common/src/key-management/crypto/services/encrypt.worker.ts" + "../../libs/common/custom-matchers.d.ts" ] } diff --git a/apps/browser/webpack.config.js b/apps/browser/webpack.config.js index 90638f4e334..551225231f7 100644 --- a/apps/browser/webpack.config.js +++ b/apps/browser/webpack.config.js @@ -199,7 +199,6 @@ const mainConfig = { "./src/autofill/overlay/inline-menu/pages/list/bootstrap-autofill-inline-menu-list.ts", "overlay/menu": "./src/autofill/overlay/inline-menu/pages/menu-container/bootstrap-autofill-inline-menu-container.ts", - "encrypt-worker": "../../libs/common/src/key-management/crypto/services/encrypt.worker.ts", "content/send-on-installed-message": "./src/vault/content/send-on-installed-message.ts", "content/send-popup-open-message": "./src/vault/content/send-popup-open-message.ts", }, diff --git a/apps/cli/src/service-container/service-container.ts b/apps/cli/src/service-container/service-container.ts index 820041b46d7..3ea471dac5a 100644 --- a/apps/cli/src/service-container/service-container.ts +++ b/apps/cli/src/service-container/service-container.ts @@ -62,7 +62,6 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs import { DefaultBillingAccountProfileStateService } from "@bitwarden/common/billing/services/account/billing-account-profile-state.service"; import { ClientType } from "@bitwarden/common/enums"; import { EncryptServiceImplementation } from "@bitwarden/common/key-management/crypto/services/encrypt.service.implementation"; -import { FallbackBulkEncryptService } from "@bitwarden/common/key-management/crypto/services/fallback-bulk-encrypt.service"; import { DeviceTrustServiceAbstraction } from "@bitwarden/common/key-management/device-trust/abstractions/device-trust.service.abstraction"; import { DeviceTrustService } from "@bitwarden/common/key-management/device-trust/services/device-trust.service.implementation"; import { KeyConnectorService } from "@bitwarden/common/key-management/key-connector/services/key-connector.service"; @@ -290,7 +289,6 @@ export class ServiceContainer { cipherAuthorizationService: CipherAuthorizationService; ssoUrlService: SsoUrlService; masterPasswordApiService: MasterPasswordApiServiceAbstraction; - bulkEncryptService: FallbackBulkEncryptService; cipherEncryptionService: CipherEncryptionService; restrictedItemTypesService: RestrictedItemTypesService; cliRestrictedItemTypesService: CliRestrictedItemTypesService; @@ -325,7 +323,6 @@ export class ServiceContainer { this.logService, true, ); - this.bulkEncryptService = new FallbackBulkEncryptService(this.encryptService); this.storageService = new LowdbStorageService(this.logService, null, p, false, true); this.secureStorageService = new NodeEnvSecureStorageService( this.storageService, @@ -719,7 +716,6 @@ export class ServiceContainer { this.stateService, this.autofillSettingsService, this.encryptService, - this.bulkEncryptService, this.cipherFileUploadService, this.configService, this.stateProvider, @@ -921,12 +917,6 @@ export class ServiceContainer { await this.sdkLoadService.loadAndInit(); await this.storageService.init(); await this.stateService.init(); - this.configService.serverConfig$.subscribe((newConfig) => { - if (newConfig != null) { - this.encryptService.onServerConfigChange(newConfig); - this.bulkEncryptService.onServerConfigChange(newConfig); - } - }); this.containerService.attachToGlobal(global); await this.i18nService.init(); this.twoFactorService.init(); diff --git a/apps/desktop/src/app/services/init.service.ts b/apps/desktop/src/app/services/init.service.ts index 26ad24e9fb9..8a193218e4b 100644 --- a/apps/desktop/src/app/services/init.service.ts +++ b/apps/desktop/src/app/services/init.service.ts @@ -7,10 +7,8 @@ import { WINDOW } from "@bitwarden/angular/services/injection-tokens"; import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/common/abstractions/event/event-upload.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { TwoFactorService as TwoFactorServiceAbstraction } from "@bitwarden/common/auth/abstractions/two-factor.service"; -import { BulkEncryptService } from "@bitwarden/common/key-management/crypto/abstractions/bulk-encrypt.service"; import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; import { DefaultVaultTimeoutService } from "@bitwarden/common/key-management/vault-timeout"; -import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service"; import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service"; @@ -53,8 +51,6 @@ export class InitService { private autofillService: DesktopAutofillService, private autotypeService: DesktopAutotypeService, private sdkLoadService: SdkLoadService, - private configService: ConfigService, - private bulkEncryptService: BulkEncryptService, @Inject(DOCUMENT) private document: Document, ) {} @@ -65,13 +61,6 @@ export class InitService { this.nativeMessagingService.init(); await this.stateService.init({ runMigrations: false }); // Desktop will run them in main process - this.configService.serverConfig$.subscribe((newConfig) => { - if (newConfig != null) { - this.encryptService.onServerConfigChange(newConfig); - this.bulkEncryptService.onServerConfigChange(newConfig); - } - }); - const accounts = await firstValueFrom(this.accountService.accounts$); const setUserKeyInMemoryPromises = []; for (const userId of Object.keys(accounts) as UserId[]) { diff --git a/apps/desktop/src/services/biometric-message-handler.service.spec.ts b/apps/desktop/src/services/biometric-message-handler.service.spec.ts index 727e37ce79c..ad555729ab3 100644 --- a/apps/desktop/src/services/biometric-message-handler.service.spec.ts +++ b/apps/desktop/src/services/biometric-message-handler.service.spec.ts @@ -90,8 +90,10 @@ describe("BiometricMessageHandlerService", () => { reloadProcess: jest.fn(), }, }; - cryptoFunctionService.rsaEncrypt.mockResolvedValue(Utils.fromUtf8ToArray("encrypted")); cryptoFunctionService.randomBytes.mockResolvedValue(new Uint8Array(64) as CsprngArray); + cryptoFunctionService.rsaEncrypt.mockResolvedValue( + Utils.fromUtf8ToArray("encrypted") as CsprngArray, + ); service = new BiometricMessageHandlerService( cryptoFunctionService, diff --git a/apps/desktop/tsconfig.json b/apps/desktop/tsconfig.json index 70a59ad164c..aef8de06968 100644 --- a/apps/desktop/tsconfig.json +++ b/apps/desktop/tsconfig.json @@ -3,6 +3,6 @@ "angularCompilerOptions": { "strictTemplates": true }, - "include": ["src", "../../libs/common/src/key-management/crypto/services/encrypt.worker.ts"], + "include": ["src"], "exclude": ["src/**/*.spec.ts"] } diff --git a/apps/web/src/app/auth/emergency-access/services/emergency-access.service.spec.ts b/apps/web/src/app/auth/emergency-access/services/emergency-access.service.spec.ts index 05373534ce7..ff062b31e6b 100644 --- a/apps/web/src/app/auth/emergency-access/services/emergency-access.service.spec.ts +++ b/apps/web/src/app/auth/emergency-access/services/emergency-access.service.spec.ts @@ -4,12 +4,10 @@ import { MockProxy } from "jest-mock-extended"; import mock from "jest-mock-extended/lib/Mock"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; -import { BulkEncryptService } from "@bitwarden/common/key-management/crypto/abstractions/bulk-encrypt.service"; import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string"; import { ListResponse } from "@bitwarden/common/models/response/list.response"; import { UserKeyResponse } from "@bitwarden/common/models/response/user-key.response"; -import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { EncryptionType } from "@bitwarden/common/platform/enums"; import { Utils } from "@bitwarden/common/platform/misc/utils"; @@ -38,11 +36,9 @@ describe("EmergencyAccessService", () => { let apiService: MockProxy; let keyService: MockProxy; let encryptService: MockProxy; - let bulkEncryptService: MockProxy; let cipherService: MockProxy; let logService: MockProxy; let emergencyAccessService: EmergencyAccessService; - let configService: ConfigService; const mockNewUserKey = new SymmetricCryptoKey(new Uint8Array(64)) as UserKey; const mockTrustedPublicKeys = [Utils.fromUtf8ToArray("trustedPublicKey")]; @@ -52,7 +48,6 @@ describe("EmergencyAccessService", () => { apiService = mock(); keyService = mock(); encryptService = mock(); - bulkEncryptService = mock(); cipherService = mock(); logService = mock(); @@ -61,10 +56,8 @@ describe("EmergencyAccessService", () => { apiService, keyService, encryptService, - bulkEncryptService, cipherService, logService, - configService, ); }); diff --git a/apps/web/src/app/auth/emergency-access/services/emergency-access.service.ts b/apps/web/src/app/auth/emergency-access/services/emergency-access.service.ts index a814af32505..9a31bd9c107 100644 --- a/apps/web/src/app/auth/emergency-access/services/emergency-access.service.ts +++ b/apps/web/src/app/auth/emergency-access/services/emergency-access.service.ts @@ -3,14 +3,11 @@ import { Injectable } from "@angular/core"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { PolicyData } from "@bitwarden/common/admin-console/models/data/policy.data"; import { Policy } from "@bitwarden/common/admin-console/models/domain/policy"; -import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; -import { BulkEncryptService } from "@bitwarden/common/key-management/crypto/abstractions/bulk-encrypt.service"; import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; import { EncryptedString, EncString, } from "@bitwarden/common/key-management/crypto/models/enc-string"; -import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { UserId } from "@bitwarden/common/types/guid"; @@ -59,10 +56,8 @@ export class EmergencyAccessService private apiService: ApiService, private keyService: KeyService, private encryptService: EncryptService, - private bulkEncryptService: BulkEncryptService, private cipherService: CipherService, private logService: LogService, - private configService: ConfigService, ) {} /** @@ -258,17 +253,8 @@ export class EmergencyAccessService )) as UserKey; let ciphers: CipherView[] = []; - if (await this.configService.getFeatureFlag(FeatureFlag.PM4154_BulkEncryptionService)) { - ciphers = await this.bulkEncryptService.decryptItems( - response.ciphers.map((c) => new Cipher(c)), - grantorUserKey, - ); - } else { - ciphers = await this.encryptService.decryptItems( - response.ciphers.map((c) => new Cipher(c)), - grantorUserKey, - ); - } + const ciphersEncrypted = response.ciphers.map((c) => new Cipher(c)); + ciphers = await Promise.all(ciphersEncrypted.map(async (c) => c.decrypt(grantorUserKey))); return ciphers.sort(this.cipherService.getLocaleSortingFunction()); } diff --git a/apps/web/src/app/core/init.service.ts b/apps/web/src/app/core/init.service.ts index 39dc6e1edd4..f4d05171d56 100644 --- a/apps/web/src/app/core/init.service.ts +++ b/apps/web/src/app/core/init.service.ts @@ -7,10 +7,8 @@ import { WINDOW } from "@bitwarden/angular/services/injection-tokens"; import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/common/abstractions/event/event-upload.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { TwoFactorService as TwoFactorServiceAbstraction } from "@bitwarden/common/auth/abstractions/two-factor.service"; -import { BulkEncryptService } from "@bitwarden/common/key-management/crypto/abstractions/bulk-encrypt.service"; import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; import { DefaultVaultTimeoutService } from "@bitwarden/common/key-management/vault-timeout"; -import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service"; import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service"; import { StateService as StateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service"; @@ -42,8 +40,6 @@ export class InitService { private versionService: VersionService, private ipcService: IpcService, private sdkLoadService: SdkLoadService, - private configService: ConfigService, - private bulkEncryptService: BulkEncryptService, private taskService: TaskService, @Inject(DOCUMENT) private document: Document, ) {} @@ -53,13 +49,6 @@ export class InitService { await this.sdkLoadService.loadAndInit(); await this.stateService.init(); - this.configService.serverConfig$.subscribe((newConfig) => { - if (newConfig != null) { - this.encryptService.onServerConfigChange(newConfig); - this.bulkEncryptService.onServerConfigChange(newConfig); - } - }); - const activeAccount = await firstValueFrom(this.accountService.activeAccount$); if (activeAccount) { // If there is an active account, we must await the process of setting the user key in memory diff --git a/apps/web/src/app/tools/send/send-access/send-access-file.component.ts b/apps/web/src/app/tools/send/send-access/send-access-file.component.ts index 3b1bf427a0b..239861dd244 100644 --- a/apps/web/src/app/tools/send/send-access/send-access-file.component.ts +++ b/apps/web/src/app/tools/send/send-access/send-access-file.component.ts @@ -63,7 +63,7 @@ export class SendAccessFileComponent { try { const encBuf = await EncArrayBuffer.fromResponse(response); - const decBuf = await this.encryptService.decryptToBytes(encBuf, this.decKey); + const decBuf = await this.encryptService.decryptFileData(encBuf, this.decKey); this.fileDownloadService.download({ fileName: this.send.file.fileName, blobData: decBuf, diff --git a/apps/web/tsconfig.build.json b/apps/web/tsconfig.build.json index 39ab37efbb8..273cddb21d2 100644 --- a/apps/web/tsconfig.build.json +++ b/apps/web/tsconfig.build.json @@ -1,8 +1,5 @@ { "extends": "./tsconfig.json", "files": ["src/polyfills.ts", "src/main.ts", "src/theme.ts"], - "include": [ - "src/connectors/*.ts", - "../../libs/common/src/key-management/crypto/services/encrypt.worker.ts" - ] + "include": ["src/connectors/*.ts"] } diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index 92cec0d6a2c..fd655b0a56b 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -4,10 +4,5 @@ "strictTemplates": true }, "files": ["src/polyfills.ts", "src/main.ts", "src/theme.ts"], - "include": [ - "src/connectors/*.ts", - "src/**/*.stories.ts", - "src/**/*.spec.ts", - "../../libs/common/src/key-management/crypto/services/encrypt.worker.ts" - ] + "include": ["src/connectors/*.ts", "src/**/*.stories.ts", "src/**/*.spec.ts"] } diff --git a/bitwarden_license/bit-common/src/admin-console/auth-requests/organization-auth-request.service.ts b/bitwarden_license/bit-common/src/admin-console/auth-requests/organization-auth-request.service.ts index 941e56e7891..f7b87d8c1a5 100644 --- a/bitwarden_license/bit-common/src/admin-console/auth-requests/organization-auth-request.service.ts +++ b/bitwarden_license/bit-common/src/admin-console/auth-requests/organization-auth-request.service.ts @@ -123,7 +123,7 @@ export class OrganizationAuthRequestService { // Decrypt Organization's encrypted Private Key with org key const orgSymKey = await this.keyService.getOrgKey(organizationId); - const decOrgPrivateKey = await this.encryptService.decryptToBytes( + const decOrgPrivateKey = await this.encryptService.decryptBytes( new EncString(encryptedOrgPrivateKey), orgSymKey, ); diff --git a/bitwarden_license/bit-web/tsconfig.build.json b/bitwarden_license/bit-web/tsconfig.build.json index 6313ce27863..66c475051ed 100644 --- a/bitwarden_license/bit-web/tsconfig.build.json +++ b/bitwarden_license/bit-web/tsconfig.build.json @@ -7,8 +7,5 @@ "../../bitwarden_license/bit-web/src/main.ts" ], - "include": [ - "../../apps/web/src/connectors/*.ts", - "../../libs/common/src/key-management/crypto/services/encrypt.worker.ts" - ] + "include": ["../../apps/web/src/connectors/*.ts"] } diff --git a/bitwarden_license/bit-web/tsconfig.json b/bitwarden_license/bit-web/tsconfig.json index 7ec0441f4c1..0836d3d54ad 100644 --- a/bitwarden_license/bit-web/tsconfig.json +++ b/bitwarden_license/bit-web/tsconfig.json @@ -11,8 +11,6 @@ "../../apps/web/src/connectors/*.ts", "../../apps/web/src/**/*.stories.ts", "../../apps/web/src/**/*.spec.ts", - "../../libs/common/src/key-management/crypto/services/encrypt.worker.ts", - "src/**/*.stories.ts", "src/**/*.spec.ts" ] diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index f619588dc9e..cdc16ba1299 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -152,11 +152,9 @@ import { OrganizationBillingApiService } from "@bitwarden/common/billing/service import { OrganizationSponsorshipApiService } from "@bitwarden/common/billing/services/organization/organization-sponsorship-api.service"; import { OrganizationBillingService } from "@bitwarden/common/billing/services/organization-billing.service"; import { TaxService } from "@bitwarden/common/billing/services/tax.service"; -import { BulkEncryptService } from "@bitwarden/common/key-management/crypto/abstractions/bulk-encrypt.service"; import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service"; import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; -import { BulkEncryptServiceImplementation } from "@bitwarden/common/key-management/crypto/services/bulk-encrypt.service.implementation"; -import { MultithreadEncryptServiceImplementation } from "@bitwarden/common/key-management/crypto/services/multithread-encrypt.service.implementation"; +import { EncryptServiceImplementation } from "@bitwarden/common/key-management/crypto/services/encrypt.service.implementation"; import { WebCryptoFunctionService } from "@bitwarden/common/key-management/crypto/services/web-crypto-function.service"; import { DeviceTrustServiceAbstraction } from "@bitwarden/common/key-management/device-trust/abstractions/device-trust.service.abstraction"; import { DeviceTrustService } from "@bitwarden/common/key-management/device-trust/services/device-trust.service.implementation"; @@ -531,7 +529,6 @@ const safeProviders: SafeProvider[] = [ stateService: StateServiceAbstraction, autofillSettingsService: AutofillSettingsServiceAbstraction, encryptService: EncryptService, - bulkEncryptService: BulkEncryptService, fileUploadService: CipherFileUploadServiceAbstraction, configService: ConfigService, stateProvider: StateProvider, @@ -548,7 +545,6 @@ const safeProviders: SafeProvider[] = [ stateService, autofillSettingsService, encryptService, - bulkEncryptService, fileUploadService, configService, stateProvider, @@ -565,7 +561,6 @@ const safeProviders: SafeProvider[] = [ StateServiceAbstraction, AutofillSettingsServiceAbstraction, EncryptService, - BulkEncryptService, CipherFileUploadServiceAbstraction, ConfigService, StateProvider, @@ -967,14 +962,9 @@ const safeProviders: SafeProvider[] = [ }), safeProvider({ provide: EncryptService, - useClass: MultithreadEncryptServiceImplementation, + useClass: EncryptServiceImplementation, deps: [CryptoFunctionServiceAbstraction, LogService, LOG_MAC_FAILURES], }), - safeProvider({ - provide: BulkEncryptService, - useClass: BulkEncryptServiceImplementation, - deps: [CryptoFunctionServiceAbstraction, LogService], - }), safeProvider({ provide: EventUploadServiceAbstraction, useClass: EventUploadService, diff --git a/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts b/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts index 3e1761290dd..69f38f40989 100644 --- a/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts +++ b/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts @@ -86,9 +86,6 @@ describe("AuthRequestService", () => { describe("approveOrDenyAuthRequest", () => { beforeEach(() => { - encryptService.rsaEncrypt.mockResolvedValue({ - encryptedString: "ENCRYPTED_STRING", - } as EncString); encryptService.encapsulateKeyUnsigned.mockResolvedValue({ encryptedString: "ENCRYPTED_STRING", } as EncString); diff --git a/libs/common/src/enums/feature-flag.enum.ts b/libs/common/src/enums/feature-flag.enum.ts index 2cfbe7a9a4c..e992ac64d46 100644 --- a/libs/common/src/enums/feature-flag.enum.ts +++ b/libs/common/src/enums/feature-flag.enum.ts @@ -36,9 +36,6 @@ export enum FeatureFlag { /* Key Management */ PrivateKeyRegeneration = "pm-12241-private-key-regeneration", - PM4154_BulkEncryptionService = "PM-4154-bulk-encryption-service", - UseSDKForDecryption = "use-sdk-for-decryption", - PM17987_BlockType0 = "pm-17987-block-type-0", EnrollAeadOnKeyRotation = "enroll-aead-on-key-rotation", ForceUpdateKDFSettings = "pm-18021-force-update-kdf-settings", @@ -122,9 +119,6 @@ export const DefaultFeatureFlagValue = { /* Key Management */ [FeatureFlag.PrivateKeyRegeneration]: FALSE, - [FeatureFlag.PM4154_BulkEncryptionService]: FALSE, - [FeatureFlag.UseSDKForDecryption]: FALSE, - [FeatureFlag.PM17987_BlockType0]: FALSE, [FeatureFlag.EnrollAeadOnKeyRotation]: FALSE, [FeatureFlag.ForceUpdateKDFSettings]: FALSE, diff --git a/libs/common/src/key-management/crypto/abstractions/bulk-encrypt.service.ts b/libs/common/src/key-management/crypto/abstractions/bulk-encrypt.service.ts deleted file mode 100644 index 399ad75231e..00000000000 --- a/libs/common/src/key-management/crypto/abstractions/bulk-encrypt.service.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ServerConfig } from "../../../platform/abstractions/config/server-config"; -import { Decryptable } from "../../../platform/interfaces/decryptable.interface"; -import { InitializerMetadata } from "../../../platform/interfaces/initializer-metadata.interface"; -import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key"; - -export abstract class BulkEncryptService { - abstract decryptItems( - items: Decryptable[], - key: SymmetricCryptoKey, - ): Promise; - - abstract onServerConfigChange(newConfig: ServerConfig): void; -} diff --git a/libs/common/src/key-management/crypto/abstractions/crypto-function.service.ts b/libs/common/src/key-management/crypto/abstractions/crypto-function.service.ts index 5e4fa86a684..705a1c1a24e 100644 --- a/libs/common/src/key-management/crypto/abstractions/crypto-function.service.ts +++ b/libs/common/src/key-management/crypto/abstractions/crypto-function.service.ts @@ -6,12 +6,20 @@ import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-cr import { CsprngArray } from "../../../types/csprng"; export abstract class CryptoFunctionService { + /** + * @deprecated HAZMAT WARNING: DO NOT USE THIS FOR NEW CODE. Implement low-level crypto operations + * in the SDK instead. Further, you should probably never find yourself using this low-level crypto function. + */ abstract pbkdf2( password: string | Uint8Array, salt: string | Uint8Array, algorithm: "sha256" | "sha512", iterations: number, ): Promise; + /** + * @deprecated HAZMAT WARNING: DO NOT USE THIS FOR NEW CODE. Implement low-level crypto operations + * in the SDK instead. Further, you should probably never find yourself using this low-level crypto function. + */ abstract hkdf( ikm: Uint8Array, salt: string | Uint8Array, @@ -19,51 +27,76 @@ export abstract class CryptoFunctionService { outputByteSize: number, algorithm: "sha256" | "sha512", ): Promise; + /** + * @deprecated HAZMAT WARNING: DO NOT USE THIS FOR NEW CODE. Implement low-level crypto operations + * in the SDK instead. Further, you should probably never find yourself using this low-level crypto function. + */ abstract hkdfExpand( prk: Uint8Array, info: string | Uint8Array, outputByteSize: number, algorithm: "sha256" | "sha512", ): Promise; + /** + * @deprecated HAZMAT WARNING: DO NOT USE THIS FOR NEW CODE. Implement low-level crypto operations + * in the SDK instead. Further, you should probably never find yourself using this low-level crypto function. + */ abstract hash( value: string | Uint8Array, algorithm: "sha1" | "sha256" | "sha512" | "md5", ): Promise; - abstract hmac( - value: Uint8Array, - key: Uint8Array, - algorithm: "sha1" | "sha256" | "sha512", - ): Promise; - abstract compare(a: Uint8Array, b: Uint8Array): Promise; + /** + * @deprecated HAZMAT WARNING: DO NOT USE THIS FOR NEW CODE. Implement low-level crypto operations + * in the SDK instead. Further, you should probably never find yourself using this low-level crypto function. + */ abstract hmacFast( value: Uint8Array | string, key: Uint8Array | string, algorithm: "sha1" | "sha256" | "sha512", ): Promise; abstract compareFast(a: Uint8Array | string, b: Uint8Array | string): Promise; + /** + * @deprecated HAZMAT WARNING: DO NOT USE THIS FOR NEW CODE. Implement low-level crypto operations + * in the SDK instead. Further, you should probably never find yourself using this low-level crypto function. + */ abstract aesDecryptFastParameters( data: string, iv: string, mac: string, key: SymmetricCryptoKey, ): CbcDecryptParameters; + /** + * @deprecated HAZMAT WARNING: DO NOT USE THIS FOR NEW CODE. Implement low-level crypto operations + * in the SDK instead. Further, you should probably never find yourself using this low-level crypto function. + */ abstract aesDecryptFast({ mode, parameters, }: | { mode: "cbc"; parameters: CbcDecryptParameters } | { mode: "ecb"; parameters: EcbDecryptParameters }): Promise; + /** + * @deprecated HAZMAT WARNING: DO NOT USE THIS FOR NEW CODE. Only used by DDG integration until DDG uses PKCS#7 padding, and by lastpass importer. + */ abstract aesDecrypt( data: Uint8Array, iv: Uint8Array, key: Uint8Array, mode: "cbc" | "ecb", ): Promise; + /** + * @deprecated HAZMAT WARNING: DO NOT USE THIS FOR NEW CODE. Implement low-level crypto operations + * in the SDK instead. Further, you should probably never find yourself using this low-level crypto function. + */ abstract rsaEncrypt( data: Uint8Array, publicKey: Uint8Array, algorithm: "sha1" | "sha256", ): Promise; + /** + * @deprecated HAZMAT WARNING: DO NOT USE THIS FOR NEW CODE. Implement low-level crypto operations + * in the SDK instead. Further, you should probably never find yourself using this low-level crypto function. + */ abstract rsaDecrypt( data: Uint8Array, privateKey: Uint8Array, @@ -77,7 +110,6 @@ export abstract class CryptoFunctionService { abstract aesGenerateKey(bitLength: 128 | 192 | 256 | 512): Promise; /** * Generates a random array of bytes of the given length. Uses a cryptographically secure random number generator. - * * Do not use this for generating encryption keys. Use aesGenerateKey or rsaGenerateKeyPair instead. */ abstract randomBytes(length: number): Promise; diff --git a/libs/common/src/key-management/crypto/abstractions/encrypt.service.ts b/libs/common/src/key-management/crypto/abstractions/encrypt.service.ts index 67db3591e74..ed43e25bd0a 100644 --- a/libs/common/src/key-management/crypto/abstractions/encrypt.service.ts +++ b/libs/common/src/key-management/crypto/abstractions/encrypt.service.ts @@ -1,51 +1,8 @@ -import { ServerConfig } from "../../../platform/abstractions/config/server-config"; -import { Decryptable } from "../../../platform/interfaces/decryptable.interface"; -import { Encrypted } from "../../../platform/interfaces/encrypted"; -import { InitializerMetadata } from "../../../platform/interfaces/initializer-metadata.interface"; import { EncArrayBuffer } from "../../../platform/models/domain/enc-array-buffer"; import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key"; import { EncString } from "../models/enc-string"; export abstract class EncryptService { - /** - * @deprecated - * Decrypts an EncString to a string - * @param encString - The EncString to decrypt - * @param key - The key to decrypt the EncString with - * @param decryptTrace - A string to identify the context of the object being decrypted. This can include: field name, encryption type, cipher id, key type, but should not include - * sensitive information like encryption keys or data. This is used for logging when decryption errors occur in order to identify what failed to decrypt - * @returns The decrypted string - */ - abstract decryptToUtf8( - encString: EncString, - key: SymmetricCryptoKey, - decryptTrace?: string, - ): Promise; - /** - * @deprecated - * Decrypts an Encrypted object to a Uint8Array - * @param encThing - The Encrypted object to decrypt - * @param key - The key to decrypt the Encrypted object with - * @param decryptTrace - A string to identify the context of the object being decrypted. This can include: field name, encryption type, cipher id, key type, but should not include - * sensitive information like encryption keys or data. This is used for logging when decryption errors occur in order to identify what failed to decrypt - * @returns The decrypted Uint8Array - */ - abstract decryptToBytes( - encThing: Encrypted, - key: SymmetricCryptoKey, - decryptTrace?: string, - ): Promise; - - /** - * @deprecated Replaced by BulkEncryptService, remove once the feature is tested and the featureflag PM-4154-multi-worker-encryption-service is removed - * @param items The items to decrypt - * @param key The key to decrypt the items with - */ - abstract decryptItems( - items: Decryptable[], - key: SymmetricCryptoKey, - ): Promise; - /** * Encrypts a string to an EncString * @param plainValue - The value to encrypt @@ -188,12 +145,6 @@ export abstract class EncryptService { decapsulationKey: Uint8Array, ): Promise; - /** - * @deprecated Use @see {@link encapsulateKeyUnsigned} instead - * @param data - The data to encrypt - * @param publicKey - The public key to encrypt with - */ - abstract rsaEncrypt(data: Uint8Array, publicKey: Uint8Array): Promise; /** * @deprecated Use @see {@link decapsulateKeyUnsigned} instead * @param data - The ciphertext to decrypt @@ -210,6 +161,4 @@ export abstract class EncryptService { value: string | Uint8Array, algorithm: "sha1" | "sha256" | "sha512", ): Promise; - - abstract onServerConfigChange(newConfig: ServerConfig): void; } diff --git a/libs/common/src/key-management/crypto/services/bulk-encrypt.service.implementation.ts b/libs/common/src/key-management/crypto/services/bulk-encrypt.service.implementation.ts deleted file mode 100644 index 1bc1827a07a..00000000000 --- a/libs/common/src/key-management/crypto/services/bulk-encrypt.service.implementation.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { BulkEncryptService } from "@bitwarden/common/key-management/crypto/abstractions/bulk-encrypt.service"; -import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service"; -import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; -import { Decryptable } from "@bitwarden/common/platform/interfaces/decryptable.interface"; -import { InitializerMetadata } from "@bitwarden/common/platform/interfaces/initializer-metadata.interface"; -import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; - -import { DefaultFeatureFlagValue, FeatureFlag } from "../../../enums/feature-flag.enum"; -import { ServerConfig } from "../../../platform/abstractions/config/server-config"; - -/** - * @deprecated Will be deleted in an immediate subsequent PR - */ -export class BulkEncryptServiceImplementation implements BulkEncryptService { - protected useSDKForDecryption: boolean = DefaultFeatureFlagValue[FeatureFlag.UseSDKForDecryption]; - - constructor( - protected cryptoFunctionService: CryptoFunctionService, - protected logService: LogService, - ) {} - - /** - * Decrypts items using a web worker if the environment supports it. - * Will fall back to the main thread if the window object is not available. - */ - async decryptItems( - items: Decryptable[], - key: SymmetricCryptoKey, - ): Promise { - if (key == null) { - throw new Error("No encryption key provided."); - } - - if (items == null || items.length < 1) { - return []; - } - - const results = []; - for (let i = 0; i < items.length; i++) { - results.push(await items[i].decrypt(key)); - } - return results; - } - - onServerConfigChange(newConfig: ServerConfig): void {} -} diff --git a/libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts b/libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts index 3e36fd334ec..6daede6be67 100644 --- a/libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts +++ b/libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts @@ -5,15 +5,11 @@ import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-st import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service"; import { EncryptionType } from "@bitwarden/common/platform/enums"; -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"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { EncArrayBuffer } from "@bitwarden/common/platform/models/domain/enc-array-buffer"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { PureCrypto } from "@bitwarden/sdk-internal"; -import { ServerConfig } from "../../../platform/abstractions/config/server-config"; import { EncryptService } from "../abstractions/encrypt.service"; export class EncryptServiceImplementation implements EncryptService { @@ -23,7 +19,6 @@ export class EncryptServiceImplementation implements EncryptService { protected logMacFailures: boolean, ) {} - // Proxy functions; Their implementation are temporary before moving at this level to the SDK async encryptString(plainValue: string, key: SymmetricCryptoKey): Promise { if (plainValue == null) { this.logService.warning( @@ -171,36 +166,6 @@ export class EncryptServiceImplementation implements EncryptService { return Utils.fromBufferToB64(hashArray); } - // Handle updating private properties to turn on/off feature flags. - onServerConfigChange(newConfig: ServerConfig): void {} - - async decryptToUtf8( - encString: EncString, - key: SymmetricCryptoKey, - _decryptContext: string = "no context", - ): Promise { - await SdkLoadService.Ready; - return PureCrypto.symmetric_decrypt(encString.encryptedString, key.toEncoded()); - } - - async decryptToBytes( - encThing: Encrypted, - key: SymmetricCryptoKey, - _decryptContext: string = "no context", - ): Promise { - 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; - await SdkLoadService.Ready; - return PureCrypto.symmetric_decrypt_array_buffer(buffer, key.toEncoded()); - } - async encapsulateKeyUnsigned( sharedKey: SymmetricCryptoKey, encapsulationKey: Uint8Array, @@ -228,45 +193,14 @@ export class EncryptServiceImplementation implements EncryptService { throw new Error("No decapsulationKey provided for decapsulation"); } + await SdkLoadService.Ready; const keyBytes = PureCrypto.decapsulate_key_unsigned( encryptedSharedKey.encryptedString, decapsulationKey, ); - await SdkLoadService.Ready; return new SymmetricCryptoKey(keyBytes); } - /** - * @deprecated Replaced by BulkEncryptService (PM-4154) - */ - async decryptItems( - items: Decryptable[], - key: SymmetricCryptoKey, - ): Promise { - if (items == null || items.length < 1) { - return []; - } - - // don't use promise.all because this task is not io bound - const results = []; - for (let i = 0; i < items.length; i++) { - results.push(await items[i].decrypt(key)); - } - return results; - } - - async rsaEncrypt(data: Uint8Array, publicKey: Uint8Array): Promise { - if (data == null) { - throw new Error("No data provided for encryption."); - } - - if (publicKey == null) { - throw new Error("No public key provided for encryption."); - } - const encrypted = await this.cryptoFunctionService.rsaEncrypt(data, publicKey, "sha1"); - return new EncString(EncryptionType.Rsa2048_OaepSha1_B64, Utils.fromBufferToB64(encrypted)); - } - async rsaDecrypt(data: EncString, privateKey: Uint8Array): Promise { if (data == null) { throw new Error("[Encrypt service] rsaDecrypt: No data provided for decryption."); diff --git a/libs/common/src/key-management/crypto/services/encrypt.service.spec.ts b/libs/common/src/key-management/crypto/services/encrypt.service.spec.ts index 4cc76d45f50..0cc7824a918 100644 --- a/libs/common/src/key-management/crypto/services/encrypt.service.spec.ts +++ b/libs/common/src/key-management/crypto/services/encrypt.service.spec.ts @@ -303,12 +303,6 @@ describe("EncryptService", () => { const actual = await encryptService.encapsulateKeyUnsigned(testKey, publicKey); expect(actual).toEqual(new EncString("encapsulated_key_unsigned")); }); - - it("throws if no data was provided", () => { - return expect(encryptService.rsaEncrypt(null, new Uint8Array(32))).rejects.toThrow( - "No data provided for encryption", - ); - }); }); describe("decapsulateKeyUnsigned", () => { @@ -338,23 +332,4 @@ describe("EncryptService", () => { expect(cryptoFunctionService.hash).toHaveBeenCalledWith("test", "sha256"); }); }); - - describe("decryptItems", () => { - it("returns empty array if no items are provided", async () => { - const key = mock(); - const actual = await encryptService.decryptItems(null, key); - expect(actual).toEqual([]); - }); - - it("returns items decrypted with provided key", async () => { - const key = mock(); - const decryptable = { - decrypt: jest.fn().mockResolvedValue("decrypted"), - }; - const items = [decryptable]; - const actual = await encryptService.decryptItems(items as any, key); - expect(actual).toEqual(["decrypted"]); - expect(decryptable.decrypt).toHaveBeenCalledWith(key); - }); - }); }); diff --git a/libs/common/src/key-management/crypto/services/encrypt.worker.ts b/libs/common/src/key-management/crypto/services/encrypt.worker.ts deleted file mode 100644 index e5aeb06560b..00000000000 --- a/libs/common/src/key-management/crypto/services/encrypt.worker.ts +++ /dev/null @@ -1,81 +0,0 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore -import { Jsonify } from "type-fest"; - -import { ServerConfig } from "../../../platform/abstractions/config/server-config"; -import { LogService } from "../../../platform/abstractions/log.service"; -import { Decryptable } from "../../../platform/interfaces/decryptable.interface"; -import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key"; -import { ConsoleLogService } from "../../../platform/services/console-log.service"; -import { ContainerService } from "../../../platform/services/container.service"; -import { getClassInitializer } from "../../../platform/services/cryptography/get-class-initializer"; -import { - DECRYPT_COMMAND, - SET_CONFIG_COMMAND, - ParsedDecryptCommandData, -} from "../types/worker-command.type"; - -import { EncryptServiceImplementation } from "./encrypt.service.implementation"; -import { WebCryptoFunctionService } from "./web-crypto-function.service"; - -const workerApi: Worker = self as any; - -let inited = false; -let encryptService: EncryptServiceImplementation; -let logService: LogService; - -/** - * Bootstrap the worker environment with services required for decryption - */ -export function init() { - const cryptoFunctionService = new WebCryptoFunctionService(self); - logService = new ConsoleLogService(false); - encryptService = new EncryptServiceImplementation(cryptoFunctionService, logService, true); - - const bitwardenContainerService = new ContainerService(null, encryptService); - bitwardenContainerService.attachToGlobal(self); - - inited = true; -} - -/** - * Listen for messages and decrypt their contents - */ -workerApi.addEventListener("message", async (event: { data: string }) => { - if (!inited) { - init(); - } - - const request: { - command: string; - } = JSON.parse(event.data); - - switch (request.command) { - case DECRYPT_COMMAND: - return await handleDecrypt(request as unknown as ParsedDecryptCommandData); - case SET_CONFIG_COMMAND: { - const newConfig = (request as unknown as { newConfig: Jsonify }).newConfig; - return await handleSetConfig(newConfig); - } - default: - logService.error(`[EncryptWorker] unknown worker command`, request.command, request); - } -}); - -async function handleDecrypt(request: ParsedDecryptCommandData) { - const key = SymmetricCryptoKey.fromJSON(request.key); - const items = request.items.map((jsonItem) => { - const initializer = getClassInitializer>(jsonItem.initializerKey); - return initializer(jsonItem); - }); - const result = await encryptService.decryptItems(items, key); - - workerApi.postMessage({ - id: request.id, - items: JSON.stringify(result), - }); -} - -async function handleSetConfig(newConfig: Jsonify) { - encryptService.onServerConfigChange(ServerConfig.fromJSON(newConfig)); -} diff --git a/libs/common/src/key-management/crypto/services/fallback-bulk-encrypt.service.ts b/libs/common/src/key-management/crypto/services/fallback-bulk-encrypt.service.ts deleted file mode 100644 index 0a05bff4422..00000000000 --- a/libs/common/src/key-management/crypto/services/fallback-bulk-encrypt.service.ts +++ /dev/null @@ -1,34 +0,0 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore -import { BulkEncryptService } from "@bitwarden/common/key-management/crypto/abstractions/bulk-encrypt.service"; -import { Decryptable } from "@bitwarden/common/platform/interfaces/decryptable.interface"; -import { InitializerMetadata } from "@bitwarden/common/platform/interfaces/initializer-metadata.interface"; -import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; - -import { ServerConfig } from "../../../platform/abstractions/config/server-config"; -import { EncryptService } from "../abstractions/encrypt.service"; - -/** - * @deprecated Will be deleted in an immediate subsequent PR - */ -export class FallbackBulkEncryptService implements BulkEncryptService { - private featureFlagEncryptService: BulkEncryptService; - private currentServerConfig: ServerConfig | undefined = undefined; - - constructor(protected encryptService: EncryptService) {} - - /** - * Decrypts items using a web worker if the environment supports it. - * Will fall back to the main thread if the window object is not available. - */ - async decryptItems( - items: Decryptable[], - key: SymmetricCryptoKey, - ): Promise { - return await this.encryptService.decryptItems(items, key); - } - - async setFeatureFlagEncryptService(featureFlagEncryptService: BulkEncryptService) {} - - onServerConfigChange(newConfig: ServerConfig): void {} -} diff --git a/libs/common/src/key-management/crypto/services/multithread-encrypt.service.implementation.ts b/libs/common/src/key-management/crypto/services/multithread-encrypt.service.implementation.ts deleted file mode 100644 index ab65074af3b..00000000000 --- a/libs/common/src/key-management/crypto/services/multithread-encrypt.service.implementation.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Decryptable } from "@bitwarden/common/platform/interfaces/decryptable.interface"; -import { InitializerMetadata } from "@bitwarden/common/platform/interfaces/initializer-metadata.interface"; -import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; - -import { ServerConfig } from "../../../platform/abstractions/config/server-config"; - -import { EncryptServiceImplementation } from "./encrypt.service.implementation"; - -/** - * @deprecated Will be deleted in an immediate subsequent PR - */ -export class MultithreadEncryptServiceImplementation extends EncryptServiceImplementation { - protected useSDKForDecryption: boolean = true; - - /** - * Sends items to a web worker to decrypt them. - * This utilises multithreading to decrypt items faster without interrupting other operations (e.g. updating UI). - */ - async decryptItems( - items: Decryptable[], - key: SymmetricCryptoKey, - ): Promise { - return await super.decryptItems(items, key); - } - - override onServerConfigChange(newConfig: ServerConfig): void {} -} diff --git a/libs/common/src/key-management/crypto/services/web-crypto-function.service.spec.ts b/libs/common/src/key-management/crypto/services/web-crypto-function.service.spec.ts index ae968fc6844..c0b5150a720 100644 --- a/libs/common/src/key-management/crypto/services/web-crypto-function.service.spec.ts +++ b/libs/common/src/key-management/crypto/services/web-crypto-function.service.spec.ts @@ -154,46 +154,6 @@ describe("WebCrypto Function Service", () => { testHmac("sha512", Sha512Mac); }); - describe("compare", () => { - it("should successfully compare two of the same values", async () => { - const cryptoFunctionService = getWebCryptoFunctionService(); - const a = new Uint8Array(2); - a[0] = 1; - a[1] = 2; - const equal = await cryptoFunctionService.compare(a, a); - expect(equal).toBe(true); - }); - - it("should successfully compare two different values of the same length", async () => { - const cryptoFunctionService = getWebCryptoFunctionService(); - const a = new Uint8Array(2); - a[0] = 1; - a[1] = 2; - const b = new Uint8Array(2); - b[0] = 3; - b[1] = 4; - const equal = await cryptoFunctionService.compare(a, b); - expect(equal).toBe(false); - }); - - it("should successfully compare two different values of different lengths", async () => { - const cryptoFunctionService = getWebCryptoFunctionService(); - const a = new Uint8Array(2); - a[0] = 1; - a[1] = 2; - const b = new Uint8Array(2); - b[0] = 3; - const equal = await cryptoFunctionService.compare(a, b); - expect(equal).toBe(false); - }); - }); - - describe("hmacFast", () => { - testHmacFast("sha1", Sha1Mac); - testHmacFast("sha256", Sha256Mac); - testHmacFast("sha512", Sha512Mac); - }); - describe("compareFast", () => { it("should successfully compare two of the same values", async () => { const cryptoFunctionService = getWebCryptoFunctionService(); @@ -523,20 +483,6 @@ function testHmac(algorithm: "sha1" | "sha256" | "sha512", mac: string) { }); } -function testHmacFast(algorithm: "sha1" | "sha256" | "sha512", mac: string) { - it("should create valid " + algorithm + " hmac", async () => { - const cryptoFunctionService = getWebCryptoFunctionService(); - const keyByteString = Utils.fromBufferToByteString(Utils.fromUtf8ToArray("secretkey")); - const dataByteString = Utils.fromBufferToByteString(Utils.fromUtf8ToArray("SignMe!!")); - const computedMac = await cryptoFunctionService.hmacFast( - dataByteString, - keyByteString, - algorithm, - ); - expect(Utils.fromBufferToHex(Utils.fromByteStringToArray(computedMac))).toBe(mac); - }); -} - function testRsaGenerateKeyPair(length: 1024 | 2048 | 4096) { it( "should successfully generate a " + length + " bit key pair", diff --git a/libs/common/src/key-management/crypto/services/web-crypto-function.service.ts b/libs/common/src/key-management/crypto/services/web-crypto-function.service.ts index 80a2a31dea6..175da716803 100644 --- a/libs/common/src/key-management/crypto/services/web-crypto-function.service.ts +++ b/libs/common/src/key-management/crypto/services/web-crypto-function.service.ts @@ -146,34 +146,6 @@ export class WebCryptoFunctionService implements CryptoFunctionService { return new Uint8Array(buffer); } - // Safely compare two values in a way that protects against timing attacks (Double HMAC Verification). - // ref: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/ - // ref: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy - async compare(a: Uint8Array, b: Uint8Array): Promise { - const macKey = await this.randomBytes(32); - const signingAlgorithm = { - name: "HMAC", - hash: { name: "SHA-256" }, - }; - const impKey = await this.subtle.importKey("raw", macKey, signingAlgorithm, false, ["sign"]); - const mac1 = await this.subtle.sign(signingAlgorithm, impKey, a); - const mac2 = await this.subtle.sign(signingAlgorithm, impKey, b); - - if (mac1.byteLength !== mac2.byteLength) { - return false; - } - - const arr1 = new Uint8Array(mac1); - const arr2 = new Uint8Array(mac2); - for (let i = 0; i < arr2.length; i++) { - if (arr1[i] !== arr2[i]) { - return false; - } - } - - return true; - } - hmacFast(value: string, key: string, algorithm: "sha1" | "sha256" | "sha512"): Promise { const hmac = forge.hmac.create(); hmac.start(algorithm, key); @@ -182,6 +154,9 @@ export class WebCryptoFunctionService implements CryptoFunctionService { return Promise.resolve(bytes); } + // Safely compare two values in a way that protects against timing attacks (Double HMAC Verification). + // ref: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/ + // ref: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy async compareFast(a: string, b: string): Promise { const rand = await this.randomBytes(32); const bytes = new Uint32Array(rand); diff --git a/libs/common/src/key-management/crypto/types/worker-command.type.spec.ts b/libs/common/src/key-management/crypto/types/worker-command.type.spec.ts deleted file mode 100644 index e820543caa9..00000000000 --- a/libs/common/src/key-management/crypto/types/worker-command.type.spec.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { mock } from "jest-mock-extended"; - -import { makeStaticByteArray } from "../../../../spec"; -import { ServerConfig } from "../../../platform/abstractions/config/server-config"; -import { Decryptable } from "../../../platform/interfaces/decryptable.interface"; -import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key"; - -import { - DECRYPT_COMMAND, - DecryptCommandData, - SET_CONFIG_COMMAND, - buildDecryptMessage, - buildSetConfigMessage, -} from "./worker-command.type"; - -describe("Worker command types", () => { - describe("buildDecryptMessage", () => { - it("builds a message with the correct command", () => { - const commandData = createDecryptCommandData(); - - const result = buildDecryptMessage(commandData); - - const parsedResult = JSON.parse(result); - expect(parsedResult.command).toBe(DECRYPT_COMMAND); - }); - - it("includes the provided data in the message", () => { - const mockItems = [{ encrypted: "test-encrypted" } as unknown as Decryptable]; - const commandData = createDecryptCommandData(mockItems); - - const result = buildDecryptMessage(commandData); - - const parsedResult = JSON.parse(result); - expect(parsedResult.command).toBe(DECRYPT_COMMAND); - expect(parsedResult.id).toBe("test-id"); - expect(parsedResult.items).toEqual(mockItems); - expect(SymmetricCryptoKey.fromJSON(parsedResult.key)).toEqual(commandData.key); - }); - }); - - describe("buildSetConfigMessage", () => { - it("builds a message with the correct command", () => { - const result = buildSetConfigMessage({ newConfig: mock() }); - - const parsedResult = JSON.parse(result); - expect(parsedResult.command).toBe(SET_CONFIG_COMMAND); - }); - - it("includes the provided data in the message", () => { - const serverConfig = { version: "test-version" } as unknown as ServerConfig; - - const result = buildSetConfigMessage({ newConfig: serverConfig }); - - const parsedResult = JSON.parse(result); - expect(parsedResult.command).toBe(SET_CONFIG_COMMAND); - expect(ServerConfig.fromJSON(parsedResult.newConfig).version).toEqual(serverConfig.version); - }); - }); -}); - -function createDecryptCommandData(items?: Decryptable[]): DecryptCommandData { - return { - id: "test-id", - items: items ?? [], - key: new SymmetricCryptoKey(makeStaticByteArray(64)), - }; -} diff --git a/libs/common/src/key-management/crypto/types/worker-command.type.ts b/libs/common/src/key-management/crypto/types/worker-command.type.ts deleted file mode 100644 index e058bf3eaac..00000000000 --- a/libs/common/src/key-management/crypto/types/worker-command.type.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Jsonify } from "type-fest"; - -import { ServerConfig } from "../../../platform/abstractions/config/server-config"; -import { Decryptable } from "../../../platform/interfaces/decryptable.interface"; -import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key"; - -export const DECRYPT_COMMAND = "decrypt"; -export const SET_CONFIG_COMMAND = "updateConfig"; - -export type DecryptCommandData = { - id: string; - items: Decryptable[]; - key: SymmetricCryptoKey; -}; - -export type ParsedDecryptCommandData = { - id: string; - items: Jsonify>[]; - key: Jsonify; -}; - -type SetConfigCommandData = { newConfig: ServerConfig }; - -export function buildDecryptMessage(data: DecryptCommandData): string { - return JSON.stringify({ - command: DECRYPT_COMMAND, - ...data, - }); -} - -export function buildSetConfigMessage(data: SetConfigCommandData): string { - return JSON.stringify({ - command: SET_CONFIG_COMMAND, - ...data, - }); -} diff --git a/libs/common/src/vault/models/domain/folder.spec.ts b/libs/common/src/vault/models/domain/folder.spec.ts index 2e5e7c74a3d..a837fbb2726 100644 --- a/libs/common/src/vault/models/domain/folder.spec.ts +++ b/libs/common/src/vault/models/domain/folder.spec.ts @@ -70,7 +70,10 @@ describe("Folder", () => { beforeEach(() => { encryptService = mock(); - encryptService.decryptString.mockResolvedValue("encName"); + // Platform code is not migrated yet + encryptService.decryptString.mockImplementation((_value, _key) => { + return Promise.resolve("encName"); + }); }); it("decrypts the name", async () => { diff --git a/libs/common/src/vault/services/cipher.service.spec.ts b/libs/common/src/vault/services/cipher.service.spec.ts index b743ae25838..996de182f6e 100644 --- a/libs/common/src/vault/services/cipher.service.spec.ts +++ b/libs/common/src/vault/services/cipher.service.spec.ts @@ -14,7 +14,6 @@ import { makeStaticByteArray, makeSymmetricCryptoKey } from "../../../spec/utils import { ApiService } from "../../abstractions/api.service"; import { AutofillSettingsService } from "../../autofill/services/autofill-settings.service"; import { DomainSettingsService } from "../../autofill/services/domain-settings.service"; -import { BulkEncryptService } from "../../key-management/crypto/abstractions/bulk-encrypt.service"; import { EncryptService } from "../../key-management/crypto/abstractions/encrypt.service"; import { EncString } from "../../key-management/crypto/models/enc-string"; import { UriMatchStrategy } from "../../models/domain/domain-service"; @@ -102,7 +101,6 @@ describe("Cipher Service", () => { const i18nService = mock(); const searchService = mock(); const encryptService = mock(); - const bulkEncryptService = mock(); const configService = mock(); accountService = mockAccountServiceWith(mockUserId); const logService = mock(); @@ -130,7 +128,6 @@ describe("Cipher Service", () => { stateService, autofillSettingsService, encryptService, - bulkEncryptService, cipherFileUploadService, configService, stateProvider, @@ -578,7 +575,6 @@ describe("Cipher Service", () => { .calledWith(FeatureFlag.PM19941MigrateCipherDomainToSdk) .mockResolvedValue(false); cipherService.getKeyForCipherKeyDecryption = jest.fn().mockResolvedValue(mockUserKey); - encryptService.decryptToBytes.mockResolvedValue(new Uint8Array(32)); jest .spyOn(encryptionContext.cipher, "decrypt") .mockResolvedValue(new CipherView(encryptionContext.cipher)); diff --git a/libs/common/src/vault/services/cipher.service.ts b/libs/common/src/vault/services/cipher.service.ts index 5302565ad9d..d3513792727 100644 --- a/libs/common/src/vault/services/cipher.service.ts +++ b/libs/common/src/vault/services/cipher.service.ts @@ -13,7 +13,6 @@ import { AccountService } from "../../auth/abstractions/account.service"; import { AutofillSettingsServiceAbstraction } from "../../autofill/services/autofill-settings.service"; import { DomainSettingsService } from "../../autofill/services/domain-settings.service"; import { FeatureFlag } from "../../enums/feature-flag.enum"; -import { BulkEncryptService } from "../../key-management/crypto/abstractions/bulk-encrypt.service"; import { EncryptService } from "../../key-management/crypto/abstractions/encrypt.service"; import { EncString } from "../../key-management/crypto/models/enc-string"; import { UriMatchStrategySetting } from "../../models/domain/domain-service"; @@ -104,7 +103,6 @@ export class CipherService implements CipherServiceAbstraction { private stateService: StateService, private autofillSettingsService: AutofillSettingsServiceAbstraction, private encryptService: EncryptService, - private bulkEncryptService: BulkEncryptService, private cipherFileUploadService: CipherFileUploadService, private configService: ConfigService, private stateProvider: StateProvider, @@ -506,17 +504,12 @@ export class CipherService implements CipherServiceAbstraction { const allCipherViews = ( await Promise.all( Object.entries(grouped).map(async ([orgId, groupedCiphers]) => { - if (await this.configService.getFeatureFlag(FeatureFlag.PM4154_BulkEncryptionService)) { - return await this.bulkEncryptService.decryptItems( - groupedCiphers, - keys.orgKeys?.[orgId as OrganizationId] ?? keys.userKey, - ); - } else { - return await this.encryptService.decryptItems( - groupedCiphers, - keys.orgKeys?.[orgId as OrganizationId] ?? keys.userKey, - ); - } + const key = keys.orgKeys[orgId as OrganizationId] ?? keys.userKey; + return await Promise.all( + groupedCiphers.map(async (cipher) => { + return await cipher.decrypt(key); + }), + ); }), ) ) @@ -684,12 +677,11 @@ export class CipherService implements CipherServiceAbstraction { const ciphers = response.data.map((cr) => new Cipher(new CipherData(cr))); const key = await this.keyService.getOrgKey(organizationId); - let decCiphers: CipherView[] = []; - if (await this.configService.getFeatureFlag(FeatureFlag.PM4154_BulkEncryptionService)) { - decCiphers = await this.bulkEncryptService.decryptItems(ciphers, key); - } else { - decCiphers = await this.encryptService.decryptItems(ciphers, key); - } + const decCiphers: CipherView[] = await Promise.all( + ciphers.map(async (cipher) => { + return await cipher.decrypt(key); + }), + ); decCiphers.sort(this.getLocaleSortingFunction()); return decCiphers; diff --git a/libs/common/src/vault/services/folder/folder.service.spec.ts b/libs/common/src/vault/services/folder/folder.service.spec.ts index e87f974d517..a520fd4852d 100644 --- a/libs/common/src/vault/services/folder/folder.service.spec.ts +++ b/libs/common/src/vault/services/folder/folder.service.spec.ts @@ -49,7 +49,6 @@ describe("Folder Service", () => { keyService.userKey$.mockReturnValue(new BehaviorSubject("mockOriginalUserKey" as any)); encryptService.decryptString.mockResolvedValue("DEC"); - encryptService.decryptToUtf8.mockResolvedValue("DEC"); folderService = new FolderService( keyService, diff --git a/libs/key-management/src/key.service.spec.ts b/libs/key-management/src/key.service.spec.ts index 27d838c6fb3..2b92f3204c9 100644 --- a/libs/key-management/src/key.service.spec.ts +++ b/libs/key-management/src/key.service.spec.ts @@ -697,7 +697,6 @@ describe("keyService", () => { }); it("returns decryption keys when some of the org keys are providers", async () => { - encryptService.decryptToBytes.mockResolvedValue(new Uint8Array(64)); const org2Id = "org2Id" as OrganizationId; updateKeys({ userKey: makeSymmetricCryptoKey(64), diff --git a/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.spec.ts b/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.spec.ts index 3a622fe72c0..b23d6e8f3bd 100644 --- a/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.spec.ts +++ b/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.spec.ts @@ -54,7 +54,6 @@ function setupUserKeyValidation( encryptService.unwrapSymmetricKey.mockResolvedValue( new SymmetricCryptoKey(makeStaticByteArray(64)), ); - encryptService.decryptToBytes.mockResolvedValue(makeStaticByteArray(64)); encryptService.decryptString.mockResolvedValue("mockDecryptedString"); (window as any).bitwardenContainerService = new ContainerService(keyService, encryptService); } @@ -276,7 +275,6 @@ describe("regenerateIfNeeded", () => { }; setupVerificationResponse(mockVerificationResponse, sdkService); setupUserKeyValidation(cipherService, keyService, encryptService); - encryptService.decryptToBytes.mockRejectedValue(new Error("error")); encryptService.decryptString.mockRejectedValue(new Error("error")); encryptService.unwrapSymmetricKey.mockRejectedValue(new Error("error")); @@ -327,7 +325,6 @@ describe("regenerateIfNeeded", () => { }; setupVerificationResponse(mockVerificationResponse, sdkService); setupUserKeyValidation(cipherService, keyService, encryptService); - encryptService.decryptToBytes.mockRejectedValue(new Error("error")); encryptService.decryptString.mockRejectedValue(new Error("error")); encryptService.unwrapSymmetricKey.mockRejectedValue(new Error("error"));