1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 16:23:44 +00:00

[PM-21586] Return null in decryptUserKeyWithMasterKey if decrypt fails (#14756)

* Return null in decryptUserKeyWithMasterKey if decrypt fails

* Show error on invalid master password

* Add logs
This commit is contained in:
Bernd Schoolmann
2025-05-13 15:42:48 +02:00
committed by GitHub
parent b2c118d607
commit 00beef617c
3 changed files with 26 additions and 7 deletions

View File

@@ -37,13 +37,13 @@ export abstract class MasterPasswordServiceAbstraction {
* @param userKey The user's encrypted symmetric key * @param userKey The user's encrypted symmetric key
* @throws If either the MasterKey or UserKey are not resolved, or if the UserKey encryption type * @throws If either the MasterKey or UserKey are not resolved, or if the UserKey encryption type
* is neither AesCbc256_B64 nor AesCbc256_HmacSha256_B64 * is neither AesCbc256_B64 nor AesCbc256_HmacSha256_B64
* @returns The user key * @returns The user key or null if the masterkey is wrong
*/ */
abstract decryptUserKeyWithMasterKey: ( abstract decryptUserKeyWithMasterKey: (
masterKey: MasterKey, masterKey: MasterKey,
userId: string, userId: string,
userKey?: EncString, userKey?: EncString,
) => Promise<UserKey>; ) => Promise<UserKey | null>;
} }
export abstract class InternalMasterPasswordServiceAbstraction extends MasterPasswordServiceAbstraction { export abstract class InternalMasterPasswordServiceAbstraction extends MasterPasswordServiceAbstraction {

View File

@@ -166,7 +166,7 @@ export class MasterPasswordService implements InternalMasterPasswordServiceAbstr
masterKey: MasterKey, masterKey: MasterKey,
userId: UserId, userId: UserId,
userKey?: EncString, userKey?: EncString,
): Promise<UserKey> { ): Promise<UserKey | null> {
userKey ??= await this.getMasterKeyEncryptedUserKey(userId); userKey ??= await this.getMasterKeyEncryptedUserKey(userId);
masterKey ??= await firstValueFrom(this.masterKey$(userId)); masterKey ??= await firstValueFrom(this.masterKey$(userId));
@@ -177,16 +177,26 @@ export class MasterPasswordService implements InternalMasterPasswordServiceAbstr
let decUserKey: SymmetricCryptoKey; let decUserKey: SymmetricCryptoKey;
if (userKey.encryptionType === EncryptionType.AesCbc256_B64) { if (userKey.encryptionType === EncryptionType.AesCbc256_B64) {
try {
decUserKey = await this.encryptService.unwrapSymmetricKey(userKey, masterKey); decUserKey = await this.encryptService.unwrapSymmetricKey(userKey, masterKey);
} catch {
this.logService.warning("Failed to decrypt user key with master key.");
return null;
}
} else if (userKey.encryptionType === EncryptionType.AesCbc256_HmacSha256_B64) { } else if (userKey.encryptionType === EncryptionType.AesCbc256_HmacSha256_B64) {
try {
const newKey = await this.keyGenerationService.stretchKey(masterKey); const newKey = await this.keyGenerationService.stretchKey(masterKey);
decUserKey = await this.encryptService.unwrapSymmetricKey(userKey, newKey); decUserKey = await this.encryptService.unwrapSymmetricKey(userKey, newKey);
} catch {
this.logService.warning("Failed to decrypt user key with stretched master key.");
return null;
}
} else { } else {
throw new Error("Unsupported encryption type."); throw new Error("Unsupported encryption type.");
} }
if (decUserKey == null) { if (decUserKey == null) {
this.logService.warning("Failed to decrypt user key with master key."); this.logService.warning("Failed to decrypt user key with master key, user key is null.");
return null; return null;
} }

View File

@@ -556,6 +556,15 @@ export class LockComponent implements OnInit, OnDestroy {
masterPasswordVerificationResponse!.masterKey, masterPasswordVerificationResponse!.masterKey,
this.activeAccount.id, this.activeAccount.id,
); );
if (userKey == null) {
this.toastService.showToast({
variant: "error",
title: this.i18nService.t("errorOccurred"),
message: this.i18nService.t("invalidMasterPassword"),
});
return;
}
await this.setUserKeyAndContinue(userKey, true); await this.setUserKeyAndContinue(userKey, true);
} }