bitwarden-estensione-browser/apps/desktop/src/services/electron-crypto.service.ts

67 lines
2.8 KiB
TypeScript

import { CryptoFunctionService } from "@bitwarden/common/abstractions/cryptoFunction.service";
import { EncryptService } from "@bitwarden/common/abstractions/encrypt.service";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { KeySuffixOptions } from "@bitwarden/common/enums";
import { Utils } from "@bitwarden/common/misc/utils";
import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetric-crypto-key";
import { CryptoService } from "@bitwarden/common/services/crypto.service";
import { CsprngString } from "@bitwarden/common/types/csprng";
import { ElectronStateService } from "./electron-state.service.abstraction";
export class ElectronCryptoService extends CryptoService {
constructor(
cryptoFunctionService: CryptoFunctionService,
encryptService: EncryptService,
platformUtilsService: PlatformUtilsService,
logService: LogService,
protected override stateService: ElectronStateService
) {
super(cryptoFunctionService, encryptService, platformUtilsService, logService, stateService);
}
protected override async storeKey(key: SymmetricCryptoKey, userId?: string) {
await super.storeKey(key, userId);
const storeBiometricKey = await this.shouldStoreKey(KeySuffixOptions.Biometric, userId);
if (storeBiometricKey) {
await this.storeBiometricKey(key, userId);
} else {
await this.stateService.setCryptoMasterKeyBiometric(null, { userId: userId });
}
}
protected async storeBiometricKey(key: SymmetricCryptoKey, userId?: string): Promise<void> {
let clientEncKeyHalf: CsprngString = null;
if (await this.stateService.getBiometricRequirePasswordOnStart({ userId })) {
clientEncKeyHalf = await this.getBiometricEncryptionClientKeyHalf(userId);
}
await this.stateService.setCryptoMasterKeyBiometric(
{ key: key.keyB64, clientEncKeyHalf },
{ userId: userId }
);
}
private async getBiometricEncryptionClientKeyHalf(userId?: string): Promise<CsprngString | null> {
try {
let biometricKey = await this.stateService
.getBiometricEncryptionClientKeyHalf({ userId })
.then((result) => result?.decrypt(null /* user encrypted */))
.then((result) => result as CsprngString);
const userKey = await this.getKeyForUserEncryption();
if (biometricKey == null && userKey != null) {
const keyBytes = await this.cryptoFunctionService.randomBytes(32);
biometricKey = Utils.fromBufferToUtf8(keyBytes) as CsprngString;
const encKey = await this.encryptService.encrypt(biometricKey, userKey);
await this.stateService.setBiometricEncryptionClientKeyHalf(encKey);
}
return biometricKey;
} catch {
return null;
}
}
}