1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-23 11:56:00 +01:00

remove some crypto functions

This commit is contained in:
Kyle Spearrin 2018-05-07 12:14:40 -04:00
parent dfcde8a29a
commit e614cffffb
6 changed files with 39 additions and 39 deletions

View File

@ -76,7 +76,7 @@ describe('NodeCrypto Function Service', () => {
testHmac('sha512', Sha512Mac); testHmac('sha512', Sha512Mac);
}); });
describe('timeSafeEqual', () => { describe('compare', () => {
testCompare(false); testCompare(false);
}); });
@ -86,7 +86,7 @@ describe('NodeCrypto Function Service', () => {
testHmac('sha512', Sha512Mac, true); testHmac('sha512', Sha512Mac, true);
}); });
describe('timeSafeEqualFast', () => { describe('compareFast', () => {
testCompare(true); testCompare(true);
}); });
@ -107,7 +107,7 @@ describe('NodeCrypto Function Service', () => {
const value = 'EncryptMe!'; const value = 'EncryptMe!';
const data = Utils.fromUtf8ToArray(value); const data = Utils.fromUtf8ToArray(value);
const encValue = await nodeCryptoFunctionService.aesEncrypt(data.buffer, iv.buffer, key.buffer); const encValue = await nodeCryptoFunctionService.aesEncrypt(data.buffer, iv.buffer, key.buffer);
const decValue = await nodeCryptoFunctionService.aesDecryptLarge(encValue, iv.buffer, key.buffer); const decValue = await nodeCryptoFunctionService.aesDecrypt(encValue, iv.buffer, key.buffer);
expect(Utils.fromBufferToUtf8(decValue)).toBe(value); expect(Utils.fromBufferToUtf8(decValue)).toBe(value);
}); });
}); });
@ -124,13 +124,13 @@ describe('NodeCrypto Function Service', () => {
}); });
}); });
describe('aesDecryptLarge', () => { describe('aesDecrypt', () => {
it('should successfully decrypt data', async () => { it('should successfully decrypt data', async () => {
const nodeCryptoFunctionService = new NodeCryptoFunctionService(); const nodeCryptoFunctionService = new NodeCryptoFunctionService();
const iv = makeStaticByteArray(16); const iv = makeStaticByteArray(16);
const key = makeStaticByteArray(32); const key = makeStaticByteArray(32);
const data = Utils.fromB64ToArray('ByUF8vhyX4ddU9gcooznwA=='); const data = Utils.fromB64ToArray('ByUF8vhyX4ddU9gcooznwA==');
const decValue = await nodeCryptoFunctionService.aesDecryptLarge(data.buffer, iv.buffer, key.buffer); const decValue = await nodeCryptoFunctionService.aesDecrypt(data.buffer, iv.buffer, key.buffer);
expect(Utils.fromBufferToUtf8(decValue)).toBe('EncryptMe!'); expect(Utils.fromBufferToUtf8(decValue)).toBe('EncryptMe!');
}); });
}); });
@ -262,8 +262,8 @@ function testCompare(fast = false) {
const a = new Uint8Array(2); const a = new Uint8Array(2);
a[0] = 1; a[0] = 1;
a[1] = 2; a[1] = 2;
const equal = fast ? await cryptoFunctionService.timeSafeEqualFast(a.buffer, a.buffer) : const equal = fast ? await cryptoFunctionService.compareFast(a.buffer, a.buffer) :
await cryptoFunctionService.timeSafeEqual(a.buffer, a.buffer); await cryptoFunctionService.compare(a.buffer, a.buffer);
expect(equal).toBe(true); expect(equal).toBe(true);
}); });
@ -275,8 +275,8 @@ function testCompare(fast = false) {
const b = new Uint8Array(2); const b = new Uint8Array(2);
b[0] = 3; b[0] = 3;
b[1] = 4; b[1] = 4;
const equal = fast ? await cryptoFunctionService.timeSafeEqualFast(a.buffer, b.buffer) : const equal = fast ? await cryptoFunctionService.compareFast(a.buffer, b.buffer) :
await cryptoFunctionService.timeSafeEqual(a.buffer, b.buffer); await cryptoFunctionService.compare(a.buffer, b.buffer);
expect(equal).toBe(false); expect(equal).toBe(false);
}); });
@ -287,8 +287,8 @@ function testCompare(fast = false) {
a[1] = 2; a[1] = 2;
const b = new Uint8Array(2); const b = new Uint8Array(2);
b[0] = 3; b[0] = 3;
const equal = fast ? await cryptoFunctionService.timeSafeEqualFast(a.buffer, b.buffer) : const equal = fast ? await cryptoFunctionService.compareFast(a.buffer, b.buffer) :
await cryptoFunctionService.timeSafeEqual(a.buffer, b.buffer); await cryptoFunctionService.compare(a.buffer, b.buffer);
expect(equal).toBe(false); expect(equal).toBe(false);
}); });
} }

View File

@ -82,13 +82,13 @@ describe('WebCrypto Function Service', () => {
testHmac('sha512', Sha512Mac); testHmac('sha512', Sha512Mac);
}); });
describe('timeSafeEqual', () => { describe('compare', () => {
it('should successfully compare two of the same values', async () => { it('should successfully compare two of the same values', async () => {
const cryptoFunctionService = getWebCryptoFunctionService(); const cryptoFunctionService = getWebCryptoFunctionService();
const a = new Uint8Array(2); const a = new Uint8Array(2);
a[0] = 1; a[0] = 1;
a[1] = 2; a[1] = 2;
const equal = await cryptoFunctionService.timeSafeEqual(a.buffer, a.buffer); const equal = await cryptoFunctionService.compare(a.buffer, a.buffer);
expect(equal).toBe(true); expect(equal).toBe(true);
}); });
@ -100,7 +100,7 @@ describe('WebCrypto Function Service', () => {
const b = new Uint8Array(2); const b = new Uint8Array(2);
b[0] = 3; b[0] = 3;
b[1] = 4; b[1] = 4;
const equal = await cryptoFunctionService.timeSafeEqual(a.buffer, b.buffer); const equal = await cryptoFunctionService.compare(a.buffer, b.buffer);
expect(equal).toBe(false); expect(equal).toBe(false);
}); });
@ -111,7 +111,7 @@ describe('WebCrypto Function Service', () => {
a[1] = 2; a[1] = 2;
const b = new Uint8Array(2); const b = new Uint8Array(2);
b[0] = 3; b[0] = 3;
const equal = await cryptoFunctionService.timeSafeEqual(a.buffer, b.buffer); const equal = await cryptoFunctionService.compare(a.buffer, b.buffer);
expect(equal).toBe(false); expect(equal).toBe(false);
}); });
}); });
@ -122,14 +122,14 @@ describe('WebCrypto Function Service', () => {
testHmacFast('sha512', Sha512Mac); testHmacFast('sha512', Sha512Mac);
}); });
describe('timeSafeEqualFast', () => { describe('compareFast', () => {
it('should successfully compare two of the same values', async () => { it('should successfully compare two of the same values', async () => {
const cryptoFunctionService = getWebCryptoFunctionService(); const cryptoFunctionService = getWebCryptoFunctionService();
const a = new Uint8Array(2); const a = new Uint8Array(2);
a[0] = 1; a[0] = 1;
a[1] = 2; a[1] = 2;
const aByteString = Utils.fromBufferToByteString(a.buffer); const aByteString = Utils.fromBufferToByteString(a.buffer);
const equal = await cryptoFunctionService.timeSafeEqualFast(aByteString, aByteString); const equal = await cryptoFunctionService.compareFast(aByteString, aByteString);
expect(equal).toBe(true); expect(equal).toBe(true);
}); });
@ -143,7 +143,7 @@ describe('WebCrypto Function Service', () => {
b[0] = 3; b[0] = 3;
b[1] = 4; b[1] = 4;
const bByteString = Utils.fromBufferToByteString(b.buffer); const bByteString = Utils.fromBufferToByteString(b.buffer);
const equal = await cryptoFunctionService.timeSafeEqualFast(aByteString, bByteString); const equal = await cryptoFunctionService.compareFast(aByteString, bByteString);
expect(equal).toBe(false); expect(equal).toBe(false);
}); });
@ -156,7 +156,7 @@ describe('WebCrypto Function Service', () => {
const b = new Uint8Array(2); const b = new Uint8Array(2);
b[0] = 3; b[0] = 3;
const bByteString = Utils.fromBufferToByteString(b.buffer); const bByteString = Utils.fromBufferToByteString(b.buffer);
const equal = await cryptoFunctionService.timeSafeEqualFast(aByteString, bByteString); const equal = await cryptoFunctionService.compareFast(aByteString, bByteString);
expect(equal).toBe(false); expect(equal).toBe(false);
}); });
}); });
@ -171,7 +171,7 @@ describe('WebCrypto Function Service', () => {
expect(Utils.fromBufferToB64(encValue)).toBe('ByUF8vhyX4ddU9gcooznwA=='); expect(Utils.fromBufferToB64(encValue)).toBe('ByUF8vhyX4ddU9gcooznwA==');
}); });
it('should successfully encrypt and then decrypt small data', async () => { it('should successfully encrypt and then decrypt data fast', async () => {
const cryptoFunctionService = getWebCryptoFunctionService(); const cryptoFunctionService = getWebCryptoFunctionService();
const iv = makeStaticByteArray(16); const iv = makeStaticByteArray(16);
const key = makeStaticByteArray(32); const key = makeStaticByteArray(32);
@ -186,14 +186,14 @@ describe('WebCrypto Function Service', () => {
expect(decValue).toBe(value); expect(decValue).toBe(value);
}); });
it('should successfully encrypt and then decrypt large data', async () => { it('should successfully encrypt and then decrypt data', async () => {
const cryptoFunctionService = getWebCryptoFunctionService(); const cryptoFunctionService = getWebCryptoFunctionService();
const iv = makeStaticByteArray(16); const iv = makeStaticByteArray(16);
const key = makeStaticByteArray(32); const key = makeStaticByteArray(32);
const value = 'EncryptMe!'; const value = 'EncryptMe!';
const data = Utils.fromUtf8ToArray(value); const data = Utils.fromUtf8ToArray(value);
const encValue = await cryptoFunctionService.aesEncrypt(data.buffer, iv.buffer, key.buffer); const encValue = await cryptoFunctionService.aesEncrypt(data.buffer, iv.buffer, key.buffer);
const decValue = await cryptoFunctionService.aesDecryptLarge(encValue, iv.buffer, key.buffer); const decValue = await cryptoFunctionService.aesDecrypt(encValue, iv.buffer, key.buffer);
expect(Utils.fromBufferToUtf8(decValue)).toBe(value); expect(Utils.fromBufferToUtf8(decValue)).toBe(value);
}); });
}); });
@ -210,13 +210,13 @@ describe('WebCrypto Function Service', () => {
}); });
}); });
describe('aesDecryptLarge', () => { describe('aesDecrypt', () => {
it('should successfully decrypt data', async () => { it('should successfully decrypt data', async () => {
const cryptoFunctionService = getWebCryptoFunctionService(); const cryptoFunctionService = getWebCryptoFunctionService();
const iv = makeStaticByteArray(16); const iv = makeStaticByteArray(16);
const key = makeStaticByteArray(32); const key = makeStaticByteArray(32);
const data = Utils.fromB64ToArray('ByUF8vhyX4ddU9gcooznwA=='); const data = Utils.fromB64ToArray('ByUF8vhyX4ddU9gcooznwA==');
const decValue = await cryptoFunctionService.aesDecryptLarge(data.buffer, iv.buffer, key.buffer); const decValue = await cryptoFunctionService.aesDecrypt(data.buffer, iv.buffer, key.buffer);
expect(Utils.fromBufferToUtf8(decValue)).toBe('EncryptMe!'); expect(Utils.fromBufferToUtf8(decValue)).toBe('EncryptMe!');
}); });
}); });

View File

@ -6,15 +6,15 @@ export abstract class CryptoFunctionService {
iterations: number) => Promise<ArrayBuffer>; iterations: number) => Promise<ArrayBuffer>;
hash: (value: string | ArrayBuffer, algorithm: 'sha1' | 'sha256' | 'sha512') => Promise<ArrayBuffer>; hash: (value: string | ArrayBuffer, algorithm: 'sha1' | 'sha256' | 'sha512') => Promise<ArrayBuffer>;
hmac: (value: ArrayBuffer, key: ArrayBuffer, algorithm: 'sha1' | 'sha256' | 'sha512') => Promise<ArrayBuffer>; hmac: (value: ArrayBuffer, key: ArrayBuffer, algorithm: 'sha1' | 'sha256' | 'sha512') => Promise<ArrayBuffer>;
timeSafeEqual: (a: ArrayBuffer, b: ArrayBuffer) => Promise<boolean>; compare: (a: ArrayBuffer, b: ArrayBuffer) => Promise<boolean>;
hmacFast: (value: ArrayBuffer | string, key: ArrayBuffer | string, algorithm: 'sha1' | 'sha256' | 'sha512') => hmacFast: (value: ArrayBuffer | string, key: ArrayBuffer | string, algorithm: 'sha1' | 'sha256' | 'sha512') =>
Promise<ArrayBuffer | string>; Promise<ArrayBuffer | string>;
timeSafeEqualFast: (a: ArrayBuffer | string, b: ArrayBuffer | string) => Promise<boolean>; compareFast: (a: ArrayBuffer | string, b: ArrayBuffer | string) => Promise<boolean>;
aesEncrypt: (data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer) => Promise<ArrayBuffer>; aesEncrypt: (data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer) => Promise<ArrayBuffer>;
aesDecryptFastParameters: (data: string, iv: string, mac: string, key: SymmetricCryptoKey) => aesDecryptFastParameters: (data: string, iv: string, mac: string, key: SymmetricCryptoKey) =>
DecryptParameters<ArrayBuffer | string>; DecryptParameters<ArrayBuffer | string>;
aesDecryptFast: (parameters: DecryptParameters<ArrayBuffer | string>) => Promise<string>; aesDecryptFast: (parameters: DecryptParameters<ArrayBuffer | string>) => Promise<string>;
aesDecryptLarge: (data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer) => Promise<ArrayBuffer>; aesDecrypt: (data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer) => Promise<ArrayBuffer>;
rsaEncrypt: (data: ArrayBuffer, publicKey: ArrayBuffer, algorithm: 'sha1' | 'sha256') => Promise<ArrayBuffer>; rsaEncrypt: (data: ArrayBuffer, publicKey: ArrayBuffer, algorithm: 'sha1' | 'sha256') => Promise<ArrayBuffer>;
rsaDecrypt: (data: ArrayBuffer, key: ArrayBuffer, algorithm: 'sha1' | 'sha256') => Promise<ArrayBuffer>; rsaDecrypt: (data: ArrayBuffer, key: ArrayBuffer, algorithm: 'sha1' | 'sha256') => Promise<ArrayBuffer>;
randomBytes: (length: number) => Promise<ArrayBuffer>; randomBytes: (length: number) => Promise<ArrayBuffer>;

View File

@ -430,7 +430,7 @@ export class CryptoService implements CryptoServiceAbstraction {
if (fastParams.macKey != null && fastParams.mac != null) { if (fastParams.macKey != null && fastParams.mac != null) {
const computedMac = await this.cryptoFunctionService.hmacFast(fastParams.macData, const computedMac = await this.cryptoFunctionService.hmacFast(fastParams.macData,
fastParams.macKey, 'sha256'); fastParams.macKey, 'sha256');
const macsEqual = await this.cryptoFunctionService.timeSafeEqualFast(fastParams.mac, computedMac); const macsEqual = await this.cryptoFunctionService.compareFast(fastParams.mac, computedMac);
if (!macsEqual) { if (!macsEqual) {
// tslint:disable-next-line // tslint:disable-next-line
console.error('mac failed.'); console.error('mac failed.');
@ -463,7 +463,7 @@ export class CryptoService implements CryptoServiceAbstraction {
return null; return null;
} }
const macsMatch = await this.cryptoFunctionService.timeSafeEqual(mac, computedMac); const macsMatch = await this.cryptoFunctionService.compare(mac, computedMac);
if (!macsMatch) { if (!macsMatch) {
// tslint:disable-next-line // tslint:disable-next-line
console.error('mac failed.'); console.error('mac failed.');
@ -471,7 +471,7 @@ export class CryptoService implements CryptoServiceAbstraction {
} }
} }
return await this.cryptoFunctionService.aesDecryptLarge(ct, iv, theKey.encKey); return await this.cryptoFunctionService.aesDecrypt(ct, iv, theKey.encKey);
} }
private async rsaDecrypt(encValue: string): Promise<ArrayBuffer> { private async rsaDecrypt(encValue: string): Promise<ArrayBuffer> {
@ -515,7 +515,7 @@ export class CryptoService implements CryptoServiceAbstraction {
if (key != null && key.macKey != null && encPieces.length > 1) { if (key != null && key.macKey != null && encPieces.length > 1) {
const mac = Utils.fromB64ToArray(encPieces[1]).buffer; const mac = Utils.fromB64ToArray(encPieces[1]).buffer;
const computedMac = await this.cryptoFunctionService.hmac(ct, key.macKey, 'sha256'); const computedMac = await this.cryptoFunctionService.hmac(ct, key.macKey, 'sha256');
const macsEqual = await this.cryptoFunctionService.timeSafeEqual(mac, computedMac); const macsEqual = await this.cryptoFunctionService.compare(mac, computedMac);
if (!macsEqual) { if (!macsEqual) {
throw new Error('MAC failed.'); throw new Error('MAC failed.');
} }

View File

@ -41,7 +41,7 @@ export class NodeCryptoFunctionService implements CryptoFunctionService {
return Promise.resolve(this.toArrayBuffer(hmac.digest())); return Promise.resolve(this.toArrayBuffer(hmac.digest()));
} }
async timeSafeEqual(a: ArrayBuffer, b: ArrayBuffer): Promise<boolean> { async compare(a: ArrayBuffer, b: ArrayBuffer): Promise<boolean> {
const key = await this.randomBytes(32); const key = await this.randomBytes(32);
const mac1 = await this.hmac(a, key, 'sha256'); const mac1 = await this.hmac(a, key, 'sha256');
const mac2 = await this.hmac(b, key, 'sha256'); const mac2 = await this.hmac(b, key, 'sha256');
@ -64,8 +64,8 @@ export class NodeCryptoFunctionService implements CryptoFunctionService {
return this.hmac(value, key, algorithm); return this.hmac(value, key, algorithm);
} }
timeSafeEqualFast(a: ArrayBuffer, b: ArrayBuffer): Promise<boolean> { compareFast(a: ArrayBuffer, b: ArrayBuffer): Promise<boolean> {
return this.timeSafeEqual(a, b); return this.compare(a, b);
} }
aesEncrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise<ArrayBuffer> { aesEncrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise<ArrayBuffer> {
@ -100,11 +100,11 @@ export class NodeCryptoFunctionService implements CryptoFunctionService {
} }
async aesDecryptFast(parameters: DecryptParameters<ArrayBuffer>): Promise<string> { async aesDecryptFast(parameters: DecryptParameters<ArrayBuffer>): Promise<string> {
const decBuf = await this.aesDecryptLarge(parameters.data, parameters.iv, parameters.encKey); const decBuf = await this.aesDecrypt(parameters.data, parameters.iv, parameters.encKey);
return Utils.fromBufferToUtf8(decBuf); return Utils.fromBufferToUtf8(decBuf);
} }
aesDecryptLarge(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise<ArrayBuffer> { aesDecrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise<ArrayBuffer> {
const nodeData = this.toNodeBuffer(data); const nodeData = this.toNodeBuffer(data);
const nodeIv = this.toNodeBuffer(iv); const nodeIv = this.toNodeBuffer(iv);
const nodeKey = this.toNodeBuffer(key); const nodeKey = this.toNodeBuffer(key);

View File

@ -69,7 +69,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
// Safely compare two values in a way that protects against timing attacks (Double HMAC Verification). // Safely compare two values in a way that protects against timing attacks (Double HMAC Verification).
// ref: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/ // ref: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/
// ref: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy // ref: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy
async timeSafeEqual(a: ArrayBuffer, b: ArrayBuffer): Promise<boolean> { async compare(a: ArrayBuffer, b: ArrayBuffer): Promise<boolean> {
const macKey = await this.randomBytes(32); const macKey = await this.randomBytes(32);
const signingAlgorithm = { const signingAlgorithm = {
name: 'HMAC', name: 'HMAC',
@ -102,7 +102,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
return Promise.resolve(bytes); return Promise.resolve(bytes);
} }
async timeSafeEqualFast(a: string, b: string): Promise<boolean> { async compareFast(a: string, b: string): Promise<boolean> {
const rand = await this.randomBytes(32); const rand = await this.randomBytes(32);
const bytes = new Uint32Array(rand); const bytes = new Uint32Array(rand);
const buffer = forge.util.createBuffer(); const buffer = forge.util.createBuffer();
@ -155,7 +155,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
return Promise.resolve(val); return Promise.resolve(val);
} }
async aesDecryptLarge(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise<ArrayBuffer> { async aesDecrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise<ArrayBuffer> {
const impKey = await this.subtle.importKey('raw', key, { name: 'AES-CBC' }, false, ['decrypt']); const impKey = await this.subtle.importKey('raw', key, { name: 'AES-CBC' }, false, ['decrypt']);
return await this.subtle.decrypt({ name: 'AES-CBC', iv: iv }, impKey, data); return await this.subtle.decrypt({ name: 'AES-CBC', iv: iv }, impKey, data);
} }