1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-10 05:13:29 +00:00

[PM-21001] Move auth code to new encrypt service interface (#14542)

* Add new encrypt service functions

* Undo changes

* Cleanup

* Fix build

* Fix comments

* Move auth code to new encrypt service interface
This commit is contained in:
Bernd Schoolmann
2025-05-05 16:50:06 +02:00
committed by GitHub
parent 9c8fc80971
commit af40ff26a2
9 changed files with 23 additions and 24 deletions

View File

@@ -58,7 +58,7 @@ export class RotateableKeySetService {
throw new Error("failed to rotate key set: newUserKey is required"); throw new Error("failed to rotate key set: newUserKey is required");
} }
const publicKey = await this.encryptService.decryptToBytes( const publicKey = await this.encryptService.unwrapEncapsulationKey(
keySet.encryptedPublicKey, keySet.encryptedPublicKey,
oldUserKey, oldUserKey,
); );

View File

@@ -95,7 +95,7 @@ describe("AcceptOrganizationInviteService", () => {
encryptService.wrapDecapsulationKey.mockResolvedValue({ encryptService.wrapDecapsulationKey.mockResolvedValue({
encryptedString: "string", encryptedString: "string",
} as EncString); } as EncString);
encryptService.encrypt.mockResolvedValue({ encryptedString: "string" } as EncString); encryptService.encryptString.mockResolvedValue({ encryptedString: "string" } as EncString);
const invite = createOrgInvite({ initOrganization: true }); const invite = createOrgInvite({ initOrganization: true });
const result = await sut.validateAndAcceptInvite(invite); const result = await sut.validateAndAcceptInvite(invite);

View File

@@ -145,7 +145,7 @@ export class AcceptOrganizationInviteService {
const [encryptedOrgKey, orgKey] = await this.keyService.makeOrgKey<OrgKey>(); const [encryptedOrgKey, orgKey] = await this.keyService.makeOrgKey<OrgKey>();
const [orgPublicKey, encryptedOrgPrivateKey] = await this.keyService.makeKeyPair(orgKey); const [orgPublicKey, encryptedOrgPrivateKey] = await this.keyService.makeKeyPair(orgKey);
const collection = await this.encryptService.encrypt( const collection = await this.encryptService.encryptString(
this.i18nService.t("defaultCollection"), this.i18nService.t("defaultCollection"),
orgKey, orgKey,
); );

View File

@@ -230,7 +230,7 @@ describe("WebAuthnLoginStrategy", () => {
const mockUserKeyArray: Uint8Array = randomBytes(32); const mockUserKeyArray: Uint8Array = randomBytes(32);
const mockUserKey = new SymmetricCryptoKey(mockUserKeyArray) as UserKey; const mockUserKey = new SymmetricCryptoKey(mockUserKeyArray) as UserKey;
encryptService.decryptToBytes.mockResolvedValue(mockPrfPrivateKey); encryptService.unwrapDecapsulationKey.mockResolvedValue(mockPrfPrivateKey);
encryptService.decapsulateKeyUnsigned.mockResolvedValue( encryptService.decapsulateKeyUnsigned.mockResolvedValue(
new SymmetricCryptoKey(mockUserKeyArray), new SymmetricCryptoKey(mockUserKeyArray),
); );
@@ -246,8 +246,8 @@ describe("WebAuthnLoginStrategy", () => {
userId, userId,
); );
expect(encryptService.decryptToBytes).toHaveBeenCalledTimes(1); expect(encryptService.unwrapDecapsulationKey).toHaveBeenCalledTimes(1);
expect(encryptService.decryptToBytes).toHaveBeenCalledWith( expect(encryptService.unwrapDecapsulationKey).toHaveBeenCalledWith(
idTokenResponse.userDecryptionOptions.webAuthnPrfOption.encryptedPrivateKey, idTokenResponse.userDecryptionOptions.webAuthnPrfOption.encryptedPrivateKey,
webAuthnCredentials.prfKey, webAuthnCredentials.prfKey,
); );
@@ -279,7 +279,7 @@ describe("WebAuthnLoginStrategy", () => {
await webAuthnLoginStrategy.logIn(webAuthnCredentials); await webAuthnLoginStrategy.logIn(webAuthnCredentials);
// Assert // Assert
expect(encryptService.decryptToBytes).not.toHaveBeenCalled(); expect(encryptService.unwrapDecapsulationKey).not.toHaveBeenCalled();
expect(encryptService.decapsulateKeyUnsigned).not.toHaveBeenCalled(); expect(encryptService.decapsulateKeyUnsigned).not.toHaveBeenCalled();
expect(keyService.setUserKey).not.toHaveBeenCalled(); expect(keyService.setUserKey).not.toHaveBeenCalled();
}); });
@@ -314,7 +314,7 @@ describe("WebAuthnLoginStrategy", () => {
apiService.postIdentityToken.mockResolvedValue(idTokenResponse); apiService.postIdentityToken.mockResolvedValue(idTokenResponse);
encryptService.decryptToBytes.mockResolvedValue(null); encryptService.unwrapDecapsulationKey.mockResolvedValue(null);
// Act // Act
await webAuthnLoginStrategy.logIn(webAuthnCredentials); await webAuthnLoginStrategy.logIn(webAuthnCredentials);

View File

@@ -82,7 +82,7 @@ export class WebAuthnLoginStrategy extends LoginStrategy {
} }
// decrypt prf encrypted private key // decrypt prf encrypted private key
const privateKey = await this.encryptService.decryptToBytes( const privateKey = await this.encryptService.unwrapDecapsulationKey(
webAuthnPrfOption.encryptedPrivateKey, webAuthnPrfOption.encryptedPrivateKey,
credentials.prfKey, credentials.prfKey,
); );

View File

@@ -8,7 +8,6 @@ import { EncryptService } from "@bitwarden/common/key-management/crypto/abstract
import { KeyGenerationService } from "@bitwarden/common/platform/abstractions/key-generation.service"; import { KeyGenerationService } from "@bitwarden/common/platform/abstractions/key-generation.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { EncString, EncryptedString } from "@bitwarden/common/platform/models/domain/enc-string"; import { EncString, EncryptedString } from "@bitwarden/common/platform/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { import {
PIN_DISK, PIN_DISK,
PIN_MEMORY, PIN_MEMORY,
@@ -221,7 +220,7 @@ export class PinService implements PinServiceAbstraction {
throw new Error("No UserKey provided. Cannot create userKeyEncryptedPin."); throw new Error("No UserKey provided. Cannot create userKeyEncryptedPin.");
} }
return await this.encryptService.encrypt(pin, userKey); return await this.encryptService.encryptString(pin, userKey);
} }
async makePinKey(pin: string, salt: string, kdfConfig: KdfConfig): Promise<PinKey> { async makePinKey(pin: string, salt: string, kdfConfig: KdfConfig): Promise<PinKey> {
@@ -339,9 +338,9 @@ export class PinService implements PinServiceAbstraction {
} }
const pinKey = await this.makePinKey(pin, salt, kdfConfig); const pinKey = await this.makePinKey(pin, salt, kdfConfig);
const userKey = await this.encryptService.decryptToBytes(pinKeyEncryptedUserKey, pinKey); const userKey = await this.encryptService.unwrapSymmetricKey(pinKeyEncryptedUserKey, pinKey);
return new SymmetricCryptoKey(userKey) as UserKey; return userKey as UserKey;
} }
/** /**
@@ -377,7 +376,7 @@ export class PinService implements PinServiceAbstraction {
this.validateUserId(userId, "Cannot validate PIN."); this.validateUserId(userId, "Cannot validate PIN.");
const userKeyEncryptedPin = await this.getUserKeyEncryptedPin(userId); const userKeyEncryptedPin = await this.getUserKeyEncryptedPin(userId);
const decryptedPin = await this.encryptService.decryptToUtf8(userKeyEncryptedPin, userKey); const decryptedPin = await this.encryptService.decryptString(userKeyEncryptedPin, userKey);
const isPinValid = this.cryptoFunctionService.compareFast(decryptedPin, pin); const isPinValid = this.cryptoFunctionService.compareFast(decryptedPin, pin);
return isPinValid; return isPinValid;

View File

@@ -259,11 +259,11 @@ describe("PinService", () => {
}); });
it("should create a userKeyEncryptedPin from the provided PIN and userKey", async () => { it("should create a userKeyEncryptedPin from the provided PIN and userKey", async () => {
encryptService.encrypt.mockResolvedValue(mockUserKeyEncryptedPin); encryptService.encryptString.mockResolvedValue(mockUserKeyEncryptedPin);
const result = await sut.createUserKeyEncryptedPin(mockPin, mockUserKey); const result = await sut.createUserKeyEncryptedPin(mockPin, mockUserKey);
expect(encryptService.encrypt).toHaveBeenCalledWith(mockPin, mockUserKey); expect(encryptService.encryptString).toHaveBeenCalledWith(mockPin, mockUserKey);
expect(result).toEqual(mockUserKeyEncryptedPin); expect(result).toEqual(mockUserKeyEncryptedPin);
}); });
}); });
@@ -425,7 +425,7 @@ describe("PinService", () => {
mockDecryptUserKeyFn(); mockDecryptUserKeyFn();
sut.getUserKeyEncryptedPin = jest.fn().mockResolvedValue(mockUserKeyEncryptedPin); sut.getUserKeyEncryptedPin = jest.fn().mockResolvedValue(mockUserKeyEncryptedPin);
encryptService.decryptToUtf8.mockResolvedValue(mockPin); encryptService.decryptString.mockResolvedValue(mockPin);
cryptoFunctionService.compareFast.calledWith(mockPin, "1234").mockResolvedValue(true); cryptoFunctionService.compareFast.calledWith(mockPin, "1234").mockResolvedValue(true);
} }
@@ -434,7 +434,7 @@ describe("PinService", () => {
.fn() .fn()
.mockResolvedValue(pinKeyEncryptedUserKeyPersistant); .mockResolvedValue(pinKeyEncryptedUserKeyPersistant);
sut.makePinKey = jest.fn().mockResolvedValue(mockPinKey); sut.makePinKey = jest.fn().mockResolvedValue(mockPinKey);
encryptService.decryptToBytes.mockResolvedValue(mockUserKey.toEncoded()); encryptService.unwrapSymmetricKey.mockResolvedValue(mockUserKey);
} }
function mockPinEncryptedKeyDataByPinLockType(pinLockType: PinLockType) { function mockPinEncryptedKeyDataByPinLockType(pinLockType: PinLockType) {
@@ -490,7 +490,7 @@ describe("PinService", () => {
it(`should return null when PIN doesn't match after successful user key decryption`, async () => { it(`should return null when PIN doesn't match after successful user key decryption`, async () => {
// Arrange // Arrange
await setupDecryptUserKeyWithPinMocks(pinLockType); await setupDecryptUserKeyWithPinMocks(pinLockType);
encryptService.decryptToUtf8.mockResolvedValue("9999"); // non matching PIN encryptService.decryptString.mockResolvedValue("9999"); // non matching PIN
// Act // Act
const result = await sut.decryptUserKeyWithPin(mockPin, mockUserId); const result = await sut.decryptUserKeyWithPin(mockPin, mockUserId);

View File

@@ -293,7 +293,7 @@ describe("TokenService", () => {
const mockEncryptedAccessToken = "encryptedAccessToken"; const mockEncryptedAccessToken = "encryptedAccessToken";
encryptService.encrypt.mockResolvedValue({ encryptService.encryptString.mockResolvedValue({
encryptedString: mockEncryptedAccessToken, encryptedString: mockEncryptedAccessToken,
} as any); } as any);
@@ -504,7 +504,7 @@ describe("TokenService", () => {
.nextState("encryptedAccessToken"); .nextState("encryptedAccessToken");
secureStorageService.get.mockResolvedValue(accessTokenKeyB64); secureStorageService.get.mockResolvedValue(accessTokenKeyB64);
encryptService.decryptToUtf8.mockResolvedValue("decryptedAccessToken"); encryptService.decryptString.mockResolvedValue("decryptedAccessToken");
// Need to have global active id set to the user id // Need to have global active id set to the user id
if (!userId) { if (!userId) {
@@ -1515,7 +1515,7 @@ describe("TokenService", () => {
.nextState(encryptedAccessToken); .nextState(encryptedAccessToken);
secureStorageService.get.mockResolvedValue(accessTokenKeyB64); secureStorageService.get.mockResolvedValue(accessTokenKeyB64);
encryptService.decryptToUtf8.mockRejectedValue(new Error("Decryption error")); encryptService.decryptString.mockRejectedValue(new Error("Decryption error"));
// Act // Act
const result = await tokenService.getAccessToken(userIdFromAccessToken); const result = await tokenService.getAccessToken(userIdFromAccessToken);

View File

@@ -289,7 +289,7 @@ export class TokenService implements TokenServiceAbstraction {
private async encryptAccessToken(accessToken: string, userId: UserId): Promise<EncString> { private async encryptAccessToken(accessToken: string, userId: UserId): Promise<EncString> {
const accessTokenKey = await this.getOrCreateAccessTokenKey(userId); const accessTokenKey = await this.getOrCreateAccessTokenKey(userId);
return await this.encryptService.encrypt(accessToken, accessTokenKey); return await this.encryptService.encryptString(accessToken, accessTokenKey);
} }
private async decryptAccessToken( private async decryptAccessToken(
@@ -302,7 +302,7 @@ export class TokenService implements TokenServiceAbstraction {
); );
} }
const decryptedAccessToken = await this.encryptService.decryptToUtf8( const decryptedAccessToken = await this.encryptService.decryptString(
encryptedAccessToken, encryptedAccessToken,
accessTokenKey, accessTokenKey,
); );