mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 16:23:44 +00:00
get fingerprint crypto method
This commit is contained in:
@@ -16,6 +16,7 @@ export abstract class CryptoService {
|
||||
getEncKey: () => Promise<SymmetricCryptoKey>;
|
||||
getPublicKey: () => Promise<ArrayBuffer>;
|
||||
getPrivateKey: () => Promise<ArrayBuffer>;
|
||||
getFingerprint: () => Promise<string[]>;
|
||||
getOrgKeys: () => Promise<Map<string, SymmetricCryptoKey>>;
|
||||
getOrgKey: (orgId: string) => Promise<SymmetricCryptoKey>;
|
||||
hasKey: () => Promise<boolean>;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import * as bigInt from 'big-integer';
|
||||
|
||||
import { EncryptionType } from '../enums/encryptionType';
|
||||
import { KdfType } from '../enums/kdfType';
|
||||
|
||||
@@ -14,6 +16,7 @@ import { ConstantsService } from './constants.service';
|
||||
|
||||
import { sequentialize } from '../misc/sequentialize';
|
||||
import { Utils } from '../misc/utils';
|
||||
import { EEFLongWordList } from '../misc/wordlist';
|
||||
|
||||
const Keys = {
|
||||
key: 'key',
|
||||
@@ -163,6 +166,16 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
return this.privateKey;
|
||||
}
|
||||
|
||||
async getFingerprint(): Promise<string[]> {
|
||||
const publicKey = await this.getPublicKey();
|
||||
if (publicKey === null) {
|
||||
throw new Error('No public key available.');
|
||||
}
|
||||
const keyFingerprint = await this.cryptoFunctionService.hash(publicKey, 'sha256');
|
||||
const userFingerprint = await this.hkdfExpand(keyFingerprint, Utils.fromUtf8ToArray('USER-ID'), 32);
|
||||
return this.hashPhrase(userFingerprint.buffer);
|
||||
}
|
||||
|
||||
@sequentialize(() => 'getOrgKeys')
|
||||
async getOrgKeys(): Promise<Map<string, SymmetricCryptoKey>> {
|
||||
if (this.orgKeys != null && this.orgKeys.size > 0) {
|
||||
@@ -675,6 +688,28 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
return okm;
|
||||
}
|
||||
|
||||
private async hashPhrase(data: ArrayBuffer, minimumEntropy: number = 64) {
|
||||
const wordListLength = EEFLongWordList.length;
|
||||
const entropyPerWord = Math.log(wordListLength) / Math.log(2);
|
||||
let numWords = Math.ceil(minimumEntropy / entropyPerWord);
|
||||
|
||||
const hashBuffer = await this.cryptoFunctionService.pbkdf2(data, '', 'sha256', 50000);
|
||||
const hash = Array.from(new Uint8Array(hashBuffer));
|
||||
const entropyAvailable = hash.length * 4;
|
||||
if (numWords * entropyPerWord > entropyAvailable) {
|
||||
throw new Error('Output entropy of hash function is too small');
|
||||
}
|
||||
|
||||
const phrase: string[] = [];
|
||||
let hashNumber = bigInt.fromArray(hash, 256);
|
||||
while (numWords--) {
|
||||
const remainder = hashNumber.mod(wordListLength);
|
||||
hashNumber = hashNumber.divide(wordListLength);
|
||||
phrase.push(EEFLongWordList[remainder as any]);
|
||||
}
|
||||
return phrase;
|
||||
}
|
||||
|
||||
private async buildEncKey(key: SymmetricCryptoKey, encKey: ArrayBuffer = null)
|
||||
: Promise<[SymmetricCryptoKey, CipherString]> {
|
||||
let encKeyEnc: CipherString = null;
|
||||
|
||||
Reference in New Issue
Block a user