1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-12 22:33:35 +00:00

[PS-2365] Kdf Configuration Options for Argon2 (#4578)

* Implement argon2 config

* Remove argon2 webassembly warning

* Replace magic numbers by enum

* Implement kdf configuration

* Update UI according to design feedback

* Further updates to follow design feedback

* Add oxford comma in argon2 description

* Fix typos in argon2 descriptions

* move key creation into promise with API call

* change casing on PBKDF2

* general improvements

* kdf config on set pin component

* SHA-256 hash argon2 salt

* Change argon2 defaults

* Change argon2 salt hash to cryptoFunctionService

* Fix isLowKdfIteration check

---------

Co-authored-by: Kyle Spearrin <kyle.spearrin@gmail.com>
Co-authored-by: Kyle Spearrin <kspearrin@users.noreply.github.com>
This commit is contained in:
Bernd Schoolmann
2023-01-30 15:07:51 +01:00
committed by GitHub
parent b1a1068906
commit 01091fe260
35 changed files with 329 additions and 143 deletions

View File

@@ -10,6 +10,7 @@ import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.serv
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { KdfType } from "@bitwarden/common/enums/kdfType";
import { EncString } from "@bitwarden/common/models/domain/enc-string";
import { KdfConfig } from "@bitwarden/common/models/domain/kdf-config";
import { MasterPasswordPolicyOptions } from "@bitwarden/common/models/domain/master-password-policy-options";
import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetric-crypto-key";
@@ -27,7 +28,7 @@ export class ChangePasswordComponent implements OnInit, OnDestroy {
protected email: string;
protected kdf: KdfType;
protected kdfIterations: number;
protected kdfConfig: KdfConfig;
protected destroy$ = new Subject<void>();
@@ -70,14 +71,14 @@ export class ChangePasswordComponent implements OnInit, OnDestroy {
if (this.kdf == null) {
this.kdf = await this.stateService.getKdfType();
}
if (this.kdfIterations == null) {
this.kdfIterations = await this.stateService.getKdfIterations();
if (this.kdfConfig == null) {
this.kdfConfig = await this.stateService.getKdfConfig();
}
const key = await this.cryptoService.makeKey(
this.masterPassword,
email.trim().toLowerCase(),
this.kdf,
this.kdfIterations
this.kdfConfig
);
const masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, key);

View File

@@ -136,13 +136,13 @@ export class LockComponent implements OnInit, OnDestroy {
let failed = true;
try {
const kdf = await this.stateService.getKdfType();
const kdfIterations = await this.stateService.getKdfIterations();
const kdfConfig = await this.stateService.getKdfConfig();
if (this.pinSet[0]) {
const key = await this.cryptoService.makeKeyFromPin(
this.pin,
this.email,
kdf,
kdfIterations,
kdfConfig,
await this.stateService.getDecryptedPinProtected()
);
const encKey = await this.cryptoService.getEncKey(key);
@@ -153,12 +153,7 @@ export class LockComponent implements OnInit, OnDestroy {
await this.setKeyAndContinue(key);
}
} else {
const key = await this.cryptoService.makeKeyFromPin(
this.pin,
this.email,
kdf,
kdfIterations
);
const key = await this.cryptoService.makeKeyFromPin(this.pin, this.email, kdf, kdfConfig);
failed = false;
await this.setKeyAndContinue(key);
}
@@ -194,14 +189,9 @@ export class LockComponent implements OnInit, OnDestroy {
private async doUnlockWithMasterPassword() {
const kdf = await this.stateService.getKdfType();
const kdfIterations = await this.stateService.getKdfIterations();
const kdfConfig = await this.stateService.getKdfConfig();
const key = await this.cryptoService.makeKey(
this.masterPassword,
this.email,
kdf,
kdfIterations
);
const key = await this.cryptoService.makeKey(this.masterPassword, this.email, kdf, kdfConfig);
const storedKeyHash = await this.cryptoService.getKeyHash();
let passwordValid = false;
@@ -244,7 +234,7 @@ export class LockComponent implements OnInit, OnDestroy {
const protectedPin = await this.stateService.getProtectedPin();
const encKey = await this.cryptoService.getEncKey(key);
const decPin = await this.cryptoService.decryptToUtf8(new EncString(protectedPin), encKey);
const pinKey = await this.cryptoService.makePinKey(decPin, this.email, kdf, kdfIterations);
const pinKey = await this.cryptoService.makePinKey(decPin, this.email, kdf, kdfConfig);
await this.stateService.setDecryptedPinProtected(
await this.cryptoService.encrypt(key.key, pinKey)
);

View File

@@ -16,7 +16,7 @@ import { LogService } from "@bitwarden/common/abstractions/log.service";
import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwordGeneration.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { DEFAULT_KDF_TYPE, DEFAULT_PBKDF2_ITERATIONS } from "@bitwarden/common/enums/kdfType";
import { DEFAULT_KDF_CONFIG, DEFAULT_KDF_TYPE } from "@bitwarden/common/enums/kdfType";
import { PasswordLogInCredentials } from "@bitwarden/common/models/domain/log-in-credentials";
import { KeysRequest } from "@bitwarden/common/models/request/keys.request";
import { ReferenceEventRequest } from "@bitwarden/common/models/request/reference-event.request";
@@ -269,8 +269,8 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn
): Promise<RegisterRequest> {
const hint = this.formGroup.value.hint;
const kdf = DEFAULT_KDF_TYPE;
const kdfIterations = DEFAULT_PBKDF2_ITERATIONS;
const key = await this.cryptoService.makeKey(masterPassword, email, kdf, kdfIterations);
const kdfConfig = DEFAULT_KDF_CONFIG;
const key = await this.cryptoService.makeKey(masterPassword, email, kdf, kdfConfig);
const encKey = await this.cryptoService.makeEncKey(key);
const hashedPassword = await this.cryptoService.hashPassword(masterPassword, key);
const keys = await this.cryptoService.makeKeyPair(encKey[0]);
@@ -280,10 +280,12 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn
hashedPassword,
hint,
encKey[1].encryptedString,
kdf,
kdfIterations,
this.referenceData,
this.captchaToken
this.captchaToken,
kdf,
kdfConfig.iterations,
kdfConfig.memory,
kdfConfig.parallelism
);
request.keys = new KeysRequest(keys[0], keys[1].encryptedString);
const orgInvite = await this.stateService.getOrganizationInvitation();

View File

@@ -16,7 +16,7 @@ import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.serv
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
import { HashPurpose } from "@bitwarden/common/enums/hashPurpose";
import { DEFAULT_KDF_TYPE, DEFAULT_PBKDF2_ITERATIONS } from "@bitwarden/common/enums/kdfType";
import { DEFAULT_KDF_TYPE, DEFAULT_KDF_CONFIG } from "@bitwarden/common/enums/kdfType";
import { Utils } from "@bitwarden/common/misc/utils";
import { EncString } from "@bitwarden/common/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetric-crypto-key";
@@ -93,7 +93,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent {
async setupSubmitActions() {
this.kdf = DEFAULT_KDF_TYPE;
this.kdfIterations = DEFAULT_PBKDF2_ITERATIONS;
this.kdfConfig = DEFAULT_KDF_CONFIG;
return true;
}
@@ -107,10 +107,12 @@ export class SetPasswordComponent extends BaseChangePasswordComponent {
masterPasswordHash,
encKey[1].encryptedString,
this.hint,
this.kdf,
this.kdfIterations,
this.identifier,
new KeysRequest(keys[0], keys[1].encryptedString)
new KeysRequest(keys[0], keys[1].encryptedString),
this.kdf,
this.kdfConfig.iterations,
this.kdfConfig.memory,
this.kdfConfig.parallelism
);
try {
if (this.resetPasswordAutoEnroll) {
@@ -173,7 +175,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent {
keys: [string, EncString]
) {
await this.stateService.setKdfType(this.kdf);
await this.stateService.setKdfIterations(this.kdfIterations);
await this.stateService.setKdfConfig(this.kdfConfig);
await this.cryptoService.setKey(key);
await this.cryptoService.setEncKey(encKey[1].encryptedString);
await this.cryptoService.setEncPrivateKey(keys[1].encryptedString);

View File

@@ -36,9 +36,9 @@ export class SetPinComponent implements OnInit {
}
const kdf = await this.stateService.getKdfType();
const kdfIterations = await this.stateService.getKdfIterations();
const kdfConfig = await this.stateService.getKdfConfig();
const email = await this.stateService.getEmail();
const pinKey = await this.cryptoService.makePinKey(this.pin, email, kdf, kdfIterations);
const pinKey = await this.cryptoService.makePinKey(this.pin, email, kdf, kdfConfig);
const key = await this.cryptoService.getKey();
const pinProtectedKey = await this.cryptoService.encrypt(key.key, pinKey);
if (this.masterPassOnRestart) {

View File

@@ -86,7 +86,7 @@ export class UpdatePasswordComponent extends BaseChangePasswordComponent {
}
this.kdf = await this.stateService.getKdfType();
this.kdfIterations = await this.stateService.getKdfIterations();
this.kdfConfig = await this.stateService.getKdfConfig();
return true;
}

View File

@@ -62,7 +62,7 @@ export class UpdateTempPasswordComponent extends BaseChangePasswordComponent {
async setupSubmitActions(): Promise<boolean> {
this.email = await this.stateService.getEmail();
this.kdf = await this.stateService.getKdfType();
this.kdfIterations = await this.stateService.getKdfIterations();
this.kdfConfig = await this.stateService.getKdfConfig();
return true;
}
@@ -82,7 +82,7 @@ export class UpdateTempPasswordComponent extends BaseChangePasswordComponent {
this.masterPassword,
this.email.trim().toLowerCase(),
this.kdf,
this.kdfIterations
this.kdfConfig
);
const newPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, newKey);