From 5b7d918f29423d9308ba80b7fefa9c2da1899b8f Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Wed, 28 Apr 2021 22:02:43 +0200 Subject: [PATCH] Validate key before using it (#366) * Validate key before using it --- src/abstractions/crypto.service.ts | 1 + src/services/crypto.service.ts | 48 ++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/abstractions/crypto.service.ts b/src/abstractions/crypto.service.ts index 3d5c0242fa..e10eb6ecb1 100644 --- a/src/abstractions/crypto.service.ts +++ b/src/abstractions/crypto.service.ts @@ -48,4 +48,5 @@ export abstract class CryptoService { decryptToUtf8: (encString: EncString, key?: SymmetricCryptoKey) => Promise; decryptFromBytes: (encBuf: ArrayBuffer, key: SymmetricCryptoKey) => Promise; randomNumber: (min: number, max: number) => Promise; + validateKey: (key: SymmetricCryptoKey) => Promise; } diff --git a/src/services/crypto.service.ts b/src/services/crypto.service.ts index 958f38ab5d..e930cf9dcc 100644 --- a/src/services/crypto.service.ts +++ b/src/services/crypto.service.ts @@ -46,10 +46,7 @@ export class CryptoService implements CryptoServiceAbstraction { async setKey(key: SymmetricCryptoKey): Promise { this.key = key; - const option = await this.storageService.get(ConstantsService.vaultTimeoutKey); - const biometric = await this.storageService.get(ConstantsService.biometricUnlockKey); - if (option != null && !(biometric && this.platformUtilService.supportsSecureStorage())) { - // if we have a lock option set, we do not store the key + if (!await this.shouldStoreKey()) { return; } @@ -96,7 +93,21 @@ export class CryptoService implements CryptoServiceAbstraction { const key = await this.secureStorageService.get(Keys.key); if (key != null) { - this.key = new SymmetricCryptoKey(Utils.fromB64ToArray(key).buffer); + if (!await this.shouldStoreKey()) { + this.logService.warning('Throwing away stored key since settings have changed'); + this.secureStorageService.remove(Keys.key); + return null; + } + + const symmetricKey = new SymmetricCryptoKey(Utils.fromB64ToArray(key).buffer); + + if (!await this.validateKey(symmetricKey)) { + this.logService.warning('Wrong key, throwing away stored key'); + this.secureStorageService.remove(Keys.key); + return null; + } + + this.key = symmetricKey; } return key == null ? null : this.key; @@ -580,8 +591,35 @@ export class CryptoService implements CryptoServiceAbstraction { return min + rval; } + async validateKey(key: SymmetricCryptoKey) { + try { + const encPrivateKey = await this.storageService.get(Keys.encPrivateKey); + if (encPrivateKey == null) { + return false; + } + + const encKey = await this.getEncKey(key); + const privateKey = await this.decryptToBytes(new EncString(encPrivateKey), encKey); + await this.cryptoFunctionService.rsaExtractPublicKey(privateKey); + } catch (e) { + return false; + } + + return true; + } + // Helpers + private async shouldStoreKey() { + const vaultTimeout = await this.storageService.get(ConstantsService.vaultTimeoutKey); + const biometricUnlock = await this.storageService.get(ConstantsService.biometricUnlockKey); + + const biometricsEnabled = biometricUnlock && this.platformUtilService.supportsSecureStorage(); + const noVaultTimeout = vaultTimeout == null; + + return noVaultTimeout || biometricsEnabled; + } + private async aesEncrypt(data: ArrayBuffer, key: SymmetricCryptoKey): Promise { const obj = new EncryptedObject(); obj.key = await this.getKeyForEncryption(key);