diff --git a/libs/auth/src/common/login-strategies/login.strategy.spec.ts b/libs/auth/src/common/login-strategies/login.strategy.spec.ts index 78561b443a..1a6592887b 100644 --- a/libs/auth/src/common/login-strategies/login.strategy.spec.ts +++ b/libs/auth/src/common/login-strategies/login.strategy.spec.ts @@ -327,6 +327,7 @@ describe("LoginStrategy", () => { const tokenResponse = identityTokenResponseFactory(); tokenResponse.privateKey = null; keyService.makeKeyPair.mockResolvedValue(["PUBLIC_KEY", new EncString("PRIVATE_KEY")]); + keyService.getUserKey.mockResolvedValue(userKey); apiService.postIdentityToken.mockResolvedValue(tokenResponse); masterPasswordService.masterKeySubject.next(masterKey); @@ -343,6 +344,15 @@ describe("LoginStrategy", () => { expect(apiService.postAccountKeys).toHaveBeenCalled(); }); + + it("throws if userKey is CoseEncrypt0 (V2 encryption) in createKeyPairForOldAccount", async () => { + keyService.getUserKey.mockResolvedValue({ + inner: () => ({ type: 7 }), + } as UserKey); + await expect(passwordLoginStrategy["createKeyPairForOldAccount"](userId)).resolves.toBe( + undefined, + ); + }); }); describe("Two-factor authentication", () => { diff --git a/libs/auth/src/common/login-strategies/login.strategy.ts b/libs/auth/src/common/login-strategies/login.strategy.ts index b8d5f64bfc..53e34147d9 100644 --- a/libs/auth/src/common/login-strategies/login.strategy.ts +++ b/libs/auth/src/common/login-strategies/login.strategy.ts @@ -31,6 +31,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service" import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; +import { EncryptionType } from "@bitwarden/common/platform/enums"; import { Account, AccountProfile } from "@bitwarden/common/platform/models/domain/account"; import { UserId } from "@bitwarden/common/types/guid"; import { @@ -326,6 +327,10 @@ export abstract class LoginStrategy { protected async createKeyPairForOldAccount(userId: UserId) { try { const userKey = await this.keyService.getUserKey(userId); + if (userKey.inner().type == EncryptionType.CoseEncrypt0) { + throw new Error("Cannot create key pair for account on V2 encryption"); + } + const [publicKey, privateKey] = await this.keyService.makeKeyPair(userKey); if (!privateKey.encryptedString) { throw new Error("Failed to create encrypted private key"); diff --git a/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.spec.ts b/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.spec.ts index abccfee4c5..3a622fe72c 100644 --- a/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.spec.ts +++ b/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.spec.ts @@ -354,4 +354,22 @@ describe("regenerateIfNeeded", () => { ).not.toHaveBeenCalled(); expect(keyService.setPrivateKey).not.toHaveBeenCalled(); }); + + it("should not regenerate when userKey type is CoseEncrypt0 (V2 encryption)", async () => { + const mockUserKey = { + keyB64: "mockKeyB64", + inner: () => ({ type: 7 }), + } as unknown as UserKey; + keyService.userKey$.mockReturnValue(of(mockUserKey)); + + await sut.regenerateIfNeeded(userId); + + expect( + userAsymmetricKeysRegenerationApiService.regenerateUserAsymmetricKeys, + ).not.toHaveBeenCalled(); + expect(keyService.setPrivateKey).not.toHaveBeenCalled(); + expect(logService.error).toHaveBeenCalledWith( + "[UserAsymmetricKeyRegeneration] Cannot regenerate asymmetric keys for accounts on V2 encryption.", + ); + }); }); diff --git a/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.ts b/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.ts index 3e83723789..335f45b0ce 100644 --- a/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.ts +++ b/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.ts @@ -6,6 +6,7 @@ import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-st import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service"; +import { EncryptionType } from "@bitwarden/common/platform/enums"; import { UserId } from "@bitwarden/common/types/guid"; import { UserKey } from "@bitwarden/common/types/key"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; @@ -60,6 +61,13 @@ export class DefaultUserAsymmetricKeysRegenerationService return false; } + if (userKey.inner().type === EncryptionType.CoseEncrypt0) { + this.logService.error( + "[UserAsymmetricKeyRegeneration] Cannot regenerate asymmetric keys for accounts on V2 encryption.", + ); + return false; + } + const [userKeyEncryptedPrivateKey, publicKeyResponse] = await firstValueFrom( combineLatest([ this.keyService.userEncryptedPrivateKey$(userId),