1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-10 21:33:27 +00:00

[PM-5735] Create kdf Service (#8715)

* key connector migration initial

* migrator complete

* fix dependencies

* finalized tests

* fix deps and sync main

* clean up definition file

* fixing tests

* fixed tests

* fixing CLI, Browser, Desktop builds

* fixed factory options

* reverting exports

* implemented UserKeyDefinition clearOn

* Initial Kdf Service Changes

* rename and account setting kdfconfig

* fixing tests and renaming migration

* fixed DI ordering for browser

* rename and fix DI

* Clean up Migrations

* fixing migrations

* begin data structure changes for kdf config

* Make KDF more type safe; co-author: jlf0dev

* fixing tests

* Fixed CLI login and comments

* set now accepts userId and test updates

---------

Co-authored-by: Jake Fink <jfink@bitwarden.com>
This commit is contained in:
Ike
2024-04-25 11:26:01 -07:00
committed by GitHub
parent dba910d0b9
commit 1e4158fd87
82 changed files with 896 additions and 361 deletions

View File

@@ -3,13 +3,13 @@ import { Subject, takeUntil } from "rxjs";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
import { KdfConfig } from "@bitwarden/common/auth/models/domain/kdf-config";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { KdfType } from "@bitwarden/common/platform/enums";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
@@ -31,7 +31,6 @@ export class ChangePasswordComponent implements OnInit, OnDestroy {
minimumLength = Utils.minimumPasswordLength;
protected email: string;
protected kdf: KdfType;
protected kdfConfig: KdfConfig;
protected destroy$ = new Subject<void>();
@@ -45,6 +44,7 @@ export class ChangePasswordComponent implements OnInit, OnDestroy {
protected policyService: PolicyService,
protected stateService: StateService,
protected dialogService: DialogService,
protected kdfConfigService: KdfConfigService,
) {}
async ngOnInit() {
@@ -73,18 +73,14 @@ export class ChangePasswordComponent implements OnInit, OnDestroy {
}
const email = await this.stateService.getEmail();
if (this.kdf == null) {
this.kdf = await this.stateService.getKdfType();
}
if (this.kdfConfig == null) {
this.kdfConfig = await this.stateService.getKdfConfig();
this.kdfConfig = await this.kdfConfigService.getKdfConfig();
}
// Create new master key
const newMasterKey = await this.cryptoService.makeMasterKey(
this.masterPassword,
email.trim().toLowerCase(),
this.kdf,
this.kdfConfig,
);
const newMasterKeyHash = await this.cryptoService.hashMasterKey(

View File

@@ -12,6 +12,7 @@ import { InternalPolicyService } from "@bitwarden/common/admin-console/abstracti
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
@@ -79,6 +80,7 @@ export class LockComponent implements OnInit, OnDestroy {
protected pinCryptoService: PinCryptoServiceAbstraction,
protected biometricStateService: BiometricStateService,
protected accountService: AccountService,
protected kdfConfigService: KdfConfigService,
) {}
async ngOnInit() {
@@ -208,14 +210,12 @@ export class LockComponent implements OnInit, OnDestroy {
}
private async doUnlockWithMasterPassword() {
const kdfConfig = await this.kdfConfigService.getKdfConfig();
const userId = (await firstValueFrom(this.accountService.activeAccount$))?.id;
const kdf = await this.stateService.getKdfType();
const kdfConfig = await this.stateService.getKdfConfig();
const masterKey = await this.cryptoService.makeMasterKey(
this.masterPassword,
this.email,
kdf,
kdfConfig,
);
const storedMasterKeyHash = await firstValueFrom(

View File

@@ -15,7 +15,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { DEFAULT_KDF_CONFIG, DEFAULT_KDF_TYPE } from "@bitwarden/common/platform/enums";
import { DEFAULT_KDF_CONFIG } from "@bitwarden/common/platform/enums";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
import { DialogService } from "@bitwarden/components";
@@ -273,9 +273,8 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn
name: string,
): Promise<RegisterRequest> {
const hint = this.formGroup.value.hint;
const kdf = DEFAULT_KDF_TYPE;
const kdfConfig = DEFAULT_KDF_CONFIG;
const key = await this.cryptoService.makeMasterKey(masterPassword, email, kdf, kdfConfig);
const key = await this.cryptoService.makeMasterKey(masterPassword, email, kdfConfig);
const newUserKey = await this.cryptoService.makeUserKey(key);
const masterKeyHash = await this.cryptoService.hashMasterKey(masterPassword, key);
const keys = await this.cryptoService.makeKeyPair(newUserKey[0]);
@@ -287,10 +286,8 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn
newUserKey[1].encryptedString,
this.referenceData,
this.captchaToken,
kdf,
kdfConfig.kdfType,
kdfConfig.iterations,
kdfConfig.memory,
kdfConfig.parallelism,
);
request.keys = new KeysRequest(keys[0], keys[1].encryptedString);
const orgInvite = await this.stateService.getOrganizationInvitation();

View File

@@ -13,6 +13,7 @@ import { PolicyService } from "@bitwarden/common/admin-console/abstractions/poli
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
import { OrganizationAutoEnrollStatusResponse } from "@bitwarden/common/admin-console/models/response/organization-auto-enroll-status.response";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
@@ -23,11 +24,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import {
HashPurpose,
DEFAULT_KDF_TYPE,
DEFAULT_KDF_CONFIG,
} from "@bitwarden/common/platform/enums";
import { HashPurpose, DEFAULT_KDF_CONFIG } from "@bitwarden/common/platform/enums";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
@@ -73,6 +70,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent {
private userDecryptionOptionsService: InternalUserDecryptionOptionsServiceAbstraction,
private ssoLoginService: SsoLoginServiceAbstraction,
dialogService: DialogService,
kdfConfigService: KdfConfigService,
) {
super(
i18nService,
@@ -83,6 +81,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent {
policyService,
stateService,
dialogService,
kdfConfigService,
);
}
@@ -139,7 +138,6 @@ export class SetPasswordComponent extends BaseChangePasswordComponent {
}
async setupSubmitActions() {
this.kdf = DEFAULT_KDF_TYPE;
this.kdfConfig = DEFAULT_KDF_CONFIG;
return true;
}
@@ -169,10 +167,8 @@ export class SetPasswordComponent extends BaseChangePasswordComponent {
this.hint,
this.orgSsoIdentifier,
keysRequest,
this.kdf,
this.kdfConfig.kdfType, //always PBKDF2 --> see this.setupSubmitActions
this.kdfConfig.iterations,
this.kdfConfig.memory,
this.kdfConfig.parallelism,
);
try {
if (this.resetPasswordAutoEnroll) {
@@ -246,9 +242,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent {
);
userDecryptionOpts.hasMasterPassword = true;
await this.userDecryptionOptionsService.setUserDecryptionOptions(userDecryptionOpts);
await this.stateService.setKdfType(this.kdf);
await this.stateService.setKdfConfig(this.kdfConfig);
await this.kdfConfigService.setKdfConfig(this.userId, this.kdfConfig);
await this.masterPasswordService.setMasterKey(masterKey, this.userId);
await this.cryptoService.setUserKey(userKey[0]);

View File

@@ -2,6 +2,7 @@ import { DialogRef } from "@angular/cdk/dialog";
import { Directive, OnInit } from "@angular/core";
import { FormBuilder, Validators } from "@angular/forms";
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
@@ -22,6 +23,7 @@ export class SetPinComponent implements OnInit {
private userVerificationService: UserVerificationService,
private stateService: StateService,
private formBuilder: FormBuilder,
private kdfConfigService: KdfConfigService,
) {}
async ngOnInit() {
@@ -43,8 +45,7 @@ export class SetPinComponent implements OnInit {
const pinKey = await this.cryptoService.makePinKey(
pin,
await this.stateService.getEmail(),
await this.stateService.getKdfType(),
await this.stateService.getKdfConfig(),
await this.kdfConfigService.getKdfConfig(),
);
const userKey = await this.cryptoService.getUserKey();
const pinProtectedKey = await this.cryptoService.encrypt(userKey.key, pinKey);

View File

@@ -4,6 +4,7 @@ import { Router } from "@angular/router";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
import { PasswordRequest } from "@bitwarden/common/auth/models/request/password.request";
@@ -44,6 +45,7 @@ export class UpdatePasswordComponent extends BaseChangePasswordComponent {
private userVerificationService: UserVerificationService,
private logService: LogService,
dialogService: DialogService,
kdfConfigService: KdfConfigService,
) {
super(
i18nService,
@@ -54,6 +56,7 @@ export class UpdatePasswordComponent extends BaseChangePasswordComponent {
policyService,
stateService,
dialogService,
kdfConfigService,
);
}
@@ -90,8 +93,7 @@ export class UpdatePasswordComponent extends BaseChangePasswordComponent {
return false;
}
this.kdf = await this.stateService.getKdfType();
this.kdfConfig = await this.stateService.getKdfConfig();
this.kdfConfig = await this.kdfConfigService.getKdfConfig();
return true;
}

View File

@@ -6,6 +6,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
@@ -59,6 +60,7 @@ export class UpdateTempPasswordComponent extends BaseChangePasswordComponent {
private userVerificationService: UserVerificationService,
protected router: Router,
dialogService: DialogService,
kdfConfigService: KdfConfigService,
private accountService: AccountService,
private masterPasswordService: InternalMasterPasswordServiceAbstraction,
) {
@@ -71,6 +73,7 @@ export class UpdateTempPasswordComponent extends BaseChangePasswordComponent {
policyService,
stateService,
dialogService,
kdfConfigService,
);
}
@@ -104,8 +107,7 @@ export class UpdateTempPasswordComponent extends BaseChangePasswordComponent {
async setupSubmitActions(): Promise<boolean> {
this.email = await this.stateService.getEmail();
this.kdf = await this.stateService.getKdfType();
this.kdfConfig = await this.stateService.getKdfConfig();
this.kdfConfig = await this.kdfConfigService.getKdfConfig();
return true;
}
@@ -124,7 +126,6 @@ export class UpdateTempPasswordComponent extends BaseChangePasswordComponent {
const newMasterKey = await this.cryptoService.makeMasterKey(
this.masterPassword,
this.email.trim().toLowerCase(),
this.kdf,
this.kdfConfig,
);
const newPasswordHash = await this.cryptoService.hashMasterKey(

View File

@@ -63,6 +63,7 @@ import { AvatarService as AvatarServiceAbstraction } from "@bitwarden/common/aut
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction";
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
import { KdfConfigService as KdfConfigServiceAbstraction } from "@bitwarden/common/auth/abstractions/kdf-config.service";
import { KeyConnectorService as KeyConnectorServiceAbstraction } from "@bitwarden/common/auth/abstractions/key-connector.service";
import {
InternalMasterPasswordServiceAbstraction,
@@ -85,6 +86,7 @@ import { AvatarService } from "@bitwarden/common/auth/services/avatar.service";
import { DeviceTrustService } from "@bitwarden/common/auth/services/device-trust.service.implementation";
import { DevicesServiceImplementation } from "@bitwarden/common/auth/services/devices/devices.service.implementation";
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
import { KdfConfigService } from "@bitwarden/common/auth/services/kdf-config.service";
import { KeyConnectorService } from "@bitwarden/common/auth/services/key-connector.service";
import { MasterPasswordService } from "@bitwarden/common/auth/services/master-password/master-password.service";
import { PasswordResetEnrollmentServiceImplementation } from "@bitwarden/common/auth/services/password-reset-enrollment.service.implementation";
@@ -390,6 +392,7 @@ const safeProviders: SafeProvider[] = [
InternalUserDecryptionOptionsServiceAbstraction,
GlobalStateProvider,
BillingAccountProfileStateService,
KdfConfigServiceAbstraction,
],
}),
safeProvider({
@@ -543,6 +546,7 @@ const safeProviders: SafeProvider[] = [
StateServiceAbstraction,
AccountServiceAbstraction,
StateProvider,
KdfConfigServiceAbstraction,
],
}),
safeProvider({
@@ -713,7 +717,7 @@ const safeProviders: SafeProvider[] = [
CipherServiceAbstraction,
CryptoServiceAbstraction,
CryptoFunctionServiceAbstraction,
StateServiceAbstraction,
KdfConfigServiceAbstraction,
],
}),
safeProvider({
@@ -724,8 +728,8 @@ const safeProviders: SafeProvider[] = [
ApiServiceAbstraction,
CryptoServiceAbstraction,
CryptoFunctionServiceAbstraction,
StateServiceAbstraction,
CollectionServiceAbstraction,
KdfConfigServiceAbstraction,
],
}),
safeProvider({
@@ -834,6 +838,7 @@ const safeProviders: SafeProvider[] = [
LogService,
VaultTimeoutSettingsServiceAbstraction,
PlatformUtilsServiceAbstraction,
KdfConfigServiceAbstraction,
],
}),
safeProvider({
@@ -985,6 +990,7 @@ const safeProviders: SafeProvider[] = [
CryptoServiceAbstraction,
VaultTimeoutSettingsServiceAbstraction,
LogService,
KdfConfigServiceAbstraction,
],
}),
safeProvider({
@@ -1150,6 +1156,11 @@ const safeProviders: SafeProvider[] = [
useClass: ProviderApiService,
deps: [ApiServiceAbstraction],
}),
safeProvider({
provide: KdfConfigServiceAbstraction,
useClass: KdfConfigService,
deps: [StateProvider],
}),
];
function encryptServiceFactory(