1
0
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:
Kyle Spearrin
2018-11-07 22:54:56 -05:00
parent f355840f3c
commit ed07c8d01f
4 changed files with 43 additions and 1 deletions

View File

@@ -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>;

View File

@@ -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;