From d92b2cbea27feb62fd23d0bceed96fa588b6b519 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Tue, 24 Sep 2024 11:28:33 +0200 Subject: [PATCH] [PM-11477] Remove deprecated cryptoservice functions (#10854) * Remove deprecated cryptoservice functions * Use getUserkeyWithLegacySupport to get userkey * Fix tests * Fix tests * Fix tests * Remove unused cryptoservice instances * Fix build * Remove unused apiService in constructor * Fix encryption * Ensure passed in key is used if present * Fix sends and folders * Fix tests * Remove logged key * Fix import for account restricted keys --- .../browser/src/background/main.background.ts | 8 +++ .../background/nativeMessaging.background.ts | 6 ++- .../add-edit-folder-dialog.component.spec.ts | 35 ++++++++++-- .../add-edit-folder-dialog.component.ts | 9 +++- .../components/vault/attachments.component.ts | 3 ++ .../popup/components/vault/view.component.ts | 3 ++ .../settings/folder-add-edit.component.ts | 6 +++ apps/cli/src/commands/download.command.ts | 6 +-- apps/cli/src/commands/edit.command.ts | 9 +++- apps/cli/src/commands/get.command.ts | 8 +-- apps/cli/src/oss-serve-configurator.ts | 5 +- .../service-container/service-container.ts | 7 +++ .../src/tools/send/commands/get.command.ts | 6 +-- .../tools/send/commands/receive.command.ts | 8 +-- apps/cli/src/tools/send/send.program.ts | 7 +-- apps/cli/src/vault.program.ts | 3 ++ apps/cli/src/vault/create.command.ts | 8 ++- .../src/app/services/services.module.ts | 2 +- .../native-message-handler.service.ts | 8 +-- .../src/services/native-messaging.service.ts | 6 ++- .../vault/app/vault/attachments.component.ts | 3 ++ .../app/vault/folder-add-edit.component.ts | 6 +++ .../src/vault/app/vault/view.component.ts | 3 ++ .../emergency-access-attachments.component.ts | 3 ++ .../organization-plans.component.ts | 6 ++- .../tools/send/send-access-file.component.ts | 6 +-- .../vault/core/collection-admin.service.ts | 6 ++- .../individual-vault/attachments.component.ts | 3 ++ .../folder-add-edit.component.ts | 11 +++- .../vault/org-vault/attachments.component.ts | 3 ++ .../bit-cli/src/service-container.ts | 1 + .../organization-auth-request.service.spec.ts | 4 ++ .../organization-auth-request.service.ts | 4 +- .../device-approvals.component.ts | 8 ++- .../services/web-provider.service.ts | 2 +- .../src/services/jslib-services.module.ts | 10 +++- .../vault/components/attachments.component.ts | 6 ++- .../components/folder-add-edit.component.ts | 9 +++- .../src/vault/components/view.component.ts | 4 +- .../auth-request-login.strategy.spec.ts | 3 ++ .../login-strategies/login.strategy.spec.ts | 5 ++ .../common/login-strategies/login.strategy.ts | 2 + .../password-login.strategy.spec.ts | 4 ++ .../sso-login.strategy.spec.ts | 4 ++ .../user-api-login.strategy.spec.ts | 3 ++ .../webauthn-login.strategy.spec.ts | 14 +++-- .../webauthn-login.strategy.ts | 2 +- .../login-strategy.service.ts | 1 + .../platform/abstractions/crypto.service.ts | 32 ----------- .../src/platform/services/crypto.service.ts | 53 ------------------- .../src/tools/send/models/domain/send.spec.ts | 12 +++-- .../src/tools/send/models/domain/send.ts | 4 +- .../folder/folder.service.abstraction.ts | 2 +- .../src/vault/services/cipher.service.spec.ts | 16 +++++- .../src/vault/services/cipher.service.ts | 43 +++++++++------ .../src/vault/services/collection.service.ts | 5 +- .../services/folder/folder.service.spec.ts | 14 +++-- .../vault/services/folder/folder.service.ts | 7 ++- ...warden-password-protected-importer.spec.ts | 6 ++- .../src/components/import.component.ts | 2 + .../bitwarden/bitwarden-json-importer.ts | 14 +++-- .../bitwarden-password-protected-importer.ts | 8 +-- .../src/services/import.service.spec.ts | 4 ++ libs/importer/src/services/import.service.ts | 6 ++- .../src/services/base-vault-export.service.ts | 8 +-- .../individual-vault-export.service.spec.ts | 27 ++++++++-- .../individual-vault-export.service.ts | 15 ++++-- .../src/services/org-vault-export.service.ts | 8 +-- .../src/services/vault-export.service.spec.ts | 26 +++++++-- 69 files changed, 404 insertions(+), 197 deletions(-) diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 7111b34875..43a6d5968e 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -693,6 +693,7 @@ export default class MainBackground { this.collectionService = new CollectionService( this.cryptoService, + this.encryptService, this.i18nService, this.stateProvider, ); @@ -803,9 +804,11 @@ export default class MainBackground { this.cipherFileUploadService, this.configService, this.stateProvider, + this.accountService, ); this.folderService = new FolderService( this.cryptoService, + this.encryptService, this.i18nService, this.cipherService, this.stateProvider, @@ -977,6 +980,7 @@ export default class MainBackground { this.i18nService, this.collectionService, this.cryptoService, + this.encryptService, this.pinService, this.accountService, ); @@ -986,8 +990,10 @@ export default class MainBackground { this.cipherService, this.pinService, this.cryptoService, + this.encryptService, this.cryptoFunctionService, this.kdfConfigService, + this.accountService, ); this.organizationVaultExportService = new OrganizationVaultExportService( @@ -995,6 +1001,7 @@ export default class MainBackground { this.apiService, this.pinService, this.cryptoService, + this.encryptService, this.cryptoFunctionService, this.collectionService, this.kdfConfigService, @@ -1098,6 +1105,7 @@ export default class MainBackground { ); this.nativeMessagingBackground = new NativeMessagingBackground( this.cryptoService, + this.encryptService, this.cryptoFunctionService, this.runtimeBackground, this.messagingService, diff --git a/apps/browser/src/background/nativeMessaging.background.ts b/apps/browser/src/background/nativeMessaging.background.ts index 8f2cac7915..68a43fbdfe 100644 --- a/apps/browser/src/background/nativeMessaging.background.ts +++ b/apps/browser/src/background/nativeMessaging.background.ts @@ -6,6 +6,7 @@ import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authenticatio import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -73,6 +74,7 @@ export class NativeMessagingBackground { constructor( private cryptoService: CryptoService, + private encryptService: EncryptService, private cryptoFunctionService: CryptoFunctionService, private runtimeBackground: RuntimeBackground, private messagingService: MessagingService, @@ -227,7 +229,7 @@ export class NativeMessagingBackground { await this.secureCommunication(); } - return await this.cryptoService.encrypt(JSON.stringify(message), this.sharedSecret); + return await this.encryptService.encrypt(JSON.stringify(message), this.sharedSecret); } getResponse(): Promise { @@ -273,7 +275,7 @@ export class NativeMessagingBackground { let message = rawMessage as ReceiveMessage; if (!this.platformUtilsService.isSafari()) { message = JSON.parse( - await this.cryptoService.decryptToUtf8(rawMessage as EncString, this.sharedSecret), + await this.encryptService.decryptToUtf8(rawMessage as EncString, this.sharedSecret), ); } diff --git a/apps/browser/src/vault/popup/components/vault-v2/add-edit-folder-dialog/add-edit-folder-dialog.component.spec.ts b/apps/browser/src/vault/popup/components/vault-v2/add-edit-folder-dialog/add-edit-folder-dialog.component.spec.ts index 8453b4cc63..156cc9d819 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/add-edit-folder-dialog/add-edit-folder-dialog.component.spec.ts +++ b/apps/browser/src/vault/popup/components/vault-v2/add-edit-folder-dialog/add-edit-folder-dialog.component.spec.ts @@ -1,9 +1,13 @@ import { DIALOG_DATA, DialogRef } from "@angular/cdk/dialog"; import { ComponentFixture, TestBed } from "@angular/core/testing"; import { NoopAnimationsModule } from "@angular/platform-browser/animations"; +import { BehaviorSubject } from "rxjs"; +import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service"; +import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { UserId } from "@bitwarden/common/types/guid"; import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction"; import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; import { Folder } from "@bitwarden/common/vault/models/domain/folder"; @@ -25,6 +29,7 @@ describe("AddEditFolderDialogComponent", () => { const save = jest.fn().mockResolvedValue(null); const deleteFolder = jest.fn().mockResolvedValue(null); const openSimpleDialog = jest.fn().mockResolvedValue(true); + const getUserKeyWithLegacySupport = jest.fn().mockResolvedValue(""); const error = jest.fn(); const close = jest.fn(); const showToast = jest.fn(); @@ -41,12 +46,29 @@ describe("AddEditFolderDialogComponent", () => { close.mockClear(); showToast.mockClear(); + const userId = "" as UserId; + const accountInfo: AccountInfo = { + email: "", + emailVerified: true, + name: undefined, + }; + await TestBed.configureTestingModule({ imports: [AddEditFolderDialogComponent, NoopAnimationsModule], providers: [ { provide: I18nService, useValue: { t: (key: string) => key } }, { provide: FolderService, useValue: { encrypt } }, { provide: FolderApiServiceAbstraction, useValue: { save, delete: deleteFolder } }, + { + provide: AccountService, + useValue: { activeAccount$: new BehaviorSubject({ id: userId, ...accountInfo }) }, + }, + { + provide: CryptoService, + useValue: { + getUserKeyWithLegacySupport, + }, + }, { provide: LogService, useValue: { error } }, { provide: ToastService, useValue: { showToast } }, { provide: DIALOG_DATA, useValue: dialogData }, @@ -82,7 +104,7 @@ describe("AddEditFolderDialogComponent", () => { const newFolder = new FolderView(); newFolder.name = "New Folder"; - expect(encrypt).toHaveBeenCalledWith(newFolder); + expect(encrypt).toHaveBeenCalledWith(newFolder, ""); expect(save).toHaveBeenCalled(); }); @@ -137,10 +159,13 @@ describe("AddEditFolderDialogComponent", () => { component.folderForm.controls.name.setValue("Edited Folder"); await component.submit(); - expect(encrypt).toHaveBeenCalledWith({ - ...dialogData.editFolderConfig.folder, - name: "Edited Folder", - }); + expect(encrypt).toHaveBeenCalledWith( + { + ...dialogData.editFolderConfig.folder, + name: "Edited Folder", + }, + "", + ); }); it("deletes the folder", async () => { diff --git a/apps/browser/src/vault/popup/components/vault-v2/add-edit-folder-dialog/add-edit-folder-dialog.component.ts b/apps/browser/src/vault/popup/components/vault-v2/add-edit-folder-dialog/add-edit-folder-dialog.component.ts index 3326353399..4f793abb6a 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/add-edit-folder-dialog/add-edit-folder-dialog.component.ts +++ b/apps/browser/src/vault/popup/components/vault-v2/add-edit-folder-dialog/add-edit-folder-dialog.component.ts @@ -11,8 +11,11 @@ import { } from "@angular/core"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms"; +import { firstValueFrom } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; +import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction"; @@ -68,6 +71,8 @@ export class AddEditFolderDialogComponent implements AfterViewInit, OnInit { private formBuilder: FormBuilder, private folderService: FolderService, private folderApiService: FolderApiServiceAbstraction, + private accountService: AccountService, + private cryptoService: CryptoService, private toastService: ToastService, private i18nService: I18nService, private logService: LogService, @@ -107,7 +112,9 @@ export class AddEditFolderDialogComponent implements AfterViewInit, OnInit { this.folder.name = this.folderForm.controls.name.value; try { - const folder = await this.folderService.encrypt(this.folder); + const activeUserId = await firstValueFrom(this.accountService.activeAccount$); + const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeUserId.id); + const folder = await this.folderService.encrypt(this.folder, userKey); await this.folderApiService.save(folder); this.toastService.showToast({ diff --git a/apps/browser/src/vault/popup/components/vault/attachments.component.ts b/apps/browser/src/vault/popup/components/vault/attachments.component.ts index 75819689b4..1ab1ff428b 100644 --- a/apps/browser/src/vault/popup/components/vault/attachments.component.ts +++ b/apps/browser/src/vault/popup/components/vault/attachments.component.ts @@ -8,6 +8,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; @@ -28,6 +29,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent implements On cipherService: CipherService, i18nService: I18nService, cryptoService: CryptoService, + encryptService: EncryptService, platformUtilsService: PlatformUtilsService, apiService: ApiService, private location: Location, @@ -44,6 +46,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent implements On cipherService, i18nService, cryptoService, + encryptService, platformUtilsService, apiService, window, diff --git a/apps/browser/src/vault/popup/components/vault/view.component.ts b/apps/browser/src/vault/popup/components/vault/view.component.ts index f8e7de21dc..a77a27046a 100644 --- a/apps/browser/src/vault/popup/components/vault/view.component.ts +++ b/apps/browser/src/vault/popup/components/vault/view.component.ts @@ -13,6 +13,7 @@ import { TokenService } from "@bitwarden/common/auth/abstractions/token.service" import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; @@ -80,6 +81,7 @@ export class ViewComponent extends BaseViewComponent implements OnInit, OnDestro tokenService: TokenService, i18nService: I18nService, cryptoService: CryptoService, + encryptService: EncryptService, platformUtilsService: PlatformUtilsService, auditService: AuditService, private route: ActivatedRoute, @@ -108,6 +110,7 @@ export class ViewComponent extends BaseViewComponent implements OnInit, OnDestro tokenService, i18nService, cryptoService, + encryptService, platformUtilsService, auditService, window, diff --git a/apps/browser/src/vault/popup/settings/folder-add-edit.component.ts b/apps/browser/src/vault/popup/settings/folder-add-edit.component.ts index b873735b46..3ef5fc73aa 100644 --- a/apps/browser/src/vault/popup/settings/folder-add-edit.component.ts +++ b/apps/browser/src/vault/popup/settings/folder-add-edit.component.ts @@ -4,6 +4,8 @@ import { ActivatedRoute, Router } from "@angular/router"; import { first } from "rxjs/operators"; import { FolderAddEditComponent as BaseFolderAddEditComponent } from "@bitwarden/angular/vault/components/folder-add-edit.component"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; +import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -20,6 +22,8 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent implement constructor( folderService: FolderService, folderApiService: FolderApiServiceAbstraction, + accountService: AccountService, + cryptoService: CryptoService, i18nService: I18nService, platformUtilsService: PlatformUtilsService, private router: Router, @@ -31,6 +35,8 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent implement super( folderService, folderApiService, + accountService, + cryptoService, i18nService, platformUtilsService, logService, diff --git a/apps/cli/src/commands/download.command.ts b/apps/cli/src/commands/download.command.ts index e417b7c3b8..f819875063 100644 --- a/apps/cli/src/commands/download.command.ts +++ b/apps/cli/src/commands/download.command.ts @@ -1,6 +1,6 @@ import * as fet from "node-fetch"; -import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { EncArrayBuffer } from "@bitwarden/common/platform/models/domain/enc-array-buffer"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; @@ -9,7 +9,7 @@ import { FileResponse } from "../models/response/file.response"; import { CliUtils } from "../utils"; export abstract class DownloadCommand { - constructor(protected cryptoService: CryptoService) {} + constructor(protected encryptService: EncryptService) {} protected async saveAttachmentToFile( url: string, @@ -26,7 +26,7 @@ export abstract class DownloadCommand { try { const encBuf = await EncArrayBuffer.fromResponse(response); - const decBuf = await this.cryptoService.decryptFromBytes(encBuf, key); + const decBuf = await this.encryptService.decryptToBytes(encBuf, key); if (process.env.BW_SERVE === "true") { const res = new FileResponse(Buffer.from(decBuf), fileName); return Response.success(res); diff --git a/apps/cli/src/commands/edit.command.ts b/apps/cli/src/commands/edit.command.ts index bac1cce7c7..84ed7190a5 100644 --- a/apps/cli/src/commands/edit.command.ts +++ b/apps/cli/src/commands/edit.command.ts @@ -7,6 +7,7 @@ import { CipherExport } from "@bitwarden/common/models/export/cipher.export"; import { CollectionExport } from "@bitwarden/common/models/export/collection.export"; import { FolderExport } from "@bitwarden/common/models/export/folder.export"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction"; @@ -25,6 +26,7 @@ export class EditCommand { private cipherService: CipherService, private folderService: FolderService, private cryptoService: CryptoService, + private encryptService: EncryptService, private apiService: ApiService, private folderApiService: FolderApiServiceAbstraction, private accountService: AccountService, @@ -139,7 +141,10 @@ export class EditCommand { let folderView = await folder.decrypt(); folderView = FolderExport.toView(req, folderView); - const encFolder = await this.folderService.encrypt(folderView); + + const activeUserId = await firstValueFrom(this.accountService.activeAccount$); + const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeUserId.id); + const encFolder = await this.folderService.encrypt(folderView, userKey); try { await this.folderApiService.save(encFolder); const updatedFolder = await this.folderService.get(folder.id); @@ -187,7 +192,7 @@ export class EditCommand { (u) => new SelectionReadOnlyRequest(u.id, u.readOnly, u.hidePasswords, u.manage), ); const request = new CollectionRequest(); - request.name = (await this.cryptoService.encrypt(req.name, orgKey)).encryptedString; + request.name = (await this.encryptService.encrypt(req.name, orgKey)).encryptedString; request.externalId = req.externalId; request.groups = groups; request.users = users; diff --git a/apps/cli/src/commands/get.command.ts b/apps/cli/src/commands/get.command.ts index 923187bfcd..3b2b18c66e 100644 --- a/apps/cli/src/commands/get.command.ts +++ b/apps/cli/src/commands/get.command.ts @@ -20,6 +20,7 @@ import { LoginExport } from "@bitwarden/common/models/export/login.export"; import { SecureNoteExport } from "@bitwarden/common/models/export/secure-note.export"; import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; @@ -56,7 +57,8 @@ export class GetCommand extends DownloadCommand { private collectionService: CollectionService, private totpService: TotpService, private auditService: AuditService, - cryptoService: CryptoService, + private cryptoService: CryptoService, + encryptService: EncryptService, private stateService: StateService, private searchService: SearchService, private apiService: ApiService, @@ -65,7 +67,7 @@ export class GetCommand extends DownloadCommand { private accountProfileService: BillingAccountProfileStateService, private accountService: AccountService, ) { - super(cryptoService); + super(encryptService); } async run(object: string, id: string, cmdOptions: Record): Promise { @@ -451,7 +453,7 @@ export class GetCommand extends DownloadCommand { const response = await this.apiService.getCollectionAccessDetails(options.organizationId, id); const decCollection = new CollectionView(response); - decCollection.name = await this.cryptoService.decryptToUtf8( + decCollection.name = await this.encryptService.decryptToUtf8( new EncString(response.name), orgKey, ); diff --git a/apps/cli/src/oss-serve-configurator.ts b/apps/cli/src/oss-serve-configurator.ts index d7ef9ac871..fd2a10975f 100644 --- a/apps/cli/src/oss-serve-configurator.ts +++ b/apps/cli/src/oss-serve-configurator.ts @@ -57,6 +57,7 @@ export class OssServeConfigurator { this.serviceContainer.totpService, this.serviceContainer.auditService, this.serviceContainer.cryptoService, + this.serviceContainer.encryptService, this.serviceContainer.stateService, this.serviceContainer.searchService, this.serviceContainer.apiService, @@ -79,6 +80,7 @@ export class OssServeConfigurator { this.serviceContainer.cipherService, this.serviceContainer.folderService, this.serviceContainer.cryptoService, + this.serviceContainer.encryptService, this.serviceContainer.apiService, this.serviceContainer.folderApiService, this.serviceContainer.billingAccountProfileStateService, @@ -89,6 +91,7 @@ export class OssServeConfigurator { this.serviceContainer.cipherService, this.serviceContainer.folderService, this.serviceContainer.cryptoService, + this.serviceContainer.encryptService, this.serviceContainer.apiService, this.serviceContainer.folderApiService, this.serviceContainer.accountService, @@ -150,7 +153,7 @@ export class OssServeConfigurator { this.serviceContainer.sendService, this.serviceContainer.environmentService, this.serviceContainer.searchService, - this.serviceContainer.cryptoService, + this.serviceContainer.encryptService, ); this.sendEditCommand = new SendEditCommand( this.serviceContainer.sendService, diff --git a/apps/cli/src/service-container/service-container.ts b/apps/cli/src/service-container/service-container.ts index b9225fec43..98c5fc86b5 100644 --- a/apps/cli/src/service-container/service-container.ts +++ b/apps/cli/src/service-container/service-container.ts @@ -494,6 +494,7 @@ export class ServiceContainer { this.collectionService = new CollectionService( this.cryptoService, + this.encryptService, this.i18nService, this.stateProvider, ); @@ -631,10 +632,12 @@ export class ServiceContainer { this.cipherFileUploadService, this.configService, this.stateProvider, + this.accountService, ); this.folderService = new FolderService( this.cryptoService, + this.encryptService, this.i18nService, this.cipherService, this.stateProvider, @@ -721,6 +724,7 @@ export class ServiceContainer { this.i18nService, this.collectionService, this.cryptoService, + this.encryptService, this.pinService, this.accountService, ); @@ -730,8 +734,10 @@ export class ServiceContainer { this.cipherService, this.pinService, this.cryptoService, + this.encryptService, this.cryptoFunctionService, this.kdfConfigService, + this.accountService, ); this.organizationExportService = new OrganizationVaultExportService( @@ -739,6 +745,7 @@ export class ServiceContainer { this.apiService, this.pinService, this.cryptoService, + this.encryptService, this.cryptoFunctionService, this.collectionService, this.kdfConfigService, diff --git a/apps/cli/src/tools/send/commands/get.command.ts b/apps/cli/src/tools/send/commands/get.command.ts index 2ffe242317..057a1c27f3 100644 --- a/apps/cli/src/tools/send/commands/get.command.ts +++ b/apps/cli/src/tools/send/commands/get.command.ts @@ -2,7 +2,7 @@ import { OptionValues } from "commander"; import { firstValueFrom } from "rxjs"; import { SearchService } from "@bitwarden/common/abstractions/search.service"; -import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { SendView } from "@bitwarden/common/tools/send/models/view/send.view"; @@ -17,9 +17,9 @@ export class SendGetCommand extends DownloadCommand { private sendService: SendService, private environmentService: EnvironmentService, private searchService: SearchService, - cryptoService: CryptoService, + encryptService: EncryptService, ) { - super(cryptoService); + super(encryptService); } async run(id: string, options: OptionValues) { diff --git a/apps/cli/src/tools/send/commands/receive.command.ts b/apps/cli/src/tools/send/commands/receive.command.ts index dc662f0272..a8740992f7 100644 --- a/apps/cli/src/tools/send/commands/receive.command.ts +++ b/apps/cli/src/tools/send/commands/receive.command.ts @@ -2,10 +2,10 @@ import { OptionValues } from "commander"; import * as inquirer from "inquirer"; import { firstValueFrom } from "rxjs"; -import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; @@ -27,14 +27,14 @@ export class SendReceiveCommand extends DownloadCommand { private sendAccessRequest: SendAccessRequest; constructor( - private apiService: ApiService, - cryptoService: CryptoService, + private cryptoService: CryptoService, + encryptService: EncryptService, private cryptoFunctionService: CryptoFunctionService, private platformUtilsService: PlatformUtilsService, private environmentService: EnvironmentService, private sendApiService: SendApiService, ) { - super(cryptoService); + super(encryptService); } async run(url: string, options: OptionValues): Promise { diff --git a/apps/cli/src/tools/send/send.program.ts b/apps/cli/src/tools/send/send.program.ts index 05e7e7d22d..878eaa52b2 100644 --- a/apps/cli/src/tools/send/send.program.ts +++ b/apps/cli/src/tools/send/send.program.ts @@ -100,8 +100,8 @@ export class SendProgram extends BaseProgram { }) .action(async (url: string, options: OptionValues) => { const cmd = new SendReceiveCommand( - this.serviceContainer.apiService, this.serviceContainer.cryptoService, + this.serviceContainer.encryptService, this.serviceContainer.cryptoFunctionService, this.serviceContainer.platformUtilsService, this.serviceContainer.environmentService, @@ -143,6 +143,7 @@ export class SendProgram extends BaseProgram { this.serviceContainer.totpService, this.serviceContainer.auditService, this.serviceContainer.cryptoService, + this.serviceContainer.encryptService, this.serviceContainer.stateService, this.serviceContainer.searchService, this.serviceContainer.apiService, @@ -187,7 +188,7 @@ export class SendProgram extends BaseProgram { this.serviceContainer.sendService, this.serviceContainer.environmentService, this.serviceContainer.searchService, - this.serviceContainer.cryptoService, + this.serviceContainer.encryptService, ); const response = await cmd.run(id, options); this.processResponse(response); @@ -246,7 +247,7 @@ export class SendProgram extends BaseProgram { this.serviceContainer.sendService, this.serviceContainer.environmentService, this.serviceContainer.searchService, - this.serviceContainer.cryptoService, + this.serviceContainer.encryptService, ); const cmd = new SendEditCommand( this.serviceContainer.sendService, diff --git a/apps/cli/src/vault.program.ts b/apps/cli/src/vault.program.ts index 2dad9a7c68..11876ef6ec 100644 --- a/apps/cli/src/vault.program.ts +++ b/apps/cli/src/vault.program.ts @@ -178,6 +178,7 @@ export class VaultProgram extends BaseProgram { this.serviceContainer.totpService, this.serviceContainer.auditService, this.serviceContainer.cryptoService, + this.serviceContainer.encryptService, this.serviceContainer.stateService, this.serviceContainer.searchService, this.serviceContainer.apiService, @@ -224,6 +225,7 @@ export class VaultProgram extends BaseProgram { this.serviceContainer.cipherService, this.serviceContainer.folderService, this.serviceContainer.cryptoService, + this.serviceContainer.encryptService, this.serviceContainer.apiService, this.serviceContainer.folderApiService, this.serviceContainer.billingAccountProfileStateService, @@ -272,6 +274,7 @@ export class VaultProgram extends BaseProgram { this.serviceContainer.cipherService, this.serviceContainer.folderService, this.serviceContainer.cryptoService, + this.serviceContainer.encryptService, this.serviceContainer.apiService, this.serviceContainer.folderApiService, this.serviceContainer.accountService, diff --git a/apps/cli/src/vault/create.command.ts b/apps/cli/src/vault/create.command.ts index 0284ccc37b..fc52720f77 100644 --- a/apps/cli/src/vault/create.command.ts +++ b/apps/cli/src/vault/create.command.ts @@ -12,6 +12,7 @@ import { CipherExport } from "@bitwarden/common/models/export/cipher.export"; import { CollectionExport } from "@bitwarden/common/models/export/collection.export"; import { FolderExport } from "@bitwarden/common/models/export/folder.export"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction"; @@ -31,6 +32,7 @@ export class CreateCommand { private cipherService: CipherService, private folderService: FolderService, private cryptoService: CryptoService, + private encryptService: EncryptService, private apiService: ApiService, private folderApiService: FolderApiServiceAbstraction, private accountProfileService: BillingAccountProfileStateService, @@ -167,7 +169,9 @@ export class CreateCommand { } private async createFolder(req: FolderExport) { - const folder = await this.folderService.encrypt(FolderExport.toView(req)); + const activeAccountId = await firstValueFrom(this.accountService.activeAccount$); + const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeAccountId.id); + const folder = await this.folderService.encrypt(FolderExport.toView(req), userKey); try { await this.folderApiService.save(folder); const newFolder = await this.folderService.get(folder.id); @@ -210,7 +214,7 @@ export class CreateCommand { (u) => new SelectionReadOnlyRequest(u.id, u.readOnly, u.hidePasswords, u.manage), ); const request = new CollectionRequest(); - request.name = (await this.cryptoService.encrypt(req.name, orgKey)).encryptedString; + request.name = (await this.encryptService.encrypt(req.name, orgKey)).encryptedString; request.externalId = req.externalId; request.groups = groups; request.users = users; diff --git a/apps/desktop/src/app/services/services.module.ts b/apps/desktop/src/app/services/services.module.ts index d5672f54c0..a6db7fe5db 100644 --- a/apps/desktop/src/app/services/services.module.ts +++ b/apps/desktop/src/app/services/services.module.ts @@ -234,7 +234,7 @@ const safeProviders: SafeProvider[] = [ provide: NativeMessageHandlerService, deps: [ StateServiceAbstraction, - CryptoServiceAbstraction, + EncryptService, CryptoFunctionServiceAbstraction, MessagingServiceAbstraction, EncryptedMessageHandlerService, diff --git a/apps/desktop/src/services/native-message-handler.service.ts b/apps/desktop/src/services/native-message-handler.service.ts index 065726559b..106dc11e41 100644 --- a/apps/desktop/src/services/native-message-handler.service.ts +++ b/apps/desktop/src/services/native-message-handler.service.ts @@ -3,7 +3,7 @@ import { firstValueFrom } from "rxjs"; import { NativeMessagingVersion } from "@bitwarden/common/enums"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; -import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; @@ -31,7 +31,7 @@ export class NativeMessageHandlerService { constructor( private stateService: StateService, - private cryptoService: CryptoService, + private encryptService: EncryptService, private cryptoFunctionService: CryptoFunctionService, private messagingService: MessagingService, private encryptedMessageHandlerService: EncryptedMessageHandlerService, @@ -162,7 +162,7 @@ export class NativeMessageHandlerService { payload: DecryptedCommandData, key: SymmetricCryptoKey, ): Promise { - return await this.cryptoService.encrypt(JSON.stringify(payload), key); + return await this.encryptService.encrypt(JSON.stringify(payload), key); } private async decryptPayload(message: EncryptedMessage): Promise { @@ -182,7 +182,7 @@ export class NativeMessageHandlerService { } try { - let decryptedResult = await this.cryptoService.decryptToUtf8( + let decryptedResult = await this.encryptService.decryptToUtf8( message.encryptedCommand as EncString, this.ddgSharedSecret, ); diff --git a/apps/desktop/src/services/native-messaging.service.ts b/apps/desktop/src/services/native-messaging.service.ts index f106d137b7..2b21800194 100644 --- a/apps/desktop/src/services/native-messaging.service.ts +++ b/apps/desktop/src/services/native-messaging.service.ts @@ -6,6 +6,7 @@ import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { BiometricStateService } from "@bitwarden/common/platform/biometrics/biometric-state.service"; @@ -33,6 +34,7 @@ export class NativeMessagingService { constructor( private cryptoFunctionService: CryptoFunctionService, private cryptoService: CryptoService, + private encryptService: EncryptService, private logService: LogService, private messagingService: MessagingService, private desktopSettingService: DesktopSettingsService, @@ -111,7 +113,7 @@ export class NativeMessagingService { } const message: LegacyMessage = JSON.parse( - await this.cryptoService.decryptToUtf8( + await this.encryptService.decryptToUtf8( rawMessage as EncString, SymmetricCryptoKey.fromString(await ipc.platform.ephemeralStore.getEphemeralValue(appId)), ), @@ -224,7 +226,7 @@ export class NativeMessagingService { private async send(message: any, appId: string) { message.timestamp = Date.now(); - const encrypted = await this.cryptoService.encrypt( + const encrypted = await this.encryptService.encrypt( JSON.stringify(message), SymmetricCryptoKey.fromString(await ipc.platform.ephemeralStore.getEphemeralValue(appId)), ); diff --git a/apps/desktop/src/vault/app/vault/attachments.component.ts b/apps/desktop/src/vault/app/vault/attachments.component.ts index 2e25d39087..47e08a13cd 100644 --- a/apps/desktop/src/vault/app/vault/attachments.component.ts +++ b/apps/desktop/src/vault/app/vault/attachments.component.ts @@ -5,6 +5,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; @@ -22,6 +23,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent { cipherService: CipherService, i18nService: I18nService, cryptoService: CryptoService, + encryptService: EncryptService, platformUtilsService: PlatformUtilsService, apiService: ApiService, logService: LogService, @@ -36,6 +38,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent { cipherService, i18nService, cryptoService, + encryptService, platformUtilsService, apiService, window, diff --git a/apps/desktop/src/vault/app/vault/folder-add-edit.component.ts b/apps/desktop/src/vault/app/vault/folder-add-edit.component.ts index 3865ec4837..0cc55d65f3 100644 --- a/apps/desktop/src/vault/app/vault/folder-add-edit.component.ts +++ b/apps/desktop/src/vault/app/vault/folder-add-edit.component.ts @@ -2,6 +2,8 @@ import { Component } from "@angular/core"; import { FormBuilder } from "@angular/forms"; import { FolderAddEditComponent as BaseFolderAddEditComponent } from "@bitwarden/angular/vault/components/folder-add-edit.component"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; +import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -17,6 +19,8 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent { constructor( folderService: FolderService, folderApiService: FolderApiServiceAbstraction, + accountService: AccountService, + cryptoService: CryptoService, i18nService: I18nService, platformUtilsService: PlatformUtilsService, logService: LogService, @@ -26,6 +30,8 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent { super( folderService, folderApiService, + accountService, + cryptoService, i18nService, platformUtilsService, logService, diff --git a/apps/desktop/src/vault/app/vault/view.component.ts b/apps/desktop/src/vault/app/vault/view.component.ts index 140e1e9ced..7f2fb9ceae 100644 --- a/apps/desktop/src/vault/app/vault/view.component.ts +++ b/apps/desktop/src/vault/app/vault/view.component.ts @@ -19,6 +19,7 @@ import { TokenService } from "@bitwarden/common/auth/abstractions/token.service" import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; @@ -48,6 +49,7 @@ export class ViewComponent extends BaseViewComponent implements OnInit, OnDestro tokenService: TokenService, i18nService: I18nService, cryptoService: CryptoService, + encryptService: EncryptService, platformUtilsService: PlatformUtilsService, auditService: AuditService, broadcasterService: BroadcasterService, @@ -72,6 +74,7 @@ export class ViewComponent extends BaseViewComponent implements OnInit, OnDestro tokenService, i18nService, cryptoService, + encryptService, platformUtilsService, auditService, window, diff --git a/apps/web/src/app/auth/settings/emergency-access/attachments/emergency-access-attachments.component.ts b/apps/web/src/app/auth/settings/emergency-access/attachments/emergency-access-attachments.component.ts index e0a6f6c53d..4912a866fd 100644 --- a/apps/web/src/app/auth/settings/emergency-access/attachments/emergency-access-attachments.component.ts +++ b/apps/web/src/app/auth/settings/emergency-access/attachments/emergency-access-attachments.component.ts @@ -5,6 +5,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; @@ -26,6 +27,7 @@ export class EmergencyAccessAttachmentsComponent extends BaseAttachmentsComponen cipherService: CipherService, i18nService: I18nService, cryptoService: CryptoService, + encryptService: EncryptService, stateService: StateService, platformUtilsService: PlatformUtilsService, apiService: ApiService, @@ -40,6 +42,7 @@ export class EmergencyAccessAttachmentsComponent extends BaseAttachmentsComponen cipherService, i18nService, cryptoService, + encryptService, platformUtilsService, apiService, window, diff --git a/apps/web/src/app/billing/organizations/organization-plans.component.ts b/apps/web/src/app/billing/organizations/organization-plans.component.ts index 3d02fa027e..924b128a50 100644 --- a/apps/web/src/app/billing/organizations/organization-plans.component.ts +++ b/apps/web/src/app/billing/organizations/organization-plans.component.ts @@ -31,6 +31,7 @@ import { PlanResponse } from "@bitwarden/common/billing/models/response/plan.res import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; @@ -147,6 +148,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy { private i18nService: I18nService, private platformUtilsService: PlatformUtilsService, private cryptoService: CryptoService, + private encryptService: EncryptService, private router: Router, private syncService: SyncService, private policyService: PolicyService, @@ -590,7 +592,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy { if (this.createOrganization) { const orgKey = await this.cryptoService.makeOrgKey(); const key = orgKey[0].encryptedString; - const collection = await this.cryptoService.encrypt( + const collection = await this.encryptService.encrypt( this.i18nService.t("defaultCollection"), orgKey[1], ); @@ -744,7 +746,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy { ); const providerKey = await this.cryptoService.getProviderKey(this.providerId); providerRequest.organizationCreateRequest.key = ( - await this.cryptoService.encrypt(orgKey.key, providerKey) + await this.encryptService.encrypt(orgKey.key, providerKey) ).encryptedString; const orgId = ( await this.apiService.postProviderCreateOrganization(this.providerId, providerRequest) diff --git a/apps/web/src/app/tools/send/send-access-file.component.ts b/apps/web/src/app/tools/send/send-access-file.component.ts index 8bb3558a69..1efabb5fec 100644 --- a/apps/web/src/app/tools/send/send-access-file.component.ts +++ b/apps/web/src/app/tools/send/send-access-file.component.ts @@ -1,6 +1,6 @@ import { Component, Input } from "@angular/core"; -import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; @@ -26,7 +26,7 @@ export class SendAccessFileComponent { constructor( private i18nService: I18nService, private toastService: ToastService, - private cryptoService: CryptoService, + private encryptService: EncryptService, private fileDownloadService: FileDownloadService, private sendApiService: SendApiService, ) {} @@ -62,7 +62,7 @@ export class SendAccessFileComponent { try { const encBuf = await EncArrayBuffer.fromResponse(response); - const decBuf = await this.cryptoService.decryptFromBytes(encBuf, this.decKey); + const decBuf = await this.encryptService.decryptToBytes(encBuf, this.decKey); this.fileDownloadService.download({ fileName: this.send.file.fileName, blobData: decBuf, diff --git a/apps/web/src/app/vault/core/collection-admin.service.ts b/apps/web/src/app/vault/core/collection-admin.service.ts index b6ddd452a1..e0c15e3404 100644 --- a/apps/web/src/app/vault/core/collection-admin.service.ts +++ b/apps/web/src/app/vault/core/collection-admin.service.ts @@ -3,6 +3,7 @@ import { Injectable } from "@angular/core"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { SelectionReadOnlyRequest } from "@bitwarden/common/admin-console/models/request/selection-read-only.request"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service"; import { CollectionData } from "@bitwarden/common/vault/models/data/collection.data"; @@ -23,6 +24,7 @@ export class CollectionAdminService { constructor( private apiService: ApiService, private cryptoService: CryptoService, + private encryptService: EncryptService, private collectionService: CollectionService, ) {} @@ -116,7 +118,7 @@ export class CollectionAdminService { const promises = collections.map(async (c) => { const view = new CollectionAdminView(); view.id = c.id; - view.name = await this.cryptoService.decryptToUtf8(new EncString(c.name), orgKey); + view.name = await this.encryptService.decryptToUtf8(new EncString(c.name), orgKey); view.externalId = c.externalId; view.organizationId = c.organizationId; @@ -146,7 +148,7 @@ export class CollectionAdminService { } const collection = new CollectionRequest(); collection.externalId = model.externalId; - collection.name = (await this.cryptoService.encrypt(model.name, key)).encryptedString; + collection.name = (await this.encryptService.encrypt(model.name, key)).encryptedString; collection.groups = model.groups.map( (group) => new SelectionReadOnlyRequest(group.id, group.readOnly, group.hidePasswords, group.manage), diff --git a/apps/web/src/app/vault/individual-vault/attachments.component.ts b/apps/web/src/app/vault/individual-vault/attachments.component.ts index b578efcae6..bb070ef688 100644 --- a/apps/web/src/app/vault/individual-vault/attachments.component.ts +++ b/apps/web/src/app/vault/individual-vault/attachments.component.ts @@ -5,6 +5,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; @@ -25,6 +26,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent { cipherService: CipherService, i18nService: I18nService, cryptoService: CryptoService, + encryptService: EncryptService, stateService: StateService, platformUtilsService: PlatformUtilsService, apiService: ApiService, @@ -39,6 +41,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent { cipherService, i18nService, cryptoService, + encryptService, platformUtilsService, apiService, window, diff --git a/apps/web/src/app/vault/individual-vault/folder-add-edit.component.ts b/apps/web/src/app/vault/individual-vault/folder-add-edit.component.ts index fe61d9b9a1..bc31cdc8cd 100644 --- a/apps/web/src/app/vault/individual-vault/folder-add-edit.component.ts +++ b/apps/web/src/app/vault/individual-vault/folder-add-edit.component.ts @@ -1,8 +1,11 @@ import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog"; import { Component, Inject } from "@angular/core"; import { FormBuilder } from "@angular/forms"; +import { firstValueFrom } from "rxjs"; import { FolderAddEditComponent as BaseFolderAddEditComponent } from "@bitwarden/angular/vault/components/folder-add-edit.component"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; +import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -19,6 +22,8 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent { constructor( folderService: FolderService, folderApiService: FolderApiServiceAbstraction, + protected accountSerivce: AccountService, + protected cryptoService: CryptoService, i18nService: I18nService, platformUtilsService: PlatformUtilsService, logService: LogService, @@ -31,6 +36,8 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent { super( folderService, folderApiService, + accountSerivce, + cryptoService, i18nService, platformUtilsService, logService, @@ -73,7 +80,9 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent { } try { - const folder = await this.folderService.encrypt(this.folder); + const activeAccountId = (await firstValueFrom(this.accountSerivce.activeAccount$)).id; + const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeAccountId); + const folder = await this.folderService.encrypt(this.folder, userKey); this.formPromise = this.folderApiService.save(folder); await this.formPromise; this.platformUtilsService.showToast( diff --git a/apps/web/src/app/vault/org-vault/attachments.component.ts b/apps/web/src/app/vault/org-vault/attachments.component.ts index 2bba4d389c..62e65ade5d 100644 --- a/apps/web/src/app/vault/org-vault/attachments.component.ts +++ b/apps/web/src/app/vault/org-vault/attachments.component.ts @@ -5,6 +5,7 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; @@ -31,6 +32,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent implements On cipherService: CipherService, i18nService: I18nService, cryptoService: CryptoService, + encryptService: EncryptService, stateService: StateService, platformUtilsService: PlatformUtilsService, apiService: ApiService, @@ -45,6 +47,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent implements On cipherService, i18nService, cryptoService, + encryptService, stateService, platformUtilsService, apiService, diff --git a/bitwarden_license/bit-cli/src/service-container.ts b/bitwarden_license/bit-cli/src/service-container.ts index 716c045fd1..c624afd946 100644 --- a/bitwarden_license/bit-cli/src/service-container.ts +++ b/bitwarden_license/bit-cli/src/service-container.ts @@ -18,6 +18,7 @@ export class ServiceContainer extends OssServiceContainer { this.organizationAuthRequestService = new OrganizationAuthRequestService( this.organizationAuthRequestApiService, this.cryptoService, + this.encryptService, this.organizationUserApiService, ); } diff --git a/bitwarden_license/bit-common/src/admin-console/auth-requests/organization-auth-request.service.spec.ts b/bitwarden_license/bit-common/src/admin-console/auth-requests/organization-auth-request.service.spec.ts index a8e6445d33..3ee89cbda5 100644 --- a/bitwarden_license/bit-common/src/admin-console/auth-requests/organization-auth-request.service.spec.ts +++ b/bitwarden_license/bit-common/src/admin-console/auth-requests/organization-auth-request.service.spec.ts @@ -6,6 +6,7 @@ import { } from "@bitwarden/admin-console/common"; import { ListResponse } from "@bitwarden/common/models/response/list.response"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; import { OrganizationAuthRequestApiService } from "./organization-auth-request-api.service"; @@ -16,16 +17,19 @@ import { PendingAuthRequestView } from "./pending-auth-request.view"; describe("OrganizationAuthRequestService", () => { let organizationAuthRequestApiService: MockProxy; let cryptoService: MockProxy; + let encryptService: MockProxy; let organizationUserApiService: MockProxy; let organizationAuthRequestService: OrganizationAuthRequestService; beforeEach(() => { organizationAuthRequestApiService = mock(); cryptoService = mock(); + encryptService = mock(); organizationUserApiService = mock(); organizationAuthRequestService = new OrganizationAuthRequestService( organizationAuthRequestApiService, cryptoService, + encryptService, organizationUserApiService, ); }); 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 edba399b8b..ad6e29c583 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 @@ -3,6 +3,7 @@ import { OrganizationUserResetPasswordDetailsResponse, } from "@bitwarden/admin-console/common"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; @@ -15,6 +16,7 @@ export class OrganizationAuthRequestService { constructor( private organizationAuthRequestApiService: OrganizationAuthRequestApiService, private cryptoService: CryptoService, + private encryptService: EncryptService, private organizationUserApiService: OrganizationUserApiService, ) {} @@ -109,7 +111,7 @@ export class OrganizationAuthRequestService { // Decrypt Organization's encrypted Private Key with org key const orgSymKey = await this.cryptoService.getOrgKey(organizationId); - const decOrgPrivateKey = await this.cryptoService.decryptToBytes( + const decOrgPrivateKey = await this.encryptService.decryptToBytes( new EncString(encryptedOrgPrivateKey), orgSymKey, ); diff --git a/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/device-approvals/device-approvals.component.ts b/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/device-approvals/device-approvals.component.ts index 34c7bba7d0..e074e0dd31 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/device-approvals/device-approvals.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/device-approvals/device-approvals.component.ts @@ -10,6 +10,7 @@ import { PendingAuthRequestView } from "@bitwarden/bit-common/admin-console/auth import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -30,7 +31,12 @@ import { SharedModule } from "@bitwarden/web-vault/app/shared/shared.module"; }), safeProvider({ provide: OrganizationAuthRequestService, - deps: [OrganizationAuthRequestApiService, CryptoService, OrganizationUserApiService], + deps: [ + OrganizationAuthRequestApiService, + CryptoService, + EncryptService, + OrganizationUserApiService, + ], }), ] satisfies SafeProvider[], imports: [SharedModule, NoItemsModule, LooseComponentsModule], diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/services/web-provider.service.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/services/web-provider.service.ts index 7609464680..3a2c7b8b64 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/providers/services/web-provider.service.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/providers/services/web-provider.service.ts @@ -27,7 +27,7 @@ export class WebProviderService { const orgKey = await this.cryptoService.getOrgKey(organizationId); const providerKey = await this.cryptoService.getProviderKey(providerId); - const encryptedOrgKey = await this.cryptoService.encrypt(orgKey.key, providerKey); + const encryptedOrgKey = await this.encryptService.encrypt(orgKey.key, providerKey); const request = new ProviderAddOrganizationRequest(); request.organizationId = organizationId; diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index 4cdf5be865..734ae03d59 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -449,6 +449,7 @@ const safeProviders: SafeProvider[] = [ fileUploadService: CipherFileUploadServiceAbstraction, configService: ConfigService, stateProvider: StateProvider, + accountService: AccountServiceAbstraction, ) => new CipherService( cryptoService, @@ -463,6 +464,7 @@ const safeProviders: SafeProvider[] = [ fileUploadService, configService, stateProvider, + accountService, ), deps: [ CryptoServiceAbstraction, @@ -477,6 +479,7 @@ const safeProviders: SafeProvider[] = [ CipherFileUploadServiceAbstraction, ConfigService, StateProvider, + AccountServiceAbstraction, ], }), safeProvider({ @@ -484,6 +487,7 @@ const safeProviders: SafeProvider[] = [ useClass: FolderService, deps: [ CryptoServiceAbstraction, + EncryptService, I18nServiceAbstraction, CipherServiceAbstraction, StateProvider, @@ -527,7 +531,7 @@ const safeProviders: SafeProvider[] = [ safeProvider({ provide: CollectionServiceAbstraction, useClass: CollectionService, - deps: [CryptoServiceAbstraction, I18nServiceAbstraction, StateProvider], + deps: [CryptoServiceAbstraction, EncryptService, I18nServiceAbstraction, StateProvider], }), safeProvider({ provide: EnvironmentService, @@ -785,6 +789,7 @@ const safeProviders: SafeProvider[] = [ I18nServiceAbstraction, CollectionServiceAbstraction, CryptoServiceAbstraction, + EncryptService, PinServiceAbstraction, AccountServiceAbstraction, ], @@ -797,8 +802,10 @@ const safeProviders: SafeProvider[] = [ CipherServiceAbstraction, PinServiceAbstraction, CryptoServiceAbstraction, + EncryptService, CryptoFunctionServiceAbstraction, KdfConfigServiceAbstraction, + AccountServiceAbstraction, ], }), safeProvider({ @@ -809,6 +816,7 @@ const safeProviders: SafeProvider[] = [ ApiServiceAbstraction, PinServiceAbstraction, CryptoServiceAbstraction, + EncryptService, CryptoFunctionServiceAbstraction, CollectionServiceAbstraction, KdfConfigServiceAbstraction, diff --git a/libs/angular/src/vault/components/attachments.component.ts b/libs/angular/src/vault/components/attachments.component.ts index 4ae68c9ca9..43c5a0d6d4 100644 --- a/libs/angular/src/vault/components/attachments.component.ts +++ b/libs/angular/src/vault/components/attachments.component.ts @@ -6,6 +6,7 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; @@ -40,6 +41,7 @@ export class AttachmentsComponent implements OnInit { protected cipherService: CipherService, protected i18nService: I18nService, protected cryptoService: CryptoService, + protected encryptService: EncryptService, protected platformUtilsService: PlatformUtilsService, protected apiService: ApiService, protected win: Window, @@ -178,7 +180,7 @@ export class AttachmentsComponent implements OnInit { attachment.key != null ? attachment.key : await this.cryptoService.getOrgKey(this.cipher.organizationId); - const decBuf = await this.cryptoService.decryptFromBytes(encBuf, key); + const decBuf = await this.encryptService.decryptToBytes(encBuf, key); this.fileDownloadService.download({ fileName: attachment.fileName, blobData: decBuf, @@ -249,7 +251,7 @@ export class AttachmentsComponent implements OnInit { attachment.key != null ? attachment.key : await this.cryptoService.getOrgKey(this.cipher.organizationId); - const decBuf = await this.cryptoService.decryptFromBytes(encBuf, key); + const decBuf = await this.encryptService.decryptToBytes(encBuf, key); const activeUserId = await firstValueFrom( this.accountService.activeAccount$.pipe(map((a) => a?.id)), ); diff --git a/libs/angular/src/vault/components/folder-add-edit.component.ts b/libs/angular/src/vault/components/folder-add-edit.component.ts index 0f179ae012..199feb599f 100644 --- a/libs/angular/src/vault/components/folder-add-edit.component.ts +++ b/libs/angular/src/vault/components/folder-add-edit.component.ts @@ -1,6 +1,9 @@ import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core"; import { Validators, FormBuilder } from "@angular/forms"; +import { firstValueFrom } from "rxjs"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; +import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -29,6 +32,8 @@ export class FolderAddEditComponent implements OnInit { constructor( protected folderService: FolderService, protected folderApiService: FolderApiServiceAbstraction, + protected accountService: AccountService, + protected cryptoService: CryptoService, protected i18nService: I18nService, protected platformUtilsService: PlatformUtilsService, protected logService: LogService, @@ -52,7 +57,9 @@ export class FolderAddEditComponent implements OnInit { } try { - const folder = await this.folderService.encrypt(this.folder); + const activeAccountId = await firstValueFrom(this.accountService.activeAccount$); + const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeAccountId.id); + const folder = await this.folderService.encrypt(this.folder, userKey); this.formPromise = this.folderApiService.save(folder); await this.formPromise; this.platformUtilsService.showToast( diff --git a/libs/angular/src/vault/components/view.component.ts b/libs/angular/src/vault/components/view.component.ts index a6e96bc542..ac644acf9e 100644 --- a/libs/angular/src/vault/components/view.component.ts +++ b/libs/angular/src/vault/components/view.component.ts @@ -21,6 +21,7 @@ import { EventType } from "@bitwarden/common/enums"; import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; @@ -87,6 +88,7 @@ export class ViewComponent implements OnDestroy, OnInit { protected tokenService: TokenService, protected i18nService: I18nService, protected cryptoService: CryptoService, + protected encryptService: EncryptService, protected platformUtilsService: PlatformUtilsService, protected auditService: AuditService, protected win: Window, @@ -442,7 +444,7 @@ export class ViewComponent implements OnDestroy, OnInit { attachment.key != null ? attachment.key : await this.cryptoService.getOrgKey(this.cipher.organizationId); - const decBuf = await this.cryptoService.decryptFromBytes(encBuf, key); + const decBuf = await this.encryptService.decryptToBytes(encBuf, key); this.fileDownloadService.download({ fileName: attachment.fileName, blobData: decBuf, diff --git a/libs/auth/src/common/login-strategies/auth-request-login.strategy.spec.ts b/libs/auth/src/common/login-strategies/auth-request-login.strategy.spec.ts index b112e5aa2a..efc6da51d9 100644 --- a/libs/auth/src/common/login-strategies/auth-request-login.strategy.spec.ts +++ b/libs/auth/src/common/login-strategies/auth-request-login.strategy.spec.ts @@ -12,6 +12,7 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -37,6 +38,7 @@ describe("AuthRequestLoginStrategy", () => { let cache: AuthRequestLoginStrategyData; let cryptoService: MockProxy; + let encryptService: MockProxy; let apiService: MockProxy; let tokenService: MockProxy; let appIdService: MockProxy; @@ -101,6 +103,7 @@ describe("AuthRequestLoginStrategy", () => { accountService, masterPasswordService, cryptoService, + encryptService, apiService, tokenService, appIdService, diff --git a/libs/auth/src/common/login-strategies/login.strategy.spec.ts b/libs/auth/src/common/login-strategies/login.strategy.spec.ts index 665857c1f4..35d62ca76b 100644 --- a/libs/auth/src/common/login-strategies/login.strategy.spec.ts +++ b/libs/auth/src/common/login-strategies/login.strategy.spec.ts @@ -22,6 +22,7 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -104,6 +105,7 @@ describe("LoginStrategy", () => { let loginStrategyService: MockProxy; let cryptoService: MockProxy; + let encryptService: MockProxy; let apiService: MockProxy; let tokenService: MockProxy; let appIdService: MockProxy; @@ -128,6 +130,7 @@ describe("LoginStrategy", () => { loginStrategyService = mock(); cryptoService = mock(); + encryptService = mock(); apiService = mock(); tokenService = mock(); appIdService = mock(); @@ -156,6 +159,7 @@ describe("LoginStrategy", () => { accountService, masterPasswordService, cryptoService, + encryptService, apiService, tokenService, appIdService, @@ -467,6 +471,7 @@ describe("LoginStrategy", () => { accountService, masterPasswordService, cryptoService, + encryptService, apiService, tokenService, appIdService, diff --git a/libs/auth/src/common/login-strategies/login.strategy.ts b/libs/auth/src/common/login-strategies/login.strategy.ts index ff6bf07af7..2e881f978d 100644 --- a/libs/auth/src/common/login-strategies/login.strategy.ts +++ b/libs/auth/src/common/login-strategies/login.strategy.ts @@ -26,6 +26,7 @@ import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action import { KeysRequest } from "@bitwarden/common/models/request/keys.request"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -66,6 +67,7 @@ export abstract class LoginStrategy { protected accountService: AccountService, protected masterPasswordService: InternalMasterPasswordServiceAbstraction, protected cryptoService: CryptoService, + protected encryptService: EncryptService, protected apiService: ApiService, protected tokenService: TokenService, protected appIdService: AppIdService, diff --git a/libs/auth/src/common/login-strategies/password-login.strategy.spec.ts b/libs/auth/src/common/login-strategies/password-login.strategy.spec.ts index 7ba58e1443..07cbf2424a 100644 --- a/libs/auth/src/common/login-strategies/password-login.strategy.spec.ts +++ b/libs/auth/src/common/login-strategies/password-login.strategy.spec.ts @@ -16,6 +16,7 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -63,6 +64,7 @@ describe("PasswordLoginStrategy", () => { let loginStrategyService: MockProxy; let cryptoService: MockProxy; + let encryptService: MockProxy; let apiService: MockProxy; let tokenService: MockProxy; let appIdService: MockProxy; @@ -88,6 +90,7 @@ describe("PasswordLoginStrategy", () => { loginStrategyService = mock(); cryptoService = mock(); + encryptService = mock(); apiService = mock(); tokenService = mock(); appIdService = mock(); @@ -127,6 +130,7 @@ describe("PasswordLoginStrategy", () => { accountService, masterPasswordService, cryptoService, + encryptService, apiService, tokenService, appIdService, diff --git a/libs/auth/src/common/login-strategies/sso-login.strategy.spec.ts b/libs/auth/src/common/login-strategies/sso-login.strategy.spec.ts index 8e28a2c022..f5de10766c 100644 --- a/libs/auth/src/common/login-strategies/sso-login.strategy.spec.ts +++ b/libs/auth/src/common/login-strategies/sso-login.strategy.spec.ts @@ -17,6 +17,7 @@ import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; @@ -44,6 +45,7 @@ describe("SsoLoginStrategy", () => { let masterPasswordService: FakeMasterPasswordService; let cryptoService: MockProxy; + let encryptService: MockProxy; let apiService: MockProxy; let tokenService: MockProxy; let appIdService: MockProxy; @@ -78,6 +80,7 @@ describe("SsoLoginStrategy", () => { masterPasswordService = new FakeMasterPasswordService(); cryptoService = mock(); + encryptService = mock(); apiService = mock(); tokenService = mock(); appIdService = mock(); @@ -125,6 +128,7 @@ describe("SsoLoginStrategy", () => { accountService, masterPasswordService, cryptoService, + encryptService, apiService, tokenService, appIdService, diff --git a/libs/auth/src/common/login-strategies/user-api-login.strategy.spec.ts b/libs/auth/src/common/login-strategies/user-api-login.strategy.spec.ts index 1661449796..d299a8e0ce 100644 --- a/libs/auth/src/common/login-strategies/user-api-login.strategy.spec.ts +++ b/libs/auth/src/common/login-strategies/user-api-login.strategy.spec.ts @@ -11,6 +11,7 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { Environment, EnvironmentService, @@ -39,6 +40,7 @@ describe("UserApiLoginStrategy", () => { let masterPasswordService: FakeMasterPasswordService; let cryptoService: MockProxy; + let encryptService: MockProxy; let apiService: MockProxy; let tokenService: MockProxy; let appIdService: MockProxy; @@ -99,6 +101,7 @@ describe("UserApiLoginStrategy", () => { accountService, masterPasswordService, cryptoService, + encryptService, apiService, tokenService, appIdService, diff --git a/libs/auth/src/common/login-strategies/webauthn-login.strategy.spec.ts b/libs/auth/src/common/login-strategies/webauthn-login.strategy.spec.ts index 0db41c1e64..b25022d25d 100644 --- a/libs/auth/src/common/login-strategies/webauthn-login.strategy.spec.ts +++ b/libs/auth/src/common/login-strategies/webauthn-login.strategy.spec.ts @@ -14,6 +14,7 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -37,6 +38,7 @@ describe("WebAuthnLoginStrategy", () => { let masterPasswordService: FakeMasterPasswordService; let cryptoService!: MockProxy; + let encryptService!: MockProxy; let apiService!: MockProxy; let tokenService!: MockProxy; let appIdService!: MockProxy; @@ -79,6 +81,7 @@ describe("WebAuthnLoginStrategy", () => { masterPasswordService = new FakeMasterPasswordService(); cryptoService = mock(); + encryptService = mock(); apiService = mock(); tokenService = mock(); appIdService = mock(); @@ -103,6 +106,7 @@ describe("WebAuthnLoginStrategy", () => { accountService, masterPasswordService, cryptoService, + encryptService, apiService, tokenService, appIdService, @@ -221,7 +225,7 @@ describe("WebAuthnLoginStrategy", () => { const mockUserKeyArray: Uint8Array = randomBytes(32); const mockUserKey = new SymmetricCryptoKey(mockUserKeyArray) as UserKey; - cryptoService.decryptToBytes.mockResolvedValue(mockPrfPrivateKey); + encryptService.decryptToBytes.mockResolvedValue(mockPrfPrivateKey); cryptoService.rsaDecrypt.mockResolvedValue(mockUserKeyArray); // Act @@ -235,8 +239,8 @@ describe("WebAuthnLoginStrategy", () => { userId, ); - expect(cryptoService.decryptToBytes).toHaveBeenCalledTimes(1); - expect(cryptoService.decryptToBytes).toHaveBeenCalledWith( + expect(encryptService.decryptToBytes).toHaveBeenCalledTimes(1); + expect(encryptService.decryptToBytes).toHaveBeenCalledWith( idTokenResponse.userDecryptionOptions.webAuthnPrfOption.encryptedPrivateKey, webAuthnCredentials.prfKey, ); @@ -268,7 +272,7 @@ describe("WebAuthnLoginStrategy", () => { await webAuthnLoginStrategy.logIn(webAuthnCredentials); // Assert - expect(cryptoService.decryptToBytes).not.toHaveBeenCalled(); + expect(encryptService.decryptToBytes).not.toHaveBeenCalled(); expect(cryptoService.rsaDecrypt).not.toHaveBeenCalled(); expect(cryptoService.setUserKey).not.toHaveBeenCalled(); }); @@ -303,7 +307,7 @@ describe("WebAuthnLoginStrategy", () => { apiService.postIdentityToken.mockResolvedValue(idTokenResponse); - cryptoService.decryptToBytes.mockResolvedValue(null); + encryptService.decryptToBytes.mockResolvedValue(null); // Act await webAuthnLoginStrategy.logIn(webAuthnCredentials); diff --git a/libs/auth/src/common/login-strategies/webauthn-login.strategy.ts b/libs/auth/src/common/login-strategies/webauthn-login.strategy.ts index d283d163da..96f8bc7d63 100644 --- a/libs/auth/src/common/login-strategies/webauthn-login.strategy.ts +++ b/libs/auth/src/common/login-strategies/webauthn-login.strategy.ts @@ -80,7 +80,7 @@ export class WebAuthnLoginStrategy extends LoginStrategy { } // decrypt prf encrypted private key - const privateKey = await this.cryptoService.decryptToBytes( + const privateKey = await this.encryptService.decryptToBytes( webAuthnPrfOption.encryptedPrivateKey, credentials.prfKey, ); diff --git a/libs/auth/src/common/services/login-strategies/login-strategy.service.ts b/libs/auth/src/common/services/login-strategies/login-strategy.service.ts index 67bcdc3658..89c2bc01d9 100644 --- a/libs/auth/src/common/services/login-strategies/login-strategy.service.ts +++ b/libs/auth/src/common/services/login-strategies/login-strategy.service.ts @@ -317,6 +317,7 @@ export class LoginStrategyService implements LoginStrategyServiceAbstraction { this.accountService, this.masterPasswordService, this.cryptoService, + this.encryptService, this.apiService, this.tokenService, this.appIdService, diff --git a/libs/common/src/platform/abstractions/crypto.service.ts b/libs/common/src/platform/abstractions/crypto.service.ts index 1fe97e023f..2a8e1ad647 100644 --- a/libs/common/src/platform/abstractions/crypto.service.ts +++ b/libs/common/src/platform/abstractions/crypto.service.ts @@ -15,7 +15,6 @@ import { UserPublicKey, } from "../../types/key"; import { KeySuffixOptions, HashPurpose } from "../enums"; -import { EncArrayBuffer } from "../models/domain/enc-array-buffer"; import { EncString } from "../models/domain/enc-string"; import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key"; @@ -373,37 +372,6 @@ export abstract class CryptoService { * @param userId The desired user */ abstract clearDeprecatedKeys(keySuffix: KeySuffixOptions, userId?: string): Promise; - /** - * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) - * and then call encryptService.encrypt - */ - abstract encrypt(plainValue: string | Uint8Array, key?: SymmetricCryptoKey): Promise; - /** - * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) - * and then call encryptService.encryptToBytes - */ - abstract encryptToBytes( - plainValue: Uint8Array, - key?: SymmetricCryptoKey, - ): Promise; - /** - * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) - * and then call encryptService.decryptToBytes - */ - abstract decryptToBytes(encString: EncString, key?: SymmetricCryptoKey): Promise; - /** - * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) - * and then call encryptService.decryptToUtf8 - */ - abstract decryptToUtf8(encString: EncString, key?: SymmetricCryptoKey): Promise; - /** - * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) - * and then call encryptService.decryptToBytes - */ - abstract decryptFromBytes( - encBuffer: EncArrayBuffer, - key: SymmetricCryptoKey, - ): Promise; /** * Retrieves all the keys needed for decrypting Ciphers diff --git a/libs/common/src/platform/services/crypto.service.ts b/libs/common/src/platform/services/crypto.service.ts index 8ce2b5e1a0..6a93ac7f3f 100644 --- a/libs/common/src/platform/services/crypto.service.ts +++ b/libs/common/src/platform/services/crypto.service.ts @@ -48,7 +48,6 @@ import { StateService } from "../abstractions/state.service"; import { KeySuffixOptions, HashPurpose, EncryptionType } from "../enums"; import { convertValues } from "../misc/convert-values"; import { EFFLongWordList } from "../misc/wordlist"; -import { EncArrayBuffer } from "../models/domain/enc-array-buffer"; import { EncString, EncryptedString } from "../models/domain/enc-string"; import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key"; import { ActiveUserState, StateProvider } from "../state"; @@ -859,58 +858,6 @@ export class CryptoService implements CryptoServiceAbstraction { } } - // --DEPRECATED METHODS-- - - /** - * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) - * and then call encryptService.encrypt - */ - async encrypt(plainValue: string | Uint8Array, key?: SymmetricCryptoKey): Promise { - key ||= await this.getUserKeyWithLegacySupport(); - return await this.encryptService.encrypt(plainValue, key); - } - - /** - * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) - * and then call encryptService.encryptToBytes - */ - async encryptToBytes(plainValue: Uint8Array, key?: SymmetricCryptoKey): Promise { - key ||= await this.getUserKeyWithLegacySupport(); - return this.encryptService.encryptToBytes(plainValue, key); - } - - /** - * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) - * and then call encryptService.decryptToBytes - */ - async decryptToBytes(encString: EncString, key?: SymmetricCryptoKey): Promise { - key ||= await this.getUserKeyWithLegacySupport(); - return this.encryptService.decryptToBytes(encString, key); - } - - /** - * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) - * and then call encryptService.decryptToUtf8 - */ - async decryptToUtf8(encString: EncString, key?: SymmetricCryptoKey): Promise { - key ||= await this.getUserKeyWithLegacySupport(); - return await this.encryptService.decryptToUtf8(encString, key); - } - - /** - * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) - * and then call encryptService.decryptToBytes - */ - async decryptFromBytes(encBuffer: EncArrayBuffer, key: SymmetricCryptoKey): Promise { - if (encBuffer == null) { - throw new Error("No buffer provided for decryption."); - } - - key ||= await this.getUserKeyWithLegacySupport(); - - return this.encryptService.decryptToBytes(encBuffer, key); - } - userKey$(userId: UserId): Observable { return this.stateProvider.getUser(userId, USER_KEY).state$; } diff --git a/libs/common/src/tools/send/models/domain/send.spec.ts b/libs/common/src/tools/send/models/domain/send.spec.ts index bd42ab09cf..5b1d7e73da 100644 --- a/libs/common/src/tools/send/models/domain/send.spec.ts +++ b/libs/common/src/tools/send/models/domain/send.spec.ts @@ -1,5 +1,8 @@ import { mock } from "jest-mock-extended"; +import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; +import { UserKey } from "@bitwarden/common/types/key"; + import { makeStaticByteArray, mockEnc } from "../../../../../spec"; import { CryptoService } from "../../../../platform/abstractions/crypto.service"; import { EncryptService } from "../../../../platform/abstractions/encrypt.service"; @@ -89,6 +92,7 @@ describe("Send", () => { it("Decrypt", async () => { const text = mock(); text.decrypt.mockResolvedValue("textView" as any); + const userKey = new SymmetricCryptoKey(new Uint8Array(32)) as UserKey; const send = new Send(); send.id = "id"; @@ -106,13 +110,13 @@ describe("Send", () => { send.disabled = false; send.hideEmail = true; + const encryptService = mock(); const cryptoService = mock(); - cryptoService.decryptToBytes - .calledWith(send.key, null) + encryptService.decryptToBytes + .calledWith(send.key, userKey) .mockResolvedValue(makeStaticByteArray(32)); cryptoService.makeSendKey.mockResolvedValue("cryptoKey" as any); - - const encryptService = mock(); + cryptoService.getUserKey.mockResolvedValue(userKey); (window as any).bitwardenContainerService = new ContainerService(cryptoService, encryptService); diff --git a/libs/common/src/tools/send/models/domain/send.ts b/libs/common/src/tools/send/models/domain/send.ts index 610980062b..41d1fecc10 100644 --- a/libs/common/src/tools/send/models/domain/send.ts +++ b/libs/common/src/tools/send/models/domain/send.ts @@ -73,9 +73,11 @@ export class Send extends Domain { const model = new SendView(this); const cryptoService = Utils.getContainerService().getCryptoService(); + const encryptService = Utils.getContainerService().getEncryptService(); try { - model.key = await cryptoService.decryptToBytes(this.key, null); + const sendKeyEncryptionKey = await cryptoService.getUserKey(); + model.key = await encryptService.decryptToBytes(this.key, sendKeyEncryptionKey); model.cryptoKey = await cryptoService.makeSendKey(model.key); } catch (e) { // TODO: error? diff --git a/libs/common/src/vault/abstractions/folder/folder.service.abstraction.ts b/libs/common/src/vault/abstractions/folder/folder.service.abstraction.ts index 3480a8aca0..857915ddb8 100644 --- a/libs/common/src/vault/abstractions/folder/folder.service.abstraction.ts +++ b/libs/common/src/vault/abstractions/folder/folder.service.abstraction.ts @@ -15,7 +15,7 @@ export abstract class FolderService implements UserKeyRotationDataProvider; clearCache: () => Promise; - encrypt: (model: FolderView, key?: SymmetricCryptoKey) => Promise; + encrypt: (model: FolderView, key: SymmetricCryptoKey) => Promise; get: (id: string) => Promise; getDecrypted$: (id: string) => Observable; getAllFromState: () => Promise; diff --git a/libs/common/src/vault/services/cipher.service.spec.ts b/libs/common/src/vault/services/cipher.service.spec.ts index b2712dee55..0873fa9d92 100644 --- a/libs/common/src/vault/services/cipher.service.spec.ts +++ b/libs/common/src/vault/services/cipher.service.spec.ts @@ -145,6 +145,7 @@ describe("Cipher Service", () => { cipherFileUploadService, configService, stateProvider, + accountService, ); cipherObj = new Cipher(cipherData); @@ -273,7 +274,7 @@ describe("Cipher Service", () => { cryptoService.makeCipherKey.mockReturnValue( Promise.resolve(new SymmetricCryptoKey(makeStaticByteArray(64)) as CipherKey), ); - cryptoService.encrypt.mockImplementation(encryptText); + encryptService.encrypt.mockImplementation(encryptText); jest.spyOn(cipherService as any, "getAutofillOnPageLoadDefault").mockResolvedValue(true); }); @@ -285,6 +286,10 @@ describe("Cipher Service", () => { { uri: "uri", match: UriMatchStrategy.RegularExpression } as LoginUriView, ]; + cryptoService.getOrgKey.mockReturnValue( + Promise.resolve(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey), + ); + const domain = await cipherService.encrypt(cipherView, userId); expect(domain.login.uris).toEqual([ @@ -301,6 +306,9 @@ describe("Cipher Service", () => { it("is null when feature flag is false", async () => { configService.getFeatureFlag.mockResolvedValue(false); + cryptoService.getOrgKey.mockReturnValue( + Promise.resolve(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey), + ); const cipher = await cipherService.encrypt(cipherView, userId); expect(cipher.key).toBeNull(); @@ -322,6 +330,9 @@ describe("Cipher Service", () => { it("is not called when feature flag is false", async () => { configService.getFeatureFlag.mockResolvedValue(false); + cryptoService.getOrgKey.mockReturnValue( + Promise.resolve(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey), + ); await cipherService.encrypt(cipherView, userId); @@ -330,6 +341,9 @@ describe("Cipher Service", () => { it("is called when feature flag is true", async () => { configService.getFeatureFlag.mockResolvedValue(true); + cryptoService.getOrgKey.mockReturnValue( + Promise.resolve(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey), + ); await cipherService.encrypt(cipherView, userId); diff --git a/libs/common/src/vault/services/cipher.service.ts b/libs/common/src/vault/services/cipher.service.ts index 70b7c77fc1..9761387284 100644 --- a/libs/common/src/vault/services/cipher.service.ts +++ b/libs/common/src/vault/services/cipher.service.ts @@ -1,6 +1,7 @@ import { firstValueFrom, map, Observable, skipWhile, switchMap } from "rxjs"; import { SemVer } from "semver"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { BulkEncryptService } from "@bitwarden/common/platform/abstractions/bulk-encrypt.service"; @@ -108,6 +109,7 @@ export class CipherService implements CipherServiceAbstraction { private cipherFileUploadService: CipherFileUploadService, private configService: ConfigService, private stateProvider: StateProvider, + private accountService: AccountService, ) { this.localDataState = this.stateProvider.getActive(LOCAL_DATA_KEY); this.encryptedCiphersState = this.stateProvider.getActive(ENCRYPTED_CIPHERS); @@ -165,7 +167,7 @@ export class CipherService implements CipherServiceAbstraction { async encrypt( model: CipherView, userId: UserId, - keyForEncryption?: SymmetricCryptoKey, + keyForCipherEncryption?: SymmetricCryptoKey, keyForCipherKeyDecryption?: SymmetricCryptoKey, originalCipher: Cipher = null, ): Promise { @@ -195,26 +197,21 @@ export class CipherService implements CipherServiceAbstraction { const userOrOrgKey = await this.getKeyForCipherKeyDecryption(cipher, userId); // The keyForEncryption is only used for encrypting the cipher key, not the cipher itself, since cipher key encryption is enabled. // If the caller has provided a key for cipher key encryption, use it. Otherwise, use the user or org key. - keyForEncryption ||= userOrOrgKey; + keyForCipherEncryption ||= userOrOrgKey; // If the caller has provided a key for cipher key decryption, use it. Otherwise, use the user or org key. keyForCipherKeyDecryption ||= userOrOrgKey; return this.encryptCipherWithCipherKey( model, cipher, - keyForEncryption, + keyForCipherEncryption, keyForCipherKeyDecryption, ); } else { - if (keyForEncryption == null && cipher.organizationId != null) { - keyForEncryption = await this.cryptoService.getOrgKey(cipher.organizationId); - if (keyForEncryption == null) { - throw new Error("Cannot encrypt cipher for organization. No key."); - } - } + keyForCipherEncryption ||= await this.getKeyForCipherKeyDecryption(cipher, userId); // We want to ensure that the cipher key is null if cipher key encryption is disabled // so that decryption uses the proper key. cipher.key = null; - return this.encryptCipher(model, cipher, keyForEncryption); + return this.encryptCipher(model, cipher, keyForCipherEncryption); } } @@ -243,7 +240,7 @@ export class CipherService implements CipherServiceAbstraction { key, ).then(async () => { if (model.key != null) { - attachment.key = await this.cryptoService.encrypt(model.key.key, key); + attachment.key = await this.encryptService.encrypt(model.key.key, key); } encAttachments.push(attachment); }); @@ -1348,7 +1345,9 @@ export class CipherService implements CipherServiceAbstraction { } const encBuf = await EncArrayBuffer.fromResponse(attachmentResponse); - const decBuf = await this.cryptoService.decryptFromBytes(encBuf, null); + const activeUserId = await firstValueFrom(this.accountService.activeAccount$); + const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeUserId.id); + const decBuf = await this.encryptService.decryptToBytes(encBuf, userKey); let encKey: UserKey | OrgKey; encKey = await this.cryptoService.getOrgKey(organizationId); @@ -1412,7 +1411,7 @@ export class CipherService implements CipherServiceAbstraction { .then(() => { const modelProp = (model as any)[map[theProp] || theProp]; if (modelProp && modelProp !== "") { - return self.cryptoService.encrypt(modelProp, key); + return self.encryptService.encrypt(modelProp, key); } return null; }) @@ -1458,7 +1457,7 @@ export class CipherService implements CipherServiceAbstraction { key, ); const uriHash = await this.encryptService.hash(model.login.uris[i].uri, "sha256"); - loginUri.uriChecksum = await this.cryptoService.encrypt(uriHash, key); + loginUri.uriChecksum = await this.encryptService.encrypt(uriHash, key); cipher.login.uris.push(loginUri); } } @@ -1485,8 +1484,8 @@ export class CipherService implements CipherServiceAbstraction { }, key, ); - domainKey.counter = await this.cryptoService.encrypt(String(viewKey.counter), key); - domainKey.discoverable = await this.cryptoService.encrypt( + domainKey.counter = await this.encryptService.encrypt(String(viewKey.counter), key); + domainKey.discoverable = await this.encryptService.encrypt( String(viewKey.discoverable), key, ); @@ -1605,11 +1604,23 @@ export class CipherService implements CipherServiceAbstraction { this.sortedCiphersCache.clear(); } + /** + * Encrypts a cipher object. + * @param model The cipher view model. + * @param cipher The cipher object. + * @param key The encryption key to encrypt with. This can be the org key, user key or cipher key, but must never be null + */ private async encryptCipher( model: CipherView, cipher: Cipher, key: SymmetricCryptoKey, ): Promise { + if (key == null) { + throw new Error( + "Key to encrypt cipher must not be null. Use the org key, user key or cipher key.", + ); + } + await Promise.all([ this.encryptObjProperty( model, diff --git a/libs/common/src/vault/services/collection.service.ts b/libs/common/src/vault/services/collection.service.ts index e9ad09a483..09d21390ae 100644 --- a/libs/common/src/vault/services/collection.service.ts +++ b/libs/common/src/vault/services/collection.service.ts @@ -1,6 +1,8 @@ import { firstValueFrom, map, Observable } from "rxjs"; import { Jsonify } from "type-fest"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; + import { CryptoService } from "../../platform/abstractions/crypto.service"; import { I18nService } from "../../platform/abstractions/i18n.service"; import { Utils } from "../../platform/misc/utils"; @@ -61,6 +63,7 @@ export class CollectionService implements CollectionServiceAbstraction { constructor( private cryptoService: CryptoService, + private encryptService: EncryptService, private i18nService: I18nService, protected stateProvider: StateProvider, ) { @@ -101,7 +104,7 @@ export class CollectionService implements CollectionServiceAbstraction { collection.organizationId = model.organizationId; collection.readOnly = model.readOnly; collection.externalId = model.externalId; - collection.name = await this.cryptoService.encrypt(model.name, key); + collection.name = await this.encryptService.encrypt(model.name, key); return collection; } 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 c27ea7646b..05e1cdebc9 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,13 @@ describe("Folder Service", () => { ); encryptService.decryptToUtf8.mockResolvedValue("DEC"); - folderService = new FolderService(cryptoService, i18nService, cipherService, stateProvider); + folderService = new FolderService( + cryptoService, + encryptService, + i18nService, + cipherService, + stateProvider, + ); folderState = stateProvider.activeUser.getFake(FOLDER_ENCRYPTED_FOLDERS); @@ -62,9 +68,9 @@ describe("Folder Service", () => { model.id = "2"; model.name = "Test Folder"; - cryptoService.encrypt.mockResolvedValue(new EncString("ENC")); + encryptService.encrypt.mockResolvedValue(new EncString("ENC")); - const result = await folderService.encrypt(model); + const result = await folderService.encrypt(model, null); expect(result).toEqual({ id: "2", @@ -185,7 +191,7 @@ describe("Folder Service", () => { beforeEach(() => { encryptedKey = new EncString("Re-encrypted Folder"); - cryptoService.encrypt.mockResolvedValue(encryptedKey); + encryptService.encrypt.mockResolvedValue(encryptedKey); }); it("returns re-encrypted user folders", async () => { diff --git a/libs/common/src/vault/services/folder/folder.service.ts b/libs/common/src/vault/services/folder/folder.service.ts index 0c17d7178b..2adbc8c6d0 100644 --- a/libs/common/src/vault/services/folder/folder.service.ts +++ b/libs/common/src/vault/services/folder/folder.service.ts @@ -1,5 +1,7 @@ import { Observable, firstValueFrom, map, shareReplay } from "rxjs"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; + import { CryptoService } from "../../../platform/abstractions/crypto.service"; import { I18nService } from "../../../platform/abstractions/i18n.service"; import { Utils } from "../../../platform/misc/utils"; @@ -25,6 +27,7 @@ export class FolderService implements InternalFolderServiceAbstraction { constructor( private cryptoService: CryptoService, + private encryptService: EncryptService, private i18nService: I18nService, private cipherService: CipherService, private stateProvider: StateProvider, @@ -48,10 +51,10 @@ export class FolderService implements InternalFolderServiceAbstraction { } // TODO: This should be moved to EncryptService or something - async encrypt(model: FolderView, key?: SymmetricCryptoKey): Promise { + async encrypt(model: FolderView, key: SymmetricCryptoKey): Promise { const folder = new Folder(); folder.id = model.id; - folder.name = await this.cryptoService.encrypt(model.name, key); + folder.name = await this.encryptService.encrypt(model.name, key); return folder; } diff --git a/libs/importer/spec/bitwarden-password-protected-importer.spec.ts b/libs/importer/spec/bitwarden-password-protected-importer.spec.ts index d36ce8b9a6..e5100e4990 100644 --- a/libs/importer/spec/bitwarden-password-protected-importer.spec.ts +++ b/libs/importer/spec/bitwarden-password-protected-importer.spec.ts @@ -3,6 +3,7 @@ import { mock, MockProxy } from "jest-mock-extended"; import { PinServiceAbstraction } from "@bitwarden/auth/common"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { KdfType } from "@bitwarden/common/platform/enums"; import { Utils } from "@bitwarden/common/platform/misc/utils"; @@ -19,6 +20,7 @@ import { emptyUnencryptedExport } from "./test-data/bitwarden-json/unencrypted.j describe("BitwardenPasswordProtectedImporter", () => { let importer: BitwardenPasswordProtectedImporter; let cryptoService: MockProxy; + let encryptService: MockProxy; let i18nService: MockProxy; let cipherService: MockProxy; let pinService: MockProxy; @@ -30,6 +32,7 @@ describe("BitwardenPasswordProtectedImporter", () => { beforeEach(() => { cryptoService = mock(); + encryptService = mock(); i18nService = mock(); cipherService = mock(); pinService = mock(); @@ -37,6 +40,7 @@ describe("BitwardenPasswordProtectedImporter", () => { importer = new BitwardenPasswordProtectedImporter( cryptoService, + encryptService, i18nService, cipherService, pinService, @@ -91,7 +95,7 @@ describe("BitwardenPasswordProtectedImporter", () => { }); it("succeeds with default jdoc", async () => { - cryptoService.decryptToUtf8.mockReturnValue(Promise.resolve(emptyUnencryptedExport)); + encryptService.decryptToUtf8.mockReturnValue(Promise.resolve(emptyUnencryptedExport)); expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(true); }); diff --git a/libs/importer/src/components/import.component.ts b/libs/importer/src/components/import.component.ts index 8ee882734b..10a3f5a89a 100644 --- a/libs/importer/src/components/import.component.ts +++ b/libs/importer/src/components/import.component.ts @@ -30,6 +30,7 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { ClientType } from "@bitwarden/common/enums"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -89,6 +90,7 @@ const safeProviders: SafeProvider[] = [ I18nService, CollectionService, CryptoService, + EncryptService, PinServiceAbstraction, AccountService, ], diff --git a/libs/importer/src/importers/bitwarden/bitwarden-json-importer.ts b/libs/importer/src/importers/bitwarden/bitwarden-json-importer.ts index 2248606814..9adc8a9781 100644 --- a/libs/importer/src/importers/bitwarden/bitwarden-json-importer.ts +++ b/libs/importer/src/importers/bitwarden/bitwarden-json-importer.ts @@ -8,8 +8,10 @@ import { FolderWithIdExport, } from "@bitwarden/common/models/export"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; +import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { OrganizationId } from "@bitwarden/common/types/guid"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view"; @@ -31,6 +33,7 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer { protected constructor( protected cryptoService: CryptoService, + protected encryptService: EncryptService, protected i18nService: I18nService, protected cipherService: CipherService, protected pinService: PinServiceAbstraction, @@ -60,11 +63,16 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer { results: BitwardenEncryptedIndividualJsonExport | BitwardenEncryptedOrgJsonExport, ) { if (results.encKeyValidation_DO_NOT_EDIT != null) { - const orgKey = await this.cryptoService.getOrgKey(this.organizationId); + let keyForDecryption: SymmetricCryptoKey = await this.cryptoService.getOrgKey( + this.organizationId, + ); + if (keyForDecryption == null) { + keyForDecryption = await this.cryptoService.getUserKeyWithLegacySupport(); + } const encKeyValidation = new EncString(results.encKeyValidation_DO_NOT_EDIT); - const encKeyValidationDecrypt = await this.cryptoService.decryptToUtf8( + const encKeyValidationDecrypt = await this.encryptService.decryptToUtf8( encKeyValidation, - orgKey, + keyForDecryption, ); if (encKeyValidationDecrypt === null) { this.result.success = false; diff --git a/libs/importer/src/importers/bitwarden/bitwarden-password-protected-importer.ts b/libs/importer/src/importers/bitwarden/bitwarden-password-protected-importer.ts index a854346bcc..35a0ec0f22 100644 --- a/libs/importer/src/importers/bitwarden/bitwarden-password-protected-importer.ts +++ b/libs/importer/src/importers/bitwarden/bitwarden-password-protected-importer.ts @@ -6,6 +6,7 @@ import { PBKDF2KdfConfig, } from "@bitwarden/common/auth/models/domain/kdf-config"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { KdfType } from "@bitwarden/common/platform/enums"; import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; @@ -23,13 +24,14 @@ export class BitwardenPasswordProtectedImporter extends BitwardenJsonImporter im constructor( cryptoService: CryptoService, + encryptService: EncryptService, i18nService: I18nService, cipherService: CipherService, pinService: PinServiceAbstraction, accountService: AccountService, private promptForPassword_callback: () => Promise, ) { - super(cryptoService, i18nService, cipherService, pinService, accountService); + super(cryptoService, encryptService, i18nService, cipherService, pinService, accountService); } async parse(data: string): Promise { @@ -65,7 +67,7 @@ export class BitwardenPasswordProtectedImporter extends BitwardenJsonImporter im } const encData = new EncString(parsedData.data); - const clearTextData = await this.cryptoService.decryptToUtf8(encData, this.key); + const clearTextData = await this.encryptService.decryptToUtf8(encData, this.key); return await super.parse(clearTextData); } @@ -86,7 +88,7 @@ export class BitwardenPasswordProtectedImporter extends BitwardenJsonImporter im const encKeyValidation = new EncString(jdoc.encKeyValidation_DO_NOT_EDIT); - const encKeyValidationDecrypt = await this.cryptoService.decryptToUtf8( + const encKeyValidationDecrypt = await this.encryptService.decryptToUtf8( encKeyValidation, this.key, ); diff --git a/libs/importer/src/services/import.service.spec.ts b/libs/importer/src/services/import.service.spec.ts index e44c8f6aa9..ef605746e6 100644 --- a/libs/importer/src/services/import.service.spec.ts +++ b/libs/importer/src/services/import.service.spec.ts @@ -3,6 +3,7 @@ import { mock, MockProxy } from "jest-mock-extended"; import { PinServiceAbstraction } from "@bitwarden/auth/common"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; @@ -27,6 +28,7 @@ describe("ImportService", () => { let i18nService: MockProxy; let collectionService: MockProxy; let cryptoService: MockProxy; + let encryptService: MockProxy; let pinService: MockProxy; let accountService: MockProxy; @@ -37,6 +39,7 @@ describe("ImportService", () => { i18nService = mock(); collectionService = mock(); cryptoService = mock(); + encryptService = mock(); pinService = mock(); importService = new ImportService( @@ -46,6 +49,7 @@ describe("ImportService", () => { i18nService, collectionService, cryptoService, + encryptService, pinService, accountService, ); diff --git a/libs/importer/src/services/import.service.ts b/libs/importer/src/services/import.service.ts index 13b77fb5b4..2295f4f704 100644 --- a/libs/importer/src/services/import.service.ts +++ b/libs/importer/src/services/import.service.ts @@ -7,6 +7,7 @@ import { ImportOrganizationCiphersRequest } from "@bitwarden/common/models/reque import { KvpRequest } from "@bitwarden/common/models/request/kvp.request"; import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; @@ -104,6 +105,7 @@ export class ImportService implements ImportServiceAbstraction { private i18nService: I18nService, private collectionService: CollectionService, private cryptoService: CryptoService, + private encryptService: EncryptService, private pinService: PinServiceAbstraction, private accountService: AccountService, ) {} @@ -207,6 +209,7 @@ export class ImportService implements ImportServiceAbstraction { case "bitwardenpasswordprotected": return new BitwardenPasswordProtectedImporter( this.cryptoService, + this.encryptService, this.i18nService, this.cipherService, this.pinService, @@ -344,9 +347,10 @@ export class ImportService implements ImportServiceAbstraction { const c = await this.cipherService.encrypt(importResult.ciphers[i], activeUserId); request.ciphers.push(new CipherRequest(c)); } + const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeUserId); if (importResult.folders != null) { for (let i = 0; i < importResult.folders.length; i++) { - const f = await this.folderService.encrypt(importResult.folders[i]); + const f = await this.folderService.encrypt(importResult.folders[i], userKey); request.folders.push(new FolderWithIdRequest(f)); } } diff --git a/libs/tools/export/vault-export/vault-export-core/src/services/base-vault-export.service.ts b/libs/tools/export/vault-export/vault-export-core/src/services/base-vault-export.service.ts index a494885698..76b008be62 100644 --- a/libs/tools/export/vault-export/vault-export-core/src/services/base-vault-export.service.ts +++ b/libs/tools/export/vault-export/vault-export-core/src/services/base-vault-export.service.ts @@ -2,7 +2,7 @@ import { PinServiceAbstraction } from "@bitwarden/auth/common"; import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service"; import { KdfConfig } from "@bitwarden/common/auth/models/domain/kdf-config"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; -import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { KdfType } from "@bitwarden/common/platform/enums"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { CipherType } from "@bitwarden/common/vault/enums"; @@ -12,7 +12,7 @@ import { BitwardenCsvExportType, BitwardenPasswordProtectedFileFormat } from ".. export class BaseVaultExportService { constructor( protected pinService: PinServiceAbstraction, - protected cryptoService: CryptoService, + protected encryptService: EncryptService, private cryptoFunctionService: CryptoFunctionService, private kdfConfigService: KdfConfigService, ) {} @@ -23,8 +23,8 @@ export class BaseVaultExportService { const salt = Utils.fromBufferToB64(await this.cryptoFunctionService.randomBytes(16)); const key = await this.pinService.makePinKey(password, salt, kdfConfig); - const encKeyValidation = await this.cryptoService.encrypt(Utils.newGuid(), key); - const encText = await this.cryptoService.encrypt(clearText, key); + const encKeyValidation = await this.encryptService.encrypt(Utils.newGuid(), key); + const encText = await this.encryptService.encrypt(clearText, key); const jsonDoc: BitwardenPasswordProtectedFileFormat = { encrypted: true, diff --git a/libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.spec.ts b/libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.spec.ts index 44df18116d..1a66fe9225 100644 --- a/libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.spec.ts +++ b/libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.spec.ts @@ -1,6 +1,8 @@ import { mock, MockProxy } from "jest-mock-extended"; +import { BehaviorSubject } from "rxjs"; import { PinServiceAbstraction } from "@bitwarden/auth/common"; +import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service"; import { DEFAULT_KDF_CONFIG, @@ -9,9 +11,11 @@ import { import { CipherWithIdExport } from "@bitwarden/common/models/export/cipher-with-ids.export"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { KdfType } from "@bitwarden/common/platform/enums"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { EncryptedString, EncString } from "@bitwarden/common/platform/models/domain/enc-string"; +import { UserId } from "@bitwarden/common/types/guid"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; import { CipherType } from "@bitwarden/common/vault/enums"; @@ -149,7 +153,9 @@ describe("VaultExportService", () => { let pinService: MockProxy; let folderService: MockProxy; let cryptoService: MockProxy; + let encryptService: MockProxy; let kdfConfigService: MockProxy; + let accountService: MockProxy; beforeEach(() => { cryptoFunctionService = mock(); @@ -157,20 +163,35 @@ describe("VaultExportService", () => { pinService = mock(); folderService = mock(); cryptoService = mock(); + encryptService = mock(); kdfConfigService = mock(); + accountService = mock(); + + cryptoService.userKey$.mockReturnValue(new BehaviorSubject("mockOriginalUserKey" as any)); + + const userId = "" as UserId; + const accountInfo: AccountInfo = { + email: "", + emailVerified: true, + name: undefined, + }; + const activeAccount = { id: userId, ...accountInfo }; + accountService.activeAccount$ = new BehaviorSubject(activeAccount); folderService.getAllDecryptedFromState.mockResolvedValue(UserFolderViews); folderService.getAllFromState.mockResolvedValue(UserFolders); kdfConfigService.getKdfConfig.mockResolvedValue(DEFAULT_KDF_CONFIG); - cryptoService.encrypt.mockResolvedValue(new EncString("encrypted")); + encryptService.encrypt.mockResolvedValue(new EncString("encrypted")); exportService = new IndividualVaultExportService( folderService, cipherService, pinService, cryptoService, + encryptService, cryptoFunctionService, kdfConfigService, + accountService, ); }); @@ -250,7 +271,7 @@ describe("VaultExportService", () => { }); it("has a mac property", async () => { - cryptoService.encrypt.mockResolvedValue(mac); + encryptService.encrypt.mockResolvedValue(mac); exportString = await exportService.getPasswordProtectedExport(password); exportObject = JSON.parse(exportString); @@ -258,7 +279,7 @@ describe("VaultExportService", () => { }); it("has data property", async () => { - cryptoService.encrypt.mockResolvedValue(data); + encryptService.encrypt.mockResolvedValue(data); exportString = await exportService.getPasswordProtectedExport(password); exportObject = JSON.parse(exportString); diff --git a/libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.ts b/libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.ts index 3da92ef16b..d6d37b28ac 100644 --- a/libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.ts +++ b/libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.ts @@ -1,10 +1,13 @@ import * as papa from "papaparse"; +import { firstValueFrom, map } from "rxjs"; import { PinServiceAbstraction } from "@bitwarden/auth/common"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service"; import { CipherWithIdExport, FolderWithIdExport } from "@bitwarden/common/models/export"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; @@ -32,11 +35,13 @@ export class IndividualVaultExportService private folderService: FolderService, private cipherService: CipherService, pinService: PinServiceAbstraction, - cryptoService: CryptoService, + private cryptoService: CryptoService, + encryptService: EncryptService, cryptoFunctionService: CryptoFunctionService, kdfConfigService: KdfConfigService, + private accountService: AccountService, ) { - super(pinService, cryptoService, cryptoFunctionService, kdfConfigService); + super(pinService, encryptService, cryptoFunctionService, kdfConfigService); } async getExport(format: ExportFormat = "csv"): Promise { @@ -96,7 +101,11 @@ export class IndividualVaultExportService await Promise.all(promises); - const encKeyValidation = await this.cryptoService.encrypt(Utils.newGuid()); + const activeUserId = await firstValueFrom( + this.accountService.activeAccount$.pipe(map((a) => a?.id)), + ); + const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeUserId); + const encKeyValidation = await this.encryptService.encrypt(Utils.newGuid(), userKey); const jsonDoc: BitwardenEncryptedIndividualJsonExport = { encrypted: true, diff --git a/libs/tools/export/vault-export/vault-export-core/src/services/org-vault-export.service.ts b/libs/tools/export/vault-export/vault-export-core/src/services/org-vault-export.service.ts index 0c3e94178f..9fc1f20b83 100644 --- a/libs/tools/export/vault-export/vault-export-core/src/services/org-vault-export.service.ts +++ b/libs/tools/export/vault-export/vault-export-core/src/services/org-vault-export.service.ts @@ -8,6 +8,7 @@ import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config import { CipherWithIdExport, CollectionWithIdExport } from "@bitwarden/common/models/export"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { OrganizationId } from "@bitwarden/common/types/guid"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; @@ -39,13 +40,14 @@ export class OrganizationVaultExportService private cipherService: CipherService, private apiService: ApiService, pinService: PinServiceAbstraction, - cryptoService: CryptoService, + private cryptoService: CryptoService, + encryptService: EncryptService, cryptoFunctionService: CryptoFunctionService, private collectionService: CollectionService, kdfConfigService: KdfConfigService, private accountService: AccountService, ) { - super(pinService, cryptoService, cryptoFunctionService, kdfConfigService); + super(pinService, encryptService, cryptoFunctionService, kdfConfigService); } async getPasswordProtectedExport( @@ -242,7 +244,7 @@ export class OrganizationVaultExportService ciphers: Cipher[], ): Promise { const orgKey = await this.cryptoService.getOrgKey(organizationId); - const encKeyValidation = await this.cryptoService.encrypt(Utils.newGuid(), orgKey); + const encKeyValidation = await this.encryptService.encrypt(Utils.newGuid(), orgKey); const jsonDoc: BitwardenEncryptedOrgJsonExport = { encrypted: true, diff --git a/libs/tools/export/vault-export/vault-export-core/src/services/vault-export.service.spec.ts b/libs/tools/export/vault-export/vault-export-core/src/services/vault-export.service.spec.ts index 44df18116d..7e93c78fc5 100644 --- a/libs/tools/export/vault-export/vault-export-core/src/services/vault-export.service.spec.ts +++ b/libs/tools/export/vault-export/vault-export-core/src/services/vault-export.service.spec.ts @@ -1,6 +1,8 @@ import { mock, MockProxy } from "jest-mock-extended"; +import { BehaviorSubject } from "rxjs"; import { PinServiceAbstraction } from "@bitwarden/auth/common"; +import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service"; import { DEFAULT_KDF_CONFIG, @@ -9,9 +11,11 @@ import { import { CipherWithIdExport } from "@bitwarden/common/models/export/cipher-with-ids.export"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { KdfType } from "@bitwarden/common/platform/enums"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { EncryptedString, EncString } from "@bitwarden/common/platform/models/domain/enc-string"; +import { UserId } from "@bitwarden/common/types/guid"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; import { CipherType } from "@bitwarden/common/vault/enums"; @@ -149,6 +153,8 @@ describe("VaultExportService", () => { let pinService: MockProxy; let folderService: MockProxy; let cryptoService: MockProxy; + let encryptService: MockProxy; + let accountService: MockProxy; let kdfConfigService: MockProxy; beforeEach(() => { @@ -157,20 +163,34 @@ describe("VaultExportService", () => { pinService = mock(); folderService = mock(); cryptoService = mock(); + encryptService = mock(); + accountService = mock(); + kdfConfigService = mock(); folderService.getAllDecryptedFromState.mockResolvedValue(UserFolderViews); folderService.getAllFromState.mockResolvedValue(UserFolders); kdfConfigService.getKdfConfig.mockResolvedValue(DEFAULT_KDF_CONFIG); - cryptoService.encrypt.mockResolvedValue(new EncString("encrypted")); + encryptService.encrypt.mockResolvedValue(new EncString("encrypted")); + cryptoService.userKey$.mockReturnValue(new BehaviorSubject("mockOriginalUserKey" as any)); + const userId = "" as UserId; + const accountInfo: AccountInfo = { + email: "", + emailVerified: true, + name: undefined, + }; + const activeAccount = { id: userId, ...accountInfo }; + accountService.activeAccount$ = new BehaviorSubject(activeAccount); exportService = new IndividualVaultExportService( folderService, cipherService, pinService, cryptoService, + encryptService, cryptoFunctionService, kdfConfigService, + accountService, ); }); @@ -250,7 +270,7 @@ describe("VaultExportService", () => { }); it("has a mac property", async () => { - cryptoService.encrypt.mockResolvedValue(mac); + encryptService.encrypt.mockResolvedValue(mac); exportString = await exportService.getPasswordProtectedExport(password); exportObject = JSON.parse(exportString); @@ -258,7 +278,7 @@ describe("VaultExportService", () => { }); it("has data property", async () => { - cryptoService.encrypt.mockResolvedValue(data); + encryptService.encrypt.mockResolvedValue(data); exportString = await exportService.getPasswordProtectedExport(password); exportObject = JSON.parse(exportString);