change KDF

This commit is contained in:
Kyle Spearrin 2018-08-27 22:40:03 -04:00
parent 85c3056223
commit 1444c99458
7 changed files with 162 additions and 1 deletions

2
jslib

@ -1 +1 @@
Subproject commit 00562d083b687fb566b09c0df8a05e90b86f9e5a
Subproject commit 0d15ae8615771842ec18567da001cf6e8b40e3e1

View File

@ -75,6 +75,7 @@ import { AccountComponent } from './settings/account.component';
import { AdjustPaymentComponent } from './settings/adjust-payment.component';
import { AdjustStorageComponent } from './settings/adjust-storage.component';
import { ChangeEmailComponent } from './settings/change-email.component';
import { ChangeKdfComponent } from './settings/change-kdf.component';
import { ChangePasswordComponent } from './settings/change-password.component';
import { CreateOrganizationComponent } from './settings/create-organization.component';
import { DeauthorizeSessionsComponent } from './settings/deauthorize-sessions.component';
@ -204,6 +205,7 @@ registerLocaleData(localeZhCn, 'zh-CN');
BulkShareComponent,
CalloutComponent,
ChangeEmailComponent,
ChangeKdfComponent,
ChangePasswordComponent,
CiphersComponent,
CollectionsComponent,

View File

@ -10,6 +10,10 @@
<h1>{{'changeMasterPassword' | i18n}}</h1>
</div>
<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">
<h1>{{'dangerZone' | i18n}}</h1>
</div>

View 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>

View 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 { }
}
}

View File

@ -7,11 +7,17 @@
<input id="currentMasterPassword" type="password" name="MasterPasswordHash" class="form-control" [(ngModel)]="currentMasterPassword"
required appInputVerbatim>
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<div class="form-group">
<label for="newMasterPassword">{{'newMasterPass' | i18n}}</label>
<input id="newMasterPassword" type="password" name="NewMasterPasswordHash" class="form-control" [(ngModel)]="newMasterPassword"
required appInputVerbatim autocomplete="new-password">
</div>
</div>
<div class="col-6">
<div class="form-group">
<label for="confirmNewMasterPassword">{{'confirmNewMasterPass' | i18n}}</label>
<input id="confirmNewMasterPassword" type="password" name="ConfirmNewMasterPasswordHash" class="form-control" [(ngModel)]="confirmNewMasterPassword"

View File

@ -855,6 +855,39 @@
"confirmNewMasterPass": {
"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": {
"message": "Danger Zone"
},