mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 16:23:44 +00:00
[Pm-13097] Rename cryptoservice to keyservice and move it to km ownership (#11358)
* Rename cryptoservice to keyservice * Rename cryptoservice to keyservice * Move key service to key management ownership * Remove accidentally added file * Fix cli build * Fix browser build * Run prettier * Fix builds * Fix cli build * Fix tests * Fix incorrect renames * Rename webauthn-login-crypto-service * Fix build errors due to merge conflicts * Fix linting
This commit is contained in:
@@ -3,7 +3,7 @@ import { PrfKey } from "../../../types/key";
|
||||
/**
|
||||
* Contains methods for all crypto operations specific to the WebAuthn login flow.
|
||||
*/
|
||||
export abstract class WebAuthnLoginPrfCryptoServiceAbstraction {
|
||||
export abstract class WebAuthnLoginPrfKeyServiceAbstraction {
|
||||
/**
|
||||
* Get the salt used to generate the PRF-output used when logging in with WebAuthn.
|
||||
*/
|
||||
@@ -1,6 +1,7 @@
|
||||
import { MockProxy, mock } from "jest-mock-extended";
|
||||
import { firstValueFrom, of } from "rxjs";
|
||||
|
||||
import { KeyService } from "../../../../key-management/src/abstractions/key.service";
|
||||
import {
|
||||
FakeAccountService,
|
||||
makeStaticByteArray,
|
||||
@@ -8,7 +9,6 @@ import {
|
||||
trackEmissions,
|
||||
} from "../../../spec";
|
||||
import { ApiService } from "../../abstractions/api.service";
|
||||
import { CryptoService } from "../../platform/abstractions/crypto.service";
|
||||
import { MessagingService } from "../../platform/abstractions/messaging.service";
|
||||
import { StateService } from "../../platform/abstractions/state.service";
|
||||
import { Utils } from "../../platform/misc/utils";
|
||||
@@ -25,7 +25,7 @@ describe("AuthService", () => {
|
||||
|
||||
let accountService: FakeAccountService;
|
||||
let messagingService: MockProxy<MessagingService>;
|
||||
let cryptoService: MockProxy<CryptoService>;
|
||||
let keyService: MockProxy<KeyService>;
|
||||
let apiService: MockProxy<ApiService>;
|
||||
let stateService: MockProxy<StateService>;
|
||||
let tokenService: MockProxy<TokenService>;
|
||||
@@ -36,7 +36,7 @@ describe("AuthService", () => {
|
||||
beforeEach(() => {
|
||||
accountService = mockAccountServiceWith(userId);
|
||||
messagingService = mock();
|
||||
cryptoService = mock();
|
||||
keyService = mock();
|
||||
apiService = mock();
|
||||
stateService = mock();
|
||||
tokenService = mock();
|
||||
@@ -44,7 +44,7 @@ describe("AuthService", () => {
|
||||
sut = new AuthService(
|
||||
accountService,
|
||||
messagingService,
|
||||
cryptoService,
|
||||
keyService,
|
||||
apiService,
|
||||
stateService,
|
||||
tokenService,
|
||||
@@ -63,7 +63,7 @@ describe("AuthService", () => {
|
||||
beforeEach(() => {
|
||||
accountService.activeAccountSubject.next(accountInfo);
|
||||
tokenService.hasAccessToken$.mockReturnValue(of(true));
|
||||
cryptoService.getInMemoryUserKeyFor$.mockReturnValue(of(undefined));
|
||||
keyService.getInMemoryUserKeyFor$.mockReturnValue(of(undefined));
|
||||
});
|
||||
|
||||
it("emits LoggedOut when there is no active account", async () => {
|
||||
@@ -84,7 +84,7 @@ describe("AuthService", () => {
|
||||
|
||||
it("emits LoggedOut when there is no access token but has a user key", async () => {
|
||||
tokenService.hasAccessToken$.mockReturnValue(of(false));
|
||||
cryptoService.getInMemoryUserKeyFor$.mockReturnValue(of(userKey));
|
||||
keyService.getInMemoryUserKeyFor$.mockReturnValue(of(userKey));
|
||||
|
||||
expect(await firstValueFrom(sut.activeAccountStatus$)).toEqual(
|
||||
AuthenticationStatus.LoggedOut,
|
||||
@@ -93,14 +93,14 @@ describe("AuthService", () => {
|
||||
|
||||
it("emits Locked when there is an access token and no user key", async () => {
|
||||
tokenService.hasAccessToken$.mockReturnValue(of(true));
|
||||
cryptoService.getInMemoryUserKeyFor$.mockReturnValue(of(undefined));
|
||||
keyService.getInMemoryUserKeyFor$.mockReturnValue(of(undefined));
|
||||
|
||||
expect(await firstValueFrom(sut.activeAccountStatus$)).toEqual(AuthenticationStatus.Locked);
|
||||
});
|
||||
|
||||
it("emits Unlocked when there is an access token and user key", async () => {
|
||||
tokenService.hasAccessToken$.mockReturnValue(of(true));
|
||||
cryptoService.getInMemoryUserKeyFor$.mockReturnValue(of(userKey));
|
||||
keyService.getInMemoryUserKeyFor$.mockReturnValue(of(userKey));
|
||||
|
||||
expect(await firstValueFrom(sut.activeAccountStatus$)).toEqual(AuthenticationStatus.Unlocked);
|
||||
});
|
||||
@@ -117,7 +117,7 @@ describe("AuthService", () => {
|
||||
const emissions = trackEmissions(sut.activeAccountStatus$);
|
||||
|
||||
tokenService.hasAccessToken$.mockReturnValue(of(true));
|
||||
cryptoService.getInMemoryUserKeyFor$.mockReturnValue(of(userKey));
|
||||
keyService.getInMemoryUserKeyFor$.mockReturnValue(of(userKey));
|
||||
accountService.activeAccountSubject.next(accountInfo2);
|
||||
|
||||
expect(emissions).toEqual([AuthenticationStatus.Locked, AuthenticationStatus.Unlocked]);
|
||||
@@ -150,7 +150,7 @@ describe("AuthService", () => {
|
||||
describe("authStatusFor$", () => {
|
||||
beforeEach(() => {
|
||||
tokenService.hasAccessToken$.mockReturnValue(of(true));
|
||||
cryptoService.getInMemoryUserKeyFor$.mockReturnValue(of(undefined));
|
||||
keyService.getInMemoryUserKeyFor$.mockReturnValue(of(undefined));
|
||||
});
|
||||
|
||||
it.each([null, undefined, "not a userId"])(
|
||||
@@ -172,14 +172,14 @@ describe("AuthService", () => {
|
||||
|
||||
it("emits Locked when there is an access token and no user key", async () => {
|
||||
tokenService.hasAccessToken$.mockReturnValue(of(true));
|
||||
cryptoService.getInMemoryUserKeyFor$.mockReturnValue(of(undefined));
|
||||
keyService.getInMemoryUserKeyFor$.mockReturnValue(of(undefined));
|
||||
|
||||
expect(await firstValueFrom(sut.authStatusFor$(userId))).toEqual(AuthenticationStatus.Locked);
|
||||
});
|
||||
|
||||
it("emits Unlocked when there is an access token and user key", async () => {
|
||||
tokenService.hasAccessToken$.mockReturnValue(of(true));
|
||||
cryptoService.getInMemoryUserKeyFor$.mockReturnValue(of(userKey));
|
||||
keyService.getInMemoryUserKeyFor$.mockReturnValue(of(userKey));
|
||||
|
||||
expect(await firstValueFrom(sut.authStatusFor$(userId))).toEqual(
|
||||
AuthenticationStatus.Unlocked,
|
||||
|
||||
@@ -9,8 +9,8 @@ import {
|
||||
switchMap,
|
||||
} from "rxjs";
|
||||
|
||||
import { KeyService } from "../../../../key-management/src/abstractions/key.service";
|
||||
import { ApiService } from "../../abstractions/api.service";
|
||||
import { CryptoService } from "../../platform/abstractions/crypto.service";
|
||||
import { StateService } from "../../platform/abstractions/state.service";
|
||||
import { MessageSender } from "../../platform/messaging";
|
||||
import { Utils } from "../../platform/misc/utils";
|
||||
@@ -27,7 +27,7 @@ export class AuthService implements AuthServiceAbstraction {
|
||||
constructor(
|
||||
protected accountService: AccountService,
|
||||
protected messageSender: MessageSender,
|
||||
protected cryptoService: CryptoService,
|
||||
protected keyService: KeyService,
|
||||
protected apiService: ApiService,
|
||||
protected stateService: StateService,
|
||||
private tokenService: TokenService,
|
||||
@@ -69,7 +69,7 @@ export class AuthService implements AuthServiceAbstraction {
|
||||
}
|
||||
|
||||
return combineLatest([
|
||||
this.cryptoService.getInMemoryUserKeyFor$(userId),
|
||||
this.keyService.getInMemoryUserKeyFor$(userId),
|
||||
this.tokenService.hasAccessToken$(userId),
|
||||
]).pipe(
|
||||
map(([userKey, hasAccessToken]) => {
|
||||
|
||||
@@ -2,10 +2,10 @@ import { firstValueFrom, map, Observable } from "rxjs";
|
||||
|
||||
import { UserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
|
||||
|
||||
import { KeyService } from "../../../../key-management/src/abstractions/key.service";
|
||||
import { AppIdService } from "../../platform/abstractions/app-id.service";
|
||||
import { ConfigService } from "../../platform/abstractions/config/config.service";
|
||||
import { CryptoFunctionService } from "../../platform/abstractions/crypto-function.service";
|
||||
import { CryptoService } from "../../platform/abstractions/crypto.service";
|
||||
import { EncryptService } from "../../platform/abstractions/encrypt.service";
|
||||
import { I18nService } from "../../platform/abstractions/i18n.service";
|
||||
import { KeyGenerationService } from "../../platform/abstractions/key-generation.service";
|
||||
@@ -64,7 +64,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
constructor(
|
||||
private keyGenerationService: KeyGenerationService,
|
||||
private cryptoFunctionService: CryptoFunctionService,
|
||||
private cryptoService: CryptoService,
|
||||
private keyService: KeyService,
|
||||
private encryptService: EncryptService,
|
||||
private appIdService: AppIdService,
|
||||
private devicesApiService: DevicesApiServiceAbstraction,
|
||||
@@ -124,7 +124,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
}
|
||||
|
||||
// Attempt to get user key
|
||||
const userKey: UserKey = await this.cryptoService.getUserKey(userId);
|
||||
const userKey: UserKey = await this.keyService.getUserKey(userId);
|
||||
|
||||
// If user key is not found, throw error
|
||||
if (!userKey) {
|
||||
@@ -187,7 +187,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
}
|
||||
|
||||
// At this point of rotating their keys, they should still have their old user key in state
|
||||
const oldUserKey = await firstValueFrom(this.cryptoService.userKey$(userId));
|
||||
const oldUserKey = await firstValueFrom(this.keyService.userKey$(userId));
|
||||
|
||||
const deviceIdentifier = await this.appIdService.getAppId();
|
||||
const secretVerificationRequest = new SecretVerificationRequest();
|
||||
|
||||
@@ -4,6 +4,7 @@ import { BehaviorSubject, of } from "rxjs";
|
||||
import { UserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
|
||||
|
||||
import { UserDecryptionOptions } from "../../../../auth/src/common/models/domain/user-decryption-options";
|
||||
import { KeyService } from "../../../../key-management/src/abstractions/key.service";
|
||||
import { FakeAccountService, mockAccountServiceWith } from "../../../spec/fake-account-service";
|
||||
import { FakeActiveUserState } from "../../../spec/fake-state";
|
||||
import { FakeStateProvider } from "../../../spec/fake-state-provider";
|
||||
@@ -11,7 +12,6 @@ import { DeviceType } from "../../enums";
|
||||
import { AppIdService } from "../../platform/abstractions/app-id.service";
|
||||
import { ConfigService } from "../../platform/abstractions/config/config.service";
|
||||
import { CryptoFunctionService } from "../../platform/abstractions/crypto-function.service";
|
||||
import { CryptoService } from "../../platform/abstractions/crypto.service";
|
||||
import { EncryptService } from "../../platform/abstractions/encrypt.service";
|
||||
import { I18nService } from "../../platform/abstractions/i18n.service";
|
||||
import { KeyGenerationService } from "../../platform/abstractions/key-generation.service";
|
||||
@@ -43,7 +43,7 @@ describe("deviceTrustService", () => {
|
||||
|
||||
const keyGenerationService = mock<KeyGenerationService>();
|
||||
const cryptoFunctionService = mock<CryptoFunctionService>();
|
||||
const cryptoService = mock<CryptoService>();
|
||||
const keyService = mock<KeyService>();
|
||||
const encryptService = mock<EncryptService>();
|
||||
const appIdService = mock<AppIdService>();
|
||||
const devicesApiService = mock<DevicesApiServiceAbstraction>();
|
||||
@@ -368,7 +368,7 @@ describe("deviceTrustService", () => {
|
||||
.mockResolvedValue(mockDeviceRsaKeyPair);
|
||||
|
||||
cryptoSvcGetUserKeySpy = jest
|
||||
.spyOn(cryptoService, "getUserKey")
|
||||
.spyOn(keyService, "getUserKey")
|
||||
.mockResolvedValue(mockUserKey);
|
||||
|
||||
cryptoSvcRsaEncryptSpy = jest
|
||||
@@ -623,7 +623,7 @@ describe("deviceTrustService", () => {
|
||||
const fakeNewUserKeyData = new Uint8Array(64);
|
||||
fakeNewUserKeyData.fill(FakeNewUserKeyMarker, 0, 1);
|
||||
fakeNewUserKey = new SymmetricCryptoKey(fakeNewUserKeyData) as UserKey;
|
||||
cryptoService.userKey$.mockReturnValue(of(fakeNewUserKey));
|
||||
keyService.userKey$.mockReturnValue(of(fakeNewUserKey));
|
||||
});
|
||||
|
||||
it("throws an error when a null user id is passed in", async () => {
|
||||
@@ -659,7 +659,7 @@ describe("deviceTrustService", () => {
|
||||
fakeOldUserKeyData.fill(FakeOldUserKeyMarker, 0, 1);
|
||||
|
||||
// Mock the retrieval of a user key that differs from the new one passed into the method
|
||||
cryptoService.userKey$.mockReturnValue(
|
||||
keyService.userKey$.mockReturnValue(
|
||||
of(new SymmetricCryptoKey(fakeOldUserKeyData) as UserKey),
|
||||
);
|
||||
|
||||
@@ -749,7 +749,7 @@ describe("deviceTrustService", () => {
|
||||
return new DeviceTrustService(
|
||||
keyGenerationService,
|
||||
cryptoFunctionService,
|
||||
cryptoService,
|
||||
keyService,
|
||||
encryptService,
|
||||
appIdService,
|
||||
devicesApiService,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { mock } from "jest-mock-extended";
|
||||
|
||||
import { KeyService } from "../../../../key-management/src/abstractions/key.service";
|
||||
import { FakeAccountService, FakeStateProvider, mockAccountServiceWith } from "../../../spec";
|
||||
import { ApiService } from "../../abstractions/api.service";
|
||||
import { OrganizationService } from "../../admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { OrganizationData } from "../../admin-console/models/data/organization.data";
|
||||
import { Organization } from "../../admin-console/models/domain/organization";
|
||||
import { ProfileOrganizationResponse } from "../../admin-console/models/response/profile-organization.response";
|
||||
import { CryptoService } from "../../platform/abstractions/crypto.service";
|
||||
import { LogService } from "../../platform/abstractions/log.service";
|
||||
import { Utils } from "../../platform/misc/utils";
|
||||
import { SymmetricCryptoKey } from "../../platform/models/domain/symmetric-crypto-key";
|
||||
@@ -27,7 +27,7 @@ import { TokenService } from "./token.service";
|
||||
describe("KeyConnectorService", () => {
|
||||
let keyConnectorService: KeyConnectorService;
|
||||
|
||||
const cryptoService = mock<CryptoService>();
|
||||
const keyService = mock<KeyService>();
|
||||
const apiService = mock<ApiService>();
|
||||
const tokenService = mock<TokenService>();
|
||||
const logService = mock<LogService>();
|
||||
@@ -56,7 +56,7 @@ describe("KeyConnectorService", () => {
|
||||
keyConnectorService = new KeyConnectorService(
|
||||
accountService,
|
||||
masterPasswordService,
|
||||
cryptoService,
|
||||
keyService,
|
||||
apiService,
|
||||
tokenService,
|
||||
logService,
|
||||
|
||||
@@ -2,12 +2,12 @@ import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { LogoutReason } from "@bitwarden/auth/common";
|
||||
|
||||
import { KeyService } from "../../../../key-management/src/abstractions/key.service";
|
||||
import { ApiService } from "../../abstractions/api.service";
|
||||
import { OrganizationService } from "../../admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { OrganizationUserType } from "../../admin-console/enums";
|
||||
import { Organization } from "../../admin-console/models/domain/organization";
|
||||
import { KeysRequest } from "../../models/request/keys.request";
|
||||
import { CryptoService } from "../../platform/abstractions/crypto.service";
|
||||
import { KeyGenerationService } from "../../platform/abstractions/key-generation.service";
|
||||
import { LogService } from "../../platform/abstractions/log.service";
|
||||
import { KdfType } from "../../platform/enums/kdf-type.enum";
|
||||
@@ -54,7 +54,7 @@ export class KeyConnectorService implements KeyConnectorServiceAbstraction {
|
||||
constructor(
|
||||
private accountService: AccountService,
|
||||
private masterPasswordService: InternalMasterPasswordServiceAbstraction,
|
||||
private cryptoService: CryptoService,
|
||||
private keyService: KeyService,
|
||||
private apiService: ApiService,
|
||||
private tokenService: TokenService,
|
||||
private logService: LogService,
|
||||
@@ -146,7 +146,7 @@ export class KeyConnectorService implements KeyConnectorServiceAbstraction {
|
||||
? new PBKDF2KdfConfig(kdfIterations)
|
||||
: new Argon2KdfConfig(kdfIterations, kdfMemory, kdfParallelism);
|
||||
|
||||
const masterKey = await this.cryptoService.makeMasterKey(
|
||||
const masterKey = await this.keyService.makeMasterKey(
|
||||
password.keyB64,
|
||||
await this.tokenService.getEmail(),
|
||||
kdfConfig,
|
||||
@@ -154,11 +154,11 @@ export class KeyConnectorService implements KeyConnectorServiceAbstraction {
|
||||
const keyConnectorRequest = new KeyConnectorUserKeyRequest(masterKey.encKeyB64);
|
||||
await this.masterPasswordService.setMasterKey(masterKey, userId);
|
||||
|
||||
const userKey = await this.cryptoService.makeUserKey(masterKey);
|
||||
await this.cryptoService.setUserKey(userKey[0], userId);
|
||||
await this.cryptoService.setMasterKeyEncryptedUserKey(userKey[1].encryptedString, userId);
|
||||
const userKey = await this.keyService.makeUserKey(masterKey);
|
||||
await this.keyService.setUserKey(userKey[0], userId);
|
||||
await this.keyService.setMasterKeyEncryptedUserKey(userKey[1].encryptedString, userId);
|
||||
|
||||
const [pubKey, privKey] = await this.cryptoService.makeKeyPair(userKey[0]);
|
||||
const [pubKey, privKey] = await this.keyService.makeKeyPair(userKey[0]);
|
||||
|
||||
try {
|
||||
const keyConnectorUrl =
|
||||
|
||||
@@ -5,9 +5,9 @@ import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
|
||||
|
||||
import { UserId } from "../../../../common/src/types/guid";
|
||||
import { KeyService } from "../../../../key-management/src/abstractions/key.service";
|
||||
import { OrganizationApiServiceAbstraction } from "../../admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
import { OrganizationAutoEnrollStatusResponse } from "../../admin-console/models/response/organization-auto-enroll-status.response";
|
||||
import { CryptoService } from "../../platform/abstractions/crypto.service";
|
||||
import { I18nService } from "../../platform/abstractions/i18n.service";
|
||||
import { AccountInfo, AccountService } from "../abstractions/account.service";
|
||||
|
||||
@@ -18,7 +18,7 @@ describe("PasswordResetEnrollmentServiceImplementation", () => {
|
||||
|
||||
let organizationApiService: MockProxy<OrganizationApiServiceAbstraction>;
|
||||
let accountService: MockProxy<AccountService>;
|
||||
let cryptoService: MockProxy<CryptoService>;
|
||||
let keyService: MockProxy<KeyService>;
|
||||
let encryptService: MockProxy<EncryptService>;
|
||||
let organizationUserApiService: MockProxy<OrganizationUserApiService>;
|
||||
let i18nService: MockProxy<I18nService>;
|
||||
@@ -28,14 +28,14 @@ describe("PasswordResetEnrollmentServiceImplementation", () => {
|
||||
organizationApiService = mock<OrganizationApiServiceAbstraction>();
|
||||
accountService = mock<AccountService>();
|
||||
accountService.activeAccount$ = activeAccountSubject;
|
||||
cryptoService = mock<CryptoService>();
|
||||
keyService = mock<KeyService>();
|
||||
encryptService = mock<EncryptService>();
|
||||
organizationUserApiService = mock<OrganizationUserApiService>();
|
||||
i18nService = mock<I18nService>();
|
||||
service = new PasswordResetEnrollmentServiceImplementation(
|
||||
organizationApiService,
|
||||
accountService,
|
||||
cryptoService,
|
||||
keyService,
|
||||
encryptService,
|
||||
organizationUserApiService,
|
||||
i18nService,
|
||||
@@ -99,7 +99,7 @@ describe("PasswordResetEnrollmentServiceImplementation", () => {
|
||||
};
|
||||
activeAccountSubject.next(Object.assign(user1AccountInfo, { id: "userId" as UserId }));
|
||||
|
||||
cryptoService.getUserKey.mockResolvedValue({ key: "key" } as any);
|
||||
keyService.getUserKey.mockResolvedValue({ key: "key" } as any);
|
||||
encryptService.rsaEncrypt.mockResolvedValue(encryptedKey as any);
|
||||
|
||||
await service.enroll("orgId");
|
||||
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
} from "@bitwarden/admin-console/common";
|
||||
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
|
||||
|
||||
import { KeyService } from "../../../../key-management/src/abstractions/key.service";
|
||||
import { OrganizationApiServiceAbstraction } from "../../admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
import { CryptoService } from "../../platform/abstractions/crypto.service";
|
||||
import { I18nService } from "../../platform/abstractions/i18n.service";
|
||||
import { Utils } from "../../platform/misc/utils";
|
||||
import { UserKey } from "../../types/key";
|
||||
@@ -20,7 +20,7 @@ export class PasswordResetEnrollmentServiceImplementation
|
||||
constructor(
|
||||
protected organizationApiService: OrganizationApiServiceAbstraction,
|
||||
protected accountService: AccountService,
|
||||
protected cryptoService: CryptoService,
|
||||
protected keyService: KeyService,
|
||||
protected encryptService: EncryptService,
|
||||
protected organizationUserApiService: OrganizationUserApiService,
|
||||
protected i18nService: I18nService,
|
||||
@@ -47,7 +47,7 @@ export class PasswordResetEnrollmentServiceImplementation
|
||||
|
||||
userId =
|
||||
userId ?? (await firstValueFrom(this.accountService.activeAccount$.pipe(map((a) => a?.id))));
|
||||
userKey = userKey ?? (await this.cryptoService.getUserKey(userId));
|
||||
userKey = userKey ?? (await this.keyService.getUserKey(userId));
|
||||
// RSA Encrypt user's userKey.key with organization public key
|
||||
const encryptedKey = await this.encryptService.rsaEncrypt(userKey.key, orgPublicKey);
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ import {
|
||||
UserDecryptionOptionsServiceAbstraction,
|
||||
} from "@bitwarden/auth/common";
|
||||
|
||||
import { KeyService } from "../../../../../key-management/src/abstractions/key.service";
|
||||
import { FakeAccountService, mockAccountServiceWith } from "../../../../spec";
|
||||
import { VaultTimeoutSettingsService } from "../../../abstractions/vault-timeout/vault-timeout-settings.service";
|
||||
import { CryptoService } from "../../../platform/abstractions/crypto.service";
|
||||
import { I18nService } from "../../../platform/abstractions/i18n.service";
|
||||
import { LogService } from "../../../platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "../../../platform/abstractions/platform-utils.service";
|
||||
@@ -31,7 +31,7 @@ import { UserVerificationService } from "./user-verification.service";
|
||||
describe("UserVerificationService", () => {
|
||||
let sut: UserVerificationService;
|
||||
|
||||
const cryptoService = mock<CryptoService>();
|
||||
const keyService = mock<KeyService>();
|
||||
const masterPasswordService = mock<InternalMasterPasswordServiceAbstraction>();
|
||||
const i18nService = mock<I18nService>();
|
||||
const userVerificationApiService = mock<UserVerificationApiServiceAbstraction>();
|
||||
@@ -50,7 +50,7 @@ describe("UserVerificationService", () => {
|
||||
accountService = mockAccountServiceWith(mockUserId);
|
||||
|
||||
sut = new UserVerificationService(
|
||||
cryptoService,
|
||||
keyService,
|
||||
accountService,
|
||||
masterPasswordService,
|
||||
i18nService,
|
||||
@@ -132,7 +132,7 @@ describe("UserVerificationService", () => {
|
||||
setMasterPasswordAvailability(false);
|
||||
setPinAvailability("DISABLED");
|
||||
vaultTimeoutSettingsService.isBiometricLockSet.mockResolvedValue(isBiometricsLockSet);
|
||||
cryptoService.hasUserKeyStored.mockResolvedValue(isBiometricsUserKeyStored);
|
||||
keyService.hasUserKeyStored.mockResolvedValue(isBiometricsUserKeyStored);
|
||||
platformUtilsService.supportsSecureStorage.mockReturnValue(platformSupportSecureStorage);
|
||||
|
||||
const result = await sut.getAvailableVerificationOptions("client");
|
||||
@@ -205,7 +205,7 @@ describe("UserVerificationService", () => {
|
||||
|
||||
kdfConfigService.getKdfConfig.mockResolvedValue("kdfConfig" as unknown as KdfConfig);
|
||||
masterPasswordService.masterKey$.mockReturnValue(of("masterKey" as unknown as MasterKey));
|
||||
cryptoService.hashMasterKey
|
||||
keyService.hashMasterKey
|
||||
.calledWith("password", "masterKey" as unknown as MasterKey, HashPurpose.LocalAuthorization)
|
||||
.mockResolvedValue("localHash");
|
||||
});
|
||||
@@ -216,7 +216,7 @@ describe("UserVerificationService", () => {
|
||||
});
|
||||
|
||||
it("returns if verification is successful", async () => {
|
||||
cryptoService.compareAndUpdateKeyHash.mockResolvedValueOnce(true);
|
||||
keyService.compareAndUpdateKeyHash.mockResolvedValueOnce(true);
|
||||
|
||||
const result = await sut.verifyUserByMasterPassword(
|
||||
{
|
||||
@@ -227,7 +227,7 @@ describe("UserVerificationService", () => {
|
||||
"email",
|
||||
);
|
||||
|
||||
expect(cryptoService.compareAndUpdateKeyHash).toHaveBeenCalled();
|
||||
expect(keyService.compareAndUpdateKeyHash).toHaveBeenCalled();
|
||||
expect(masterPasswordService.setMasterKeyHash).toHaveBeenCalledWith(
|
||||
"localHash",
|
||||
mockUserId,
|
||||
@@ -240,7 +240,7 @@ describe("UserVerificationService", () => {
|
||||
});
|
||||
|
||||
it("throws if verification fails", async () => {
|
||||
cryptoService.compareAndUpdateKeyHash.mockResolvedValueOnce(false);
|
||||
keyService.compareAndUpdateKeyHash.mockResolvedValueOnce(false);
|
||||
|
||||
await expect(
|
||||
sut.verifyUserByMasterPassword(
|
||||
@@ -253,7 +253,7 @@ describe("UserVerificationService", () => {
|
||||
),
|
||||
).rejects.toThrow("Invalid master password");
|
||||
|
||||
expect(cryptoService.compareAndUpdateKeyHash).toHaveBeenCalled();
|
||||
expect(keyService.compareAndUpdateKeyHash).toHaveBeenCalled();
|
||||
expect(masterPasswordService.setMasterKeyHash).not.toHaveBeenCalledWith();
|
||||
expect(masterPasswordService.setMasterKey).not.toHaveBeenCalledWith();
|
||||
});
|
||||
@@ -265,7 +265,7 @@ describe("UserVerificationService", () => {
|
||||
});
|
||||
|
||||
it("returns if verification is successful", async () => {
|
||||
cryptoService.hashMasterKey
|
||||
keyService.hashMasterKey
|
||||
.calledWith(
|
||||
"password",
|
||||
"masterKey" as unknown as MasterKey,
|
||||
@@ -285,7 +285,7 @@ describe("UserVerificationService", () => {
|
||||
"email",
|
||||
);
|
||||
|
||||
expect(cryptoService.compareAndUpdateKeyHash).not.toHaveBeenCalled();
|
||||
expect(keyService.compareAndUpdateKeyHash).not.toHaveBeenCalled();
|
||||
expect(masterPasswordService.setMasterKeyHash).toHaveBeenCalledWith(
|
||||
"localHash",
|
||||
mockUserId,
|
||||
@@ -298,7 +298,7 @@ describe("UserVerificationService", () => {
|
||||
});
|
||||
|
||||
it("throws if verification fails", async () => {
|
||||
cryptoService.hashMasterKey
|
||||
keyService.hashMasterKey
|
||||
.calledWith(
|
||||
"password",
|
||||
"masterKey" as unknown as MasterKey,
|
||||
@@ -318,7 +318,7 @@ describe("UserVerificationService", () => {
|
||||
),
|
||||
).rejects.toThrow("Invalid master password");
|
||||
|
||||
expect(cryptoService.compareAndUpdateKeyHash).not.toHaveBeenCalled();
|
||||
expect(keyService.compareAndUpdateKeyHash).not.toHaveBeenCalled();
|
||||
expect(masterPasswordService.setMasterKeyHash).not.toHaveBeenCalledWith();
|
||||
expect(masterPasswordService.setMasterKey).not.toHaveBeenCalledWith();
|
||||
});
|
||||
@@ -380,7 +380,7 @@ describe("UserVerificationService", () => {
|
||||
it("throws if master key cannot be created", async () => {
|
||||
kdfConfigService.getKdfConfig.mockResolvedValueOnce("kdfConfig" as unknown as KdfConfig);
|
||||
masterPasswordService.masterKey$.mockReturnValueOnce(of(null));
|
||||
cryptoService.makeMasterKey.mockResolvedValueOnce(null);
|
||||
keyService.makeMasterKey.mockResolvedValueOnce(null);
|
||||
|
||||
await expect(
|
||||
sut.verifyUserByMasterPassword(
|
||||
|
||||
@@ -3,8 +3,8 @@ import { firstValueFrom, map } from "rxjs";
|
||||
import { UserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
|
||||
|
||||
import { PinServiceAbstraction } from "../../../../../auth/src/common/abstractions/pin.service.abstraction";
|
||||
import { KeyService } from "../../../../../key-management/src/abstractions/key.service";
|
||||
import { VaultTimeoutSettingsService as VaultTimeoutSettingsServiceAbstraction } from "../../../abstractions/vault-timeout/vault-timeout-settings.service";
|
||||
import { CryptoService } from "../../../platform/abstractions/crypto.service";
|
||||
import { I18nService } from "../../../platform/abstractions/i18n.service";
|
||||
import { LogService } from "../../../platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "../../../platform/abstractions/platform-utils.service";
|
||||
@@ -39,7 +39,7 @@ import {
|
||||
*/
|
||||
export class UserVerificationService implements UserVerificationServiceAbstraction {
|
||||
constructor(
|
||||
private cryptoService: CryptoService,
|
||||
private keyService: KeyService,
|
||||
private accountService: AccountService,
|
||||
private masterPasswordService: InternalMasterPasswordServiceAbstraction,
|
||||
private i18nService: I18nService,
|
||||
@@ -66,7 +66,7 @@ export class UserVerificationService implements UserVerificationServiceAbstracti
|
||||
this.hasMasterPasswordAndMasterKeyHash(userId),
|
||||
this.pinService.isPinDecryptionAvailable(userId),
|
||||
this.vaultTimeoutSettingsService.isBiometricLockSet(userId),
|
||||
this.cryptoService.hasUserKeyStored(KeySuffixOptions.Biometric, userId),
|
||||
this.keyService.hasUserKeyStored(KeySuffixOptions.Biometric, userId),
|
||||
]);
|
||||
|
||||
// note: we do not need to check this.platformUtilsService.supportsBiometric() because
|
||||
@@ -119,7 +119,7 @@ export class UserVerificationService implements UserVerificationServiceAbstracti
|
||||
);
|
||||
let masterKey = await firstValueFrom(this.masterPasswordService.masterKey$(userId));
|
||||
if (!masterKey && !alreadyHashed) {
|
||||
masterKey = await this.cryptoService.makeMasterKey(
|
||||
masterKey = await this.keyService.makeMasterKey(
|
||||
verification.secret,
|
||||
email,
|
||||
await this.kdfConfigService.getKdfConfig(),
|
||||
@@ -127,7 +127,7 @@ export class UserVerificationService implements UserVerificationServiceAbstracti
|
||||
}
|
||||
request.masterPasswordHash = alreadyHashed
|
||||
? verification.secret
|
||||
: await this.cryptoService.hashMasterKey(verification.secret, masterKey);
|
||||
: await this.keyService.hashMasterKey(verification.secret, masterKey);
|
||||
}
|
||||
|
||||
return request;
|
||||
@@ -196,7 +196,7 @@ export class UserVerificationService implements UserVerificationServiceAbstracti
|
||||
|
||||
let masterKey = await firstValueFrom(this.masterPasswordService.masterKey$(userId));
|
||||
if (!masterKey) {
|
||||
masterKey = await this.cryptoService.makeMasterKey(verification.secret, email, kdfConfig);
|
||||
masterKey = await this.keyService.makeMasterKey(verification.secret, email, kdfConfig);
|
||||
}
|
||||
|
||||
if (!masterKey) {
|
||||
@@ -206,7 +206,7 @@ export class UserVerificationService implements UserVerificationServiceAbstracti
|
||||
let policyOptions: MasterPasswordPolicyResponse | null;
|
||||
// Client-side verification
|
||||
if (await this.hasMasterPasswordAndMasterKeyHash(userId)) {
|
||||
const passwordValid = await this.cryptoService.compareAndUpdateKeyHash(
|
||||
const passwordValid = await this.keyService.compareAndUpdateKeyHash(
|
||||
verification.secret,
|
||||
masterKey,
|
||||
);
|
||||
@@ -217,7 +217,7 @@ export class UserVerificationService implements UserVerificationServiceAbstracti
|
||||
} else {
|
||||
// Server-side verification
|
||||
const request = new SecretVerificationRequest();
|
||||
const serverKeyHash = await this.cryptoService.hashMasterKey(
|
||||
const serverKeyHash = await this.keyService.hashMasterKey(
|
||||
verification.secret,
|
||||
masterKey,
|
||||
HashPurpose.ServerAuthorization,
|
||||
@@ -230,7 +230,7 @@ export class UserVerificationService implements UserVerificationServiceAbstracti
|
||||
}
|
||||
}
|
||||
|
||||
const localKeyHash = await this.cryptoService.hashMasterKey(
|
||||
const localKeyHash = await this.keyService.hashMasterKey(
|
||||
verification.secret,
|
||||
masterKey,
|
||||
HashPurpose.LocalAuthorization,
|
||||
@@ -254,7 +254,7 @@ export class UserVerificationService implements UserVerificationServiceAbstracti
|
||||
let userKey: UserKey;
|
||||
// Biometrics crashes and doesn't return a value if the user cancels the prompt
|
||||
try {
|
||||
userKey = await this.cryptoService.getUserKeyFromStorage(KeySuffixOptions.Biometric);
|
||||
userKey = await this.keyService.getUserKeyFromStorage(KeySuffixOptions.Biometric);
|
||||
} catch (e) {
|
||||
this.logService.error(`Biometrics User Verification failed: ${e.message}`);
|
||||
// So, any failures should be treated as a failed verification
|
||||
|
||||
@@ -2,15 +2,15 @@ import { mock, MockProxy } from "jest-mock-extended";
|
||||
|
||||
import { CryptoFunctionService } from "../../../platform/abstractions/crypto-function.service";
|
||||
|
||||
import { WebAuthnLoginPrfCryptoService } from "./webauthn-login-prf-crypto.service";
|
||||
import { WebAuthnLoginPrfKeyService } from "./webauthn-login-prf-key.service";
|
||||
|
||||
describe("WebAuthnLoginPrfCryptoService", () => {
|
||||
describe("WebAuthnLoginPrfKeyService", () => {
|
||||
let cryptoFunctionService: MockProxy<CryptoFunctionService>;
|
||||
let service: WebAuthnLoginPrfCryptoService;
|
||||
let service: WebAuthnLoginPrfKeyService;
|
||||
|
||||
beforeEach(() => {
|
||||
cryptoFunctionService = mock<CryptoFunctionService>();
|
||||
service = new WebAuthnLoginPrfCryptoService(cryptoFunctionService);
|
||||
service = new WebAuthnLoginPrfKeyService(cryptoFunctionService);
|
||||
});
|
||||
|
||||
describe("createSymmetricKeyFromPrf", () => {
|
||||
@@ -1,11 +1,11 @@
|
||||
import { CryptoFunctionService } from "../../../platform/abstractions/crypto-function.service";
|
||||
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
|
||||
import { PrfKey } from "../../../types/key";
|
||||
import { WebAuthnLoginPrfCryptoServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-prf-crypto.service.abstraction";
|
||||
import { WebAuthnLoginPrfKeyServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-prf-key.service.abstraction";
|
||||
|
||||
const LoginWithPrfSalt = "passwordless-login";
|
||||
|
||||
export class WebAuthnLoginPrfCryptoService implements WebAuthnLoginPrfCryptoServiceAbstraction {
|
||||
export class WebAuthnLoginPrfKeyService implements WebAuthnLoginPrfKeyServiceAbstraction {
|
||||
constructor(private cryptoFunctionService: CryptoFunctionService) {}
|
||||
|
||||
async getLoginWithPrfSalt(): Promise<ArrayBuffer> {
|
||||
@@ -7,7 +7,7 @@ import { Utils } from "../../../platform/misc/utils";
|
||||
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
|
||||
import { PrfKey } from "../../../types/key";
|
||||
import { WebAuthnLoginApiServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-api.service.abstraction";
|
||||
import { WebAuthnLoginPrfCryptoServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-prf-crypto.service.abstraction";
|
||||
import { WebAuthnLoginPrfKeyServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-prf-key.service.abstraction";
|
||||
import { AuthResult } from "../../models/domain/auth-result";
|
||||
import { WebAuthnLoginCredentialAssertionOptionsView } from "../../models/view/webauthn-login/webauthn-login-credential-assertion-options.view";
|
||||
import { WebAuthnLoginCredentialAssertionView } from "../../models/view/webauthn-login/webauthn-login-credential-assertion.view";
|
||||
@@ -21,7 +21,7 @@ describe("WebAuthnLoginService", () => {
|
||||
|
||||
const webAuthnLoginApiService = mock<WebAuthnLoginApiServiceAbstraction>();
|
||||
const loginStrategyService = mock<LoginStrategyServiceAbstraction>();
|
||||
const webAuthnLoginPrfCryptoService = mock<WebAuthnLoginPrfCryptoServiceAbstraction>();
|
||||
const webAuthnLoginPrfKeyService = mock<WebAuthnLoginPrfKeyServiceAbstraction>();
|
||||
const navigatorCredentials = mock<CredentialsContainer>();
|
||||
const logService = mock<LogService>();
|
||||
|
||||
@@ -72,7 +72,7 @@ describe("WebAuthnLoginService", () => {
|
||||
return new WebAuthnLoginService(
|
||||
webAuthnLoginApiService,
|
||||
loginStrategyService,
|
||||
webAuthnLoginPrfCryptoService,
|
||||
webAuthnLoginPrfKeyService,
|
||||
window,
|
||||
logService,
|
||||
);
|
||||
@@ -141,8 +141,8 @@ describe("WebAuthnLoginService", () => {
|
||||
publicKeyCredential.getClientExtensionResults().prf?.results?.first;
|
||||
const prfKey = new SymmetricCryptoKey(new Uint8Array(prfResult)) as PrfKey;
|
||||
|
||||
webAuthnLoginPrfCryptoService.getLoginWithPrfSalt.mockResolvedValue(saltArrayBuffer);
|
||||
webAuthnLoginPrfCryptoService.createSymmetricKeyFromPrf.mockResolvedValue(prfKey);
|
||||
webAuthnLoginPrfKeyService.getLoginWithPrfSalt.mockResolvedValue(saltArrayBuffer);
|
||||
webAuthnLoginPrfKeyService.createSymmetricKeyFromPrf.mockResolvedValue(prfKey);
|
||||
|
||||
// Mock implementations
|
||||
navigatorCredentials.get.mockResolvedValue(publicKeyCredential);
|
||||
@@ -152,7 +152,7 @@ describe("WebAuthnLoginService", () => {
|
||||
|
||||
// Assert
|
||||
|
||||
expect(webAuthnLoginPrfCryptoService.getLoginWithPrfSalt).toHaveBeenCalled();
|
||||
expect(webAuthnLoginPrfKeyService.getLoginWithPrfSalt).toHaveBeenCalled();
|
||||
|
||||
expect(navigatorCredentials.get).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
@@ -169,9 +169,7 @@ describe("WebAuthnLoginService", () => {
|
||||
}),
|
||||
);
|
||||
|
||||
expect(webAuthnLoginPrfCryptoService.createSymmetricKeyFromPrf).toHaveBeenCalledWith(
|
||||
prfResult,
|
||||
);
|
||||
expect(webAuthnLoginPrfKeyService.createSymmetricKeyFromPrf).toHaveBeenCalledWith(prfResult);
|
||||
|
||||
expect(result).toBeInstanceOf(WebAuthnLoginCredentialAssertionView);
|
||||
expect(result.token).toEqual(credentialAssertionOptions.token);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { LoginStrategyServiceAbstraction, WebAuthnLoginCredentials } from "@bitw
|
||||
import { LogService } from "../../../platform/abstractions/log.service";
|
||||
import { PrfKey } from "../../../types/key";
|
||||
import { WebAuthnLoginApiServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-api.service.abstraction";
|
||||
import { WebAuthnLoginPrfCryptoServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-prf-crypto.service.abstraction";
|
||||
import { WebAuthnLoginPrfKeyServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-prf-key.service.abstraction";
|
||||
import { WebAuthnLoginServiceAbstraction } from "../../abstractions/webauthn/webauthn-login.service.abstraction";
|
||||
import { AuthResult } from "../../models/domain/auth-result";
|
||||
import { WebAuthnLoginCredentialAssertionOptionsView } from "../../models/view/webauthn-login/webauthn-login-credential-assertion-options.view";
|
||||
@@ -17,7 +17,7 @@ export class WebAuthnLoginService implements WebAuthnLoginServiceAbstraction {
|
||||
constructor(
|
||||
private webAuthnLoginApiService: WebAuthnLoginApiServiceAbstraction,
|
||||
private loginStrategyService: LoginStrategyServiceAbstraction,
|
||||
private webAuthnLoginPrfCryptoService: WebAuthnLoginPrfCryptoServiceAbstraction,
|
||||
private webAuthnLoginPrfKeyService: WebAuthnLoginPrfKeyServiceAbstraction,
|
||||
private window: Window,
|
||||
private logService?: LogService,
|
||||
) {
|
||||
@@ -37,7 +37,7 @@ export class WebAuthnLoginService implements WebAuthnLoginServiceAbstraction {
|
||||
};
|
||||
// TODO: Remove `any` when typescript typings add support for PRF
|
||||
nativeOptions.publicKey.extensions = {
|
||||
prf: { eval: { first: await this.webAuthnLoginPrfCryptoService.getLoginWithPrfSalt() } },
|
||||
prf: { eval: { first: await this.webAuthnLoginPrfKeyService.getLoginWithPrfSalt() } },
|
||||
} as any;
|
||||
|
||||
try {
|
||||
@@ -50,7 +50,7 @@ export class WebAuthnLoginService implements WebAuthnLoginServiceAbstraction {
|
||||
let symmetricPrfKey: PrfKey | undefined;
|
||||
if (prfResult != undefined) {
|
||||
symmetricPrfKey =
|
||||
await this.webAuthnLoginPrfCryptoService.createSymmetricKeyFromPrf(prfResult);
|
||||
await this.webAuthnLoginPrfKeyService.createSymmetricKeyFromPrf(prfResult);
|
||||
}
|
||||
|
||||
const deviceResponse = new WebAuthnLoginAssertionResponseRequest(response);
|
||||
|
||||
Reference in New Issue
Block a user