mirror of
https://github.com/bitwarden/web
synced 2025-12-06 00:03:28 +00:00
change KDF
This commit is contained in:
2
jslib
2
jslib
Submodule jslib updated: 00562d083b...0d15ae8615
@@ -75,6 +75,7 @@ import { AccountComponent } from './settings/account.component';
|
|||||||
import { AdjustPaymentComponent } from './settings/adjust-payment.component';
|
import { AdjustPaymentComponent } from './settings/adjust-payment.component';
|
||||||
import { AdjustStorageComponent } from './settings/adjust-storage.component';
|
import { AdjustStorageComponent } from './settings/adjust-storage.component';
|
||||||
import { ChangeEmailComponent } from './settings/change-email.component';
|
import { ChangeEmailComponent } from './settings/change-email.component';
|
||||||
|
import { ChangeKdfComponent } from './settings/change-kdf.component';
|
||||||
import { ChangePasswordComponent } from './settings/change-password.component';
|
import { ChangePasswordComponent } from './settings/change-password.component';
|
||||||
import { CreateOrganizationComponent } from './settings/create-organization.component';
|
import { CreateOrganizationComponent } from './settings/create-organization.component';
|
||||||
import { DeauthorizeSessionsComponent } from './settings/deauthorize-sessions.component';
|
import { DeauthorizeSessionsComponent } from './settings/deauthorize-sessions.component';
|
||||||
@@ -204,6 +205,7 @@ registerLocaleData(localeZhCn, 'zh-CN');
|
|||||||
BulkShareComponent,
|
BulkShareComponent,
|
||||||
CalloutComponent,
|
CalloutComponent,
|
||||||
ChangeEmailComponent,
|
ChangeEmailComponent,
|
||||||
|
ChangeKdfComponent,
|
||||||
ChangePasswordComponent,
|
ChangePasswordComponent,
|
||||||
CiphersComponent,
|
CiphersComponent,
|
||||||
CollectionsComponent,
|
CollectionsComponent,
|
||||||
|
|||||||
@@ -10,6 +10,10 @@
|
|||||||
<h1>{{'changeMasterPassword' | i18n}}</h1>
|
<h1>{{'changeMasterPassword' | i18n}}</h1>
|
||||||
</div>
|
</div>
|
||||||
<app-change-password></app-change-password>
|
<app-change-password></app-change-password>
|
||||||
|
<div class="secondary-header">
|
||||||
|
<h1>{{'encKeySettings' | i18n}}</h1>
|
||||||
|
</div>
|
||||||
|
<app-change-kdf></app-change-kdf>
|
||||||
<div class="secondary-header text-danger border-0 mb-0">
|
<div class="secondary-header text-danger border-0 mb-0">
|
||||||
<h1>{{'dangerZone' | i18n}}</h1>
|
<h1>{{'dangerZone' | i18n}}</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
47
src/app/settings/change-kdf.component.html
Normal file
47
src/app/settings/change-kdf.component.html
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<app-callout type="warning">{{'loggedOutWarning' | i18n}}</app-callout>
|
||||||
|
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate autocomplete="off">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="kdfMasterPassword">{{'masterPass' | i18n}}</label>
|
||||||
|
<input id="kdfMasterPassword" type="password" name="MasterPasswordHash" class="form-control" [(ngModel)]="masterPassword"
|
||||||
|
required appInputVerbatim>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="form-group mb-0">
|
||||||
|
<label for="kdf">{{'kdfAlgorithm' | i18n}}</label>
|
||||||
|
<a class="ml-auto" href="https://en.wikipedia.org/wiki/Key_derivation_function" target="_blank" rel="noopener" title="{{'learnMore' | i18n}}">
|
||||||
|
<i class="fa fa-question-circle-o"></i>
|
||||||
|
</a>
|
||||||
|
<select id="kdf" name="Kdf" [(ngModel)]="kdf" class="form-control" required>
|
||||||
|
<option *ngFor="let o of kdfOptions" [ngValue]="o.value">{{o.name}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="form-group mb-0">
|
||||||
|
<label for="kdfIterations">{{'kdfIterations' | i18n}}</label>
|
||||||
|
<a class="ml-auto" href="https://en.wikipedia.org/wiki/PBKDF2" target="_blank" rel="noopener" title="{{'learnMore' | i18n}}">
|
||||||
|
<i class="fa fa-question-circle-o"></i>
|
||||||
|
</a>
|
||||||
|
<input id="kdfIterations" type="number" min="5000" max="1000000" name="KdfIterations" class="form-control" [(ngModel)]="kdfIterations"
|
||||||
|
required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="small form-text text-muted">
|
||||||
|
<p>{{'kdfIterationsDesc' | i18n : (100000 | number)}}</p>
|
||||||
|
<strong>{{'warning' | i18n}}</strong>: {{'kdfIterationsWarning' | i18n : (50000 | number)}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
|
||||||
|
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}"></i>
|
||||||
|
<span>{{'changeKdf' | i18n}}</span>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
69
src/app/settings/change-kdf.component.ts
Normal file
69
src/app/settings/change-kdf.component.ts
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import { ToasterService } from 'angular2-toaster';
|
||||||
|
import { Angulartics2 } from 'angulartics2';
|
||||||
|
|
||||||
|
import { ApiService } from 'jslib/abstractions/api.service';
|
||||||
|
import { CryptoService } from 'jslib/abstractions/crypto.service';
|
||||||
|
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||||
|
import { MessagingService } from 'jslib/abstractions/messaging.service';
|
||||||
|
import { UserService } from 'jslib/abstractions/user.service';
|
||||||
|
|
||||||
|
import { KdfRequest } from 'jslib/models/request/kdfRequest';
|
||||||
|
|
||||||
|
import { KdfType } from 'jslib/enums/kdfType';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-change-kdf',
|
||||||
|
templateUrl: 'change-kdf.component.html',
|
||||||
|
})
|
||||||
|
export class ChangeKdfComponent implements OnInit {
|
||||||
|
masterPassword: string;
|
||||||
|
kdfIterations: number;
|
||||||
|
kdf = KdfType.PBKDF2_SHA256;
|
||||||
|
kdfOptions: any[] = [];
|
||||||
|
formPromise: Promise<any>;
|
||||||
|
|
||||||
|
constructor(private apiService: ApiService, private i18nService: I18nService,
|
||||||
|
private analytics: Angulartics2, private toasterService: ToasterService,
|
||||||
|
private cryptoService: CryptoService, private messagingService: MessagingService,
|
||||||
|
private userService: UserService) {
|
||||||
|
this.kdfOptions = [
|
||||||
|
{ name: 'PBKDF2 SHA-256', value: KdfType.PBKDF2_SHA256 },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
async ngOnInit() {
|
||||||
|
this.kdf = await this.userService.getKdf();
|
||||||
|
this.kdfIterations = await this.userService.getKdfIterations();
|
||||||
|
}
|
||||||
|
|
||||||
|
async submit() {
|
||||||
|
const hasEncKey = await this.cryptoService.hasEncKey();
|
||||||
|
if (!hasEncKey) {
|
||||||
|
this.toasterService.popAsync('error', null, this.i18nService.t('updateKey'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const request = new KdfRequest();
|
||||||
|
request.kdf = this.kdf;
|
||||||
|
request.kdfIterations = this.kdfIterations;
|
||||||
|
request.masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, null);
|
||||||
|
const email = await this.userService.getEmail();
|
||||||
|
const newKey = await this.cryptoService.makeKey(this.masterPassword, email, this.kdf, this.kdfIterations);
|
||||||
|
request.newMasterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, newKey);
|
||||||
|
const newEncKey = await this.cryptoService.remakeEncKey(newKey);
|
||||||
|
request.key = newEncKey[1].encryptedString;
|
||||||
|
try {
|
||||||
|
this.formPromise = this.apiService.postAccountKdf(request);
|
||||||
|
await this.formPromise;
|
||||||
|
this.analytics.eventTrack.next({ action: 'Changed KDF' });
|
||||||
|
this.toasterService.popAsync('success', this.i18nService.t('encKeySettingsChanged'),
|
||||||
|
this.i18nService.t('logBackIn'));
|
||||||
|
this.messagingService.send('logout');
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,11 +7,17 @@
|
|||||||
<input id="currentMasterPassword" type="password" name="MasterPasswordHash" class="form-control" [(ngModel)]="currentMasterPassword"
|
<input id="currentMasterPassword" type="password" name="MasterPasswordHash" class="form-control" [(ngModel)]="currentMasterPassword"
|
||||||
required appInputVerbatim>
|
required appInputVerbatim>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="newMasterPassword">{{'newMasterPass' | i18n}}</label>
|
<label for="newMasterPassword">{{'newMasterPass' | i18n}}</label>
|
||||||
<input id="newMasterPassword" type="password" name="NewMasterPasswordHash" class="form-control" [(ngModel)]="newMasterPassword"
|
<input id="newMasterPassword" type="password" name="NewMasterPasswordHash" class="form-control" [(ngModel)]="newMasterPassword"
|
||||||
required appInputVerbatim autocomplete="new-password">
|
required appInputVerbatim autocomplete="new-password">
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="confirmNewMasterPassword">{{'confirmNewMasterPass' | i18n}}</label>
|
<label for="confirmNewMasterPassword">{{'confirmNewMasterPass' | i18n}}</label>
|
||||||
<input id="confirmNewMasterPassword" type="password" name="ConfirmNewMasterPasswordHash" class="form-control" [(ngModel)]="confirmNewMasterPassword"
|
<input id="confirmNewMasterPassword" type="password" name="ConfirmNewMasterPasswordHash" class="form-control" [(ngModel)]="confirmNewMasterPassword"
|
||||||
|
|||||||
@@ -855,6 +855,39 @@
|
|||||||
"confirmNewMasterPass": {
|
"confirmNewMasterPass": {
|
||||||
"message": "Confirm New Master Password"
|
"message": "Confirm New Master Password"
|
||||||
},
|
},
|
||||||
|
"encKeySettings": {
|
||||||
|
"message": "Encryption Key Settings"
|
||||||
|
},
|
||||||
|
"kdfAlgorithm": {
|
||||||
|
"message": "KDF Algorithm"
|
||||||
|
},
|
||||||
|
"kdfIterations": {
|
||||||
|
"message": "KDF Iterations"
|
||||||
|
},
|
||||||
|
"kdfIterationsDesc": {
|
||||||
|
"message": "Higher KDF iterations can help protect your master password from being brute forced by an attacker. We recommend a value of $VALUE$ or more.",
|
||||||
|
"placeholders": {
|
||||||
|
"value": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "100,000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"kdfIterationsWarning": {
|
||||||
|
"message": "Setting your KDF iterations too high could result in poor performance when logging into (and unlocking) Bitwarden on devices with slower CPUs. We recommend that you increase the value in increments of $INCREMENT$ and then test all of your devices.",
|
||||||
|
"placeholders": {
|
||||||
|
"increment": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "50,000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"changeKdf": {
|
||||||
|
"message": "Change KDF"
|
||||||
|
},
|
||||||
|
"encKeySettingsChanged": {
|
||||||
|
"message": "Encryption Key Settings Changed"
|
||||||
|
},
|
||||||
"dangerZone": {
|
"dangerZone": {
|
||||||
"message": "Danger Zone"
|
"message": "Danger Zone"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user