1
0
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:
Jake Fink
2023-09-20 15:57:01 -04:00
committed by GitHub
parent 020018085a
commit 8c06508435
30 changed files with 834 additions and 273 deletions

View File

@@ -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,

View File

@@ -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(