mirror of
https://github.com/bitwarden/browser
synced 2025-12-14 23:33:31 +00:00
[PM-3726] Force migration of legacy user's encryption key (#6195)
* [PM-3726] migrate legacy user's encryption key * [PM-3726] add 2fa support and pr feedback * [PM-3726] revert launch.json & webpack.config changes * [PM-3726] remove update key component - also remove card in vault since legacy users can't login * [PM-3726] Fix i18n & PR feedback * [PM-3726] make standalone component * [PM-3726] linter * [PM-3726] missing await * [PM-3726] logout legacy users with vault timeout to never * [PM-3726] add await * [PM-3726] skip auto key migration for legacy users * [PM-3726] pr feedback * [PM-3726] move check for web into migrate method --------- Co-authored-by: Jared Snider <116684653+JaredSnider-Bitwarden@users.noreply.github.com>
This commit is contained in:
@@ -42,6 +42,12 @@ export abstract class CryptoService {
|
||||
* @returns The user key
|
||||
*/
|
||||
getUserKey: (userId?: string) => Promise<UserKey>;
|
||||
|
||||
/**
|
||||
* Checks if the user is using an old encryption scheme that used the master key
|
||||
* for encryption of data instead of the user key.
|
||||
*/
|
||||
isLegacyUser: (masterKey?: MasterKey, userId?: string) => Promise<boolean>;
|
||||
/**
|
||||
* Use for encryption/decryption of data in order to support legacy
|
||||
* encryption models. It will return the user key if available,
|
||||
|
||||
@@ -77,6 +77,12 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
}
|
||||
}
|
||||
|
||||
async isLegacyUser(masterKey?: MasterKey, userId?: string): Promise<boolean> {
|
||||
return await this.validateUserKey(
|
||||
(masterKey ?? (await this.getMasterKey(userId))) as unknown as UserKey
|
||||
);
|
||||
}
|
||||
|
||||
async getUserKeyWithLegacySupport(userId?: string): Promise<UserKey> {
|
||||
const userKey = await this.getUserKey(userId);
|
||||
if (userKey) {
|
||||
@@ -510,7 +516,8 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
}
|
||||
|
||||
async makeKeyPair(key?: SymmetricCryptoKey): Promise<[string, EncString]> {
|
||||
key ||= await this.getUserKey();
|
||||
// Default to user key
|
||||
key ||= await this.getUserKeyWithLegacySupport();
|
||||
|
||||
const keyPair = await this.cryptoFunctionService.rsaGenerateKeyPair(2048);
|
||||
const publicB64 = Utils.fromBufferToB64(keyPair[0]);
|
||||
@@ -943,23 +950,30 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
|
||||
async migrateAutoKeyIfNeeded(userId?: string) {
|
||||
const oldAutoKey = await this.stateService.getCryptoMasterKeyAuto({ userId: userId });
|
||||
if (oldAutoKey) {
|
||||
// decrypt
|
||||
const masterKey = new SymmetricCryptoKey(Utils.fromB64ToArray(oldAutoKey)) as MasterKey;
|
||||
const encryptedUserKey = await this.stateService.getEncryptedCryptoSymmetricKey({
|
||||
userId: userId,
|
||||
});
|
||||
const userKey = await this.decryptUserKeyWithMasterKey(
|
||||
masterKey,
|
||||
new EncString(encryptedUserKey),
|
||||
userId
|
||||
);
|
||||
// migrate
|
||||
await this.stateService.setUserKeyAutoUnlock(userKey.keyB64, { userId: userId });
|
||||
await this.stateService.setCryptoMasterKeyAuto(null, { userId: userId });
|
||||
// set encrypted user key in case user immediately locks without syncing
|
||||
await this.setMasterKeyEncryptedUserKey(encryptedUserKey);
|
||||
if (!oldAutoKey) {
|
||||
return;
|
||||
}
|
||||
// Decrypt
|
||||
const masterKey = new SymmetricCryptoKey(Utils.fromB64ToArray(oldAutoKey)) as MasterKey;
|
||||
if (await this.isLegacyUser(masterKey, userId)) {
|
||||
// Legacy users don't have a user key, so no need to migrate.
|
||||
// Instead, set the master key for additional isLegacyUser checks that will log the user out.
|
||||
await this.setMasterKey(masterKey, userId);
|
||||
return;
|
||||
}
|
||||
const encryptedUserKey = await this.stateService.getEncryptedCryptoSymmetricKey({
|
||||
userId: userId,
|
||||
});
|
||||
const userKey = await this.decryptUserKeyWithMasterKey(
|
||||
masterKey,
|
||||
new EncString(encryptedUserKey),
|
||||
userId
|
||||
);
|
||||
// Migrate
|
||||
await this.stateService.setUserKeyAutoUnlock(userKey.keyB64, { userId: userId });
|
||||
await this.stateService.setCryptoMasterKeyAuto(null, { userId: userId });
|
||||
// Set encrypted user key in case user immediately locks without syncing
|
||||
await this.setMasterKeyEncryptedUserKey(encryptedUserKey);
|
||||
}
|
||||
|
||||
async decryptAndMigrateOldPinKey(
|
||||
|
||||
Reference in New Issue
Block a user