1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-04 10:43:47 +00:00

Remove unused functions

This commit is contained in:
Bernd Schoolmann
2025-10-02 14:29:10 +02:00
parent 727689d827
commit d19caa3340
3 changed files with 1 additions and 254 deletions

View File

@@ -22,12 +22,6 @@ import {
import { KdfConfig } from "../models/kdf-config";
export class UserPrivateKeyDecryptionFailedError extends Error {
constructor() {
super("Failed to decrypt the user's private key.");
}
}
/**
* An object containing all the users key needed to decrypt a users personal and organization vaults.
*/
@@ -67,20 +61,6 @@ export abstract class KeyService {
* @param userId The desired user
*/
abstract setUserKey(key: UserKey, userId: UserId): Promise<void>;
/**
* Sets the provided user keys and stores any other necessary versions
* (such as auto, biometrics, or pin).
* Also sets the user's encrypted private key in storage and
* clears the decrypted private key from memory
* Note: does not clear the private key if null is provided
*
* @throws Error when userKey, encPrivateKey or userId is null
* @throws UserPrivateKeyDecryptionFailedError when the userKey cannot decrypt encPrivateKey
* @param userKey The user key to set
* @param encPrivateKey An encrypted private key
* @param userId The desired user
*/
abstract setUserKeys(userKey: UserKey, encPrivateKey: string, userId: UserId): Promise<void>;
/**
* Gets the user key from memory and sets it again,
* kicking off a refresh of any additional keys
@@ -139,13 +119,6 @@ export abstract class KeyService {
* @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
* @param userId The desired user
* @throws Error when userId is null or undefined.
*/
abstract clearStoredUserKey(keySuffix: KeySuffixOptions, userId: string): Promise<void>;
/**
* Retrieves the user's master key if it is in state, or derives it from the provided password
* @param password The user's master password that will be used to derive a master key if one isn't found
@@ -295,28 +268,6 @@ export abstract class KeyService {
*/
abstract userEncryptedPrivateKey$(userId: UserId): Observable<EncryptedString | null>;
/**
* Gets an observable stream of the given users decrypted private key and public key, guaranteed to be consistent.
* Will emit null if the user doesn't have a userkey to decrypt the encrypted private key, or null if the user doesn't have a private key
* at all.
*
* @param userId The user id of the user to get the data for.
*/
abstract userEncryptionKeyPair$(
userId: UserId,
): Observable<{ privateKey: UserPrivateKey; publicKey: UserPublicKey } | null>;
/**
* Gets an observable stream of the given users decrypted private key and public key, guaranteed to be consistent.
* Will emit null if the user doesn't have a userkey to decrypt the encrypted private key, or null if the user doesn't have a private key
* at all.
*
* @param userId The user id of the user to get the data for.
*/
abstract userEncryptionKeyPair$(
userId: UserId,
): Observable<{ privateKey: UserPrivateKey; publicKey: UserPublicKey } | null>;
/**
* Generates a fingerprint phrase for the public key provided.
*

View File

@@ -48,7 +48,6 @@ import {
} from "@bitwarden/common/types/key";
import { KdfConfigService } from "./abstractions/kdf-config.service";
import { UserPrivateKeyDecryptionFailedError } from "./abstractions/key.service";
import { DefaultKeyService } from "./key.service";
import { KdfConfig } from "./models/kdf-config";
@@ -304,70 +303,6 @@ describe("keyService", () => {
});
});
describe("setUserKeys", () => {
let mockUserKey: UserKey;
let mockEncPrivateKey: EncryptedString;
let everHadUserKeyState: FakeSingleUserState<boolean>;
beforeEach(() => {
const mockRandomBytes = new Uint8Array(64) as CsprngArray;
mockUserKey = new SymmetricCryptoKey(mockRandomBytes) as UserKey;
mockEncPrivateKey = new SymmetricCryptoKey(mockRandomBytes).toString() as EncryptedString;
everHadUserKeyState = stateProvider.singleUser.getFake(mockUserId, USER_EVER_HAD_USER_KEY);
// Initialize storage
everHadUserKeyState.nextState(null);
// Mock private key decryption
encryptService.unwrapDecapsulationKey.mockResolvedValue(mockRandomBytes);
});
it("throws if userKey is null", async () => {
await expect(
keyService.setUserKeys(null as unknown as UserKey, mockEncPrivateKey, mockUserId),
).rejects.toThrow("No userKey provided.");
});
it("throws if encPrivateKey is null", async () => {
await expect(
keyService.setUserKeys(mockUserKey, null as unknown as EncryptedString, mockUserId),
).rejects.toThrow("No encPrivateKey provided.");
});
it("throws if userId is null", async () => {
await expect(
keyService.setUserKeys(mockUserKey, mockEncPrivateKey, null as unknown as UserId),
).rejects.toThrow("No userId provided.");
});
it("throws if encPrivateKey cannot be decrypted with the userKey", async () => {
encryptService.unwrapDecapsulationKey.mockResolvedValue(null);
await expect(
keyService.setUserKeys(mockUserKey, mockEncPrivateKey, mockUserId),
).rejects.toThrow(UserPrivateKeyDecryptionFailedError);
});
// We already have tests for setUserKey, so we just need to test that the correct methods are called
it("calls setUserKey with the userKey and userId", async () => {
const setUserKeySpy = jest.spyOn(keyService, "setUserKey");
await keyService.setUserKeys(mockUserKey, mockEncPrivateKey, mockUserId);
expect(setUserKeySpy).toHaveBeenCalledWith(mockUserKey, mockUserId);
});
// We already have tests for setPrivateKey, so we just need to test that the correct methods are called
// TODO: Move those tests into here since `setPrivateKey` will be converted to a private method
it("calls setPrivateKey with the encPrivateKey and userId", async () => {
const setEncryptedPrivateKeySpy = jest.spyOn(keyService, "setPrivateKey");
await keyService.setUserKeys(mockUserKey, mockEncPrivateKey, mockUserId);
expect(setEncryptedPrivateKeySpy).toHaveBeenCalledWith(mockEncPrivateKey, mockUserId);
});
});
describe("makeSendKey", () => {
const mockRandomBytes = new Uint8Array(16) as CsprngArray;
it("calls keyGenerationService with expected hard coded parameters", async () => {
@@ -381,45 +316,6 @@ describe("keyService", () => {
});
});
describe("clearStoredUserKey", () => {
describe("input validation", () => {
const invalidUserIdTestCases = [
{ keySuffix: KeySuffixOptions.Auto, userId: null as unknown as UserId },
{ keySuffix: KeySuffixOptions.Auto, userId: undefined as unknown as UserId },
{ keySuffix: KeySuffixOptions.Pin, userId: null as unknown as UserId },
{ keySuffix: KeySuffixOptions.Pin, userId: undefined as unknown as UserId },
];
test.each(invalidUserIdTestCases)(
"throws when keySuffix is $keySuffix and userId is $userId",
async ({ keySuffix, userId }) => {
await expect(keyService.clearStoredUserKey(keySuffix, userId)).rejects.toThrow(
"UserId is required",
);
},
);
});
describe("with Auto key suffix", () => {
it("UserKeyAutoUnlock is cleared and pin keys are not cleared", async () => {
await keyService.clearStoredUserKey(KeySuffixOptions.Auto, mockUserId);
expect(stateService.setUserKeyAutoUnlock).toHaveBeenCalledWith(null, {
userId: mockUserId,
});
expect(pinService.clearPinKeyEncryptedUserKeyEphemeral).not.toHaveBeenCalled();
});
});
describe("with PIN key suffix", () => {
it("pin keys are cleared and user key auto unlock not", async () => {
await keyService.clearStoredUserKey(KeySuffixOptions.Pin, mockUserId);
expect(stateService.setUserKeyAutoUnlock).not.toHaveBeenCalled();
expect(pinService.clearPinKeyEncryptedUserKeyEphemeral).toHaveBeenCalledWith(mockUserId);
});
});
});
describe("clearKeys", () => {
test.each([null as unknown as UserId, undefined as unknown as UserId])(
"throws when the provided userId is %s",
@@ -1095,53 +991,6 @@ describe("keyService", () => {
});
});
describe("userEncryptionKeyPair$", () => {
type SetupKeysParams = {
makeMasterKey: boolean;
makeUserKey: boolean;
};
function setupKeys({ makeMasterKey, makeUserKey }: SetupKeysParams): [UserKey, MasterKey] {
const userKeyState = stateProvider.singleUser.getFake(mockUserId, USER_KEY);
const fakeMasterKey = makeMasterKey ? makeSymmetricCryptoKey<MasterKey>(64) : null;
masterPasswordService.masterKeySubject.next(fakeMasterKey);
userKeyState.nextState(null);
const fakeUserKey = makeUserKey ? makeSymmetricCryptoKey<UserKey>(64) : null;
userKeyState.nextState(fakeUserKey);
return [fakeUserKey, fakeMasterKey];
}
it("returns null when private key is null", async () => {
setupKeys({ makeMasterKey: false, makeUserKey: false });
keyService.userPrivateKey$ = jest.fn().mockReturnValue(new BehaviorSubject(null));
const key = await firstValueFrom(keyService.userEncryptionKeyPair$(mockUserId));
expect(key).toEqual(null);
});
it("returns null when private key is undefined", async () => {
setupKeys({ makeUserKey: true, makeMasterKey: false });
keyService.userPrivateKey$ = jest.fn().mockReturnValue(new BehaviorSubject(undefined));
const key = await firstValueFrom(keyService.userEncryptionKeyPair$(mockUserId));
expect(key).toEqual(null);
});
it("returns keys when private key is defined", async () => {
setupKeys({ makeUserKey: false, makeMasterKey: true });
keyService.userPrivateKey$ = jest.fn().mockReturnValue(new BehaviorSubject("private key"));
cryptoFunctionService.rsaExtractPublicKey.mockResolvedValue(
Utils.fromUtf8ToArray("public key"),
);
const key = await firstValueFrom(keyService.userEncryptionKeyPair$(mockUserId));
expect(key).toEqual({
privateKey: "private key",
publicKey: Utils.fromUtf8ToArray("public key"),
});
});
});
describe("getUserKeyFromStorage", () => {
let mockUserKey: UserKey;
let validateUserKeySpy: jest.SpyInstance;

View File

@@ -62,7 +62,6 @@ import { KdfConfigService } from "./abstractions/kdf-config.service";
import {
CipherDecryptionKeys,
KeyService as KeyServiceAbstraction,
UserPrivateKeyDecryptionFailedError,
} from "./abstractions/key.service";
import { KdfConfig } from "./models/kdf-config";
@@ -105,30 +104,6 @@ export class DefaultKeyService implements KeyServiceAbstraction {
await this.storeAdditionalKeys(key, userId);
}
async setUserKeys(
userKey: UserKey,
encPrivateKey: EncryptedString,
userId: UserId,
): Promise<void> {
if (userKey == null) {
throw new Error("No userKey provided. Lock the user to clear the key");
}
if (encPrivateKey == null) {
throw new Error("No encPrivateKey provided.");
}
if (userId == null) {
throw new Error("No userId provided.");
}
const decryptedPrivateKey = await this.decryptPrivateKey(encPrivateKey, userKey);
if (decryptedPrivateKey == null) {
throw new UserPrivateKeyDecryptionFailedError();
}
await this.setUserKey(userKey, userId);
await this.setPrivateKey(encPrivateKey, userId);
}
async refreshAdditionalKeys(userId: UserId): Promise<void> {
if (userId == null) {
throw new Error("UserId is required.");
@@ -221,19 +196,6 @@ export class DefaultKeyService implements KeyServiceAbstraction {
await this.clearAllStoredUserKeys(userId);
}
async clearStoredUserKey(keySuffix: KeySuffixOptions, userId: UserId): Promise<void> {
if (userId == null) {
throw new Error("UserId is required");
}
if (keySuffix === KeySuffixOptions.Auto) {
await this.stateService.setUserKeyAutoUnlock(null, { userId: userId });
}
if (keySuffix === KeySuffixOptions.Pin) {
await this.pinService.clearPinKeyEncryptedUserKeyEphemeral(userId);
}
}
/**
* @deprecated Please use `makeMasterPasswordAuthenticationData`, `unwrapUserKeyFromMasterPasswordUnlockData` or `makeMasterPasswordUnlockData` in @link MasterPasswordService instead.
*/
@@ -577,7 +539,7 @@ export class DefaultKeyService implements KeyServiceAbstraction {
}
// ---HELPERS---
async validateUserKey(key: UserKey | MasterKey | null, userId: UserId): Promise<boolean> {
async validateUserKey(key: UserKey, userId: UserId): Promise<boolean> {
if (key == null) {
return false;
}
@@ -799,21 +761,6 @@ export class DefaultKeyService implements KeyServiceAbstraction {
return this.userPrivateKeyHelper$(userId).pipe(map((keys) => keys?.userPrivateKey ?? null));
}
userEncryptionKeyPair$(
userId: UserId,
): Observable<{ privateKey: UserPrivateKey; publicKey: UserPublicKey } | null> {
return this.userPrivateKey$(userId).pipe(
switchMap(async (privateKey) => {
if (privateKey == null) {
return null;
}
const publicKey = (await this.derivePublicKey(privateKey))!;
return { privateKey, publicKey };
}),
);
}
userEncryptedPrivateKey$(userId: UserId): Observable<EncryptedString | null> {
return this.stateProvider.getUser(userId, USER_ENCRYPTED_PRIVATE_KEY).state$;
}