diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 7e9da00aba..62f9bf05da 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -753,6 +753,7 @@ export default class MainBackground { this.accountService, this.masterPasswordService, this.cryptoService, + this.encryptService, this.apiService, this.stateProvider, ); diff --git a/apps/cli/src/admin-console/commands/confirm.command.ts b/apps/cli/src/admin-console/commands/confirm.command.ts index 066cca48f1..42ceea5510 100644 --- a/apps/cli/src/admin-console/commands/confirm.command.ts +++ b/apps/cli/src/admin-console/commands/confirm.command.ts @@ -4,6 +4,7 @@ import { } from "@bitwarden/admin-console/common"; import { ApiService } from "@bitwarden/common/abstractions/api.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 { Response } from "../../models/response"; @@ -12,6 +13,7 @@ export class ConfirmCommand { constructor( private apiService: ApiService, private cryptoService: CryptoService, + private encryptService: EncryptService, private organizationUserApiService: OrganizationUserApiService, ) {} @@ -53,7 +55,7 @@ export class ConfirmCommand { } const publicKeyResponse = await this.apiService.getUserPublicKey(orgUser.userId); const publicKey = Utils.fromB64ToArray(publicKeyResponse.publicKey); - const key = await this.cryptoService.rsaEncrypt(orgKey.key, publicKey); + const key = await this.encryptService.rsaEncrypt(orgKey.key, publicKey); const req = new OrganizationUserConfirmRequest(); req.key = key.encryptedString; await this.organizationUserApiService.postOrganizationUserConfirm( diff --git a/apps/cli/src/oss-serve-configurator.ts b/apps/cli/src/oss-serve-configurator.ts index fd2a10975f..94f466b447 100644 --- a/apps/cli/src/oss-serve-configurator.ts +++ b/apps/cli/src/oss-serve-configurator.ts @@ -117,6 +117,7 @@ export class OssServeConfigurator { this.confirmCommand = new ConfirmCommand( this.serviceContainer.apiService, this.serviceContainer.cryptoService, + this.serviceContainer.encryptService, this.serviceContainer.organizationUserApiService, ); this.restoreCommand = new RestoreCommand(this.serviceContainer.cipherService); diff --git a/apps/cli/src/service-container/service-container.ts b/apps/cli/src/service-container/service-container.ts index 2149b74f61..c339990ab9 100644 --- a/apps/cli/src/service-container/service-container.ts +++ b/apps/cli/src/service-container/service-container.ts @@ -534,6 +534,7 @@ export class ServiceContainer { this.accountService, this.masterPasswordService, this.cryptoService, + this.encryptService, this.apiService, this.stateProvider, ); diff --git a/apps/cli/src/vault.program.ts b/apps/cli/src/vault.program.ts index 11876ef6ec..60b40b1433 100644 --- a/apps/cli/src/vault.program.ts +++ b/apps/cli/src/vault.program.ts @@ -415,6 +415,7 @@ export class VaultProgram extends BaseProgram { const command = new ConfirmCommand( this.serviceContainer.apiService, this.serviceContainer.cryptoService, + this.serviceContainer.encryptService, this.serviceContainer.organizationUserApiService, ); const response = await command.run(object, id, cmd); diff --git a/apps/desktop/src/app/services/services.module.ts b/apps/desktop/src/app/services/services.module.ts index c4d50f359a..d3d41d277b 100644 --- a/apps/desktop/src/app/services/services.module.ts +++ b/apps/desktop/src/app/services/services.module.ts @@ -287,6 +287,7 @@ const safeProviders: SafeProvider[] = [ deps: [ ApiService, CryptoService, + EncryptService, I18nServiceAbstraction, KdfConfigService, InternalMasterPasswordServiceAbstraction, diff --git a/apps/web/src/app/admin-console/organizations/members/components/bulk/base-bulk-confirm.component.ts b/apps/web/src/app/admin-console/organizations/members/components/bulk/base-bulk-confirm.component.ts index 5a5da935a6..3cbb71878c 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/bulk/base-bulk-confirm.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/bulk/base-bulk-confirm.component.ts @@ -8,6 +8,7 @@ import { ProviderUserBulkPublicKeyResponse } from "@bitwarden/common/admin-conso import { ProviderUserBulkResponse } from "@bitwarden/common/admin-console/models/response/provider/provider-user-bulk.response"; 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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; @@ -31,6 +32,7 @@ export abstract class BaseBulkConfirmComponent implements OnInit { protected constructor( protected cryptoService: CryptoService, + protected encryptService: EncryptService, protected i18nService: I18nService, ) {} @@ -67,7 +69,7 @@ export abstract class BaseBulkConfirmComponent implements OnInit { if (publicKey == null) { continue; } - const encryptedKey = await this.cryptoService.rsaEncrypt(key.key, publicKey); + const encryptedKey = await this.encryptService.rsaEncrypt(key.key, publicKey); userIdsWithKeys.push({ id: user.id, key: encryptedKey.encryptedString, diff --git a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-confirm.component.ts b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-confirm.component.ts index 1465316933..ee50684062 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-confirm.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-confirm.component.ts @@ -8,6 +8,7 @@ import { import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { OrganizationUserStatusType } from "@bitwarden/common/admin-console/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 { Utils } from "@bitwarden/common/platform/misc/utils"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; @@ -41,6 +42,7 @@ export class BulkConfirmComponent implements OnInit { constructor( @Inject(DIALOG_DATA) protected data: BulkConfirmDialogData, protected cryptoService: CryptoService, + protected encryptService: EncryptService, protected apiService: ApiService, private organizationUserApiService: OrganizationUserApiService, private i18nService: I18nService, @@ -81,7 +83,7 @@ export class BulkConfirmComponent implements OnInit { if (publicKey == null) { continue; } - const encryptedKey = await this.cryptoService.rsaEncrypt(key.key, publicKey); + const encryptedKey = await this.encryptService.rsaEncrypt(key.key, publicKey); userIdsWithKeys.push({ id: user.id, key: encryptedKey.encryptedString, diff --git a/apps/web/src/app/admin-console/organizations/members/members.component.ts b/apps/web/src/app/admin-console/organizations/members/members.component.ts index f4a5e73847..0ce5ef10c8 100644 --- a/apps/web/src/app/admin-console/organizations/members/members.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/members.component.ts @@ -39,6 +39,7 @@ import { isNotSelfUpgradable, ProductTierType } from "@bitwarden/common/billing/ 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 { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service"; @@ -107,6 +108,7 @@ export class MembersComponent extends BaseMembersComponent i18nService: I18nService, organizationManagementPreferencesService: OrganizationManagementPreferencesService, cryptoService: CryptoService, + private encryptService: EncryptService, validationService: ValidationService, logService: LogService, userNamePipe: UserNamePipe, @@ -289,7 +291,7 @@ export class MembersComponent extends BaseMembersComponent async confirmUser(user: OrganizationUserView, publicKey: Uint8Array): Promise { const orgKey = await this.cryptoService.getOrgKey(this.organization.id); - const key = await this.cryptoService.rsaEncrypt(orgKey.key, publicKey); + const key = await this.encryptService.rsaEncrypt(orgKey.key, publicKey); const request = new OrganizationUserConfirmRequest(); request.key = key.encryptedString; await this.organizationUserApiService.postOrganizationUserConfirm( diff --git a/apps/web/src/app/admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service.spec.ts b/apps/web/src/app/admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service.spec.ts index b94cb4e926..3b903701d6 100644 --- a/apps/web/src/app/admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service.spec.ts +++ b/apps/web/src/app/admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service.spec.ts @@ -71,7 +71,7 @@ describe("OrganizationUserResetPasswordService", () => { const mockUserKey = new SymmetricCryptoKey(mockRandomBytes) as UserKey; cryptoService.getUserKey.mockResolvedValue(mockUserKey); - cryptoService.rsaEncrypt.mockResolvedValue( + encryptService.rsaEncrypt.mockResolvedValue( new EncString(EncryptionType.Rsa2048_OaepSha1_B64, "mockEncryptedUserKey"), ); }); @@ -103,7 +103,7 @@ describe("OrganizationUserResetPasswordService", () => { it("should rsa encrypt the user key", async () => { await sut.buildRecoveryKey(mockOrgId); - expect(cryptoService.rsaEncrypt).toHaveBeenCalledWith(expect.anything(), expect.anything()); + expect(encryptService.rsaEncrypt).toHaveBeenCalledWith(expect.anything(), expect.anything()); }); }); @@ -128,7 +128,7 @@ describe("OrganizationUserResetPasswordService", () => { cryptoService.getOrgKey.mockResolvedValue(mockOrgKey); encryptService.decryptToBytes.mockResolvedValue(mockRandomBytes); - cryptoService.rsaDecrypt.mockResolvedValue(mockRandomBytes); + encryptService.rsaDecrypt.mockResolvedValue(mockRandomBytes); const mockMasterKey = new SymmetricCryptoKey(mockRandomBytes) as MasterKey; cryptoService.makeMasterKey.mockResolvedValue(mockMasterKey); cryptoService.hashMasterKey.mockResolvedValue("test-master-key-hash"); @@ -172,7 +172,7 @@ describe("OrganizationUserResetPasswordService", () => { publicKey: "test-public-key", }), ); - cryptoService.rsaEncrypt.mockResolvedValue( + encryptService.rsaEncrypt.mockResolvedValue( new EncString(EncryptionType.Rsa2048_OaepSha1_B64, "mockEncryptedUserKey"), ); }); diff --git a/apps/web/src/app/admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service.ts b/apps/web/src/app/admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service.ts index b3107f2b93..6d5d7508b6 100644 --- a/apps/web/src/app/admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service.ts +++ b/apps/web/src/app/admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service.ts @@ -57,7 +57,7 @@ export class OrganizationUserResetPasswordService if (userKey == null) { throw new Error("No user key found"); } - const encryptedKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey); + const encryptedKey = await this.encryptService.rsaEncrypt(userKey.key, publicKey); return encryptedKey.encryptedString; } @@ -96,7 +96,10 @@ export class OrganizationUserResetPasswordService ); // Decrypt User's Reset Password Key to get UserKey - const decValue = await this.cryptoService.rsaDecrypt(response.resetPasswordKey, decPrivateKey); + const decValue = await this.encryptService.rsaDecrypt( + new EncString(response.resetPasswordKey), + decPrivateKey, + ); const existingUserKey = new SymmetricCryptoKey(decValue) as UserKey; // determine Kdf Algorithm diff --git a/apps/web/src/app/auth/core/services/rotateable-key-set.service.spec.ts b/apps/web/src/app/auth/core/services/rotateable-key-set.service.spec.ts index 7d9bed97fe..7ba586e957 100644 --- a/apps/web/src/app/auth/core/services/rotateable-key-set.service.spec.ts +++ b/apps/web/src/app/auth/core/services/rotateable-key-set.service.spec.ts @@ -35,7 +35,7 @@ describe("RotateableKeySetService", () => { const encryptedPrivateKey = Symbol(); cryptoService.makeKeyPair.mockResolvedValue(["publicKey", encryptedPrivateKey as any]); cryptoService.getUserKey.mockResolvedValue({ key: userKey.key } as any); - cryptoService.rsaEncrypt.mockResolvedValue(encryptedUserKey as any); + encryptService.rsaEncrypt.mockResolvedValue(encryptedUserKey as any); encryptService.encrypt.mockResolvedValue(encryptedPublicKey as any); const result = await service.createKeySet(externalKey as any); diff --git a/apps/web/src/app/auth/core/services/rotateable-key-set.service.ts b/apps/web/src/app/auth/core/services/rotateable-key-set.service.ts index 72f9744056..2c1df24b75 100644 --- a/apps/web/src/app/auth/core/services/rotateable-key-set.service.ts +++ b/apps/web/src/app/auth/core/services/rotateable-key-set.service.ts @@ -25,7 +25,7 @@ export class RotateableKeySetService { const userKey = await this.cryptoService.getUserKey(); const rawPublicKey = Utils.fromB64ToArray(publicKey); - const encryptedUserKey = await this.cryptoService.rsaEncrypt(userKey.key, rawPublicKey); + const encryptedUserKey = await this.encryptService.rsaEncrypt(userKey.key, rawPublicKey); const encryptedPublicKey = await this.encryptService.encrypt(rawPublicKey, userKey); return new RotateableKeySet(encryptedUserKey, encryptedPublicKey, encryptedPrivateKey); } diff --git a/apps/web/src/app/auth/emergency-access/services/emergency-access.service.spec.ts b/apps/web/src/app/auth/emergency-access/services/emergency-access.service.spec.ts index 6f68821943..1ea91c68d0 100644 --- a/apps/web/src/app/auth/emergency-access/services/emergency-access.service.spec.ts +++ b/apps/web/src/app/auth/emergency-access/services/emergency-access.service.spec.ts @@ -132,7 +132,7 @@ describe("EmergencyAccessService", () => { cryptoService.getUserKey.mockResolvedValueOnce(mockUserKey); apiService.getUserPublicKey.mockResolvedValueOnce(mockUserPublicKeyResponse); - cryptoService.rsaEncrypt.mockResolvedValueOnce(mockUserPublicKeyEncryptedUserKey); + encryptService.rsaEncrypt.mockResolvedValueOnce(mockUserPublicKeyEncryptedUserKey); emergencyAccessApiService.postEmergencyAccessConfirm.mockResolvedValueOnce(); @@ -162,7 +162,7 @@ describe("EmergencyAccessService", () => { const mockDecryptedGrantorUserKey = new Uint8Array(64); cryptoService.getPrivateKey.mockResolvedValue(new Uint8Array(64)); - cryptoService.rsaDecrypt.mockResolvedValueOnce(mockDecryptedGrantorUserKey); + encryptService.rsaDecrypt.mockResolvedValueOnce(mockDecryptedGrantorUserKey); const mockMasterKey = new SymmetricCryptoKey(new Uint8Array(64) as CsprngArray) as MasterKey; @@ -200,7 +200,7 @@ describe("EmergencyAccessService", () => { }); it("should not post a new password if decryption fails", async () => { - cryptoService.rsaDecrypt.mockResolvedValueOnce(null); + encryptService.rsaDecrypt.mockResolvedValueOnce(null); emergencyAccessApiService.postEmergencyAccessTakeover.mockResolvedValueOnce({ keyEncrypted: "EncryptedKey", kdf: KdfType.PBKDF2_SHA256, @@ -259,7 +259,7 @@ describe("EmergencyAccessService", () => { publicKey: "mockPublicKey", } as UserKeyResponse); - cryptoService.rsaEncrypt.mockImplementation((plainValue, publicKey) => { + encryptService.rsaEncrypt.mockImplementation((plainValue, publicKey) => { return Promise.resolve( new EncString(EncryptionType.Rsa2048_OaepSha1_B64, "Encrypted: " + plainValue), ); diff --git a/apps/web/src/app/auth/emergency-access/services/emergency-access.service.ts b/apps/web/src/app/auth/emergency-access/services/emergency-access.service.ts index 5b9d73c75e..83a2808d4e 100644 --- a/apps/web/src/app/auth/emergency-access/services/emergency-access.service.ts +++ b/apps/web/src/app/auth/emergency-access/services/emergency-access.service.ts @@ -17,7 +17,7 @@ import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt. import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { KdfType } from "@bitwarden/common/platform/enums"; import { Utils } from "@bitwarden/common/platform/misc/utils"; -import { EncryptedString } from "@bitwarden/common/platform/models/domain/enc-string"; +import { EncryptedString, EncString } from "@bitwarden/common/platform/models/domain/enc-string"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { UserId } from "@bitwarden/common/types/guid"; import { UserKey } from "@bitwarden/common/types/key"; @@ -224,8 +224,8 @@ export class EmergencyAccessService throw new Error("Active user does not have a private key, cannot get view only ciphers."); } - const grantorKeyBuffer = await this.cryptoService.rsaDecrypt( - response.keyEncrypted, + const grantorKeyBuffer = await this.encryptService.rsaDecrypt( + new EncString(response.keyEncrypted), activeUserPrivateKey, ); const grantorUserKey = new SymmetricCryptoKey(grantorKeyBuffer) as UserKey; @@ -261,8 +261,8 @@ export class EmergencyAccessService throw new Error("Active user does not have a private key, cannot complete a takeover."); } - const grantorKeyBuffer = await this.cryptoService.rsaDecrypt( - takeoverResponse.keyEncrypted, + const grantorKeyBuffer = await this.encryptService.rsaDecrypt( + new EncString(takeoverResponse.keyEncrypted), activeUserPrivateKey, ); if (grantorKeyBuffer == null) { @@ -355,6 +355,6 @@ export class EmergencyAccessService } private async encryptKey(userKey: UserKey, publicKey: Uint8Array): Promise { - return (await this.cryptoService.rsaEncrypt(userKey.key, publicKey)).encryptedString; + return (await this.encryptService.rsaEncrypt(userKey.key, publicKey)).encryptedString; } } diff --git a/apps/web/src/app/auth/organization-invite/accept-organization.service.ts b/apps/web/src/app/auth/organization-invite/accept-organization.service.ts index a7798d480f..f014372a7b 100644 --- a/apps/web/src/app/auth/organization-invite/accept-organization.service.ts +++ b/apps/web/src/app/auth/organization-invite/accept-organization.service.ts @@ -184,7 +184,7 @@ export class AcceptOrganizationInviteService { // RSA Encrypt user's encKey.key with organization public key const userKey = await this.cryptoService.getUserKey(); - const encryptedKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey); + const encryptedKey = await this.encryptService.rsaEncrypt(userKey.key, publicKey); // Add reset password key to accept request request.resetPasswordKey = encryptedKey.encryptedString; diff --git a/apps/web/src/app/core/core.module.ts b/apps/web/src/app/core/core.module.ts index c7d68856ea..419794fe3b 100644 --- a/apps/web/src/app/core/core.module.ts +++ b/apps/web/src/app/core/core.module.ts @@ -35,6 +35,7 @@ import { ClientType } from "@bitwarden/common/enums"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { CryptoService as CryptoServiceAbstraction } 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 { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service"; import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service"; @@ -202,6 +203,7 @@ const safeProviders: SafeProvider[] = [ deps: [ ApiService, CryptoServiceAbstraction, + EncryptService, I18nServiceAbstraction, KdfConfigService, InternalMasterPasswordServiceAbstraction, 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 3ee89cbda5..0eda8aa765 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 @@ -124,8 +124,8 @@ describe("OrganizationAuthRequestService", () => { ); const encryptedUserKey = new EncString("encryptedUserKey"); - cryptoService.rsaDecrypt.mockResolvedValue(new Uint8Array(32)); - cryptoService.rsaEncrypt.mockResolvedValue(encryptedUserKey); + encryptService.rsaDecrypt.mockResolvedValue(new Uint8Array(32)); + encryptService.rsaEncrypt.mockResolvedValue(encryptedUserKey); const mockPendingAuthRequest = new PendingAuthRequestView(); mockPendingAuthRequest.id = "requestId1"; @@ -166,8 +166,8 @@ describe("OrganizationAuthRequestService", () => { ); const encryptedUserKey = new EncString("encryptedUserKey"); - cryptoService.rsaDecrypt.mockResolvedValue(new Uint8Array(32)); - cryptoService.rsaEncrypt.mockResolvedValue(encryptedUserKey); + encryptService.rsaDecrypt.mockResolvedValue(new Uint8Array(32)); + encryptService.rsaEncrypt.mockResolvedValue(encryptedUserKey); const mockPendingAuthRequest = new PendingAuthRequestView(); mockPendingAuthRequest.id = "requestId1"; 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 ad6e29c583..9c86b59dfb 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 @@ -117,10 +117,13 @@ export class OrganizationAuthRequestService { ); // Decrypt user key with decrypted org private key - const decValue = await this.cryptoService.rsaDecrypt(encryptedUserKey, decOrgPrivateKey); + const decValue = await this.encryptService.rsaDecrypt( + new EncString(encryptedUserKey), + decOrgPrivateKey, + ); const userKey = new SymmetricCryptoKey(decValue); // Re-encrypt user Key with the Device Public Key - return await this.cryptoService.rsaEncrypt(userKey.key, devicePubKey); + return await this.encryptService.rsaEncrypt(userKey.key, devicePubKey); } } diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/dialogs/bulk-confirm-dialog.component.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/dialogs/bulk-confirm-dialog.component.ts index 986cf4d30e..8a04cb6452 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/dialogs/bulk-confirm-dialog.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/dialogs/bulk-confirm-dialog.component.ts @@ -13,6 +13,7 @@ import { ProviderUserBulkPublicKeyResponse } from "@bitwarden/common/admin-conso import { ProviderUserBulkResponse } from "@bitwarden/common/admin-console/models/response/provider/provider-user-bulk.response"; 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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { DialogService } from "@bitwarden/components"; @@ -34,10 +35,11 @@ export class BulkConfirmDialogComponent extends BaseBulkConfirmComponent { constructor( private apiService: ApiService, protected cryptoService: CryptoService, + protected encryptService: EncryptService, @Inject(DIALOG_DATA) protected dialogParams: BulkConfirmDialogParams, protected i18nService: I18nService, ) { - super(cryptoService, i18nService); + super(cryptoService, encryptService, i18nService); this.providerId = dialogParams.providerId; this.users = dialogParams.users; diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/members.component.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/members.component.ts index f78bccd354..38c2dade20 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/members.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/members.component.ts @@ -15,6 +15,7 @@ import { ProviderUserConfirmRequest } from "@bitwarden/common/admin-console/mode import { ProviderUserUserDetailsResponse } from "@bitwarden/common/admin-console/models/response/provider/provider-user.response"; 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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service"; @@ -66,6 +67,7 @@ export class MembersComponent extends BaseMembersComponent { toastService: ToastService, userNamePipe: UserNamePipe, validationService: ValidationService, + private encryptService: EncryptService, private activatedRoute: ActivatedRoute, private providerService: ProviderService, private router: Router, @@ -184,7 +186,7 @@ export class MembersComponent extends BaseMembersComponent { async confirmUser(user: ProviderUser, publicKey: Uint8Array): Promise { const providerKey = await this.cryptoService.getProviderKey(this.providerId); - const key = await this.cryptoService.rsaEncrypt(providerKey.key, publicKey); + const key = await this.encryptService.rsaEncrypt(providerKey.key, publicKey); const request = new ProviderUserConfirmRequest(); request.key = key.encryptedString; await this.apiService.postProviderUserConfirm(this.providerId, user.id, request); diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/people.component.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/people.component.ts index 49961e0c7f..9293f8c6eb 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/people.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/people.component.ts @@ -17,6 +17,7 @@ import { ProviderUserUserDetailsResponse } from "@bitwarden/common/admin-console import { ListResponse } from "@bitwarden/common/models/response/list.response"; 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"; @@ -65,6 +66,7 @@ export class PeopleComponent modalService: ModalService, platformUtilsService: PlatformUtilsService, cryptoService: CryptoService, + private encryptService: EncryptService, private router: Router, searchService: SearchService, validationService: ValidationService, @@ -150,7 +152,7 @@ export class PeopleComponent async confirmUser(user: ProviderUserUserDetailsResponse, publicKey: Uint8Array): Promise { const providerKey = await this.cryptoService.getProviderKey(this.providerId); - const key = await this.cryptoService.rsaEncrypt(providerKey.key, publicKey); + const key = await this.encryptService.rsaEncrypt(providerKey.key, publicKey); const request = new ProviderUserConfirmRequest(); request.key = key.encryptedString; await this.apiService.postProviderUserConfirm(this.providerId, user.id, request); diff --git a/libs/angular/src/auth/components/set-password.component.ts b/libs/angular/src/auth/components/set-password.component.ts index ea4c2fb926..d1a21e4abb 100644 --- a/libs/angular/src/auth/components/set-password.component.ts +++ b/libs/angular/src/auth/components/set-password.component.ts @@ -215,7 +215,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent implements // RSA Encrypt user key with organization public key const userKey = await this.cryptoService.getUserKey(); - const encryptedUserKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey); + const encryptedUserKey = await this.encryptService.rsaEncrypt(userKey.key, publicKey); const resetRequest = new OrganizationUserResetPasswordEnrollmentRequest(); resetRequest.masterPasswordHash = masterPasswordHash; diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index 0cc6e74d5b..512f0730f8 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -961,6 +961,7 @@ const safeProviders: SafeProvider[] = [ OrganizationApiServiceAbstraction, AccountServiceAbstraction, CryptoServiceAbstraction, + EncryptService, OrganizationUserApiService, I18nServiceAbstraction, ], @@ -1090,6 +1091,7 @@ const safeProviders: SafeProvider[] = [ AccountServiceAbstraction, InternalMasterPasswordServiceAbstraction, CryptoServiceAbstraction, + EncryptService, ApiServiceAbstraction, StateProvider, ], @@ -1285,6 +1287,7 @@ const safeProviders: SafeProvider[] = [ deps: [ ApiServiceAbstraction, CryptoServiceAbstraction, + EncryptService, I18nServiceAbstraction, KdfConfigServiceAbstraction, InternalMasterPasswordServiceAbstraction, diff --git a/libs/auth/src/angular/set-password-jit/default-set-password-jit.service.spec.ts b/libs/auth/src/angular/set-password-jit/default-set-password-jit.service.spec.ts index f47e217d0e..f36283e0c0 100644 --- a/libs/auth/src/angular/set-password-jit/default-set-password-jit.service.spec.ts +++ b/libs/auth/src/angular/set-password-jit/default-set-password-jit.service.spec.ts @@ -15,6 +15,7 @@ import { DEFAULT_KDF_CONFIG } from "@bitwarden/common/auth/models/domain/kdf-con import { SetPasswordRequest } from "@bitwarden/common/auth/models/request/set-password.request"; import { KeysRequest } from "@bitwarden/common/models/request/keys.request"; 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 { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; @@ -33,6 +34,7 @@ describe("DefaultSetPasswordJitService", () => { let apiService: MockProxy; let cryptoService: MockProxy; + let encryptService: MockProxy; let i18nService: MockProxy; let kdfConfigService: MockProxy; let masterPasswordService: MockProxy; @@ -43,6 +45,7 @@ describe("DefaultSetPasswordJitService", () => { beforeEach(() => { apiService = mock(); cryptoService = mock(); + encryptService = mock(); i18nService = mock(); kdfConfigService = mock(); masterPasswordService = mock(); @@ -53,6 +56,7 @@ describe("DefaultSetPasswordJitService", () => { sut = new DefaultSetPasswordJitService( apiService, cryptoService, + encryptService, i18nService, kdfConfigService, masterPasswordService, @@ -168,7 +172,7 @@ describe("DefaultSetPasswordJitService", () => { } cryptoService.userKey$.mockReturnValue(of(userKey)); - cryptoService.rsaEncrypt.mockResolvedValue(userKeyEncString); + encryptService.rsaEncrypt.mockResolvedValue(userKeyEncString); organizationUserApiService.putOrganizationUserResetPasswordEnrollment.mockResolvedValue( undefined, @@ -210,7 +214,7 @@ describe("DefaultSetPasswordJitService", () => { // Assert expect(apiService.setPassword).toHaveBeenCalledWith(setPasswordRequest); expect(organizationApiService.getKeys).toHaveBeenCalledWith(orgId); - expect(cryptoService.rsaEncrypt).toHaveBeenCalledWith(userKey.key, orgPublicKey); + expect(encryptService.rsaEncrypt).toHaveBeenCalledWith(userKey.key, orgPublicKey); expect( organizationUserApiService.putOrganizationUserResetPasswordEnrollment, ).toHaveBeenCalled(); diff --git a/libs/auth/src/angular/set-password-jit/default-set-password-jit.service.ts b/libs/auth/src/angular/set-password-jit/default-set-password-jit.service.ts index 968ba60dec..1993877966 100644 --- a/libs/auth/src/angular/set-password-jit/default-set-password-jit.service.ts +++ b/libs/auth/src/angular/set-password-jit/default-set-password-jit.service.ts @@ -14,6 +14,7 @@ import { PBKDF2KdfConfig } from "@bitwarden/common/auth/models/domain/kdf-config import { SetPasswordRequest } from "@bitwarden/common/auth/models/request/set-password.request"; import { KeysRequest } from "@bitwarden/common/models/request/keys.request"; 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 { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; @@ -29,6 +30,7 @@ export class DefaultSetPasswordJitService implements SetPasswordJitService { constructor( protected apiService: ApiService, protected cryptoService: CryptoService, + protected encryptService: EncryptService, protected i18nService: I18nService, protected kdfConfigService: KdfConfigService, protected masterPasswordService: InternalMasterPasswordServiceAbstraction, @@ -157,7 +159,7 @@ export class DefaultSetPasswordJitService implements SetPasswordJitService { throw new Error("userKey not found. Could not handle reset password auto enroll."); } - const encryptedUserKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey); + const encryptedUserKey = await this.encryptService.rsaEncrypt(userKey.key, publicKey); const resetRequest = new OrganizationUserResetPasswordEnrollmentRequest(); resetRequest.masterPasswordHash = masterKeyHash; 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 b25022d25d..e4b1f74031 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 @@ -226,7 +226,7 @@ describe("WebAuthnLoginStrategy", () => { const mockUserKey = new SymmetricCryptoKey(mockUserKeyArray) as UserKey; encryptService.decryptToBytes.mockResolvedValue(mockPrfPrivateKey); - cryptoService.rsaDecrypt.mockResolvedValue(mockUserKeyArray); + encryptService.rsaDecrypt.mockResolvedValue(mockUserKeyArray); // Act await webAuthnLoginStrategy.logIn(webAuthnCredentials); @@ -244,9 +244,9 @@ describe("WebAuthnLoginStrategy", () => { idTokenResponse.userDecryptionOptions.webAuthnPrfOption.encryptedPrivateKey, webAuthnCredentials.prfKey, ); - expect(cryptoService.rsaDecrypt).toHaveBeenCalledTimes(1); - expect(cryptoService.rsaDecrypt).toHaveBeenCalledWith( - idTokenResponse.userDecryptionOptions.webAuthnPrfOption.encryptedUserKey.encryptedString, + expect(encryptService.rsaDecrypt).toHaveBeenCalledTimes(1); + expect(encryptService.rsaDecrypt).toHaveBeenCalledWith( + idTokenResponse.userDecryptionOptions.webAuthnPrfOption.encryptedUserKey, mockPrfPrivateKey, ); expect(cryptoService.setUserKey).toHaveBeenCalledWith(mockUserKey, userId); @@ -273,7 +273,7 @@ describe("WebAuthnLoginStrategy", () => { // Assert expect(encryptService.decryptToBytes).not.toHaveBeenCalled(); - expect(cryptoService.rsaDecrypt).not.toHaveBeenCalled(); + expect(encryptService.rsaDecrypt).not.toHaveBeenCalled(); expect(cryptoService.setUserKey).not.toHaveBeenCalled(); }); @@ -325,7 +325,7 @@ describe("WebAuthnLoginStrategy", () => { apiService.postIdentityToken.mockResolvedValue(idTokenResponse); - cryptoService.rsaDecrypt.mockResolvedValue(null); + encryptService.rsaDecrypt.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 96f8bc7d63..c5451d13df 100644 --- a/libs/auth/src/common/login-strategies/webauthn-login.strategy.ts +++ b/libs/auth/src/common/login-strategies/webauthn-login.strategy.ts @@ -4,6 +4,7 @@ import { Jsonify } from "type-fest"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result"; import { WebAuthnLoginTokenRequest } from "@bitwarden/common/auth/models/request/identity-token/webauthn-login-token.request"; import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response"; +import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { UserId } from "@bitwarden/common/types/guid"; import { UserKey } from "@bitwarden/common/types/key"; @@ -86,8 +87,8 @@ export class WebAuthnLoginStrategy extends LoginStrategy { ); // decrypt user key with private key - const userKey = await this.cryptoService.rsaDecrypt( - webAuthnPrfOption.encryptedUserKey.encryptedString, + const userKey = await this.encryptService.rsaDecrypt( + new EncString(webAuthnPrfOption.encryptedUserKey.encryptedString), privateKey, ); diff --git a/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts b/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts index 14f807a770..58dbae6d78 100644 --- a/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts +++ b/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts @@ -6,6 +6,7 @@ import { FakeMasterPasswordService } from "@bitwarden/common/auth/services/maste import { AuthRequestPushNotification } from "@bitwarden/common/models/response/notification.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 { 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"; @@ -24,6 +25,7 @@ describe("AuthRequestService", () => { let masterPasswordService: FakeMasterPasswordService; const appIdService = mock(); const cryptoService = mock(); + const encryptService = mock(); const apiService = mock(); let mockPrivateKey: Uint8Array; @@ -40,6 +42,7 @@ describe("AuthRequestService", () => { accountService, masterPasswordService, cryptoService, + encryptService, apiService, stateProvider, ); @@ -82,7 +85,7 @@ describe("AuthRequestService", () => { describe("approveOrDenyAuthRequest", () => { beforeEach(() => { - cryptoService.rsaEncrypt.mockResolvedValue({ + encryptService.rsaEncrypt.mockResolvedValue({ encryptedString: "ENCRYPTED_STRING", } as EncString); appIdService.getAppId.mockResolvedValue("APP_ID"); @@ -108,7 +111,7 @@ describe("AuthRequestService", () => { new AuthRequestResponse({ id: "123", publicKey: "KEY" }), ); - expect(cryptoService.rsaEncrypt).toHaveBeenCalledWith(new Uint8Array(64), expect.anything()); + expect(encryptService.rsaEncrypt).toHaveBeenCalledWith(new Uint8Array(64), expect.anything()); }); it("should use the user key if the master key and hash do not exist", async () => { @@ -119,7 +122,7 @@ describe("AuthRequestService", () => { new AuthRequestResponse({ id: "123", publicKey: "KEY" }), ); - expect(cryptoService.rsaEncrypt).toHaveBeenCalledWith(new Uint8Array(64), expect.anything()); + expect(encryptService.rsaEncrypt).toHaveBeenCalledWith(new Uint8Array(64), expect.anything()); }); }); describe("setUserKeyAfterDecryptingSharedUserKey", () => { @@ -211,7 +214,7 @@ describe("AuthRequestService", () => { const mockDecryptedUserKeyBytes = new Uint8Array(64); const mockDecryptedUserKey = new SymmetricCryptoKey(mockDecryptedUserKeyBytes) as UserKey; - cryptoService.rsaDecrypt.mockResolvedValueOnce(mockDecryptedUserKeyBytes); + encryptService.rsaDecrypt.mockResolvedValueOnce(mockDecryptedUserKeyBytes); // Act const result = await sut.decryptPubKeyEncryptedUserKey( @@ -220,7 +223,10 @@ describe("AuthRequestService", () => { ); // Assert - expect(cryptoService.rsaDecrypt).toBeCalledWith(mockPubKeyEncryptedUserKey, mockPrivateKey); + expect(encryptService.rsaDecrypt).toBeCalledWith( + new EncString(mockPubKeyEncryptedUserKey), + mockPrivateKey, + ); expect(result).toEqual(mockDecryptedUserKey); }); }); @@ -238,7 +244,7 @@ describe("AuthRequestService", () => { const mockDecryptedMasterKeyHashBytes = new Uint8Array(64); const mockDecryptedMasterKeyHash = Utils.fromBufferToUtf8(mockDecryptedMasterKeyHashBytes); - cryptoService.rsaDecrypt + encryptService.rsaDecrypt .mockResolvedValueOnce(mockDecryptedMasterKeyBytes) .mockResolvedValueOnce(mockDecryptedMasterKeyHashBytes); @@ -250,14 +256,14 @@ describe("AuthRequestService", () => { ); // Assert - expect(cryptoService.rsaDecrypt).toHaveBeenNthCalledWith( + expect(encryptService.rsaDecrypt).toHaveBeenNthCalledWith( 1, - mockPubKeyEncryptedMasterKey, + new EncString(mockPubKeyEncryptedMasterKey), mockPrivateKey, ); - expect(cryptoService.rsaDecrypt).toHaveBeenNthCalledWith( + expect(encryptService.rsaDecrypt).toHaveBeenNthCalledWith( 2, - mockPubKeyEncryptedMasterKeyHash, + new EncString(mockPubKeyEncryptedMasterKeyHash), mockPrivateKey, ); expect(result.masterKey).toEqual(mockDecryptedMasterKey); diff --git a/libs/auth/src/common/services/auth-request/auth-request.service.ts b/libs/auth/src/common/services/auth-request/auth-request.service.ts index eefee511f8..51926d6598 100644 --- a/libs/auth/src/common/services/auth-request/auth-request.service.ts +++ b/libs/auth/src/common/services/auth-request/auth-request.service.ts @@ -10,7 +10,9 @@ import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth import { AuthRequestPushNotification } from "@bitwarden/common/models/response/notification.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 { 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"; import { AUTH_REQUEST_DISK_LOCAL, @@ -44,6 +46,7 @@ export class AuthRequestService implements AuthRequestServiceAbstraction { private accountService: AccountService, private masterPasswordService: InternalMasterPasswordServiceAbstraction, private cryptoService: CryptoService, + private encryptService: EncryptService, private apiService: ApiService, private stateProvider: StateProvider, ) { @@ -102,7 +105,7 @@ export class AuthRequestService implements AuthRequestServiceAbstraction { if (masterKey && masterKeyHash) { // Only encrypt the master password hash if masterKey exists as // we won't have a masterKeyHash without a masterKey - encryptedMasterKeyHash = await this.cryptoService.rsaEncrypt( + encryptedMasterKeyHash = await this.encryptService.rsaEncrypt( Utils.fromUtf8ToArray(masterKeyHash), pubKey, ); @@ -112,7 +115,7 @@ export class AuthRequestService implements AuthRequestServiceAbstraction { keyToEncrypt = userKey.key; } - const encryptedKey = await this.cryptoService.rsaEncrypt(keyToEncrypt, pubKey); + const encryptedKey = await this.encryptService.rsaEncrypt(keyToEncrypt, pubKey); const response = new PasswordlessAuthRequest( encryptedKey.encryptedString, @@ -161,8 +164,8 @@ export class AuthRequestService implements AuthRequestServiceAbstraction { pubKeyEncryptedUserKey: string, privateKey: Uint8Array, ): Promise { - const decryptedUserKeyBytes = await this.cryptoService.rsaDecrypt( - pubKeyEncryptedUserKey, + const decryptedUserKeyBytes = await this.encryptService.rsaDecrypt( + new EncString(pubKeyEncryptedUserKey), privateKey, ); @@ -174,13 +177,13 @@ export class AuthRequestService implements AuthRequestServiceAbstraction { pubKeyEncryptedMasterKeyHash: string, privateKey: Uint8Array, ): Promise<{ masterKey: MasterKey; masterKeyHash: string }> { - const decryptedMasterKeyArrayBuffer = await this.cryptoService.rsaDecrypt( - pubKeyEncryptedMasterKey, + const decryptedMasterKeyArrayBuffer = await this.encryptService.rsaDecrypt( + new EncString(pubKeyEncryptedMasterKey), privateKey, ); - const decryptedMasterKeyHashArrayBuffer = await this.cryptoService.rsaDecrypt( - pubKeyEncryptedMasterKeyHash, + const decryptedMasterKeyHashArrayBuffer = await this.encryptService.rsaDecrypt( + new EncString(pubKeyEncryptedMasterKeyHash), privateKey, ); diff --git a/libs/common/src/auth/services/device-trust.service.implementation.ts b/libs/common/src/auth/services/device-trust.service.implementation.ts index c1cf871e25..178f4b0654 100644 --- a/libs/common/src/auth/services/device-trust.service.implementation.ts +++ b/libs/common/src/auth/services/device-trust.service.implementation.ts @@ -144,7 +144,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction { deviceKeyEncryptedDevicePrivateKey, ] = await Promise.all([ // Encrypt user key with the DevicePublicKey - this.cryptoService.rsaEncrypt(userKey.key, devicePublicKey), + this.encryptService.rsaEncrypt(userKey.key, devicePublicKey), // Encrypt devicePublicKey with user key this.encryptService.encrypt(devicePublicKey, userKey), @@ -206,7 +206,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction { ); // Encrypt the brand new user key with the now-decrypted public key for the device - const encryptedNewUserKey = await this.cryptoService.rsaEncrypt( + const encryptedNewUserKey = await this.encryptService.rsaEncrypt( newUserKey.key, decryptedDevicePublicKey, ); @@ -317,8 +317,8 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction { ); // Attempt to decrypt encryptedUserDataKey with devicePrivateKey - const userKey = await this.cryptoService.rsaDecrypt( - encryptedUserKey.encryptedString, + const userKey = await this.encryptService.rsaDecrypt( + new EncString(encryptedUserKey.encryptedString), devicePrivateKey, ); diff --git a/libs/common/src/auth/services/device-trust.service.spec.ts b/libs/common/src/auth/services/device-trust.service.spec.ts index 7afd38ec0a..1171ae2918 100644 --- a/libs/common/src/auth/services/device-trust.service.spec.ts +++ b/libs/common/src/auth/services/device-trust.service.spec.ts @@ -372,7 +372,7 @@ describe("deviceTrustService", () => { .mockResolvedValue(mockUserKey); cryptoSvcRsaEncryptSpy = jest - .spyOn(cryptoService, "rsaEncrypt") + .spyOn(encryptService, "rsaEncrypt") .mockResolvedValue(mockDevicePublicKeyEncryptedUserKey); encryptServiceEncryptSpy = jest @@ -577,7 +577,7 @@ describe("deviceTrustService", () => { .spyOn(encryptService, "decryptToBytes") .mockResolvedValue(new Uint8Array(userKeyBytesLength)); const rsaDecryptSpy = jest - .spyOn(cryptoService, "rsaDecrypt") + .spyOn(encryptService, "rsaDecrypt") .mockResolvedValue(new Uint8Array(userKeyBytesLength)); const result = await deviceTrustService.decryptUserKeyWithDeviceKey( @@ -696,7 +696,7 @@ describe("deviceTrustService", () => { }); // Mock the encryption of the new user key with the decrypted public key - cryptoService.rsaEncrypt.mockImplementationOnce((data, publicKey) => { + encryptService.rsaEncrypt.mockImplementationOnce((data, publicKey) => { expect(data.byteLength).toBe(64); // New key should also be 64 bytes expect(new Uint8Array(data)[0]).toBe(FakeNewUserKeyMarker); // New key should have the first byte be '1'; diff --git a/libs/common/src/auth/services/password-reset-enrollment.service.implementation.spec.ts b/libs/common/src/auth/services/password-reset-enrollment.service.implementation.spec.ts index 575b3a6ee7..b78ef52f07 100644 --- a/libs/common/src/auth/services/password-reset-enrollment.service.implementation.spec.ts +++ b/libs/common/src/auth/services/password-reset-enrollment.service.implementation.spec.ts @@ -2,6 +2,7 @@ import { mock, MockProxy } from "jest-mock-extended"; import { BehaviorSubject } from "rxjs"; import { OrganizationUserApiService } from "@bitwarden/admin-console/common"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { UserId } from "../../../../common/src/types/guid"; import { OrganizationApiServiceAbstraction } from "../../admin-console/abstractions/organization/organization-api.service.abstraction"; @@ -18,6 +19,7 @@ describe("PasswordResetEnrollmentServiceImplementation", () => { let organizationApiService: MockProxy; let accountService: MockProxy; let cryptoService: MockProxy; + let encryptService: MockProxy; let organizationUserApiService: MockProxy; let i18nService: MockProxy; let service: PasswordResetEnrollmentServiceImplementation; @@ -27,12 +29,14 @@ describe("PasswordResetEnrollmentServiceImplementation", () => { accountService = mock(); accountService.activeAccount$ = activeAccountSubject; cryptoService = mock(); + encryptService = mock(); organizationUserApiService = mock(); i18nService = mock(); service = new PasswordResetEnrollmentServiceImplementation( organizationApiService, accountService, cryptoService, + encryptService, organizationUserApiService, i18nService, ); @@ -96,7 +100,7 @@ describe("PasswordResetEnrollmentServiceImplementation", () => { activeAccountSubject.next(Object.assign(user1AccountInfo, { id: "userId" as UserId })); cryptoService.getUserKey.mockResolvedValue({ key: "key" } as any); - cryptoService.rsaEncrypt.mockResolvedValue(encryptedKey as any); + encryptService.rsaEncrypt.mockResolvedValue(encryptedKey as any); await service.enroll("orgId"); @@ -118,7 +122,7 @@ describe("PasswordResetEnrollmentServiceImplementation", () => { }; const encryptedKey = { encryptedString: "encryptedString" }; organizationApiService.getKeys.mockResolvedValue(orgKeyResponse as any); - cryptoService.rsaEncrypt.mockResolvedValue(encryptedKey as any); + encryptService.rsaEncrypt.mockResolvedValue(encryptedKey as any); await service.enroll("orgId", "userId", { key: "key" } as any); diff --git a/libs/common/src/auth/services/password-reset-enrollment.service.implementation.ts b/libs/common/src/auth/services/password-reset-enrollment.service.implementation.ts index 65718d9669..7dc5f44995 100644 --- a/libs/common/src/auth/services/password-reset-enrollment.service.implementation.ts +++ b/libs/common/src/auth/services/password-reset-enrollment.service.implementation.ts @@ -4,6 +4,7 @@ import { OrganizationUserApiService, OrganizationUserResetPasswordEnrollmentRequest, } from "@bitwarden/admin-console/common"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { OrganizationApiServiceAbstraction } from "../../admin-console/abstractions/organization/organization-api.service.abstraction"; import { CryptoService } from "../../platform/abstractions/crypto.service"; @@ -20,6 +21,7 @@ export class PasswordResetEnrollmentServiceImplementation protected organizationApiService: OrganizationApiServiceAbstraction, protected accountService: AccountService, protected cryptoService: CryptoService, + protected encryptService: EncryptService, protected organizationUserApiService: OrganizationUserApiService, protected i18nService: I18nService, ) {} @@ -47,7 +49,7 @@ export class PasswordResetEnrollmentServiceImplementation userId ?? (await firstValueFrom(this.accountService.activeAccount$.pipe(map((a) => a?.id)))); userKey = userKey ?? (await this.cryptoService.getUserKey(userId)); // RSA Encrypt user's userKey.key with organization public key - const encryptedKey = await this.cryptoService.rsaEncrypt(userKey.key, orgPublicKey); + const encryptedKey = await this.encryptService.rsaEncrypt(userKey.key, orgPublicKey); const resetRequest = new OrganizationUserResetPasswordEnrollmentRequest(); resetRequest.resetPasswordKey = encryptedKey.encryptedString; diff --git a/libs/common/src/platform/abstractions/crypto.service.ts b/libs/common/src/platform/abstractions/crypto.service.ts index 2a8e1ad647..020cfb8175 100644 --- a/libs/common/src/platform/abstractions/crypto.service.ts +++ b/libs/common/src/platform/abstractions/crypto.service.ts @@ -329,22 +329,6 @@ export abstract class CryptoService { * @param userId The user's Id */ abstract clearKeys(userId?: string): Promise; - /** - * RSA encrypts a value. - * @param data The data to encrypt - * @param publicKey The public key to use for encryption, if not provided, the user's public key will be used - * @returns The encrypted data - * @throws If the given publicKey is a null-ish value. - */ - abstract rsaEncrypt(data: Uint8Array, publicKey: Uint8Array): Promise; - /** - * Decrypts a value using RSA. - * @param encValue The encrypted value to decrypt - * @param privateKey The private key to use for decryption - * @returns The decrypted value - * @throws If the given privateKey is a null-ish value. - */ - abstract rsaDecrypt(encValue: string, privateKey: Uint8Array): Promise; abstract randomNumber(min: number, max: number): Promise; /** * Generates a new cipher key diff --git a/libs/common/src/platform/services/crypto.service.ts b/libs/common/src/platform/services/crypto.service.ts index 6a93ac7f3f..6b2afdb980 100644 --- a/libs/common/src/platform/services/crypto.service.ts +++ b/libs/common/src/platform/services/crypto.service.ts @@ -45,7 +45,7 @@ import { KeyGenerationService } from "../abstractions/key-generation.service"; import { LogService } from "../abstractions/log.service"; import { PlatformUtilsService } from "../abstractions/platform-utils.service"; import { StateService } from "../abstractions/state.service"; -import { KeySuffixOptions, HashPurpose, EncryptionType } from "../enums"; +import { KeySuffixOptions, HashPurpose } from "../enums"; import { convertValues } from "../misc/convert-values"; import { EFFLongWordList } from "../misc/wordlist"; import { EncString, EncryptedString } from "../models/domain/enc-string"; @@ -441,7 +441,7 @@ export class CryptoService implements CryptoServiceAbstraction { const shareKey = await this.keyGenerationService.createKey(512); userId ??= await firstValueFrom(this.stateProvider.activeUserId$); const publicKey = await firstValueFrom(this.userPublicKey$(userId)); - const encShareKey = await this.rsaEncrypt(shareKey.key, publicKey); + const encShareKey = await this.encryptService.rsaEncrypt(shareKey.key, publicKey); return [encShareKey, shareKey as T]; } @@ -550,68 +550,6 @@ export class CryptoService implements CryptoServiceAbstraction { await this.stateProvider.setUserState(USER_EVER_HAD_USER_KEY, null, userId); } - async rsaEncrypt(data: Uint8Array, publicKey: Uint8Array): Promise { - if (publicKey == null) { - throw new Error("'publicKey' is a required parameter and must be non-null"); - } - - const encBytes = await this.cryptoFunctionService.rsaEncrypt(data, publicKey, "sha1"); - return new EncString(EncryptionType.Rsa2048_OaepSha1_B64, Utils.fromBufferToB64(encBytes)); - } - - async rsaDecrypt(encValue: string, privateKey: Uint8Array): Promise { - if (privateKey == null) { - throw new Error("'privateKey' is a required parameter and must be non-null"); - } - - const headerPieces = encValue.split("."); - let encType: EncryptionType = null; - let encPieces: string[]; - - if (headerPieces.length === 1) { - encType = EncryptionType.Rsa2048_OaepSha256_B64; - encPieces = [headerPieces[0]]; - } else if (headerPieces.length === 2) { - try { - encType = parseInt(headerPieces[0], null); - encPieces = headerPieces[1].split("|"); - } catch (e) { - this.logService.error(e); - } - } - - switch (encType) { - case EncryptionType.Rsa2048_OaepSha256_B64: - case EncryptionType.Rsa2048_OaepSha1_B64: - case EncryptionType.Rsa2048_OaepSha256_HmacSha256_B64: // HmacSha256 types are deprecated - case EncryptionType.Rsa2048_OaepSha1_HmacSha256_B64: - break; - default: - throw new Error("encType unavailable."); - } - - if (encPieces == null || encPieces.length <= 0) { - throw new Error("encPieces unavailable."); - } - - const data = Utils.fromB64ToArray(encPieces[0]); - - let alg: "sha1" | "sha256" = "sha1"; - switch (encType) { - case EncryptionType.Rsa2048_OaepSha256_B64: - case EncryptionType.Rsa2048_OaepSha256_HmacSha256_B64: - alg = "sha256"; - break; - case EncryptionType.Rsa2048_OaepSha1_B64: - case EncryptionType.Rsa2048_OaepSha1_HmacSha256_B64: - break; - default: - throw new Error("encType unavailable."); - } - - return this.cryptoFunctionService.rsaDecrypt(data, privateKey, alg); - } - // EFForg/OpenWireless // ref https://github.com/EFForg/OpenWireless/blob/master/app/js/diceware.js async randomNumber(min: number, max: number): Promise {