From bd1d7d25ebec9692c95dc25a749a6177b6beba1a Mon Sep 17 00:00:00 2001 From: Matt Gibson Date: Tue, 1 Aug 2023 16:37:43 -0400 Subject: [PATCH] Change everything to Uint8Array related to https://github.com/jestjs/jest/issues/14379 --- .../background/nativeMessaging.background.ts | 8 +- ...cal-backed-session-storage.service.spec.ts | 4 +- .../admin-console/commands/confirm.command.ts | 2 +- apps/cli/src/commands/get.command.ts | 2 +- .../node-env-secure-storage.service.ts | 4 +- .../tools/send/commands/receive.command.ts | 4 +- .../auth/login/login-approval.component.ts | 2 +- .../services/electron-state.service.ts | 2 +- .../native-message-handler.service.ts | 2 +- .../src/services/native-messaging.service.ts | 4 +- .../manage/user-confirm.component.ts | 5 +- .../components/bulk/bulk-confirm.component.ts | 4 +- .../organizations/members/people.component.ts | 2 +- .../settings/account.component.ts | 4 +- .../enroll-master-password-reset.component.ts | 2 +- .../app/auth/accept-organization.component.ts | 2 +- .../emergency-access-confirm.component.ts | 2 +- .../emergency-access.component.ts | 4 +- .../src/app/common/base.people.component.ts | 2 +- .../app/settings/change-password.component.ts | 4 +- .../account-fingerprint.component.ts | 2 +- .../vault-items/vault-items.stories.ts | 2 +- .../device-approvals.component.ts | 2 +- .../providers/manage/people.component.ts | 2 +- .../components/login-with-device.component.ts | 2 +- .../src/components/set-password.component.ts | 5 +- .../src/platform/pipes/fingerprint.pipe.ts | 5 +- libs/common/spec/matchers/to-equal-buffer.ts | 7 +- libs/common/src/auth/services/auth.service.ts | 4 +- .../abstractions/crypto-function.service.ts | 70 ++++----- .../platform/abstractions/crypto.service.ts | 20 +-- .../platform/abstractions/encrypt.service.ts | 6 +- .../platform/abstractions/state.service.ts | 8 +- .../src/platform/interfaces/encrypted.ts | 6 +- .../models/domain/account-keys.spec.ts | 6 +- .../src/platform/models/domain/account.ts | 11 +- .../models/domain/enc-array-buffer.spec.ts | 8 +- .../models/domain/enc-array-buffer.ts | 24 ++-- .../src/platform/models/domain/enc-string.ts | 12 +- .../models/domain/encrypted-object.ts | 6 +- .../domain/symmetric-crypto-key.spec.ts | 4 +- .../models/domain/symmetric-crypto-key.ts | 10 +- .../src/platform/services/crypto.service.ts | 34 ++--- .../encrypt.service.implementation.ts | 22 ++- .../src/platform/services/state.service.ts | 8 +- .../web-crypto-function.service.spec.ts | 69 +++++---- .../services/web-crypto-function.service.ts | 106 ++++++++------ libs/common/src/services/totp.service.ts | 2 +- .../src/tools/send/models/view/send.view.ts | 2 +- .../src/tools/send/services/send.service.ts | 2 +- libs/common/src/types/csprng.d.ts | 2 +- .../src/vault/services/cipher.service.ts | 2 +- .../services/node-crypto-function.service.ts | 134 +++++++++--------- 53 files changed, 330 insertions(+), 340 deletions(-) diff --git a/apps/browser/src/background/nativeMessaging.background.ts b/apps/browser/src/background/nativeMessaging.background.ts index 90c114a8650..e482c7cc83e 100644 --- a/apps/browser/src/background/nativeMessaging.background.ts +++ b/apps/browser/src/background/nativeMessaging.background.ts @@ -59,8 +59,8 @@ export class NativeMessagingBackground { private port: browser.runtime.Port | chrome.runtime.Port; private resolver: any = null; - private privateKey: ArrayBuffer = null; - private publicKey: ArrayBuffer = null; + private privateKey: Uint8Array = null; + private publicKey: Uint8Array = null; private secureSetupResolve: any = null; private sharedSecret: SymmetricCryptoKey; private appId: string; @@ -129,7 +129,7 @@ export class NativeMessagingBackground { const encrypted = Utils.fromB64ToArray(message.sharedSecret); const decrypted = await this.cryptoFunctionService.rsaDecrypt( - encrypted.buffer, + encrypted, this.privateKey, EncryptionAlgorithm ); @@ -321,7 +321,7 @@ export class NativeMessagingBackground { if (message.response === "unlocked") { await this.cryptoService.setKey( - new SymmetricCryptoKey(Utils.fromB64ToArray(message.keyB64).buffer) + new SymmetricCryptoKey(Utils.fromB64ToArray(message.keyB64)) ); // Verify key is correct by attempting to decrypt a secret diff --git a/apps/browser/src/platform/services/local-backed-session-storage.service.spec.ts b/apps/browser/src/platform/services/local-backed-session-storage.service.spec.ts index d2da5f6fc1a..49465414721 100644 --- a/apps/browser/src/platform/services/local-backed-session-storage.service.spec.ts +++ b/apps/browser/src/platform/services/local-backed-session-storage.service.spec.ts @@ -21,9 +21,7 @@ describe("Browser Session Storage Service", () => { let localStorage: BrowserLocalStorageService; let sessionStorage: BrowserMemoryStorageService; - const key = new SymmetricCryptoKey( - Utils.fromUtf8ToArray("00000000000000000000000000000000").buffer - ); + const key = new SymmetricCryptoKey(Utils.fromUtf8ToArray("00000000000000000000000000000000")); let getSessionKeySpy: jest.SpyInstance; const mockEnc = (input: string) => Promise.resolve(new EncString("ENCRYPTED" + input)); diff --git a/apps/cli/src/admin-console/commands/confirm.command.ts b/apps/cli/src/admin-console/commands/confirm.command.ts index 912c8417753..be1264c399b 100644 --- a/apps/cli/src/admin-console/commands/confirm.command.ts +++ b/apps/cli/src/admin-console/commands/confirm.command.ts @@ -51,7 +51,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.buffer); + const key = await this.cryptoService.rsaEncrypt(orgKey.key, publicKey); const req = new OrganizationUserConfirmRequest(); req.key = key.encryptedString; await this.organizationUserService.postOrganizationUserConfirm( diff --git a/apps/cli/src/commands/get.command.ts b/apps/cli/src/commands/get.command.ts index 44a94fb430d..265e24c9d4e 100644 --- a/apps/cli/src/commands/get.command.ts +++ b/apps/cli/src/commands/get.command.ts @@ -513,7 +513,7 @@ export class GetCommand extends DownloadCommand { try { const response = await this.apiService.getUserPublicKey(id); const pubKey = Utils.fromB64ToArray(response.publicKey); - fingerprint = await this.cryptoService.getFingerprint(id, pubKey.buffer); + fingerprint = await this.cryptoService.getFingerprint(id, pubKey); } catch { // eslint-disable-next-line } diff --git a/apps/cli/src/platform/services/node-env-secure-storage.service.ts b/apps/cli/src/platform/services/node-env-secure-storage.service.ts index 80e3cea64c4..491ec32cb62 100644 --- a/apps/cli/src/platform/services/node-env-secure-storage.service.ts +++ b/apps/cli/src/platform/services/node-env-secure-storage.service.ts @@ -47,7 +47,7 @@ export class NodeEnvSecureStorageService implements AbstractStorageService { throw new Error("No session key available."); } const encValue = await this.cryptoService().encryptToBytes( - Utils.fromB64ToArray(plainValue).buffer, + Utils.fromB64ToArray(plainValue), sessionKey ); if (encValue == null) { @@ -81,7 +81,7 @@ export class NodeEnvSecureStorageService implements AbstractStorageService { private getSessionKey() { try { if (process.env.BW_SESSION != null) { - const sessionBuffer = Utils.fromB64ToArray(process.env.BW_SESSION).buffer; + const sessionBuffer = Utils.fromB64ToArray(process.env.BW_SESSION); if (sessionBuffer != null) { const sessionKey = new SymmetricCryptoKey(sessionBuffer); if (sessionBuffer != null) { diff --git a/apps/cli/src/tools/send/commands/receive.command.ts b/apps/cli/src/tools/send/commands/receive.command.ts index 486afed2613..52cff0b462e 100644 --- a/apps/cli/src/tools/send/commands/receive.command.ts +++ b/apps/cli/src/tools/send/commands/receive.command.ts @@ -121,7 +121,7 @@ export class SendReceiveCommand extends DownloadCommand { } } - private async getUnlockedPassword(password: string, keyArray: ArrayBuffer) { + private async getUnlockedPassword(password: string, keyArray: Uint8Array) { const passwordHash = await this.cryptoFunctionService.pbkdf2( password, keyArray, @@ -134,7 +134,7 @@ export class SendReceiveCommand extends DownloadCommand { private async sendRequest( url: string, id: string, - key: ArrayBuffer + key: Uint8Array ): Promise { try { const sendResponse = await this.sendApiService.postSendAccess( diff --git a/apps/desktop/src/auth/login/login-approval.component.ts b/apps/desktop/src/auth/login/login-approval.component.ts index d28e69e3580..807059107fd 100644 --- a/apps/desktop/src/auth/login/login-approval.component.ts +++ b/apps/desktop/src/auth/login/login-approval.component.ts @@ -68,7 +68,7 @@ export class LoginApprovalComponent implements OnInit, OnDestroy { const publicKey = Utils.fromB64ToArray(this.authRequestResponse.publicKey); this.email = await this.stateService.getEmail(); this.fingerprintPhrase = ( - await this.cryptoService.getFingerprint(this.email, publicKey.buffer) + await this.cryptoService.getFingerprint(this.email, publicKey) ).join("-"); this.updateTimeText(); diff --git a/apps/desktop/src/platform/services/electron-state.service.ts b/apps/desktop/src/platform/services/electron-state.service.ts index 7c3ff38a1b5..334cab96698 100644 --- a/apps/desktop/src/platform/services/electron-state.service.ts +++ b/apps/desktop/src/platform/services/electron-state.service.ts @@ -98,7 +98,7 @@ export class ElectronStateService options ); - return new SymmetricCryptoKey(Utils.fromB64ToArray(b64DeviceKey).buffer) as DeviceKey; + return new SymmetricCryptoKey(Utils.fromB64ToArray(b64DeviceKey)) as DeviceKey; } override async setDeviceKey(value: DeviceKey, options?: StorageOptions): Promise { diff --git a/apps/desktop/src/services/native-message-handler.service.ts b/apps/desktop/src/services/native-message-handler.service.ts index 1921ea5fa05..644dfe8f906 100644 --- a/apps/desktop/src/services/native-message-handler.service.ts +++ b/apps/desktop/src/services/native-message-handler.service.ts @@ -70,7 +70,7 @@ export class NativeMessageHandlerService { } try { - const remotePublicKey = Utils.fromB64ToArray(publicKey).buffer; + const remotePublicKey = Utils.fromB64ToArray(publicKey); const ddgEnabled = await this.stateService.getEnableDuckDuckGoBrowserIntegration(); if (!ddgEnabled) { diff --git a/apps/desktop/src/services/native-messaging.service.ts b/apps/desktop/src/services/native-messaging.service.ts index 494a65b6703..7647410fd75 100644 --- a/apps/desktop/src/services/native-messaging.service.ts +++ b/apps/desktop/src/services/native-messaging.service.ts @@ -56,7 +56,7 @@ export class NativeMessagingService { // Request to setup secure encryption if ("command" in rawMessage && rawMessage.command === "setupEncryption") { - const remotePublicKey = Utils.fromB64ToArray(rawMessage.publicKey).buffer; + const remotePublicKey = Utils.fromB64ToArray(rawMessage.publicKey); // Validate the UserId to ensure we are logged into the same account. const accounts = await firstValueFrom(this.stateService.accounts$); @@ -169,7 +169,7 @@ export class NativeMessagingService { ipcRenderer.send("nativeMessagingReply", { appId: appId, message: encrypted }); } - private async secureCommunication(remotePublicKey: ArrayBuffer, appId: string) { + private async secureCommunication(remotePublicKey: Uint8Array, appId: string) { const secret = await this.cryptoFunctionService.randomBytes(64); this.sharedSecrets.set(appId, new SymmetricCryptoKey(secret)); diff --git a/apps/web/src/app/admin-console/organizations/manage/user-confirm.component.ts b/apps/web/src/app/admin-console/organizations/manage/user-confirm.component.ts index 4d3cd0b6ede..22f080b9912 100644 --- a/apps/web/src/app/admin-console/organizations/manage/user-confirm.component.ts +++ b/apps/web/src/app/admin-console/organizations/manage/user-confirm.component.ts @@ -28,10 +28,7 @@ export class UserConfirmComponent implements OnInit { async ngOnInit() { try { if (this.publicKey != null) { - const fingerprint = await this.cryptoService.getFingerprint( - this.userId, - this.publicKey.buffer - ); + const fingerprint = await this.cryptoService.getFingerprint(this.userId, this.publicKey); if (fingerprint != null) { this.fingerprint = fingerprint.join("-"); } 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 669a8954eee..31ced8aee10 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 @@ -47,7 +47,7 @@ export class BulkConfirmComponent implements OnInit { for (const entry of response.data) { const publicKey = Utils.fromB64ToArray(entry.key); - const fingerprint = await this.cryptoService.getFingerprint(entry.userId, publicKey.buffer); + const fingerprint = await this.cryptoService.getFingerprint(entry.userId, publicKey); if (fingerprint != null) { this.publicKeys.set(entry.id, publicKey); this.fingerprints.set(entry.id, fingerprint.join("-")); @@ -67,7 +67,7 @@ export class BulkConfirmComponent implements OnInit { if (publicKey == null) { continue; } - const encryptedKey = await this.cryptoService.rsaEncrypt(key.key, publicKey.buffer); + const encryptedKey = await this.cryptoService.rsaEncrypt(key.key, publicKey); userIdsWithKeys.push({ id: user.id, key: encryptedKey.encryptedString, diff --git a/apps/web/src/app/admin-console/organizations/members/people.component.ts b/apps/web/src/app/admin-console/organizations/members/people.component.ts index ec353fa7ff4..8c4d565c85f 100644 --- a/apps/web/src/app/admin-console/organizations/members/people.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/people.component.ts @@ -302,7 +302,7 @@ export class PeopleComponent 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.buffer); + const key = await this.cryptoService.rsaEncrypt(orgKey.key, publicKey); const request = new OrganizationUserConfirmRequest(); request.key = key.encryptedString; await this.organizationUserService.postOrganizationUserConfirm( diff --git a/apps/web/src/app/admin-console/organizations/settings/account.component.ts b/apps/web/src/app/admin-console/organizations/settings/account.component.ts index 48dcb2c88c6..f8628ed1f79 100644 --- a/apps/web/src/app/admin-console/organizations/settings/account.component.ts +++ b/apps/web/src/app/admin-console/organizations/settings/account.component.ts @@ -61,7 +61,7 @@ export class AccountComponent { }); protected organizationId: string; - protected publicKeyBuffer: ArrayBuffer; + protected publicKeyBuffer: Uint8Array; private destroy$ = new Subject(); @@ -106,7 +106,7 @@ export class AccountComponent { this.org = orgResponse; // Public Key Buffer for Org Fingerprint Generation - this.publicKeyBuffer = Utils.fromB64ToArray(orgKeys?.publicKey)?.buffer; + this.publicKeyBuffer = Utils.fromB64ToArray(orgKeys?.publicKey); // Patch existing values this.formGroup.patchValue({ diff --git a/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts b/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts index 882bb78ceaf..a533967d8f5 100644 --- a/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts +++ b/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts @@ -59,7 +59,7 @@ export class EnrollMasterPasswordReset { // RSA Encrypt user's encKey.key with organization public key const encKey = await this.cryptoService.getEncKey(); - const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer); + const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey); keyString = encryptedKey.encryptedString; toastStringRef = "enrollPasswordResetSuccess"; diff --git a/apps/web/src/app/auth/accept-organization.component.ts b/apps/web/src/app/auth/accept-organization.component.ts index 291cea09a49..bdc3511f760 100644 --- a/apps/web/src/app/auth/accept-organization.component.ts +++ b/apps/web/src/app/auth/accept-organization.component.ts @@ -142,7 +142,7 @@ export class AcceptOrganizationComponent extends BaseAcceptComponent { // RSA Encrypt user's encKey.key with organization public key const encKey = await this.cryptoService.getEncKey(); - const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer); + const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey); // Add reset password key to accept request request.resetPasswordKey = encryptedKey.encryptedString; diff --git a/apps/web/src/app/auth/settings/emergency-access/emergency-access-confirm.component.ts b/apps/web/src/app/auth/settings/emergency-access/emergency-access-confirm.component.ts index 1b5cf883d44..d55d1ceb42a 100644 --- a/apps/web/src/app/auth/settings/emergency-access/emergency-access-confirm.component.ts +++ b/apps/web/src/app/auth/settings/emergency-access/emergency-access-confirm.component.ts @@ -33,7 +33,7 @@ export class EmergencyAccessConfirmComponent implements OnInit { const publicKeyResponse = await this.apiService.getUserPublicKey(this.userId); if (publicKeyResponse != null) { const publicKey = Utils.fromB64ToArray(publicKeyResponse.publicKey); - const fingerprint = await this.cryptoService.getFingerprint(this.userId, publicKey.buffer); + const fingerprint = await this.cryptoService.getFingerprint(this.userId, publicKey); if (fingerprint != null) { this.fingerprint = fingerprint.join("-"); } diff --git a/apps/web/src/app/auth/settings/emergency-access/emergency-access.component.ts b/apps/web/src/app/auth/settings/emergency-access/emergency-access.component.ts index 73f8f1f6531..fd1158ed477 100644 --- a/apps/web/src/app/auth/settings/emergency-access/emergency-access.component.ts +++ b/apps/web/src/app/auth/settings/emergency-access/emergency-access.component.ts @@ -309,13 +309,13 @@ export class EmergencyAccessComponent implements OnInit { try { this.logService.debug( "User's fingerprint: " + - (await this.cryptoService.getFingerprint(details.granteeId, publicKey.buffer)).join("-") + (await this.cryptoService.getFingerprint(details.granteeId, publicKey)).join("-") ); } catch { // Ignore errors since it's just a debug message } - const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer); + const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey); const request = new EmergencyAccessConfirmRequest(); request.key = encryptedKey.encryptedString; await this.apiService.postEmergencyAccessConfirm(details.id, request); diff --git a/apps/web/src/app/common/base.people.component.ts b/apps/web/src/app/common/base.people.component.ts index d6044bc9efd..e14706c2e92 100644 --- a/apps/web/src/app/common/base.people.component.ts +++ b/apps/web/src/app/common/base.people.component.ts @@ -374,7 +374,7 @@ export abstract class BasePeopleComponent< } try { - const fingerprint = await this.cryptoService.getFingerprint(user.userId, publicKey.buffer); + const fingerprint = await this.cryptoService.getFingerprint(user.userId, publicKey); this.logService.info(`User's fingerprint: ${fingerprint.join("-")}`); } catch (e) { this.logService.error(e); diff --git a/apps/web/src/app/settings/change-password.component.ts b/apps/web/src/app/settings/change-password.component.ts index 8b57c6cfb60..4b6d5d5af4b 100644 --- a/apps/web/src/app/settings/change-password.component.ts +++ b/apps/web/src/app/settings/change-password.component.ts @@ -274,7 +274,7 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent { const publicKeyResponse = await this.apiService.getUserPublicKey(details.granteeId); const publicKey = Utils.fromB64ToArray(publicKeyResponse.publicKey); - const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer); + const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey); const updateRequest = new EmergencyAccessUpdateRequest(); updateRequest.type = details.type; @@ -299,7 +299,7 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent { const publicKey = Utils.fromB64ToArray(response?.publicKey); // Re-enroll - encrypt user's encKey.key with organization public key - const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer); + const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey); // Create/Execute request const request = new OrganizationUserResetPasswordEnrollmentRequest(); diff --git a/apps/web/src/app/shared/components/account-fingerprint/account-fingerprint.component.ts b/apps/web/src/app/shared/components/account-fingerprint/account-fingerprint.component.ts index f3d67880f2e..012b9c52234 100644 --- a/apps/web/src/app/shared/components/account-fingerprint/account-fingerprint.component.ts +++ b/apps/web/src/app/shared/components/account-fingerprint/account-fingerprint.component.ts @@ -12,7 +12,7 @@ import { SharedModule } from "../../shared.module"; }) export class AccountFingerprintComponent implements OnInit { @Input() fingerprintMaterial: string; - @Input() publicKeyBuffer: ArrayBuffer; + @Input() publicKeyBuffer: Uint8Array; @Input() fingerprintLabel: string; protected fingerprint: string; diff --git a/apps/web/src/app/vault/components/vault-items/vault-items.stories.ts b/apps/web/src/app/vault/components/vault-items/vault-items.stories.ts index cfe5e41719a..e6736348430 100644 --- a/apps/web/src/app/vault/components/vault-items/vault-items.stories.ts +++ b/apps/web/src/app/vault/components/vault-items/vault-items.stories.ts @@ -277,7 +277,7 @@ function createCipherView(i: number, deleted = false): CipherView { view.attachments = [attachment]; } else if (i % 5 === 0) { const attachment = new AttachmentView(); - attachment.key = new SymmetricCryptoKey(new ArrayBuffer(32)); + attachment.key = new SymmetricCryptoKey(new Uint8Array(32)); view.attachments = [attachment]; } 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 6325a72f80d..b0f7b8bcad5 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 @@ -90,7 +90,7 @@ export class DeviceApprovalsComponent implements OnInit, OnDestroy { const userSymKey = new SymmetricCryptoKey(decValue); // Re-encrypt User's Symmetric Key with the Device Public Key - return await this.cryptoService.rsaEncrypt(userSymKey.key, devicePubKey.buffer); + return await this.cryptoService.rsaEncrypt(userSymKey.key, devicePubKey); } async approveRequest(authRequest: PendingAuthRequestView) { 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 304ab346f33..48cad98f1d3 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 @@ -138,7 +138,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.buffer); + const key = await this.cryptoService.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/login-with-device.component.ts b/libs/angular/src/auth/components/login-with-device.component.ts index 7af5afeca7a..a991f0a8b1c 100644 --- a/libs/angular/src/auth/components/login-with-device.component.ts +++ b/libs/angular/src/auth/components/login-with-device.component.ts @@ -46,7 +46,7 @@ export class LoginWithDeviceComponent protected successRoute = "vault"; protected forcePasswordResetRoute = "update-temp-password"; private resendTimeout = 12000; - private authRequestKeyPair: [publicKey: ArrayBuffer, privateKey: ArrayBuffer]; + private authRequestKeyPair: [publicKey: Uint8Array, privateKey: Uint8Array]; constructor( protected router: Router, diff --git a/libs/angular/src/components/set-password.component.ts b/libs/angular/src/components/set-password.component.ts index a4ae3edb80a..3f0d6eab5ec 100644 --- a/libs/angular/src/components/set-password.component.ts +++ b/libs/angular/src/components/set-password.component.ts @@ -133,10 +133,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent { // RSA Encrypt user's encKey.key with organization public key const userEncKey = await this.cryptoService.getEncKey(); - const encryptedKey = await this.cryptoService.rsaEncrypt( - userEncKey.key, - publicKey.buffer - ); + const encryptedKey = await this.cryptoService.rsaEncrypt(userEncKey.key, publicKey); const resetRequest = new OrganizationUserResetPasswordEnrollmentRequest(); resetRequest.masterPasswordHash = masterPasswordHash; diff --git a/libs/angular/src/platform/pipes/fingerprint.pipe.ts b/libs/angular/src/platform/pipes/fingerprint.pipe.ts index 198b3a57f7c..a01ec21e6cb 100644 --- a/libs/angular/src/platform/pipes/fingerprint.pipe.ts +++ b/libs/angular/src/platform/pipes/fingerprint.pipe.ts @@ -15,10 +15,7 @@ export class FingerprintPipe { publicKey = Utils.fromB64ToArray(publicKey); } - const fingerprint = await this.cryptoService.getFingerprint( - fingerprintMaterial, - publicKey.buffer - ); + const fingerprint = await this.cryptoService.getFingerprint(fingerprintMaterial, publicKey); if (fingerprint != null) { return fingerprint.join("-"); diff --git a/libs/common/spec/matchers/to-equal-buffer.ts b/libs/common/spec/matchers/to-equal-buffer.ts index 796d88cd82b..b1058a389f3 100644 --- a/libs/common/spec/matchers/to-equal-buffer.ts +++ b/libs/common/spec/matchers/to-equal-buffer.ts @@ -6,13 +6,10 @@ */ export const toEqualBuffer: jest.CustomMatcher = function ( received: ArrayBuffer, - expected: Uint8Array | ArrayBuffer + expected: ArrayBuffer ) { received = new Uint8Array(received); - - if (expected instanceof ArrayBuffer) { - expected = new Uint8Array(expected); - } + expected = new Uint8Array(expected); if (this.equals(received, expected)) { return { diff --git a/libs/common/src/auth/services/auth.service.ts b/libs/common/src/auth/services/auth.service.ts index 7164b0ae4f2..53d1b799229 100644 --- a/libs/common/src/auth/services/auth.service.ts +++ b/libs/common/src/auth/services/auth.service.ts @@ -302,13 +302,13 @@ export class AuthService implements AuthServiceAbstraction { ( await this.cryptoService.getKey() ).encKey, - pubKey.buffer + pubKey ); let encryptedMasterPassword = null; if ((await this.stateService.getKeyHash()) != null) { encryptedMasterPassword = await this.cryptoService.rsaEncrypt( Utils.fromUtf8ToArray(await this.stateService.getKeyHash()), - pubKey.buffer + pubKey ); } const request = new PasswordlessAuthRequest( diff --git a/libs/common/src/platform/abstractions/crypto-function.service.ts b/libs/common/src/platform/abstractions/crypto-function.service.ts index 98b47b0f38c..7c76702532d 100644 --- a/libs/common/src/platform/abstractions/crypto-function.service.ts +++ b/libs/common/src/platform/abstractions/crypto-function.service.ts @@ -4,67 +4,67 @@ import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key"; export abstract class CryptoFunctionService { pbkdf2: ( - password: string | ArrayBuffer, - salt: string | ArrayBuffer, + password: string | Uint8Array, + salt: string | Uint8Array, algorithm: "sha256" | "sha512", iterations: number - ) => Promise; + ) => Promise; argon2: ( - password: string | ArrayBuffer, - salt: string | ArrayBuffer, + password: string | Uint8Array, + salt: string | Uint8Array, iterations: number, memory: number, parallelism: number - ) => Promise; + ) => Promise; hkdf: ( - ikm: ArrayBuffer, - salt: string | ArrayBuffer, - info: string | ArrayBuffer, + ikm: Uint8Array, + salt: string | Uint8Array, + info: string | Uint8Array, outputByteSize: number, algorithm: "sha256" | "sha512" - ) => Promise; + ) => Promise; hkdfExpand: ( - prk: ArrayBuffer, - info: string | ArrayBuffer, + prk: Uint8Array, + info: string | Uint8Array, outputByteSize: number, algorithm: "sha256" | "sha512" - ) => Promise; + ) => Promise; hash: ( - value: string | ArrayBuffer, + value: string | Uint8Array, algorithm: "sha1" | "sha256" | "sha512" | "md5" - ) => Promise; + ) => Promise; hmac: ( - value: ArrayBuffer, - key: ArrayBuffer, + value: Uint8Array, + key: Uint8Array, algorithm: "sha1" | "sha256" | "sha512" - ) => Promise; - compare: (a: ArrayBuffer, b: ArrayBuffer) => Promise; + ) => Promise; + compare: (a: Uint8Array, b: Uint8Array) => Promise; hmacFast: ( - value: ArrayBuffer | string, - key: ArrayBuffer | string, + value: Uint8Array | string, + key: Uint8Array | string, algorithm: "sha1" | "sha256" | "sha512" - ) => Promise; - compareFast: (a: ArrayBuffer | string, b: ArrayBuffer | string) => Promise; - aesEncrypt: (data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer) => Promise; + ) => Promise; + compareFast: (a: Uint8Array | string, b: Uint8Array | string) => Promise; + aesEncrypt: (data: Uint8Array, iv: Uint8Array, key: Uint8Array) => Promise; aesDecryptFastParameters: ( data: string, iv: string, mac: string, key: SymmetricCryptoKey - ) => DecryptParameters; - aesDecryptFast: (parameters: DecryptParameters) => Promise; - aesDecrypt: (data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer) => Promise; + ) => DecryptParameters; + aesDecryptFast: (parameters: DecryptParameters) => Promise; + aesDecrypt: (data: Uint8Array, iv: Uint8Array, key: Uint8Array) => Promise; rsaEncrypt: ( - data: ArrayBuffer, - publicKey: ArrayBuffer, + data: Uint8Array, + publicKey: Uint8Array, algorithm: "sha1" | "sha256" - ) => Promise; + ) => Promise; rsaDecrypt: ( - data: ArrayBuffer, - privateKey: ArrayBuffer, + data: Uint8Array, + privateKey: Uint8Array, algorithm: "sha1" | "sha256" - ) => Promise; - rsaExtractPublicKey: (privateKey: ArrayBuffer) => Promise; - rsaGenerateKeyPair: (length: 1024 | 2048 | 4096) => Promise<[ArrayBuffer, ArrayBuffer]>; + ) => Promise; + rsaExtractPublicKey: (privateKey: Uint8Array) => Promise; + rsaGenerateKeyPair: (length: 1024 | 2048 | 4096) => Promise<[Uint8Array, Uint8Array]>; randomBytes: (length: number) => Promise; } diff --git a/libs/common/src/platform/abstractions/crypto.service.ts b/libs/common/src/platform/abstractions/crypto.service.ts index 990fed0c310..e8b95ff2f16 100644 --- a/libs/common/src/platform/abstractions/crypto.service.ts +++ b/libs/common/src/platform/abstractions/crypto.service.ts @@ -22,9 +22,9 @@ export abstract class CryptoService { getKeyHash: () => Promise; compareAndUpdateKeyHash: (masterPassword: string, key: SymmetricCryptoKey) => Promise; getEncKey: (key?: SymmetricCryptoKey) => Promise; - getPublicKey: () => Promise; - getPrivateKey: () => Promise; - getFingerprint: (fingerprintMaterial: string, publicKey?: ArrayBuffer) => Promise; + getPublicKey: () => Promise; + getPrivateKey: () => Promise; + getFingerprint: (fingerprintMaterial: string, publicKey?: Uint8Array) => Promise; getOrgKeys: () => Promise>; getOrgKey: (orgId: string) => Promise; getProviderKey: (providerId: string) => Promise; @@ -63,7 +63,7 @@ export abstract class CryptoService { kdf: KdfType, kdfConfig: KdfConfig ) => Promise; - makeSendKey: (keyMaterial: ArrayBuffer) => Promise; + makeSendKey: (keyMaterial: Uint8Array) => Promise; hashPassword: ( password: string, key: SymmetricCryptoKey, @@ -74,13 +74,13 @@ export abstract class CryptoService { key: SymmetricCryptoKey, encKey?: SymmetricCryptoKey ) => Promise<[SymmetricCryptoKey, EncString]>; - encrypt: (plainValue: string | ArrayBuffer, key?: SymmetricCryptoKey) => Promise; - encryptToBytes: (plainValue: ArrayBuffer, key?: SymmetricCryptoKey) => Promise; - rsaEncrypt: (data: ArrayBuffer, publicKey?: ArrayBuffer) => Promise; - rsaDecrypt: (encValue: string, privateKeyValue?: ArrayBuffer) => Promise; - decryptToBytes: (encString: EncString, key?: SymmetricCryptoKey) => Promise; + encrypt: (plainValue: string | Uint8Array, key?: SymmetricCryptoKey) => Promise; + encryptToBytes: (plainValue: Uint8Array, key?: SymmetricCryptoKey) => Promise; + rsaEncrypt: (data: Uint8Array, publicKey?: Uint8Array) => Promise; + rsaDecrypt: (encValue: string, privateKeyValue?: Uint8Array) => Promise; + decryptToBytes: (encString: EncString, key?: SymmetricCryptoKey) => Promise; decryptToUtf8: (encString: EncString, key?: SymmetricCryptoKey) => Promise; - decryptFromBytes: (encBuffer: EncArrayBuffer, key: SymmetricCryptoKey) => Promise; + decryptFromBytes: (encBuffer: EncArrayBuffer, key: SymmetricCryptoKey) => Promise; randomNumber: (min: number, max: number) => Promise; validateKey: (key: SymmetricCryptoKey) => Promise; } diff --git a/libs/common/src/platform/abstractions/encrypt.service.ts b/libs/common/src/platform/abstractions/encrypt.service.ts index 98802b5b3ba..588a8bb0438 100644 --- a/libs/common/src/platform/abstractions/encrypt.service.ts +++ b/libs/common/src/platform/abstractions/encrypt.service.ts @@ -6,13 +6,13 @@ import { EncString } from "../models/domain/enc-string"; import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key"; export abstract class EncryptService { - abstract encrypt(plainValue: string | ArrayBuffer, key: SymmetricCryptoKey): Promise; + abstract encrypt(plainValue: string | Uint8Array, key: SymmetricCryptoKey): Promise; abstract encryptToBytes: ( - plainValue: ArrayBuffer, + plainValue: Uint8Array, key?: SymmetricCryptoKey ) => Promise; abstract decryptToUtf8: (encString: EncString, key: SymmetricCryptoKey) => Promise; - abstract decryptToBytes: (encThing: Encrypted, key: SymmetricCryptoKey) => Promise; + abstract decryptToBytes: (encThing: Encrypted, key: SymmetricCryptoKey) => Promise; abstract resolveLegacyKey: (key: SymmetricCryptoKey, encThing: Encrypted) => SymmetricCryptoKey; abstract decryptItems: ( items: Decryptable[], diff --git a/libs/common/src/platform/abstractions/state.service.ts b/libs/common/src/platform/abstractions/state.service.ts index e5b4e17fb8d..80159a9a8b9 100644 --- a/libs/common/src/platform/abstractions/state.service.ts +++ b/libs/common/src/platform/abstractions/state.service.ts @@ -113,8 +113,8 @@ export abstract class StateService { * @deprecated Do not call this, use PolicyService */ setDecryptedPolicies: (value: Policy[], options?: StorageOptions) => Promise; - getDecryptedPrivateKey: (options?: StorageOptions) => Promise; - setDecryptedPrivateKey: (value: ArrayBuffer, options?: StorageOptions) => Promise; + getDecryptedPrivateKey: (options?: StorageOptions) => Promise; + setDecryptedPrivateKey: (value: Uint8Array, options?: StorageOptions) => Promise; getDecryptedProviderKeys: (options?: StorageOptions) => Promise>; setDecryptedProviderKeys: ( value: Map, @@ -331,8 +331,8 @@ export abstract class StateService { setProtectedPin: (value: string, options?: StorageOptions) => Promise; getProviders: (options?: StorageOptions) => Promise<{ [id: string]: ProviderData }>; setProviders: (value: { [id: string]: ProviderData }, options?: StorageOptions) => Promise; - getPublicKey: (options?: StorageOptions) => Promise; - setPublicKey: (value: ArrayBuffer, options?: StorageOptions) => Promise; + getPublicKey: (options?: StorageOptions) => Promise; + setPublicKey: (value: Uint8Array, options?: StorageOptions) => Promise; getRefreshToken: (options?: StorageOptions) => Promise; setRefreshToken: (value: string, options?: StorageOptions) => Promise; getRememberedEmail: (options?: StorageOptions) => Promise; diff --git a/libs/common/src/platform/interfaces/encrypted.ts b/libs/common/src/platform/interfaces/encrypted.ts index a5730302dca..26a49a32ec5 100644 --- a/libs/common/src/platform/interfaces/encrypted.ts +++ b/libs/common/src/platform/interfaces/encrypted.ts @@ -2,7 +2,7 @@ import { EncryptionType } from "../../enums"; export interface Encrypted { encryptionType?: EncryptionType; - dataBytes: ArrayBuffer; - macBytes: ArrayBuffer; - ivBytes: ArrayBuffer; + dataBytes: Uint8Array; + macBytes: Uint8Array; + ivBytes: Uint8Array; } diff --git a/libs/common/src/platform/models/domain/account-keys.spec.ts b/libs/common/src/platform/models/domain/account-keys.spec.ts index 88183229f55..36fdb6a2763 100644 --- a/libs/common/src/platform/models/domain/account-keys.spec.ts +++ b/libs/common/src/platform/models/domain/account-keys.spec.ts @@ -8,7 +8,7 @@ describe("AccountKeys", () => { describe("toJSON", () => { it("should serialize itself", () => { const keys = new AccountKeys(); - const buffer = makeStaticByteArray(64).buffer; + const buffer = makeStaticByteArray(64); keys.publicKey = buffer; const bufferSpy = jest.spyOn(Utils, "fromBufferToByteString"); @@ -18,7 +18,7 @@ describe("AccountKeys", () => { it("should serialize public key as a string", () => { const keys = new AccountKeys(); - keys.publicKey = Utils.fromByteStringToArray("hello").buffer; + keys.publicKey = Utils.fromByteStringToArray("hello"); const json = JSON.stringify(keys); expect(json).toContain('"publicKey":"hello"'); }); @@ -29,7 +29,7 @@ describe("AccountKeys", () => { const keys = AccountKeys.fromJSON({ publicKey: "hello", }); - expect(keys.publicKey).toEqual(Utils.fromByteStringToArray("hello").buffer); + expect(keys.publicKey).toEqual(Utils.fromByteStringToArray("hello")); }); it("should deserialize cryptoMasterKey", () => { diff --git a/libs/common/src/platform/models/domain/account.ts b/libs/common/src/platform/models/domain/account.ts index a8cea255c17..f40df3aa538 100644 --- a/libs/common/src/platform/models/domain/account.ts +++ b/libs/common/src/platform/models/domain/account.ts @@ -119,8 +119,8 @@ export class AccountKeys { any, Record >(); - privateKey?: EncryptionPair = new EncryptionPair(); - publicKey?: ArrayBuffer; + privateKey?: EncryptionPair = new EncryptionPair(); + publicKey?: Uint8Array; apiKeyClientSecret?: string; toJSON() { @@ -142,11 +142,10 @@ export class AccountKeys { ), organizationKeys: AccountKeys.initRecordEncryptionPairsFromJSON(obj?.organizationKeys), providerKeys: AccountKeys.initRecordEncryptionPairsFromJSON(obj?.providerKeys), - privateKey: EncryptionPair.fromJSON( - obj?.privateKey, - (decObj: string) => Utils.fromByteStringToArray(decObj).buffer + privateKey: EncryptionPair.fromJSON(obj?.privateKey, (decObj: string) => + Utils.fromByteStringToArray(decObj) ), - publicKey: Utils.fromByteStringToArray(obj?.publicKey)?.buffer, + publicKey: Utils.fromByteStringToArray(obj?.publicKey), }); } diff --git a/libs/common/src/platform/models/domain/enc-array-buffer.spec.ts b/libs/common/src/platform/models/domain/enc-array-buffer.spec.ts index 9e15d05e883..7a03cdc6be3 100644 --- a/libs/common/src/platform/models/domain/enc-array-buffer.spec.ts +++ b/libs/common/src/platform/models/domain/enc-array-buffer.spec.ts @@ -20,7 +20,7 @@ describe("encArrayBuffer", () => { array.set(mac, 1 + iv.byteLength); array.set(data, 1 + iv.byteLength + mac.byteLength); - const actual = new EncArrayBuffer(array.buffer); + const actual = new EncArrayBuffer(array); expect(actual.encryptionType).toEqual(encType); expect(actual.ivBytes).toEqualBuffer(iv); @@ -39,7 +39,7 @@ describe("encArrayBuffer", () => { array.set(iv, 1); array.set(data, 1 + iv.byteLength); - const actual = new EncArrayBuffer(array.buffer); + const actual = new EncArrayBuffer(array); expect(actual.encryptionType).toEqual(encType); expect(actual.ivBytes).toEqualBuffer(iv); @@ -62,9 +62,7 @@ describe("encArrayBuffer", () => { invalidArray.set([encType]); invalidArray.set(invalidBytes, 1); - expect(() => new EncArrayBuffer(invalidArray.buffer)).toThrow( - "Error parsing encrypted ArrayBuffer" - ); + expect(() => new EncArrayBuffer(invalidArray)).toThrow("Error parsing encrypted ArrayBuffer"); }); }); diff --git a/libs/common/src/platform/models/domain/enc-array-buffer.ts b/libs/common/src/platform/models/domain/enc-array-buffer.ts index afaa4a5fb6f..afe9bad57f2 100644 --- a/libs/common/src/platform/models/domain/enc-array-buffer.ts +++ b/libs/common/src/platform/models/domain/enc-array-buffer.ts @@ -9,12 +9,12 @@ const MIN_DATA_LENGTH = 1; export class EncArrayBuffer implements Encrypted { readonly encryptionType: EncryptionType = null; - readonly dataBytes: ArrayBuffer = null; - readonly ivBytes: ArrayBuffer = null; - readonly macBytes: ArrayBuffer = null; + readonly dataBytes: Uint8Array = null; + readonly ivBytes: Uint8Array = null; + readonly macBytes: Uint8Array = null; - constructor(readonly buffer: ArrayBuffer) { - const encBytes = new Uint8Array(buffer); + constructor(readonly buffer: Uint8Array) { + const encBytes = buffer; const encType = encBytes[0]; switch (encType) { @@ -25,12 +25,12 @@ export class EncArrayBuffer implements Encrypted { this.throwDecryptionError(); } - this.ivBytes = encBytes.slice(ENC_TYPE_LENGTH, ENC_TYPE_LENGTH + IV_LENGTH).buffer; + this.ivBytes = encBytes.slice(ENC_TYPE_LENGTH, ENC_TYPE_LENGTH + IV_LENGTH); this.macBytes = encBytes.slice( ENC_TYPE_LENGTH + IV_LENGTH, ENC_TYPE_LENGTH + IV_LENGTH + MAC_LENGTH - ).buffer; - this.dataBytes = encBytes.slice(ENC_TYPE_LENGTH + IV_LENGTH + MAC_LENGTH).buffer; + ); + this.dataBytes = encBytes.slice(ENC_TYPE_LENGTH + IV_LENGTH + MAC_LENGTH); break; } case EncryptionType.AesCbc256_B64: { @@ -39,8 +39,8 @@ export class EncArrayBuffer implements Encrypted { this.throwDecryptionError(); } - this.ivBytes = encBytes.slice(ENC_TYPE_LENGTH, ENC_TYPE_LENGTH + IV_LENGTH).buffer; - this.dataBytes = encBytes.slice(ENC_TYPE_LENGTH + IV_LENGTH).buffer; + this.ivBytes = encBytes.slice(ENC_TYPE_LENGTH, ENC_TYPE_LENGTH + IV_LENGTH); + this.dataBytes = encBytes.slice(ENC_TYPE_LENGTH + IV_LENGTH); break; } default: @@ -63,11 +63,11 @@ export class EncArrayBuffer implements Encrypted { if (buffer == null) { throw new Error("Cannot create EncArrayBuffer from Response - Response is empty"); } - return new EncArrayBuffer(buffer); + return new EncArrayBuffer(new Uint8Array(buffer)); } static fromB64(b64: string) { - const buffer = Utils.fromB64ToArray(b64).buffer; + const buffer = Utils.fromB64ToArray(b64); return new EncArrayBuffer(buffer); } } diff --git a/libs/common/src/platform/models/domain/enc-string.ts b/libs/common/src/platform/models/domain/enc-string.ts index 8fe9fbe93f9..017e0211146 100644 --- a/libs/common/src/platform/models/domain/enc-string.ts +++ b/libs/common/src/platform/models/domain/enc-string.ts @@ -27,16 +27,16 @@ export class EncString implements Encrypted { } } - get ivBytes(): ArrayBuffer { - return this.iv == null ? null : Utils.fromB64ToArray(this.iv).buffer; + get ivBytes(): Uint8Array { + return this.iv == null ? null : Utils.fromB64ToArray(this.iv); } - get macBytes(): ArrayBuffer { - return this.mac == null ? null : Utils.fromB64ToArray(this.mac).buffer; + get macBytes(): Uint8Array { + return this.mac == null ? null : Utils.fromB64ToArray(this.mac); } - get dataBytes(): ArrayBuffer { - return this.data == null ? null : Utils.fromB64ToArray(this.data).buffer; + get dataBytes(): Uint8Array { + return this.data == null ? null : Utils.fromB64ToArray(this.data); } toJSON() { diff --git a/libs/common/src/platform/models/domain/encrypted-object.ts b/libs/common/src/platform/models/domain/encrypted-object.ts index 7679788efa0..22d5a388114 100644 --- a/libs/common/src/platform/models/domain/encrypted-object.ts +++ b/libs/common/src/platform/models/domain/encrypted-object.ts @@ -1,8 +1,8 @@ import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key"; export class EncryptedObject { - iv: ArrayBuffer; - data: ArrayBuffer; - mac: ArrayBuffer; + iv: Uint8Array; + data: Uint8Array; + mac: Uint8Array; key: SymmetricCryptoKey; } diff --git a/libs/common/src/platform/models/domain/symmetric-crypto-key.spec.ts b/libs/common/src/platform/models/domain/symmetric-crypto-key.spec.ts index 85aae2e30ea..13d5835c918 100644 --- a/libs/common/src/platform/models/domain/symmetric-crypto-key.spec.ts +++ b/libs/common/src/platform/models/domain/symmetric-crypto-key.spec.ts @@ -68,7 +68,7 @@ describe("SymmetricCryptoKey", () => { }); it("toJSON creates object for serialization", () => { - const key = new SymmetricCryptoKey(makeStaticByteArray(64).buffer); + const key = new SymmetricCryptoKey(makeStaticByteArray(64)); const actual = key.toJSON(); const expected = { keyB64: key.keyB64 }; @@ -77,7 +77,7 @@ describe("SymmetricCryptoKey", () => { }); it("fromJSON hydrates new object", () => { - const expected = new SymmetricCryptoKey(makeStaticByteArray(64).buffer); + const expected = new SymmetricCryptoKey(makeStaticByteArray(64)); const actual = SymmetricCryptoKey.fromJSON({ keyB64: expected.keyB64 }); expect(actual).toEqual(expected); diff --git a/libs/common/src/platform/models/domain/symmetric-crypto-key.ts b/libs/common/src/platform/models/domain/symmetric-crypto-key.ts index a553b1ae4fb..8ba6c411276 100644 --- a/libs/common/src/platform/models/domain/symmetric-crypto-key.ts +++ b/libs/common/src/platform/models/domain/symmetric-crypto-key.ts @@ -4,9 +4,9 @@ import { EncryptionType } from "../../../enums"; import { Utils } from "../../../platform/misc/utils"; export class SymmetricCryptoKey { - key: ArrayBuffer; - encKey?: ArrayBuffer; - macKey?: ArrayBuffer; + key: Uint8Array; + encKey?: Uint8Array; + macKey?: Uint8Array; encType: EncryptionType; keyB64: string; @@ -15,7 +15,7 @@ export class SymmetricCryptoKey { meta: any; - constructor(key: ArrayBuffer, encType?: EncryptionType) { + constructor(key: Uint8Array, encType?: EncryptionType) { if (key == null) { throw new Error("Must provide key"); } @@ -67,7 +67,7 @@ export class SymmetricCryptoKey { return null; } - const arrayBuffer = Utils.fromB64ToArray(s).buffer; + const arrayBuffer = Utils.fromB64ToArray(s); return new SymmetricCryptoKey(arrayBuffer); } diff --git a/libs/common/src/platform/services/crypto.service.ts b/libs/common/src/platform/services/crypto.service.ts index 6dc4a8c8839..c42c7cc32a1 100644 --- a/libs/common/src/platform/services/crypto.service.ts +++ b/libs/common/src/platform/services/crypto.service.ts @@ -123,7 +123,7 @@ export class CryptoService implements CryptoServiceAbstraction { ): Promise { const key = await this.retrieveKeyFromStorage(keySuffix, userId); if (key != null) { - const symmetricKey = new SymmetricCryptoKey(Utils.fromB64ToArray(key).buffer); + const symmetricKey = new SymmetricCryptoKey(Utils.fromB64ToArray(key)); if (!(await this.validateKey(symmetricKey))) { this.logService.warning("Wrong key, throwing away stored key"); @@ -172,7 +172,7 @@ export class CryptoService implements CryptoServiceAbstraction { return this.getEncKeyHelper(key); } - async getPublicKey(): Promise { + async getPublicKey(): Promise { const inMemoryPublicKey = await this.stateService.getPublicKey(); if (inMemoryPublicKey != null) { return inMemoryPublicKey; @@ -188,7 +188,7 @@ export class CryptoService implements CryptoServiceAbstraction { return publicKey; } - async getPrivateKey(): Promise { + async getPrivateKey(): Promise { const decryptedPrivateKey = await this.stateService.getDecryptedPrivateKey(); if (decryptedPrivateKey != null) { return decryptedPrivateKey; @@ -204,7 +204,7 @@ export class CryptoService implements CryptoServiceAbstraction { return privateKey; } - async getFingerprint(fingerprintMaterial: string, publicKey?: ArrayBuffer): Promise { + async getFingerprint(fingerprintMaterial: string, publicKey?: Uint8Array): Promise { if (publicKey == null) { publicKey = await this.getPublicKey(); } @@ -416,7 +416,7 @@ export class CryptoService implements CryptoServiceAbstraction { kdf: KdfType, kdfConfig: KdfConfig ): Promise { - let key: ArrayBuffer = null; + let key: Uint8Array = null; if (kdf == null || kdf === KdfType.PBKDF2_SHA256) { if (kdfConfig.iterations == null) { kdfConfig.iterations = 5000; @@ -502,7 +502,7 @@ export class CryptoService implements CryptoServiceAbstraction { return await this.stretchKey(pinKey); } - async makeSendKey(keyMaterial: ArrayBuffer): Promise { + async makeSendKey(keyMaterial: Uint8Array): Promise { const sendKey = await this.cryptoFunctionService.hkdf( keyMaterial, "bitwarden-send", @@ -550,7 +550,7 @@ export class CryptoService implements CryptoServiceAbstraction { * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) * and then call encryptService.encrypt */ - async encrypt(plainValue: string | ArrayBuffer, key?: SymmetricCryptoKey): Promise { + async encrypt(plainValue: string | Uint8Array, key?: SymmetricCryptoKey): Promise { key = await this.getKeyForUserEncryption(key); return await this.encryptService.encrypt(plainValue, key); } @@ -559,12 +559,12 @@ export class CryptoService implements CryptoServiceAbstraction { * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) * and then call encryptService.encryptToBytes */ - async encryptToBytes(plainValue: ArrayBuffer, key?: SymmetricCryptoKey): Promise { + async encryptToBytes(plainValue: Uint8Array, key?: SymmetricCryptoKey): Promise { key = await this.getKeyForUserEncryption(key); return this.encryptService.encryptToBytes(plainValue, key); } - async rsaEncrypt(data: ArrayBuffer, publicKey?: ArrayBuffer): Promise { + async rsaEncrypt(data: Uint8Array, publicKey?: Uint8Array): Promise { if (publicKey == null) { publicKey = await this.getPublicKey(); } @@ -576,7 +576,7 @@ export class CryptoService implements CryptoServiceAbstraction { return new EncString(EncryptionType.Rsa2048_OaepSha1_B64, Utils.fromBufferToB64(encBytes)); } - async rsaDecrypt(encValue: string, privateKeyValue?: ArrayBuffer): Promise { + async rsaDecrypt(encValue: string, privateKeyValue?: Uint8Array): Promise { const headerPieces = encValue.split("."); let encType: EncryptionType = null; let encPieces: string[]; @@ -607,7 +607,7 @@ export class CryptoService implements CryptoServiceAbstraction { throw new Error("encPieces unavailable."); } - const data = Utils.fromB64ToArray(encPieces[0]).buffer; + const data = Utils.fromB64ToArray(encPieces[0]); const privateKey = privateKeyValue ?? (await this.getPrivateKey()); if (privateKey == null) { throw new Error("No private key."); @@ -633,7 +633,7 @@ export class CryptoService implements CryptoServiceAbstraction { * @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 { + async decryptToBytes(encString: EncString, key?: SymmetricCryptoKey): Promise { const keyForEnc = await this.getKeyForUserEncryption(key); return this.encryptService.decryptToBytes(encString, keyForEnc); } @@ -651,7 +651,7 @@ export class CryptoService implements CryptoServiceAbstraction { * @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 { + async decryptFromBytes(encBuffer: EncArrayBuffer, key: SymmetricCryptoKey): Promise { if (encBuffer == null) { throw new Error("No buffer provided for decryption."); } @@ -768,10 +768,10 @@ export class CryptoService implements CryptoServiceAbstraction { const macKey = await this.cryptoFunctionService.hkdfExpand(key.key, "mac", 32, "sha256"); newKey.set(new Uint8Array(encKey)); newKey.set(new Uint8Array(macKey), 32); - return new SymmetricCryptoKey(newKey.buffer); + return new SymmetricCryptoKey(newKey); } - private async hashPhrase(hash: ArrayBuffer, minimumEntropy = 64) { + private async hashPhrase(hash: Uint8Array, minimumEntropy = 64) { const entropyPerWord = Math.log(EFFLongWordList.length) / Math.log(2); let numWords = Math.ceil(minimumEntropy / entropyPerWord); @@ -793,7 +793,7 @@ export class CryptoService implements CryptoServiceAbstraction { private async buildEncKey( key: SymmetricCryptoKey, - encKey: ArrayBuffer + encKey: Uint8Array ): Promise<[SymmetricCryptoKey, EncString]> { let encKeyEnc: EncString = null; if (key.key.byteLength === 32) { @@ -830,7 +830,7 @@ export class CryptoService implements CryptoServiceAbstraction { return null; } - let decEncKey: ArrayBuffer; + let decEncKey: Uint8Array; const encKeyCipher = new EncString(encKey); if (encKeyCipher.encryptionType === EncryptionType.AesCbc256_B64) { decEncKey = await this.decryptToBytes(encKeyCipher, key); diff --git a/libs/common/src/platform/services/cryptography/encrypt.service.implementation.ts b/libs/common/src/platform/services/cryptography/encrypt.service.implementation.ts index 2ccd6208ce7..d847dcf77b4 100644 --- a/libs/common/src/platform/services/cryptography/encrypt.service.implementation.ts +++ b/libs/common/src/platform/services/cryptography/encrypt.service.implementation.ts @@ -18,7 +18,7 @@ export class EncryptServiceImplementation implements EncryptService { protected logMacFailures: boolean ) {} - async encrypt(plainValue: string | ArrayBuffer, key: SymmetricCryptoKey): Promise { + async encrypt(plainValue: string | Uint8Array, key: SymmetricCryptoKey): Promise { if (key == null) { throw new Error("No encryption key provided."); } @@ -27,9 +27,9 @@ export class EncryptServiceImplementation implements EncryptService { return Promise.resolve(null); } - let plainBuf: ArrayBuffer; + let plainBuf: Uint8Array; if (typeof plainValue === "string") { - plainBuf = Utils.fromUtf8ToArray(plainValue).buffer; + plainBuf = Utils.fromUtf8ToArray(plainValue); } else { plainBuf = plainValue; } @@ -41,7 +41,7 @@ export class EncryptServiceImplementation implements EncryptService { return new EncString(encObj.key.encType, data, iv, mac); } - async encryptToBytes(plainValue: ArrayBuffer, key: SymmetricCryptoKey): Promise { + async encryptToBytes(plainValue: Uint8Array, key: SymmetricCryptoKey): Promise { if (key == null) { throw new Error("No encryption key provided."); } @@ -60,7 +60,7 @@ export class EncryptServiceImplementation implements EncryptService { } encBytes.set(new Uint8Array(encValue.data), 1 + encValue.iv.byteLength + macLen); - return new EncArrayBuffer(encBytes.buffer); + return new EncArrayBuffer(encBytes); } async decryptToUtf8(encString: EncString, key: SymmetricCryptoKey): Promise { @@ -102,7 +102,7 @@ export class EncryptServiceImplementation implements EncryptService { return await this.cryptoFunctionService.aesDecryptFast(fastParams); } - async decryptToBytes(encThing: Encrypted, key: SymmetricCryptoKey): Promise { + async decryptToBytes(encThing: Encrypted, key: SymmetricCryptoKey): Promise { if (key == null) { throw new Error("No encryption key provided."); } @@ -125,11 +125,7 @@ export class EncryptServiceImplementation implements EncryptService { const macData = new Uint8Array(encThing.ivBytes.byteLength + encThing.dataBytes.byteLength); macData.set(new Uint8Array(encThing.ivBytes), 0); macData.set(new Uint8Array(encThing.dataBytes), encThing.ivBytes.byteLength); - const computedMac = await this.cryptoFunctionService.hmac( - macData.buffer, - key.macKey, - "sha256" - ); + const computedMac = await this.cryptoFunctionService.hmac(macData, key.macKey, "sha256"); if (computedMac === null) { return null; } @@ -161,7 +157,7 @@ export class EncryptServiceImplementation implements EncryptService { return await Promise.all(items.map((item) => item.decrypt(key))); } - private async aesEncrypt(data: ArrayBuffer, key: SymmetricCryptoKey): Promise { + private async aesEncrypt(data: Uint8Array, key: SymmetricCryptoKey): Promise { const obj = new EncryptedObject(); obj.key = key; obj.iv = await this.cryptoFunctionService.randomBytes(16); @@ -171,7 +167,7 @@ export class EncryptServiceImplementation implements EncryptService { const macData = new Uint8Array(obj.iv.byteLength + obj.data.byteLength); macData.set(new Uint8Array(obj.iv), 0); macData.set(new Uint8Array(obj.data), obj.iv.byteLength); - obj.mac = await this.cryptoFunctionService.hmac(macData.buffer, obj.key.macKey, "sha256"); + obj.mac = await this.cryptoFunctionService.hmac(macData, obj.key.macKey, "sha256"); } return obj; diff --git a/libs/common/src/platform/services/state.service.ts b/libs/common/src/platform/services/state.service.ts index 57b2a47da84..98525c16b06 100644 --- a/libs/common/src/platform/services/state.service.ts +++ b/libs/common/src/platform/services/state.service.ts @@ -763,13 +763,13 @@ export class StateService< ); } - async getDecryptedPrivateKey(options?: StorageOptions): Promise { + async getDecryptedPrivateKey(options?: StorageOptions): Promise { return ( await this.getAccount(this.reconcileOptions(options, await this.defaultInMemoryOptions())) )?.keys?.privateKey.decrypted; } - async setDecryptedPrivateKey(value: ArrayBuffer, options?: StorageOptions): Promise { + async setDecryptedPrivateKey(value: Uint8Array, options?: StorageOptions): Promise { const account = await this.getAccount( this.reconcileOptions(options, await this.defaultInMemoryOptions()) ); @@ -2097,14 +2097,14 @@ export class StateService< ); } - async getPublicKey(options?: StorageOptions): Promise { + async getPublicKey(options?: StorageOptions): Promise { const keys = ( await this.getAccount(this.reconcileOptions(options, await this.defaultInMemoryOptions())) )?.keys; return keys?.publicKey; } - async setPublicKey(value: ArrayBuffer, options?: StorageOptions): Promise { + async setPublicKey(value: Uint8Array, options?: StorageOptions): Promise { const account = await this.getAccount( this.reconcileOptions(options, await this.defaultInMemoryOptions()) ); diff --git a/libs/common/src/platform/services/web-crypto-function.service.spec.ts b/libs/common/src/platform/services/web-crypto-function.service.spec.ts index fa3562cb50a..1f88a41982b 100644 --- a/libs/common/src/platform/services/web-crypto-function.service.spec.ts +++ b/libs/common/src/platform/services/web-crypto-function.service.spec.ts @@ -160,7 +160,7 @@ describe("WebCrypto Function Service", () => { const a = new Uint8Array(2); a[0] = 1; a[1] = 2; - const equal = await cryptoFunctionService.compare(a.buffer, a.buffer); + const equal = await cryptoFunctionService.compare(a, a); expect(equal).toBe(true); }); @@ -172,7 +172,7 @@ describe("WebCrypto Function Service", () => { const b = new Uint8Array(2); b[0] = 3; b[1] = 4; - const equal = await cryptoFunctionService.compare(a.buffer, b.buffer); + const equal = await cryptoFunctionService.compare(a, b); expect(equal).toBe(false); }); @@ -183,7 +183,7 @@ describe("WebCrypto Function Service", () => { a[1] = 2; const b = new Uint8Array(2); b[0] = 3; - const equal = await cryptoFunctionService.compare(a.buffer, b.buffer); + const equal = await cryptoFunctionService.compare(a, b); expect(equal).toBe(false); }); }); @@ -200,7 +200,7 @@ describe("WebCrypto Function Service", () => { const a = new Uint8Array(2); a[0] = 1; a[1] = 2; - const aByteString = Utils.fromBufferToByteString(a.buffer); + const aByteString = Utils.fromBufferToByteString(a); const equal = await cryptoFunctionService.compareFast(aByteString, aByteString); expect(equal).toBe(true); }); @@ -210,11 +210,11 @@ describe("WebCrypto Function Service", () => { const a = new Uint8Array(2); a[0] = 1; a[1] = 2; - const aByteString = Utils.fromBufferToByteString(a.buffer); + const aByteString = Utils.fromBufferToByteString(a); const b = new Uint8Array(2); b[0] = 3; b[1] = 4; - const bByteString = Utils.fromBufferToByteString(b.buffer); + const bByteString = Utils.fromBufferToByteString(b); const equal = await cryptoFunctionService.compareFast(aByteString, bByteString); expect(equal).toBe(false); }); @@ -224,10 +224,10 @@ describe("WebCrypto Function Service", () => { const a = new Uint8Array(2); a[0] = 1; a[1] = 2; - const aByteString = Utils.fromBufferToByteString(a.buffer); + const aByteString = Utils.fromBufferToByteString(a); const b = new Uint8Array(2); b[0] = 3; - const bByteString = Utils.fromBufferToByteString(b.buffer); + const bByteString = Utils.fromBufferToByteString(b); const equal = await cryptoFunctionService.compareFast(aByteString, bByteString); expect(equal).toBe(false); }); @@ -239,7 +239,7 @@ describe("WebCrypto Function Service", () => { const iv = makeStaticByteArray(16); const key = makeStaticByteArray(32); const data = Utils.fromUtf8ToArray("EncryptMe!"); - const encValue = await cryptoFunctionService.aesEncrypt(data.buffer, iv.buffer, key.buffer); + const encValue = await cryptoFunctionService.aesEncrypt(data, iv, key); expect(Utils.fromBufferToB64(encValue)).toBe("ByUF8vhyX4ddU9gcooznwA=="); }); @@ -249,10 +249,10 @@ describe("WebCrypto Function Service", () => { const key = makeStaticByteArray(32); const value = "EncryptMe!"; const data = Utils.fromUtf8ToArray(value); - const encValue = await cryptoFunctionService.aesEncrypt(data.buffer, iv.buffer, key.buffer); + const encValue = await cryptoFunctionService.aesEncrypt(data, iv, key); const encData = Utils.fromBufferToB64(encValue); - const b64Iv = Utils.fromBufferToB64(iv.buffer); - const symKey = new SymmetricCryptoKey(key.buffer); + const b64Iv = Utils.fromBufferToB64(iv); + const symKey = new SymmetricCryptoKey(key); const params = cryptoFunctionService.aesDecryptFastParameters(encData, b64Iv, null, symKey); const decValue = await cryptoFunctionService.aesDecryptFast(params); expect(decValue).toBe(value); @@ -264,8 +264,8 @@ describe("WebCrypto Function Service", () => { const key = makeStaticByteArray(32); const value = "EncryptMe!"; const data = Utils.fromUtf8ToArray(value); - const encValue = await cryptoFunctionService.aesEncrypt(data.buffer, iv.buffer, key.buffer); - const decValue = await cryptoFunctionService.aesDecrypt(encValue, iv.buffer, key.buffer); + const encValue = new Uint8Array(await cryptoFunctionService.aesEncrypt(data, iv, key)); + const decValue = await cryptoFunctionService.aesDecrypt(encValue, iv, key); expect(Utils.fromBufferToUtf8(decValue)).toBe(value); }); }); @@ -273,8 +273,8 @@ describe("WebCrypto Function Service", () => { describe("aesDecryptFast", () => { it("should successfully decrypt data", async () => { const cryptoFunctionService = getWebCryptoFunctionService(); - const iv = Utils.fromBufferToB64(makeStaticByteArray(16).buffer); - const symKey = new SymmetricCryptoKey(makeStaticByteArray(32).buffer); + const iv = Utils.fromBufferToB64(makeStaticByteArray(16)); + const symKey = new SymmetricCryptoKey(makeStaticByteArray(32)); const data = "ByUF8vhyX4ddU9gcooznwA=="; const params = cryptoFunctionService.aesDecryptFastParameters(data, iv, null, symKey); const decValue = await cryptoFunctionService.aesDecryptFast(params); @@ -288,7 +288,7 @@ describe("WebCrypto Function Service", () => { const iv = makeStaticByteArray(16); const key = makeStaticByteArray(32); const data = Utils.fromB64ToArray("ByUF8vhyX4ddU9gcooznwA=="); - const decValue = await cryptoFunctionService.aesDecrypt(data.buffer, iv.buffer, key.buffer); + const decValue = await cryptoFunctionService.aesDecrypt(data, iv, key); expect(Utils.fromBufferToUtf8(decValue)).toBe("EncryptMe!"); }); }); @@ -300,8 +300,8 @@ describe("WebCrypto Function Service", () => { const privKey = Utils.fromB64ToArray(RsaPrivateKey); const value = "EncryptMe!"; const data = Utils.fromUtf8ToArray(value); - const encValue = await cryptoFunctionService.rsaEncrypt(data.buffer, pubKey.buffer, "sha1"); - const decValue = await cryptoFunctionService.rsaDecrypt(encValue, privKey.buffer, "sha1"); + const encValue = new Uint8Array(await cryptoFunctionService.rsaEncrypt(data, pubKey, "sha1")); + const decValue = await cryptoFunctionService.rsaDecrypt(encValue, privKey, "sha1"); expect(Utils.fromBufferToUtf8(decValue)).toBe(value); }); }); @@ -316,7 +316,7 @@ describe("WebCrypto Function Service", () => { "zFOIEPF2S1zgperEP23M01mr4dWVdYN18B32YF67xdJHMbFhp5dkQwv9CmscoWq7OE5HIfOb+JAh7BEZb+CmKhM3yWJvoR/D" + "/5jcercUtK2o+XrzNrL4UQ7yLZcFz6Bfwb/j6ICYvqd/YJwXNE6dwlL57OfwJyCdw2rRYf0/qI00t9u8Iitw==" ); - const decValue = await cryptoFunctionService.rsaDecrypt(data.buffer, privKey.buffer, "sha1"); + const decValue = await cryptoFunctionService.rsaDecrypt(data, privKey, "sha1"); expect(Utils.fromBufferToUtf8(decValue)).toBe("EncryptMe!"); }); }); @@ -325,7 +325,7 @@ describe("WebCrypto Function Service", () => { it("should successfully extract key", async () => { const cryptoFunctionService = getWebCryptoFunctionService(); const privKey = Utils.fromB64ToArray(RsaPrivateKey); - const publicKey = await cryptoFunctionService.rsaExtractPublicKey(privKey.buffer); + const publicKey = await cryptoFunctionService.rsaExtractPublicKey(privKey); expect(Utils.fromBufferToB64(publicKey)).toBe(RsaPublicKey); }); }); @@ -390,8 +390,8 @@ function testPbkdf2( it("should create valid " + algorithm + " key from array buffer input", async () => { const cryptoFunctionService = getWebCryptoFunctionService(); const key = await cryptoFunctionService.pbkdf2( - Utils.fromUtf8ToArray(regularPassword).buffer, - Utils.fromUtf8ToArray(regularEmail).buffer, + Utils.fromUtf8ToArray(regularPassword), + Utils.fromUtf8ToArray(regularEmail), algorithm, 5000 ); @@ -437,8 +437,8 @@ function testHkdf( const cryptoFunctionService = getWebCryptoFunctionService(); const key = await cryptoFunctionService.hkdf( ikm, - Utils.fromUtf8ToArray(regularSalt).buffer, - Utils.fromUtf8ToArray(regularInfo).buffer, + Utils.fromUtf8ToArray(regularSalt), + Utils.fromUtf8ToArray(regularInfo), 32, algorithm ); @@ -496,10 +496,7 @@ function testHash( it("should create valid " + algorithm + " hash from array buffer input", async () => { const cryptoFunctionService = getWebCryptoFunctionService(); - const hash = await cryptoFunctionService.hash( - Utils.fromUtf8ToArray(regularValue).buffer, - algorithm - ); + const hash = await cryptoFunctionService.hash(Utils.fromUtf8ToArray(regularValue), algorithm); expect(Utils.fromBufferToHex(hash)).toBe(regularHash); }); } @@ -508,8 +505,8 @@ function testHmac(algorithm: "sha1" | "sha256" | "sha512", mac: string) { it("should create valid " + algorithm + " hmac", async () => { const cryptoFunctionService = getWebCryptoFunctionService(); const computedMac = await cryptoFunctionService.hmac( - Utils.fromUtf8ToArray("SignMe!!").buffer, - Utils.fromUtf8ToArray("secretkey").buffer, + Utils.fromUtf8ToArray("SignMe!!"), + Utils.fromUtf8ToArray("secretkey"), algorithm ); expect(Utils.fromBufferToHex(computedMac)).toBe(mac); @@ -519,14 +516,14 @@ function testHmac(algorithm: "sha1" | "sha256" | "sha512", mac: string) { function testHmacFast(algorithm: "sha1" | "sha256" | "sha512", mac: string) { it("should create valid " + algorithm + " hmac", async () => { const cryptoFunctionService = getWebCryptoFunctionService(); - const keyByteString = Utils.fromBufferToByteString(Utils.fromUtf8ToArray("secretkey").buffer); - const dataByteString = Utils.fromBufferToByteString(Utils.fromUtf8ToArray("SignMe!!").buffer); + const keyByteString = Utils.fromBufferToByteString(Utils.fromUtf8ToArray("secretkey")); + const dataByteString = Utils.fromBufferToByteString(Utils.fromUtf8ToArray("SignMe!!")); const computedMac = await cryptoFunctionService.hmacFast( dataByteString, keyByteString, algorithm ); - expect(Utils.fromBufferToHex(Utils.fromByteStringToArray(computedMac).buffer)).toBe(mac); + expect(Utils.fromBufferToHex(Utils.fromByteStringToArray(computedMac))).toBe(mac); }); } @@ -535,7 +532,9 @@ function testRsaGenerateKeyPair(length: 1024 | 2048 | 4096) { "should successfully generate a " + length + " bit key pair", async () => { const cryptoFunctionService = getWebCryptoFunctionService(); - const keyPair = await cryptoFunctionService.rsaGenerateKeyPair(length); + const keyPair = (await cryptoFunctionService.rsaGenerateKeyPair(length)).map( + (k) => new Uint8Array(k) + ); expect(keyPair[0] == null || keyPair[1] == null).toBe(false); const publicKey = await cryptoFunctionService.rsaExtractPublicKey(keyPair[1]); expect(Utils.fromBufferToB64(keyPair[0])).toBe(Utils.fromBufferToB64(publicKey)); diff --git a/libs/common/src/platform/services/web-crypto-function.service.ts b/libs/common/src/platform/services/web-crypto-function.service.ts index 65ee74aa630..4cf8636a098 100644 --- a/libs/common/src/platform/services/web-crypto-function.service.ts +++ b/libs/common/src/platform/services/web-crypto-function.service.ts @@ -20,11 +20,11 @@ export class WebCryptoFunctionService implements CryptoFunctionService { } async pbkdf2( - password: string | ArrayBuffer, - salt: string | ArrayBuffer, + password: string | Uint8Array, + salt: string | Uint8Array, algorithm: "sha256" | "sha512", iterations: number - ): Promise { + ): Promise { const wcLen = algorithm === "sha256" ? 256 : 512; const passwordBuf = this.toBuf(password); const saltBuf = this.toBuf(salt); @@ -43,16 +43,17 @@ export class WebCryptoFunctionService implements CryptoFunctionService { false, ["deriveBits"] ); - return await this.subtle.deriveBits(pbkdf2Params, impKey, wcLen); + const buffer = await this.subtle.deriveBits(pbkdf2Params as any, impKey, wcLen); + return new Uint8Array(buffer); } async argon2( - password: string | ArrayBuffer, - salt: string | ArrayBuffer, + password: string | Uint8Array, + salt: string | Uint8Array, iterations: number, memory: number, parallelism: number - ): Promise { + ): Promise { if (!this.wasmSupported) { throw "Webassembly support is required for the Argon2 KDF feature."; } @@ -74,12 +75,12 @@ export class WebCryptoFunctionService implements CryptoFunctionService { } async hkdf( - ikm: ArrayBuffer, - salt: string | ArrayBuffer, - info: string | ArrayBuffer, + ikm: Uint8Array, + salt: string | Uint8Array, + info: string | Uint8Array, outputByteSize: number, algorithm: "sha256" | "sha512" - ): Promise { + ): Promise { const saltBuf = this.toBuf(salt); const infoBuf = this.toBuf(info); @@ -93,16 +94,17 @@ export class WebCryptoFunctionService implements CryptoFunctionService { const impKey = await this.subtle.importKey("raw", ikm, { name: "HKDF" } as any, false, [ "deriveBits", ]); - return await this.subtle.deriveBits(hkdfParams as any, impKey, outputByteSize * 8); + const buffer = await this.subtle.deriveBits(hkdfParams as any, impKey, outputByteSize * 8); + return new Uint8Array(buffer); } // ref: https://tools.ietf.org/html/rfc5869 async hkdfExpand( - prk: ArrayBuffer, - info: string | ArrayBuffer, + prk: Uint8Array, + info: string | Uint8Array, outputByteSize: number, algorithm: "sha256" | "sha512" - ): Promise { + ): Promise { const hashLen = algorithm === "sha256" ? 32 : 64; if (outputByteSize > 255 * hashLen) { throw new Error("outputByteSize is too large."); @@ -122,49 +124,54 @@ export class WebCryptoFunctionService implements CryptoFunctionService { t.set(previousT); t.set(infoArr, previousT.length); t.set([i + 1], t.length - 1); - previousT = new Uint8Array(await this.hmac(t.buffer, prk, algorithm)); + previousT = new Uint8Array(await this.hmac(t, prk, algorithm)); okm.set(previousT, runningOkmLength); runningOkmLength += previousT.length; if (runningOkmLength >= outputByteSize) { break; } } - return okm.slice(0, outputByteSize).buffer; + return okm.slice(0, outputByteSize); } async hash( - value: string | ArrayBuffer, + value: string | Uint8Array, algorithm: "sha1" | "sha256" | "sha512" | "md5" - ): Promise { + ): Promise { if (algorithm === "md5") { const md = algorithm === "md5" ? forge.md.md5.create() : forge.md.sha1.create(); const valueBytes = this.toByteString(value); md.update(valueBytes, "raw"); - return Utils.fromByteStringToArray(md.digest().data).buffer; + return Utils.fromByteStringToArray(md.digest().data); } const valueBuf = this.toBuf(value); - return await this.subtle.digest({ name: this.toWebCryptoAlgorithm(algorithm) }, valueBuf); + const buffer = await this.subtle.digest( + { name: this.toWebCryptoAlgorithm(algorithm) }, + valueBuf + ); + return new Uint8Array(buffer); } async hmac( - value: ArrayBuffer, - key: ArrayBuffer, + value: Uint8Array, + key: Uint8Array, algorithm: "sha1" | "sha256" | "sha512" - ): Promise { + ): Promise { const signingAlgorithm = { name: "HMAC", hash: { name: this.toWebCryptoAlgorithm(algorithm) }, }; const impKey = await this.subtle.importKey("raw", key, signingAlgorithm, false, ["sign"]); - return await this.subtle.sign(signingAlgorithm, impKey, value); + const buffer = await this.subtle.sign(signingAlgorithm, impKey, value); + return new Uint8Array(buffer); } // Safely compare two values in a way that protects against timing attacks (Double HMAC Verification). // ref: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/ // ref: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy - async compare(a: ArrayBuffer, b: ArrayBuffer): Promise { + async compare(a: Uint8Array, b: Uint8Array): Promise { const macKey = await this.randomBytes(32); const signingAlgorithm = { name: "HMAC", @@ -219,11 +226,12 @@ export class WebCryptoFunctionService implements CryptoFunctionService { return equals; } - async aesEncrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise { + async aesEncrypt(data: Uint8Array, iv: Uint8Array, key: Uint8Array): Promise { const impKey = await this.subtle.importKey("raw", key, { name: "AES-CBC" } as any, false, [ "encrypt", ]); - return await this.subtle.encrypt({ name: "AES-CBC", iv: iv }, impKey, data); + const buffer = await this.subtle.encrypt({ name: "AES-CBC", iv: iv }, impKey, data); + return new Uint8Array(buffer); } aesDecryptFastParameters( @@ -275,18 +283,19 @@ export class WebCryptoFunctionService implements CryptoFunctionService { return Promise.resolve(val); } - async aesDecrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise { + async aesDecrypt(data: Uint8Array, iv: Uint8Array, key: Uint8Array): Promise { const impKey = await this.subtle.importKey("raw", key, { name: "AES-CBC" } as any, false, [ "decrypt", ]); - return await this.subtle.decrypt({ name: "AES-CBC", iv: iv }, impKey, data); + const buffer = await this.subtle.decrypt({ name: "AES-CBC", iv: iv }, impKey, data); + return new Uint8Array(buffer); } async rsaEncrypt( - data: ArrayBuffer, - publicKey: ArrayBuffer, + data: Uint8Array, + publicKey: Uint8Array, algorithm: "sha1" | "sha256" - ): Promise { + ): Promise { // Note: Edge browser requires that we specify name and hash for both key import and decrypt. // We cannot use the proper types here. const rsaParams = { @@ -294,14 +303,15 @@ export class WebCryptoFunctionService implements CryptoFunctionService { hash: { name: this.toWebCryptoAlgorithm(algorithm) }, }; const impKey = await this.subtle.importKey("spki", publicKey, rsaParams, false, ["encrypt"]); - return await this.subtle.encrypt(rsaParams, impKey, data); + const buffer = await this.subtle.encrypt(rsaParams, impKey, data); + return new Uint8Array(buffer); } async rsaDecrypt( - data: ArrayBuffer, - privateKey: ArrayBuffer, + data: Uint8Array, + privateKey: Uint8Array, algorithm: "sha1" | "sha256" - ): Promise { + ): Promise { // Note: Edge browser requires that we specify name and hash for both key import and decrypt. // We cannot use the proper types here. const rsaParams = { @@ -309,10 +319,11 @@ export class WebCryptoFunctionService implements CryptoFunctionService { hash: { name: this.toWebCryptoAlgorithm(algorithm) }, }; const impKey = await this.subtle.importKey("pkcs8", privateKey, rsaParams, false, ["decrypt"]); - return await this.subtle.decrypt(rsaParams, impKey, data); + const buffer = await this.subtle.decrypt(rsaParams, impKey, data); + return new Uint8Array(buffer); } - async rsaExtractPublicKey(privateKey: ArrayBuffer): Promise { + async rsaExtractPublicKey(privateKey: Uint8Array): Promise { const rsaParams = { name: "RSA-OAEP", // Have to specify some algorithm @@ -332,10 +343,11 @@ export class WebCryptoFunctionService implements CryptoFunctionService { const impPublicKey = await this.subtle.importKey("jwk", jwkPublicKeyParams, rsaParams, true, [ "encrypt", ]); - return await this.subtle.exportKey("spki", impPublicKey); + const buffer = await this.subtle.exportKey("spki", impPublicKey); + return new Uint8Array(buffer); } - async rsaGenerateKeyPair(length: 1024 | 2048 | 4096): Promise<[ArrayBuffer, ArrayBuffer]> { + async rsaGenerateKeyPair(length: 1024 | 2048 | 4096): Promise<[Uint8Array, Uint8Array]> { const rsaParams = { name: "RSA-OAEP", modulusLength: length, @@ -349,26 +361,26 @@ export class WebCryptoFunctionService implements CryptoFunctionService { ])) as CryptoKeyPair; const publicKey = await this.subtle.exportKey("spki", keyPair.publicKey); const privateKey = await this.subtle.exportKey("pkcs8", keyPair.privateKey); - return [publicKey, privateKey]; + return [new Uint8Array(publicKey), new Uint8Array(privateKey)]; } randomBytes(length: number): Promise { const arr = new Uint8Array(length); this.crypto.getRandomValues(arr); - return Promise.resolve(arr.buffer as CsprngArray); + return Promise.resolve(arr as CsprngArray); } - private toBuf(value: string | ArrayBuffer): ArrayBuffer { - let buf: ArrayBuffer; + private toBuf(value: string | Uint8Array): Uint8Array { + let buf: Uint8Array; if (typeof value === "string") { - buf = Utils.fromUtf8ToArray(value).buffer; + buf = Utils.fromUtf8ToArray(value); } else { buf = value; } return buf; } - private toByteString(value: string | ArrayBuffer): string { + private toByteString(value: string | Uint8Array): string { let bytes: string; if (typeof value === "string") { bytes = forge.util.encodeUtf8(value); diff --git a/libs/common/src/services/totp.service.ts b/libs/common/src/services/totp.service.ts index 54c583b5cd2..7896a8c4516 100644 --- a/libs/common/src/services/totp.service.ts +++ b/libs/common/src/services/totp.service.ts @@ -162,7 +162,7 @@ export class TotpService implements TotpServiceAbstraction { timeBytes: Uint8Array, alg: "sha1" | "sha256" | "sha512" ) { - const signature = await this.cryptoFunctionService.hmac(timeBytes.buffer, keyBytes.buffer, alg); + const signature = await this.cryptoFunctionService.hmac(timeBytes, keyBytes, alg); return new Uint8Array(signature); } } diff --git a/libs/common/src/tools/send/models/view/send.view.ts b/libs/common/src/tools/send/models/view/send.view.ts index 9b85e945629..bf8a247e570 100644 --- a/libs/common/src/tools/send/models/view/send.view.ts +++ b/libs/common/src/tools/send/models/view/send.view.ts @@ -13,7 +13,7 @@ export class SendView implements View { accessId: string = null; name: string = null; notes: string = null; - key: ArrayBuffer; + key: Uint8Array; cryptoKey: SymmetricCryptoKey; type: SendType = null; text = new SendTextView(); diff --git a/libs/common/src/tools/send/services/send.service.ts b/libs/common/src/tools/send/services/send.service.ts index eddc35ae795..2b4a2684030 100644 --- a/libs/common/src/tools/send/services/send.service.ts +++ b/libs/common/src/tools/send/services/send.service.ts @@ -241,7 +241,7 @@ export class SendService implements InternalSendServiceAbstraction { key: SymmetricCryptoKey ): Promise<[EncString, EncArrayBuffer]> { const encFileName = await this.cryptoService.encrypt(fileName, key); - const encFileData = await this.cryptoService.encryptToBytes(data, key); + const encFileData = await this.cryptoService.encryptToBytes(new Uint8Array(data), key); return [encFileName, encFileData]; } diff --git a/libs/common/src/types/csprng.d.ts b/libs/common/src/types/csprng.d.ts index ec0a31a9f78..6d1c8a7cdb9 100644 --- a/libs/common/src/types/csprng.d.ts +++ b/libs/common/src/types/csprng.d.ts @@ -4,6 +4,6 @@ import { Opaque } from "type-fest"; // represents an array or string value generated from a // cryptographic secure pseudorandom number generator (CSPRNG) -type CsprngArray = Opaque; +type CsprngArray = Opaque; type CsprngString = Opaque; diff --git a/libs/common/src/vault/services/cipher.service.ts b/libs/common/src/vault/services/cipher.service.ts index 122eea4ee66..8eec2c6865a 100644 --- a/libs/common/src/vault/services/cipher.service.ts +++ b/libs/common/src/vault/services/cipher.service.ts @@ -630,7 +630,7 @@ export class CipherService implements CipherServiceAbstraction { async saveAttachmentRawWithServer( cipher: Cipher, filename: string, - data: ArrayBuffer, + data: Uint8Array, admin = false ): Promise { const key = await this.cryptoService.getOrgKey(cipher.organizationId); diff --git a/libs/node/src/services/node-crypto-function.service.ts b/libs/node/src/services/node-crypto-function.service.ts index a127074dc63..b824fe1b8ca 100644 --- a/libs/node/src/services/node-crypto-function.service.ts +++ b/libs/node/src/services/node-crypto-function.service.ts @@ -11,34 +11,34 @@ import { CsprngArray } from "@bitwarden/common/types/csprng"; export class NodeCryptoFunctionService implements CryptoFunctionService { pbkdf2( - password: string | ArrayBuffer, - salt: string | ArrayBuffer, + password: string | Uint8Array, + salt: string | Uint8Array, algorithm: "sha256" | "sha512", iterations: number - ): Promise { + ): Promise { const len = algorithm === "sha256" ? 32 : 64; const nodePassword = this.toNodeValue(password); const nodeSalt = this.toNodeValue(salt); - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { crypto.pbkdf2(nodePassword, nodeSalt, iterations, len, algorithm, (error, key) => { if (error != null) { reject(error); } else { - resolve(this.toArrayBuffer(key)); + resolve(this.toUint8Buffer(key)); } }); }); } async argon2( - password: string | ArrayBuffer, - salt: string | ArrayBuffer, + password: string | Uint8Array, + salt: string | Uint8Array, iterations: number, memory: number, parallelism: number - ): Promise { + ): Promise { const nodePassword = this.toNodeValue(password); - const nodeSalt = this.toNodeBuffer(this.toArrayBuffer(salt)); + const nodeSalt = this.toNodeBuffer(this.toUint8Buffer(salt)); const hash = await argon2.hash(nodePassword, { salt: nodeSalt, @@ -49,29 +49,29 @@ export class NodeCryptoFunctionService implements CryptoFunctionService { parallelism: parallelism, type: argon2.argon2id, }); - return this.toArrayBuffer(hash); + return this.toUint8Buffer(hash); } // ref: https://tools.ietf.org/html/rfc5869 async hkdf( - ikm: ArrayBuffer, - salt: string | ArrayBuffer, - info: string | ArrayBuffer, + ikm: Uint8Array, + salt: string | Uint8Array, + info: string | Uint8Array, outputByteSize: number, algorithm: "sha256" | "sha512" - ): Promise { - const saltBuf = this.toArrayBuffer(salt); + ): Promise { + const saltBuf = this.toUint8Buffer(salt); const prk = await this.hmac(ikm, saltBuf, algorithm); return this.hkdfExpand(prk, info, outputByteSize, algorithm); } // ref: https://tools.ietf.org/html/rfc5869 async hkdfExpand( - prk: ArrayBuffer, - info: string | ArrayBuffer, + prk: Uint8Array, + info: string | Uint8Array, outputByteSize: number, algorithm: "sha256" | "sha512" - ): Promise { + ): Promise { const hashLen = algorithm === "sha256" ? 32 : 64; if (outputByteSize > 255 * hashLen) { throw new Error("outputByteSize is too large."); @@ -80,7 +80,7 @@ export class NodeCryptoFunctionService implements CryptoFunctionService { if (prkArr.length < hashLen) { throw new Error("prk is too small."); } - const infoBuf = this.toArrayBuffer(info); + const infoBuf = this.toUint8Buffer(info); const infoArr = new Uint8Array(infoBuf); let runningOkmLength = 0; let previousT = new Uint8Array(0); @@ -91,39 +91,39 @@ export class NodeCryptoFunctionService implements CryptoFunctionService { t.set(previousT); t.set(infoArr, previousT.length); t.set([i + 1], t.length - 1); - previousT = new Uint8Array(await this.hmac(t.buffer, prk, algorithm)); + previousT = await this.hmac(t, prk, algorithm); okm.set(previousT, runningOkmLength); runningOkmLength += previousT.length; if (runningOkmLength >= outputByteSize) { break; } } - return okm.slice(0, outputByteSize).buffer; + return okm.slice(0, outputByteSize); } hash( - value: string | ArrayBuffer, + value: string | Uint8Array, algorithm: "sha1" | "sha256" | "sha512" | "md5" - ): Promise { + ): Promise { const nodeValue = this.toNodeValue(value); const hash = crypto.createHash(algorithm); hash.update(nodeValue); - return Promise.resolve(this.toArrayBuffer(hash.digest())); + return Promise.resolve(this.toUint8Buffer(hash.digest())); } hmac( - value: ArrayBuffer, - key: ArrayBuffer, + value: Uint8Array, + key: Uint8Array, algorithm: "sha1" | "sha256" | "sha512" - ): Promise { + ): Promise { const nodeValue = this.toNodeBuffer(value); const nodeKey = this.toNodeBuffer(key); const hmac = crypto.createHmac(algorithm, nodeKey); hmac.update(nodeValue); - return Promise.resolve(this.toArrayBuffer(hmac.digest())); + return Promise.resolve(this.toUint8Buffer(hmac.digest())); } - async compare(a: ArrayBuffer, b: ArrayBuffer): Promise { + async compare(a: Uint8Array, b: Uint8Array): Promise { const key = await this.randomBytes(32); const mac1 = await this.hmac(a, key, "sha256"); const mac2 = await this.hmac(b, key, "sha256"); @@ -143,24 +143,24 @@ export class NodeCryptoFunctionService implements CryptoFunctionService { } hmacFast( - value: ArrayBuffer, - key: ArrayBuffer, + value: Uint8Array, + key: Uint8Array, algorithm: "sha1" | "sha256" | "sha512" - ): Promise { + ): Promise { return this.hmac(value, key, algorithm); } - compareFast(a: ArrayBuffer, b: ArrayBuffer): Promise { + compareFast(a: Uint8Array, b: Uint8Array): Promise { return this.compare(a, b); } - aesEncrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise { + aesEncrypt(data: Uint8Array, iv: Uint8Array, key: Uint8Array): Promise { const nodeData = this.toNodeBuffer(data); const nodeIv = this.toNodeBuffer(iv); const nodeKey = this.toNodeBuffer(key); const cipher = crypto.createCipheriv("aes-256-cbc", nodeKey, nodeIv); const encBuf = Buffer.concat([cipher.update(nodeData), cipher.final()]); - return Promise.resolve(this.toArrayBuffer(encBuf)); + return Promise.resolve(this.toUint8Buffer(encBuf)); } aesDecryptFastParameters( @@ -168,70 +168,70 @@ export class NodeCryptoFunctionService implements CryptoFunctionService { iv: string, mac: string, key: SymmetricCryptoKey - ): DecryptParameters { - const p = new DecryptParameters(); + ): DecryptParameters { + const p = new DecryptParameters(); p.encKey = key.encKey; - p.data = Utils.fromB64ToArray(data).buffer; - p.iv = Utils.fromB64ToArray(iv).buffer; + p.data = Utils.fromB64ToArray(data); + p.iv = Utils.fromB64ToArray(iv); const macData = new Uint8Array(p.iv.byteLength + p.data.byteLength); macData.set(new Uint8Array(p.iv), 0); macData.set(new Uint8Array(p.data), p.iv.byteLength); - p.macData = macData.buffer; + p.macData = macData; if (key.macKey != null) { p.macKey = key.macKey; } if (mac != null) { - p.mac = Utils.fromB64ToArray(mac).buffer; + p.mac = Utils.fromB64ToArray(mac); } return p; } - async aesDecryptFast(parameters: DecryptParameters): Promise { + async aesDecryptFast(parameters: DecryptParameters): Promise { const decBuf = await this.aesDecrypt(parameters.data, parameters.iv, parameters.encKey); return Utils.fromBufferToUtf8(decBuf); } - aesDecrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise { + aesDecrypt(data: Uint8Array, iv: Uint8Array, key: Uint8Array): Promise { const nodeData = this.toNodeBuffer(data); const nodeIv = this.toNodeBuffer(iv); const nodeKey = this.toNodeBuffer(key); const decipher = crypto.createDecipheriv("aes-256-cbc", nodeKey, nodeIv); const decBuf = Buffer.concat([decipher.update(nodeData), decipher.final()]); - return Promise.resolve(this.toArrayBuffer(decBuf)); + return Promise.resolve(this.toUint8Buffer(decBuf)); } rsaEncrypt( - data: ArrayBuffer, - publicKey: ArrayBuffer, + data: Uint8Array, + publicKey: Uint8Array, algorithm: "sha1" | "sha256" - ): Promise { + ): Promise { if (algorithm === "sha256") { throw new Error("Node crypto does not support RSA-OAEP SHA-256"); } const pem = this.toPemPublicKey(publicKey); const decipher = crypto.publicEncrypt(pem, this.toNodeBuffer(data)); - return Promise.resolve(this.toArrayBuffer(decipher)); + return Promise.resolve(this.toUint8Buffer(decipher)); } rsaDecrypt( - data: ArrayBuffer, - privateKey: ArrayBuffer, + data: Uint8Array, + privateKey: Uint8Array, algorithm: "sha1" | "sha256" - ): Promise { + ): Promise { if (algorithm === "sha256") { throw new Error("Node crypto does not support RSA-OAEP SHA-256"); } const pem = this.toPemPrivateKey(privateKey); const decipher = crypto.privateDecrypt(pem, this.toNodeBuffer(data)); - return Promise.resolve(this.toArrayBuffer(decipher)); + return Promise.resolve(this.toUint8Buffer(decipher)); } - rsaExtractPublicKey(privateKey: ArrayBuffer): Promise { + rsaExtractPublicKey(privateKey: Uint8Array): Promise { const privateKeyByteString = Utils.fromBufferToByteString(privateKey); const privateKeyAsn1 = forge.asn1.fromDer(privateKeyByteString); const forgePrivateKey: any = forge.pki.privateKeyFromAsn1(privateKeyAsn1); @@ -239,11 +239,11 @@ export class NodeCryptoFunctionService implements CryptoFunctionService { const publicKeyAsn1 = forge.pki.publicKeyToAsn1(forgePublicKey); const publicKeyByteString = forge.asn1.toDer(publicKeyAsn1).data; const publicKeyArray = Utils.fromByteStringToArray(publicKeyByteString); - return Promise.resolve(publicKeyArray.buffer); + return Promise.resolve(publicKeyArray); } - async rsaGenerateKeyPair(length: 1024 | 2048 | 4096): Promise<[ArrayBuffer, ArrayBuffer]> { - return new Promise<[ArrayBuffer, ArrayBuffer]>((resolve, reject) => { + async rsaGenerateKeyPair(length: 1024 | 2048 | 4096): Promise<[Uint8Array, Uint8Array]> { + return new Promise<[Uint8Array, Uint8Array]>((resolve, reject) => { forge.pki.rsa.generateKeyPair( { bits: length, @@ -265,7 +265,7 @@ export class NodeCryptoFunctionService implements CryptoFunctionService { const privateKeyByteString = forge.asn1.toDer(privateKeyPkcs8).getBytes(); const privateKey = Utils.fromByteStringToArray(privateKeyByteString); - resolve([publicKey.buffer, privateKey.buffer]); + resolve([publicKey, privateKey]); } ); }); @@ -277,13 +277,13 @@ export class NodeCryptoFunctionService implements CryptoFunctionService { if (error != null) { reject(error); } else { - resolve(this.toArrayBuffer(bytes) as CsprngArray); + resolve(this.toUint8Buffer(bytes) as CsprngArray); } }); }); } - private toNodeValue(value: string | ArrayBuffer): string | Buffer { + private toNodeValue(value: string | Uint8Array): string | Buffer { let nodeValue: string | Buffer; if (typeof value === "string") { nodeValue = value; @@ -293,21 +293,21 @@ export class NodeCryptoFunctionService implements CryptoFunctionService { return nodeValue; } - private toNodeBuffer(value: ArrayBuffer): Buffer { - return Buffer.from(new Uint8Array(value) as any); + private toNodeBuffer(value: Uint8Array): Buffer { + return Buffer.from(value); } - private toArrayBuffer(value: Buffer | string | ArrayBuffer): ArrayBuffer { - let buf: ArrayBuffer; + private toUint8Buffer(value: Buffer | string | Uint8Array): Uint8Array { + let buf: Uint8Array; if (typeof value === "string") { - buf = Utils.fromUtf8ToArray(value).buffer; + buf = Utils.fromUtf8ToArray(value); } else { - buf = new Uint8Array(value).buffer; + buf = value; } return buf; } - private toPemPrivateKey(key: ArrayBuffer): string { + private toPemPrivateKey(key: Uint8Array): string { const byteString = Utils.fromBufferToByteString(key); const asn1 = forge.asn1.fromDer(byteString); const privateKey = forge.pki.privateKeyFromAsn1(asn1); @@ -316,7 +316,7 @@ export class NodeCryptoFunctionService implements CryptoFunctionService { return forge.pki.privateKeyInfoToPem(privateKeyInfo); } - private toPemPublicKey(key: ArrayBuffer): string { + private toPemPublicKey(key: Uint8Array): string { const byteString = Utils.fromBufferToByteString(key); const asn1 = forge.asn1.fromDer(byteString); const publicKey = forge.pki.publicKeyFromAsn1(asn1);