1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-06 11:43:51 +00:00

Cleanup and deprecate more functions

This commit is contained in:
Bernd Schoolmann
2025-07-23 20:56:46 +02:00
parent e158225a9d
commit a82fad1073
7 changed files with 49 additions and 30 deletions

View File

@@ -669,6 +669,7 @@ export default class MainBackground {
this.encryptService,
this.logService,
this.cryptoFunctionService,
this.accountService,
);
this.i18nService = new I18nService(BrowserApi.getUILanguage(), this.globalStateProvider);

View File

@@ -439,6 +439,7 @@ export class ServiceContainer {
this.encryptService,
this.logService,
this.cryptoFunctionService,
this.accountService,
);
this.pinService = new PinService(

View File

@@ -2,6 +2,7 @@ import { mock, MockProxy } from "jest-mock-extended";
import { of } from "rxjs";
import * as rxjs from "rxjs";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
// eslint-disable-next-line no-restricted-imports
@@ -32,6 +33,7 @@ describe("MasterPasswordService", () => {
let encryptService: MockProxy<EncryptService>;
let logService: MockProxy<LogService>;
let cryptoFunctionService: MockProxy<CryptoFunctionService>;
let accountService: MockProxy<AccountService>;
const userId = "user-id" as UserId;
const mockUserState = {
@@ -54,6 +56,7 @@ describe("MasterPasswordService", () => {
encryptService = mock<EncryptService>();
logService = mock<LogService>();
cryptoFunctionService = mock<CryptoFunctionService>();
accountService = mock<AccountService>();
stateProvider.getUser.mockReturnValue(mockUserState as any);
@@ -66,6 +69,7 @@ describe("MasterPasswordService", () => {
encryptService,
logService,
cryptoFunctionService,
accountService,
);
encryptService.unwrapSymmetricKey.mockResolvedValue(makeSymmetricCryptoKey(64, 1));

View File

@@ -2,6 +2,8 @@
// @ts-strict-ignore
import { firstValueFrom, map, Observable } from "rxjs";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { assertNonNullish } from "@bitwarden/common/auth/utils";
import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
// eslint-disable-next-line no-restricted-imports
@@ -74,8 +76,17 @@ export class MasterPasswordService implements InternalMasterPasswordServiceAbstr
private encryptService: EncryptService,
private logService: LogService,
private cryptoFunctionService: CryptoFunctionService,
private accountService: AccountService,
) {}
saltForUser$(userId: UserId): Observable<MasterPasswordSalt> {
assertNonNullish(userId, "userId");
return this.accountService.accounts$.pipe(
map((accounts) => accounts[userId].email),
map((email) => this.emailToSalt(email)),
);
}
masterKey$(userId: UserId): Observable<MasterKey> {
if (userId == null) {
throw new Error("User ID is required.");
@@ -227,15 +238,12 @@ export class MasterPasswordService implements InternalMasterPasswordServiceAbstr
kdf: KdfConfig,
salt: MasterPasswordSalt,
): Promise<MasterPasswordAuthenticationData> {
if (password == null) {
throw new Error("Password is required.");
}
if (kdf == null) {
throw new Error("KDF configuration is required.");
}
if (salt == null) {
throw new Error("Salt is required.");
}
assertNonNullish(password, "password");
assertNonNullish(kdf, "kdf");
assertNonNullish(salt, "salt");
// We don't trust callers to use masterpasswordsalt correctly. They may type assert incorrectly.
salt = salt.toLowerCase().trim() as MasterPasswordSalt;
const SERVER_AUTHENTICATION_HASH_ITERATIONS = 1;
@@ -267,18 +275,13 @@ export class MasterPasswordService implements InternalMasterPasswordServiceAbstr
salt: MasterPasswordSalt,
userKey: UserKey,
): Promise<MasterPasswordUnlockData> {
if (password == null) {
throw new Error("Password is required.");
}
if (kdf == null) {
throw new Error("KDF configuration is required.");
}
if (salt == null) {
throw new Error("Salt is required.");
}
if (userKey == null) {
throw new Error("User key is required.");
}
assertNonNullish(password, "password");
assertNonNullish(kdf, "kdf");
assertNonNullish(salt, "salt");
assertNonNullish(userKey, "userKey");
// We don't trust callers to use masterpasswordsalt correctly. They may type assert incorrectly.
salt = salt.toLowerCase().trim() as MasterPasswordSalt;
await SdkLoadService.Ready;
const masterKeyWrappedUserKey = new EncString(
@@ -300,12 +303,8 @@ export class MasterPasswordService implements InternalMasterPasswordServiceAbstr
password: string,
masterPasswordUnlockData: MasterPasswordUnlockData,
): Promise<UserKey> {
if (password == null) {
throw new Error("Password is required.");
}
if (masterPasswordUnlockData == null) {
throw new Error("Master password unlock data is required.");
}
assertNonNullish(password, "password");
assertNonNullish(masterPasswordUnlockData, "masterPasswordUnlockData");
await SdkLoadService.Ready;
const userKey = new SymmetricCryptoKey(

View File

@@ -6,6 +6,7 @@ import { SymmetricCryptoKey } from "../platform/models/domain/symmetric-crypto-k
export type DeviceKey = Opaque<SymmetricCryptoKey, "DeviceKey">;
export type PrfKey = Opaque<SymmetricCryptoKey, "PrfKey">;
export type UserKey = Opaque<SymmetricCryptoKey, "UserKey">;
/** @deprecated Interacting with the master key directly is prohibited. Use a high level function from MasterPasswordService instead. */
export type MasterKey = Opaque<SymmetricCryptoKey, "MasterKey">;
export type PinKey = Opaque<SymmetricCryptoKey, "PinKey">;
export type OrgKey = Opaque<SymmetricCryptoKey, "OrgKey">;

View File

@@ -150,11 +150,17 @@ export abstract class KeyService {
/**
* Generates a new user key
* @deprecated Interacting with the master key directly is prohibited. Use a high level function from MasterPasswordService instead.
* @throws Error when master key is null and there is no active user
* @param masterKey The user's master key. When null, grabs master key from active user.
* @returns A new user key and the master key protected version of it
*/
abstract makeUserKey(masterKey: MasterKey | null): Promise<[UserKey, EncString]>;
/**
* Generates a new user key for a V1 user
* @returns A new user key
*/
abstract makeUserKeyV1(): Promise<UserKey>;
/**
* Clears the user's stored version of the user key
* @param keySuffix The desired version of the key to clear
@@ -164,12 +170,14 @@ export abstract class KeyService {
abstract clearStoredUserKey(keySuffix: KeySuffixOptions, userId: string): Promise<void>;
/**
* @throws Error when userId is null and no active user
* @deprecated Interacting with the master key directly is prohibited. Use a high level function from MasterPasswordService instead.
* @param password The user's master password that will be used to derive a master key if one isn't found
* @param userId The desired user
*/
abstract getOrDeriveMasterKey(password: string, userId?: string): Promise<MasterKey>;
/**
* Generates a master key from the provided password
* @deprecated Interacting with the master key directly is prohibited.
* @param password The user's master password
* @param email The user's email
* @param KdfConfig The user's key derivation function configuration
@@ -179,6 +187,7 @@ export abstract class KeyService {
/**
* Encrypts the existing (or provided) user key with the
* provided master key
* @deprecated Interacting with the master key directly is prohibited. Use a high level function from MasterPasswordService instead.
* @param masterKey The user's master key
* @param userKey The user key
* @returns The user key and the master key protected version of it
@@ -191,6 +200,7 @@ export abstract class KeyService {
* Creates a master password hash from the user's master password. Can
* be used for local authentication or for server authentication depending
* on the hashPurpose provided.
* @deprecated Interacting with the master key directly is prohibited. Use a high level function from MasterPasswordService instead.
* @throws Error when password is null or key is null and no active user or active user have no master key
* @param password The user's master password
* @param key The user's master key or active's user master key.
@@ -204,6 +214,7 @@ export abstract class KeyService {
): Promise<string>;
/**
* Compares the provided master password to the stored password hash.
* @deprecated Interacting with the master key directly is prohibited. Use a high level function from MasterPasswordService instead.
* @param masterPassword The user's master password
* @param key The user's master key
* @param userId The id of the user to do the operation for.

View File

@@ -215,9 +215,6 @@ export class DefaultKeyService implements KeyServiceAbstraction {
return (await firstValueFrom(this.stateProvider.getUserState$(USER_KEY, userId))) != null;
}
/**
* @deprecated Please use `makeMasterPasswordUnlockData` in {@link MasterPasswordService} instead.
*/
async makeUserKey(masterKey: MasterKey | null): Promise<[UserKey, EncString]> {
if (masterKey == null) {
const userId = await firstValueFrom(this.stateProvider.activeUserId$);
@@ -235,6 +232,11 @@ export class DefaultKeyService implements KeyServiceAbstraction {
return this.buildProtectedSymmetricKey(masterKey, newUserKey);
}
async makeUserKeyV1(): Promise<UserKey> {
const newUserKey = await this.keyGenerationService.createKey(512);
return newUserKey as UserKey;
}
/**
* Clears the user key. Clears all stored versions of the user keys as well, such as the biometrics key
* @param userId The desired user