mirror of
https://github.com/bitwarden/browser
synced 2026-02-20 11:24:07 +00:00
Remove SymmetricCryptoKey buffer representation
This commit is contained in:
@@ -60,7 +60,7 @@ export class OrganizationUserResetPasswordService
|
||||
if (userKey == null) {
|
||||
throw new Error("No user key found");
|
||||
}
|
||||
const encryptedKey = await this.encryptService.rsaEncrypt(userKey.key, publicKey);
|
||||
const encryptedKey = await this.encryptService.rsaEncrypt(userKey.toEncoded(), publicKey);
|
||||
|
||||
return encryptedKey.encryptedString;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { mock, MockProxy } from "jest-mock-extended";
|
||||
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { UserKey } from "@bitwarden/common/types/key";
|
||||
import { KeyService } from "@bitwarden/key-management";
|
||||
|
||||
import { RotateableKeySetService } from "./rotateable-key-set.service";
|
||||
@@ -34,7 +35,7 @@ describe("RotateableKeySetService", () => {
|
||||
const encryptedPublicKey = Symbol();
|
||||
const encryptedPrivateKey = Symbol();
|
||||
keyService.makeKeyPair.mockResolvedValue(["publicKey", encryptedPrivateKey as any]);
|
||||
keyService.getUserKey.mockResolvedValue({ key: userKey.key } as any);
|
||||
keyService.getUserKey.mockResolvedValue(userKey as UserKey);
|
||||
encryptService.rsaEncrypt.mockResolvedValue(encryptedUserKey as any);
|
||||
encryptService.encrypt.mockResolvedValue(encryptedPublicKey as any);
|
||||
|
||||
|
||||
@@ -25,7 +25,10 @@ export class RotateableKeySetService {
|
||||
|
||||
const userKey = await this.keyService.getUserKey();
|
||||
const rawPublicKey = Utils.fromB64ToArray(publicKey);
|
||||
const encryptedUserKey = await this.encryptService.rsaEncrypt(userKey.key, rawPublicKey);
|
||||
const encryptedUserKey = await this.encryptService.rsaEncrypt(
|
||||
userKey.toEncoded(),
|
||||
rawPublicKey,
|
||||
);
|
||||
const encryptedPublicKey = await this.encryptService.encrypt(rawPublicKey, userKey);
|
||||
return new RotateableKeySet(encryptedUserKey, encryptedPublicKey, encryptedPrivateKey);
|
||||
}
|
||||
@@ -60,7 +63,10 @@ export class RotateableKeySetService {
|
||||
throw new Error("failed to rotate key set: could not decrypt public key");
|
||||
}
|
||||
const newEncryptedPublicKey = await this.encryptService.encrypt(publicKey, newUserKey);
|
||||
const newEncryptedUserKey = await this.encryptService.rsaEncrypt(newUserKey.key, publicKey);
|
||||
const newEncryptedUserKey = await this.encryptService.rsaEncrypt(
|
||||
newUserKey.toEncoded(),
|
||||
publicKey,
|
||||
);
|
||||
|
||||
const newRotateableKeySet = new RotateableKeySet<ExternalKey>(
|
||||
newEncryptedUserKey,
|
||||
|
||||
@@ -209,7 +209,10 @@ export class SetPasswordComponent extends BaseChangePasswordComponent implements
|
||||
|
||||
// RSA Encrypt user key with organization public key
|
||||
const userKey = await this.keyService.getUserKey();
|
||||
const encryptedUserKey = await this.encryptService.rsaEncrypt(userKey.key, publicKey);
|
||||
const encryptedUserKey = await this.encryptService.rsaEncrypt(
|
||||
userKey.toEncoded(),
|
||||
publicKey,
|
||||
);
|
||||
|
||||
const resetRequest = new OrganizationUserResetPasswordEnrollmentRequest();
|
||||
resetRequest.masterPasswordHash = masterPasswordHash;
|
||||
|
||||
@@ -212,7 +212,7 @@ describe("DefaultSetPasswordJitService", () => {
|
||||
// Assert
|
||||
expect(apiService.setPassword).toHaveBeenCalledWith(setPasswordRequest);
|
||||
expect(organizationApiService.getKeys).toHaveBeenCalledWith(orgId);
|
||||
expect(encryptService.rsaEncrypt).toHaveBeenCalledWith(userKey.key, orgPublicKey);
|
||||
expect(encryptService.rsaEncrypt).toHaveBeenCalledWith(userKey.toEncoded(), orgPublicKey);
|
||||
expect(
|
||||
organizationUserApiService.putOrganizationUserResetPasswordEnrollment,
|
||||
).toHaveBeenCalled();
|
||||
|
||||
@@ -159,7 +159,7 @@ export class DefaultSetPasswordJitService implements SetPasswordJitService {
|
||||
throw new Error("userKey not found. Could not handle reset password auto enroll.");
|
||||
}
|
||||
|
||||
const encryptedUserKey = await this.encryptService.rsaEncrypt(userKey.key, publicKey);
|
||||
const encryptedUserKey = await this.encryptService.rsaEncrypt(userKey.toEncoded(), publicKey);
|
||||
|
||||
const resetRequest = new OrganizationUserResetPasswordEnrollmentRequest();
|
||||
resetRequest.masterPasswordHash = masterKeyHash;
|
||||
|
||||
@@ -117,7 +117,9 @@ describe("AuthRequestService", () => {
|
||||
});
|
||||
|
||||
it("should use the user key if the master key and hash do not exist", async () => {
|
||||
keyService.getUserKey.mockResolvedValueOnce({ key: new Uint8Array(64) } as UserKey);
|
||||
keyService.getUserKey.mockResolvedValueOnce(
|
||||
new SymmetricCryptoKey(new Uint8Array(64)) as UserKey,
|
||||
);
|
||||
|
||||
await sut.approveOrDenyAuthRequest(
|
||||
true,
|
||||
|
||||
@@ -117,7 +117,7 @@ export class AuthRequestService implements AuthRequestServiceAbstraction {
|
||||
keyToEncrypt = (masterKey.inner() as Aes256CbcKey).encryptionKey;
|
||||
} else {
|
||||
const userKey = await this.keyService.getUserKey();
|
||||
keyToEncrypt = userKey.key;
|
||||
keyToEncrypt = userKey.toEncoded();
|
||||
}
|
||||
|
||||
const encryptedKey = await this.encryptService.rsaEncrypt(keyToEncrypt, pubKey);
|
||||
|
||||
@@ -10,7 +10,10 @@ import { KeyGenerationService } from "@bitwarden/common/platform/abstractions/ke
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { EncString, EncryptedString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import {
|
||||
Aes256CbcKey,
|
||||
SymmetricCryptoKey,
|
||||
} from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import {
|
||||
PIN_DISK,
|
||||
PIN_MEMORY,
|
||||
@@ -193,7 +196,7 @@ export class PinService implements PinServiceAbstraction {
|
||||
|
||||
const pinKey = await this.makePinKey(pin, email, kdfConfig);
|
||||
|
||||
return await this.encryptService.encrypt(userKey.key, pinKey);
|
||||
return await this.encryptService.encrypt(userKey.toEncoded(), pinKey);
|
||||
}
|
||||
|
||||
async storePinKeyEncryptedUserKey(
|
||||
@@ -258,7 +261,7 @@ export class PinService implements PinServiceAbstraction {
|
||||
|
||||
async makePinKey(pin: string, salt: string, kdfConfig: KdfConfig): Promise<PinKey> {
|
||||
const pinKey = await this.keyGenerationService.deriveKeyFromPassword(pin, salt, kdfConfig);
|
||||
return (await this.keyGenerationService.stretchKey(pinKey)) as PinKey;
|
||||
return (await this.keyGenerationService.stretchKey(pinKey.inner() as Aes256CbcKey)) as PinKey;
|
||||
}
|
||||
|
||||
async getPinLockType(userId: UserId): Promise<PinLockType> {
|
||||
|
||||
@@ -189,7 +189,7 @@ describe("PinService", () => {
|
||||
await sut.createPinKeyEncryptedUserKey(mockPin, mockUserKey, mockUserId);
|
||||
|
||||
// Assert
|
||||
expect(encryptService.encrypt).toHaveBeenCalledWith(mockUserKey.key, mockPinKey);
|
||||
expect(encryptService.encrypt).toHaveBeenCalledWith(mockUserKey.toEncoded(), mockPinKey);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -327,7 +327,7 @@ describe("PinService", () => {
|
||||
mockUserEmail,
|
||||
DEFAULT_KDF_CONFIG,
|
||||
);
|
||||
expect(keyGenerationService.stretchKey).toHaveBeenCalledWith(mockPinKey);
|
||||
expect(keyGenerationService.stretchKey).toHaveBeenCalledWith(mockPinKey.inner());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -499,7 +499,7 @@ describe("PinService", () => {
|
||||
|
||||
async function mockDecryptAndMigrateOldPinKeyEncryptedMasterKeyFn() {
|
||||
sut.makePinKey = jest.fn().mockResolvedValue(mockPinKey);
|
||||
encryptService.decryptToBytes.mockResolvedValue(mockMasterKey.key);
|
||||
encryptService.decryptToBytes.mockResolvedValue(mockMasterKey.toEncoded());
|
||||
|
||||
stateService.getEncryptedCryptoSymmetricKey.mockResolvedValue(mockUserKey.keyB64);
|
||||
masterPasswordService.mock.decryptUserKeyWithMasterKey.mockResolvedValue(mockUserKey);
|
||||
@@ -521,7 +521,7 @@ describe("PinService", () => {
|
||||
.fn()
|
||||
.mockResolvedValue(pinKeyEncryptedUserKeyPersistant);
|
||||
sut.makePinKey = jest.fn().mockResolvedValue(mockPinKey);
|
||||
encryptService.decryptToBytes.mockResolvedValue(mockUserKey.key);
|
||||
encryptService.decryptToBytes.mockResolvedValue(mockUserKey.toEncoded());
|
||||
}
|
||||
|
||||
function mockPinEncryptedKeyDataByPinLockType(
|
||||
|
||||
@@ -156,7 +156,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
deviceKeyEncryptedDevicePrivateKey,
|
||||
] = await Promise.all([
|
||||
// Encrypt user key with the DevicePublicKey
|
||||
this.encryptService.rsaEncrypt(userKey.key, devicePublicKey),
|
||||
this.encryptService.rsaEncrypt(userKey.toEncoded(), devicePublicKey),
|
||||
|
||||
// Encrypt devicePublicKey with user key
|
||||
this.encryptService.encrypt(devicePublicKey, userKey),
|
||||
@@ -224,7 +224,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
|
||||
// Encrypt the brand new user key with the now-decrypted public key for the device
|
||||
const encryptedNewUserKey = await this.encryptService.rsaEncrypt(
|
||||
newUserKey.key,
|
||||
newUserKey.toEncoded(),
|
||||
decryptedDevicePublicKey,
|
||||
);
|
||||
|
||||
|
||||
@@ -731,8 +731,8 @@ describe("deviceTrustService", () => {
|
||||
|
||||
// Mock the decryption of the public key with the old user key
|
||||
encryptService.decryptToBytes.mockImplementationOnce((_encValue, privateKeyValue) => {
|
||||
expect(privateKeyValue.key.byteLength).toBe(64);
|
||||
expect(new Uint8Array(privateKeyValue.key)[0]).toBe(FakeOldUserKeyMarker);
|
||||
expect(privateKeyValue.inner().type).toBe(EncryptionType.AesCbc256_HmacSha256_B64);
|
||||
expect(new Uint8Array(privateKeyValue.toEncoded())[0]).toBe(FakeOldUserKeyMarker);
|
||||
const data = new Uint8Array(250);
|
||||
data.fill(FakeDecryptedPublicKeyMarker, 0, 1);
|
||||
return Promise.resolve(data);
|
||||
@@ -752,7 +752,7 @@ describe("deviceTrustService", () => {
|
||||
expect(plainValue).toBeInstanceOf(Uint8Array);
|
||||
expect(new Uint8Array(plainValue as Uint8Array)[0]).toBe(FakeDecryptedPublicKeyMarker);
|
||||
|
||||
expect(new Uint8Array(key.key)[0]).toBe(FakeNewUserKeyMarker);
|
||||
expect(new Uint8Array(key.toEncoded())[0]).toBe(FakeNewUserKeyMarker);
|
||||
return Promise.resolve(
|
||||
new EncString("2.ZW5jcnlwdGVkcHVibGlj|ZW5jcnlwdGVkcHVibGlj|ZW5jcnlwdGVkcHVibGlj"),
|
||||
);
|
||||
|
||||
@@ -8,7 +8,10 @@ import { LogService } from "../../../platform/abstractions/log.service";
|
||||
import { StateService } from "../../../platform/abstractions/state.service";
|
||||
import { EncryptionType } from "../../../platform/enums";
|
||||
import { EncryptedString, EncString } from "../../../platform/models/domain/enc-string";
|
||||
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
|
||||
import {
|
||||
Aes256CbcKey,
|
||||
SymmetricCryptoKey,
|
||||
} from "../../../platform/models/domain/symmetric-crypto-key";
|
||||
import {
|
||||
MASTER_PASSWORD_DISK,
|
||||
MASTER_PASSWORD_MEMORY,
|
||||
@@ -185,7 +188,7 @@ export class MasterPasswordService implements InternalMasterPasswordServiceAbstr
|
||||
"Content: User Key; Encrypting Key: Master Key",
|
||||
);
|
||||
} else if (userKey.encryptionType === EncryptionType.AesCbc256_HmacSha256_B64) {
|
||||
const newKey = await this.keyGenerationService.stretchKey(masterKey);
|
||||
const newKey = await this.keyGenerationService.stretchKey(masterKey.inner() as Aes256CbcKey);
|
||||
decUserKey = await this.encryptService.decryptToBytes(
|
||||
userKey,
|
||||
newKey,
|
||||
|
||||
@@ -2,6 +2,8 @@ import { mock, MockProxy } from "jest-mock-extended";
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
|
||||
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { UserKey } from "@bitwarden/common/types/key";
|
||||
import { KeyService } from "@bitwarden/key-management";
|
||||
|
||||
import { OrganizationApiServiceAbstraction } from "../../admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
@@ -99,7 +101,9 @@ describe("PasswordResetEnrollmentServiceImplementation", () => {
|
||||
};
|
||||
activeAccountSubject.next(Object.assign(user1AccountInfo, { id: "userId" as UserId }));
|
||||
|
||||
keyService.getUserKey.mockResolvedValue({ key: "key" } as any);
|
||||
keyService.getUserKey.mockResolvedValue(
|
||||
new SymmetricCryptoKey(new Uint8Array(64)) as UserKey,
|
||||
);
|
||||
encryptService.rsaEncrypt.mockResolvedValue(encryptedKey as any);
|
||||
|
||||
await service.enroll("orgId");
|
||||
@@ -124,7 +128,11 @@ describe("PasswordResetEnrollmentServiceImplementation", () => {
|
||||
organizationApiService.getKeys.mockResolvedValue(orgKeyResponse as any);
|
||||
encryptService.rsaEncrypt.mockResolvedValue(encryptedKey as any);
|
||||
|
||||
await service.enroll("orgId", "userId", { key: "key" } as any);
|
||||
await service.enroll(
|
||||
"orgId",
|
||||
"userId",
|
||||
new SymmetricCryptoKey(new Uint8Array(64)) as UserKey,
|
||||
);
|
||||
|
||||
expect(
|
||||
organizationUserApiService.putOrganizationUserResetPasswordEnrollment,
|
||||
|
||||
@@ -51,7 +51,7 @@ export class PasswordResetEnrollmentServiceImplementation
|
||||
userId ?? (await firstValueFrom(this.accountService.activeAccount$.pipe(map((a) => a?.id))));
|
||||
userKey = userKey ?? (await this.keyService.getUserKey(userId));
|
||||
// RSA Encrypt user's userKey.key with organization public key
|
||||
const encryptedKey = await this.encryptService.rsaEncrypt(userKey.key, orgPublicKey);
|
||||
const encryptedKey = await this.encryptService.rsaEncrypt(userKey.toEncoded(), orgPublicKey);
|
||||
|
||||
const resetRequest = new OrganizationUserResetPasswordEnrollmentRequest();
|
||||
resetRequest.resetPasswordKey = encryptedKey.encryptedString;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
|
||||
import { EncryptionType } from "@bitwarden/common/platform/enums";
|
||||
|
||||
import { CryptoFunctionService } from "../../../platform/abstractions/crypto-function.service";
|
||||
|
||||
import { WebAuthnLoginPrfKeyService } from "./webauthn-login-prf-key.service";
|
||||
@@ -21,7 +23,7 @@ describe("WebAuthnLoginPrfKeyService", () => {
|
||||
|
||||
const result = await service.createSymmetricKeyFromPrf(randomBytes(32));
|
||||
|
||||
expect(result.key.length).toBe(64);
|
||||
expect(result.inner().type).toBe(EncryptionType.AesCbc256_HmacSha256_B64);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { KdfConfig } from "@bitwarden/key-management";
|
||||
|
||||
import { CsprngArray } from "../../types/csprng";
|
||||
import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key";
|
||||
import { Aes256CbcKey, SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key";
|
||||
|
||||
export abstract class KeyGenerationService {
|
||||
/**
|
||||
@@ -60,5 +60,5 @@ export abstract class KeyGenerationService {
|
||||
* @param key 32 byte key.
|
||||
* @returns 64 byte derived key.
|
||||
*/
|
||||
abstract stretchKey(key: SymmetricCryptoKey): Promise<SymmetricCryptoKey>;
|
||||
abstract stretchKey(key: Aes256CbcKey): Promise<SymmetricCryptoKey>;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ describe("SymmetricCryptoKey", () => {
|
||||
const cryptoKey = new SymmetricCryptoKey(key);
|
||||
|
||||
expect(cryptoKey).toEqual({
|
||||
key: key,
|
||||
keyB64: "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=",
|
||||
innerKey: {
|
||||
type: EncryptionType.AesCbc256_B64,
|
||||
@@ -33,7 +32,6 @@ describe("SymmetricCryptoKey", () => {
|
||||
const cryptoKey = new SymmetricCryptoKey(key);
|
||||
|
||||
expect(cryptoKey).toEqual({
|
||||
key: key,
|
||||
keyB64:
|
||||
"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+Pw==",
|
||||
innerKey: {
|
||||
|
||||
@@ -24,7 +24,6 @@ export type Aes256CbcKey = {
|
||||
export class SymmetricCryptoKey {
|
||||
private innerKey: Aes256CbcHmacKey | Aes256CbcKey;
|
||||
|
||||
key: Uint8Array;
|
||||
keyB64: string;
|
||||
|
||||
/**
|
||||
@@ -40,7 +39,6 @@ export class SymmetricCryptoKey {
|
||||
type: EncryptionType.AesCbc256_B64,
|
||||
encryptionKey: key,
|
||||
};
|
||||
this.key = key;
|
||||
this.keyB64 = this.toBase64();
|
||||
} else if (key.byteLength === 64) {
|
||||
this.innerKey = {
|
||||
@@ -48,7 +46,6 @@ export class SymmetricCryptoKey {
|
||||
encryptionKey: key.slice(0, 32),
|
||||
authenticationKey: key.slice(32),
|
||||
};
|
||||
this.key = key;
|
||||
this.keyB64 = this.toBase64();
|
||||
} else {
|
||||
throw new Error(`Unsupported encType/key length ${key.byteLength}`);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { PBKDF2KdfConfig, Argon2KdfConfig } from "@bitwarden/key-management";
|
||||
|
||||
import { CsprngArray } from "../../types/csprng";
|
||||
import { CryptoFunctionService } from "../abstractions/crypto-function.service";
|
||||
import { EncryptionType } from "../enums";
|
||||
|
||||
import { KeyGenerationService } from "./key-generation.service";
|
||||
|
||||
@@ -52,7 +53,7 @@ describe("KeyGenerationService", () => {
|
||||
|
||||
expect(salt).toEqual(inputSalt);
|
||||
expect(material).toEqual(inputMaterial);
|
||||
expect(derivedKey.key.length).toEqual(64);
|
||||
expect(derivedKey.inner().type).toEqual(EncryptionType.AesCbc256_HmacSha256_B64);
|
||||
},
|
||||
);
|
||||
});
|
||||
@@ -67,7 +68,7 @@ describe("KeyGenerationService", () => {
|
||||
|
||||
const key = await sut.deriveKeyFromMaterial(material, salt, purpose);
|
||||
|
||||
expect(key.key.length).toEqual(64);
|
||||
expect(key.inner().type).toEqual(EncryptionType.AesCbc256_HmacSha256_B64);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -81,7 +82,7 @@ describe("KeyGenerationService", () => {
|
||||
|
||||
const key = await sut.deriveKeyFromPassword(password, salt, kdfConfig);
|
||||
|
||||
expect(key.key.length).toEqual(32);
|
||||
expect(key.inner().type).toEqual(EncryptionType.AesCbc256_B64);
|
||||
});
|
||||
|
||||
it("should derive a 32 byte key from a password using argon2id", async () => {
|
||||
@@ -94,7 +95,7 @@ describe("KeyGenerationService", () => {
|
||||
|
||||
const key = await sut.deriveKeyFromPassword(password, salt, kdfConfig);
|
||||
|
||||
expect(key.key.length).toEqual(32);
|
||||
expect(key.inner().type).toEqual(EncryptionType.AesCbc256_B64);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ import { CsprngArray } from "../../types/csprng";
|
||||
import { CryptoFunctionService } from "../abstractions/crypto-function.service";
|
||||
import { KeyGenerationService as KeyGenerationServiceAbstraction } from "../abstractions/key-generation.service";
|
||||
import { Utils } from "../misc/utils";
|
||||
import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key";
|
||||
import { Aes256CbcKey, SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key";
|
||||
|
||||
export class KeyGenerationService implements KeyGenerationServiceAbstraction {
|
||||
constructor(private cryptoFunctionService: CryptoFunctionService) {}
|
||||
@@ -78,10 +78,20 @@ export class KeyGenerationService implements KeyGenerationServiceAbstraction {
|
||||
return new SymmetricCryptoKey(key);
|
||||
}
|
||||
|
||||
async stretchKey(key: SymmetricCryptoKey): Promise<SymmetricCryptoKey> {
|
||||
async stretchKey(key: Aes256CbcKey): Promise<SymmetricCryptoKey> {
|
||||
const newKey = new Uint8Array(64);
|
||||
const encKey = await this.cryptoFunctionService.hkdfExpand(key.key, "enc", 32, "sha256");
|
||||
const macKey = await this.cryptoFunctionService.hkdfExpand(key.key, "mac", 32, "sha256");
|
||||
const encKey = await this.cryptoFunctionService.hkdfExpand(
|
||||
key.encryptionKey,
|
||||
"enc",
|
||||
32,
|
||||
"sha256",
|
||||
);
|
||||
const macKey = await this.cryptoFunctionService.hkdfExpand(
|
||||
key.encryptionKey,
|
||||
"mac",
|
||||
32,
|
||||
"sha256",
|
||||
);
|
||||
|
||||
newKey.set(new Uint8Array(encKey));
|
||||
newKey.set(new Uint8Array(macKey), 32);
|
||||
|
||||
@@ -271,7 +271,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
key,
|
||||
).then(async () => {
|
||||
if (model.key != null) {
|
||||
attachment.key = await this.encryptService.encrypt(model.key.key, key);
|
||||
attachment.key = await this.encryptService.encrypt(model.key.toEncoded(), key);
|
||||
}
|
||||
encAttachments.push(attachment);
|
||||
});
|
||||
@@ -1812,7 +1812,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
|
||||
// Then, we have to encrypt the cipher key with the proper key.
|
||||
cipher.key = await this.encryptService.encrypt(
|
||||
decryptedCipherKey.key,
|
||||
decryptedCipherKey.toEncoded(),
|
||||
keyForCipherKeyEncryption,
|
||||
);
|
||||
|
||||
|
||||
@@ -505,7 +505,7 @@ describe("keyService", () => {
|
||||
const output = new Uint8Array(64);
|
||||
output.set(encryptedPrivateKey.dataBytes);
|
||||
output.set(
|
||||
key.key.subarray(0, 64 - encryptedPrivateKey.dataBytes.length),
|
||||
key.toEncoded().subarray(0, 64 - encryptedPrivateKey.dataBytes.length),
|
||||
encryptedPrivateKey.dataBytes.length,
|
||||
);
|
||||
return output;
|
||||
@@ -789,7 +789,7 @@ describe("keyService", () => {
|
||||
masterPasswordService.masterKeyHashSubject.next(storedMasterKeyHash);
|
||||
|
||||
cryptoFunctionService.pbkdf2
|
||||
.calledWith(masterKey.key, masterPassword as string, "sha256", 2)
|
||||
.calledWith(masterKey.inner().encryptionKey, masterPassword as string, "sha256", 2)
|
||||
.mockResolvedValue(Utils.fromB64ToArray(mockReturnedHash));
|
||||
|
||||
const actualDidMatch = await keyService.compareKeyHash(
|
||||
|
||||
@@ -24,7 +24,7 @@ import { KeyGenerationService } from "@bitwarden/common/platform/abstractions/ke
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { KeySuffixOptions, HashPurpose } from "@bitwarden/common/platform/enums";
|
||||
import { KeySuffixOptions, HashPurpose, EncryptionType } from "@bitwarden/common/platform/enums";
|
||||
import { convertValues } from "@bitwarden/common/platform/misc/convert-values";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { EFFLongWordList } from "@bitwarden/common/platform/misc/wordlist";
|
||||
@@ -232,7 +232,7 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
}
|
||||
|
||||
const newUserKey = await this.keyGenerationService.createKey(512);
|
||||
return this.buildProtectedSymmetricKey(masterKey, newUserKey.key);
|
||||
return this.buildProtectedSymmetricKey(masterKey, newUserKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -320,7 +320,7 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
userKey?: UserKey,
|
||||
): Promise<[UserKey, EncString]> {
|
||||
userKey ||= await this.getUserKey();
|
||||
return await this.buildProtectedSymmetricKey(masterKey, userKey.key);
|
||||
return await this.buildProtectedSymmetricKey(masterKey, userKey);
|
||||
}
|
||||
|
||||
// TODO: move to MasterPasswordService
|
||||
@@ -343,7 +343,12 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
}
|
||||
|
||||
const iterations = hashPurpose === HashPurpose.LocalAuthorization ? 2 : 1;
|
||||
const hash = await this.cryptoFunctionService.pbkdf2(key.key, password, "sha256", iterations);
|
||||
const hash = await this.cryptoFunctionService.pbkdf2(
|
||||
key.inner().encryptionKey,
|
||||
password,
|
||||
"sha256",
|
||||
iterations,
|
||||
);
|
||||
return Utils.fromBufferToB64(hash);
|
||||
}
|
||||
|
||||
@@ -430,7 +435,7 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
}
|
||||
|
||||
const newSymKey = await this.keyGenerationService.createKey(512);
|
||||
return this.buildProtectedSymmetricKey(key, newSymKey.key);
|
||||
return this.buildProtectedSymmetricKey(key, newSymKey);
|
||||
}
|
||||
|
||||
private async clearOrgKeys(userId: UserId): Promise<void> {
|
||||
@@ -490,7 +495,7 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
throw new Error("No public key found.");
|
||||
}
|
||||
|
||||
const encShareKey = await this.encryptService.rsaEncrypt(shareKey.key, publicKey);
|
||||
const encShareKey = await this.encryptService.rsaEncrypt(shareKey.toEncoded(), publicKey);
|
||||
return [encShareKey, shareKey as T];
|
||||
}
|
||||
|
||||
@@ -821,19 +826,23 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
}
|
||||
|
||||
private async buildProtectedSymmetricKey<T extends SymmetricCryptoKey>(
|
||||
encryptionKey: SymmetricCryptoKey,
|
||||
newSymKey: Uint8Array,
|
||||
protectingKey: SymmetricCryptoKey,
|
||||
protectedKey: SymmetricCryptoKey,
|
||||
): Promise<[T, EncString]> {
|
||||
let protectedSymKey: EncString;
|
||||
if (encryptionKey.key.byteLength === 32) {
|
||||
const stretchedEncryptionKey = await this.keyGenerationService.stretchKey(encryptionKey);
|
||||
protectedSymKey = await this.encryptService.encrypt(newSymKey, stretchedEncryptionKey);
|
||||
} else if (encryptionKey.key.byteLength === 64) {
|
||||
protectedSymKey = await this.encryptService.encrypt(newSymKey, encryptionKey);
|
||||
const protectingKeyInner = protectingKey.inner();
|
||||
if (protectingKeyInner.type === EncryptionType.AesCbc256_B64) {
|
||||
const stretchedEncryptionKey = await this.keyGenerationService.stretchKey(protectingKeyInner);
|
||||
protectedSymKey = await this.encryptService.encrypt(
|
||||
protectedKey.toEncoded(),
|
||||
stretchedEncryptionKey,
|
||||
);
|
||||
} else if (protectingKeyInner.type === EncryptionType.AesCbc256_HmacSha256_B64) {
|
||||
protectedSymKey = await this.encryptService.encrypt(protectedKey.toEncoded(), protectingKey);
|
||||
} else {
|
||||
throw new Error("Invalid key size.");
|
||||
throw new Error("Unsupported key type");
|
||||
}
|
||||
return [new SymmetricCryptoKey(newSymKey) as T, protectedSymKey];
|
||||
return [new SymmetricCryptoKey(protectedKey.toEncoded()) as T, protectedSymKey];
|
||||
}
|
||||
|
||||
// --LEGACY METHODS--
|
||||
|
||||
Reference in New Issue
Block a user