diff --git a/src/abstractions/crypto.service.ts b/src/abstractions/crypto.service.ts index 3ee45f1bc..2805e1e98 100644 --- a/src/abstractions/crypto.service.ts +++ b/src/abstractions/crypto.service.ts @@ -13,7 +13,7 @@ export abstract class CryptoService { setOrgKeys: (orgs: ProfileOrganizationResponse[]) => Promise<{}>; getKey: () => Promise; getKeyHash: () => Promise; - getEncKey: () => Promise; + getEncKey: (key?: SymmetricCryptoKey) => Promise; getPublicKey: () => Promise; getPrivateKey: () => Promise; getFingerprint: (userId: string, publicKey?: ArrayBuffer) => Promise; @@ -30,7 +30,8 @@ export abstract class CryptoService { clearKeys: () => Promise; toggleKey: () => Promise; makeKey: (password: string, salt: string, kdf: KdfType, kdfIterations: number) => Promise; - makeKeyFromPin: (pin: string, salt: string, kdf: KdfType, kdfIterations: number) => Promise; + makeKeyFromPin: (pin: string, salt: string, kdf: KdfType, kdfIterations: number, + protectedKeyCs?: CipherString) => Promise; makeShareKey: () => Promise<[CipherString, SymmetricCryptoKey]>; makeKeyPair: (key?: SymmetricCryptoKey) => Promise<[string, CipherString]>; makePinKey: (pin: string, salt: string, kdf: KdfType, kdfIterations: number) => Promise; diff --git a/src/abstractions/lock.service.ts b/src/abstractions/lock.service.ts index ede31db0b..f43938bb4 100644 --- a/src/abstractions/lock.service.ts +++ b/src/abstractions/lock.service.ts @@ -1,5 +1,7 @@ +import { CipherString } from '../models/domain/cipherString'; + export abstract class LockService { - pinLocked: boolean; + pinProtectedKey: CipherString; isLocked: () => Promise; checkLock: () => Promise; lock: (allowSoftLock?: boolean) => Promise; diff --git a/src/angular/components/lock.component.ts b/src/angular/components/lock.component.ts index a5357f897..1258b545d 100644 --- a/src/angular/components/lock.component.ts +++ b/src/angular/components/lock.component.ts @@ -40,8 +40,7 @@ export class LockComponent implements OnInit { async ngOnInit() { this.pinSet = await this.lockService.isPinLockSet(); - const hasKey = await this.cryptoService.hasKey(); - this.pinLock = (this.pinSet[0] && hasKey) || this.pinSet[1]; + this.pinLock = (this.pinSet[0] && this.lockService.pinProtectedKey != null) || this.pinSet[1]; this.email = await this.userService.getEmail(); let vaultUrl = this.environmentService.getWebVaultUrl(); if (vaultUrl == null) { @@ -69,12 +68,14 @@ export class LockComponent implements OnInit { let failed = true; try { if (this.pinSet[0]) { + const key = await this.cryptoService.makeKeyFromPin(this.pin, this.email, kdf, kdfIterations, + this.lockService.pinProtectedKey); + const encKey = await this.cryptoService.getEncKey(key); const protectedPin = await this.storageService.get(ConstantsService.protectedPin); - const decPin = await this.cryptoService.decryptToUtf8(new CipherString(protectedPin)); + const decPin = await this.cryptoService.decryptToUtf8(new CipherString(protectedPin), encKey); failed = decPin !== this.pin; - this.lockService.pinLocked = failed; if (!failed) { - this.doContinue(); + await this.setKeyAndContinue(key); } } else { const key = await this.cryptoService.makeKeyFromPin(this.pin, this.email, kdf, kdfIterations); @@ -100,6 +101,13 @@ export class LockComponent implements OnInit { const storedKeyHash = await this.cryptoService.getKeyHash(); if (storedKeyHash != null && keyHash != null && storedKeyHash === keyHash) { + if (this.pinSet[0]) { + const protectedPin = await this.storageService.get(ConstantsService.protectedPin); + const encKey = await this.cryptoService.getEncKey(key); + const decPin = await this.cryptoService.decryptToUtf8(new CipherString(protectedPin), encKey); + const pinKey = await this.cryptoService.makePinKey(decPin, this.email, kdf, kdfIterations); + this.lockService.pinProtectedKey = await this.cryptoService.encrypt(key.key, pinKey); + } this.setKeyAndContinue(key); } else { this.platformUtilsService.showToast('error', this.i18nService.t('errorOccurred'), diff --git a/src/services/crypto.service.ts b/src/services/crypto.service.ts index dae82f5be..b0a38f6d2 100644 --- a/src/services/crypto.service.ts +++ b/src/services/crypto.service.ts @@ -110,7 +110,7 @@ export class CryptoService implements CryptoServiceAbstraction { } @sequentialize(() => 'getEncKey') - async getEncKey(): Promise { + async getEncKey(key: SymmetricCryptoKey = null): Promise { if (this.encKey != null) { return this.encKey; } @@ -120,7 +120,9 @@ export class CryptoService implements CryptoServiceAbstraction { return null; } - const key = await this.getKey(); + if (key == null) { + key = await this.getKey(); + } if (key == null) { return null; } @@ -315,13 +317,16 @@ export class CryptoService implements CryptoServiceAbstraction { return new SymmetricCryptoKey(key); } - async makeKeyFromPin(pin: string, salt: string, kdf: KdfType, kdfIterations: number): + async makeKeyFromPin(pin: string, salt: string, kdf: KdfType, kdfIterations: number, + protectedKeyCs: CipherString = null): Promise { - const pinProtectedKey = await this.storageService.get(ConstantsService.pinProtectedKey); - if (pinProtectedKey == null) { - throw new Error('No PIN protected key found.'); + if (protectedKeyCs == null) { + const pinProtectedKey = await this.storageService.get(ConstantsService.pinProtectedKey); + if (pinProtectedKey == null) { + throw new Error('No PIN protected key found.'); + } + protectedKeyCs = new CipherString(pinProtectedKey); } - const protectedKeyCs = new CipherString(pinProtectedKey); const pinKey = await this.makePinKey(pin, salt, kdf, kdfIterations); const decKey = await this.decryptToBytes(protectedKeyCs, pinKey); return new SymmetricCryptoKey(decKey); diff --git a/src/services/lock.service.ts b/src/services/lock.service.ts index 851838b80..b82c87661 100644 --- a/src/services/lock.service.ts +++ b/src/services/lock.service.ts @@ -11,8 +11,10 @@ import { SearchService } from '../abstractions/search.service'; import { StorageService } from '../abstractions/storage.service'; import { UserService } from '../abstractions/user.service'; +import { CipherString } from '../models/domain/cipherString'; + export class LockService implements LockServiceAbstraction { - pinLocked = false; + pinProtectedKey: CipherString = null; private inited = false; @@ -37,9 +39,6 @@ export class LockService implements LockServiceAbstraction { async isLocked(): Promise { const hasKey = await this.cryptoService.hasKey(); - if (hasKey && this.pinLocked) { - return true; - } return !hasKey; } @@ -85,18 +84,6 @@ export class LockService implements LockServiceAbstraction { return; } - if (allowSoftLock) { - const pinSet = await this.isPinLockSet(); - if (pinSet[0]) { - this.pinLocked = true; - this.messagingService.send('locked'); - if (this.lockedCallback != null) { - await this.lockedCallback(); - } - return; - } - } - await Promise.all([ this.cryptoService.clearKey(), this.cryptoService.clearOrgKeys(true), @@ -126,6 +113,7 @@ export class LockService implements LockServiceAbstraction { } clear(): Promise { + this.pinProtectedKey = null; return this.storageService.remove(ConstantsService.protectedPin); } } diff --git a/src/services/system.service.ts b/src/services/system.service.ts index a53b39800..aa77cb3d8 100644 --- a/src/services/system.service.ts +++ b/src/services/system.service.ts @@ -19,7 +19,7 @@ export class SystemService implements SystemServiceAbstraction { } startProcessReload(): void { - if (this.lockService.pinLocked || this.reloadInterval != null) { + if (this.lockService.pinProtectedKey != null || this.reloadInterval != null) { return; } this.cancelProcessReload();