mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-24 16:49:26 +01:00
remove some crypto functions
This commit is contained in:
parent
dfcde8a29a
commit
e614cffffb
@ -76,7 +76,7 @@ describe('NodeCrypto Function Service', () => {
|
||||
testHmac('sha512', Sha512Mac);
|
||||
});
|
||||
|
||||
describe('timeSafeEqual', () => {
|
||||
describe('compare', () => {
|
||||
testCompare(false);
|
||||
});
|
||||
|
||||
@ -86,7 +86,7 @@ describe('NodeCrypto Function Service', () => {
|
||||
testHmac('sha512', Sha512Mac, true);
|
||||
});
|
||||
|
||||
describe('timeSafeEqualFast', () => {
|
||||
describe('compareFast', () => {
|
||||
testCompare(true);
|
||||
});
|
||||
|
||||
@ -107,7 +107,7 @@ describe('NodeCrypto Function Service', () => {
|
||||
const value = 'EncryptMe!';
|
||||
const data = Utils.fromUtf8ToArray(value);
|
||||
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);
|
||||
});
|
||||
});
|
||||
@ -124,13 +124,13 @@ describe('NodeCrypto Function Service', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('aesDecryptLarge', () => {
|
||||
describe('aesDecrypt', () => {
|
||||
it('should successfully decrypt data', async () => {
|
||||
const nodeCryptoFunctionService = new NodeCryptoFunctionService();
|
||||
const iv = makeStaticByteArray(16);
|
||||
const key = makeStaticByteArray(32);
|
||||
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!');
|
||||
});
|
||||
});
|
||||
@ -262,8 +262,8 @@ function testCompare(fast = false) {
|
||||
const a = new Uint8Array(2);
|
||||
a[0] = 1;
|
||||
a[1] = 2;
|
||||
const equal = fast ? await cryptoFunctionService.timeSafeEqualFast(a.buffer, a.buffer) :
|
||||
await cryptoFunctionService.timeSafeEqual(a.buffer, a.buffer);
|
||||
const equal = fast ? await cryptoFunctionService.compareFast(a.buffer, a.buffer) :
|
||||
await cryptoFunctionService.compare(a.buffer, a.buffer);
|
||||
expect(equal).toBe(true);
|
||||
});
|
||||
|
||||
@ -275,8 +275,8 @@ function testCompare(fast = false) {
|
||||
const b = new Uint8Array(2);
|
||||
b[0] = 3;
|
||||
b[1] = 4;
|
||||
const equal = fast ? await cryptoFunctionService.timeSafeEqualFast(a.buffer, b.buffer) :
|
||||
await cryptoFunctionService.timeSafeEqual(a.buffer, b.buffer);
|
||||
const equal = fast ? await cryptoFunctionService.compareFast(a.buffer, b.buffer) :
|
||||
await cryptoFunctionService.compare(a.buffer, b.buffer);
|
||||
expect(equal).toBe(false);
|
||||
});
|
||||
|
||||
@ -287,8 +287,8 @@ function testCompare(fast = false) {
|
||||
a[1] = 2;
|
||||
const b = new Uint8Array(2);
|
||||
b[0] = 3;
|
||||
const equal = fast ? await cryptoFunctionService.timeSafeEqualFast(a.buffer, b.buffer) :
|
||||
await cryptoFunctionService.timeSafeEqual(a.buffer, b.buffer);
|
||||
const equal = fast ? await cryptoFunctionService.compareFast(a.buffer, b.buffer) :
|
||||
await cryptoFunctionService.compare(a.buffer, b.buffer);
|
||||
expect(equal).toBe(false);
|
||||
});
|
||||
}
|
||||
|
@ -82,13 +82,13 @@ describe('WebCrypto Function Service', () => {
|
||||
testHmac('sha512', Sha512Mac);
|
||||
});
|
||||
|
||||
describe('timeSafeEqual', () => {
|
||||
describe('compare', () => {
|
||||
it('should successfully compare two of the same values', async () => {
|
||||
const cryptoFunctionService = getWebCryptoFunctionService();
|
||||
const a = new Uint8Array(2);
|
||||
a[0] = 1;
|
||||
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);
|
||||
});
|
||||
|
||||
@ -100,7 +100,7 @@ describe('WebCrypto Function Service', () => {
|
||||
const b = new Uint8Array(2);
|
||||
b[0] = 3;
|
||||
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);
|
||||
});
|
||||
|
||||
@ -111,7 +111,7 @@ describe('WebCrypto Function Service', () => {
|
||||
a[1] = 2;
|
||||
const b = new Uint8Array(2);
|
||||
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);
|
||||
});
|
||||
});
|
||||
@ -122,14 +122,14 @@ describe('WebCrypto Function Service', () => {
|
||||
testHmacFast('sha512', Sha512Mac);
|
||||
});
|
||||
|
||||
describe('timeSafeEqualFast', () => {
|
||||
describe('compareFast', () => {
|
||||
it('should successfully compare two of the same values', async () => {
|
||||
const cryptoFunctionService = getWebCryptoFunctionService();
|
||||
const a = new Uint8Array(2);
|
||||
a[0] = 1;
|
||||
a[1] = 2;
|
||||
const aByteString = Utils.fromBufferToByteString(a.buffer);
|
||||
const equal = await cryptoFunctionService.timeSafeEqualFast(aByteString, aByteString);
|
||||
const equal = await cryptoFunctionService.compareFast(aByteString, aByteString);
|
||||
expect(equal).toBe(true);
|
||||
});
|
||||
|
||||
@ -143,7 +143,7 @@ describe('WebCrypto Function Service', () => {
|
||||
b[0] = 3;
|
||||
b[1] = 4;
|
||||
const bByteString = Utils.fromBufferToByteString(b.buffer);
|
||||
const equal = await cryptoFunctionService.timeSafeEqualFast(aByteString, bByteString);
|
||||
const equal = await cryptoFunctionService.compareFast(aByteString, bByteString);
|
||||
expect(equal).toBe(false);
|
||||
});
|
||||
|
||||
@ -156,7 +156,7 @@ describe('WebCrypto Function Service', () => {
|
||||
const b = new Uint8Array(2);
|
||||
b[0] = 3;
|
||||
const bByteString = Utils.fromBufferToByteString(b.buffer);
|
||||
const equal = await cryptoFunctionService.timeSafeEqualFast(aByteString, bByteString);
|
||||
const equal = await cryptoFunctionService.compareFast(aByteString, bByteString);
|
||||
expect(equal).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -171,7 +171,7 @@ describe('WebCrypto Function Service', () => {
|
||||
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 iv = makeStaticByteArray(16);
|
||||
const key = makeStaticByteArray(32);
|
||||
@ -186,14 +186,14 @@ describe('WebCrypto Function Service', () => {
|
||||
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 iv = makeStaticByteArray(16);
|
||||
const key = makeStaticByteArray(32);
|
||||
const value = 'EncryptMe!';
|
||||
const data = Utils.fromUtf8ToArray(value);
|
||||
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);
|
||||
});
|
||||
});
|
||||
@ -210,13 +210,13 @@ describe('WebCrypto Function Service', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('aesDecryptLarge', () => {
|
||||
describe('aesDecrypt', () => {
|
||||
it('should successfully decrypt data', async () => {
|
||||
const cryptoFunctionService = getWebCryptoFunctionService();
|
||||
const iv = makeStaticByteArray(16);
|
||||
const key = makeStaticByteArray(32);
|
||||
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!');
|
||||
});
|
||||
});
|
||||
|
@ -6,15 +6,15 @@ export abstract class CryptoFunctionService {
|
||||
iterations: number) => Promise<ArrayBuffer>;
|
||||
hash: (value: string | 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') =>
|
||||
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>;
|
||||
aesDecryptFastParameters: (data: string, iv: string, mac: string, key: SymmetricCryptoKey) =>
|
||||
DecryptParameters<ArrayBuffer | 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>;
|
||||
rsaDecrypt: (data: ArrayBuffer, key: ArrayBuffer, algorithm: 'sha1' | 'sha256') => Promise<ArrayBuffer>;
|
||||
randomBytes: (length: number) => Promise<ArrayBuffer>;
|
||||
|
@ -430,7 +430,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
if (fastParams.macKey != null && fastParams.mac != null) {
|
||||
const computedMac = await this.cryptoFunctionService.hmacFast(fastParams.macData,
|
||||
fastParams.macKey, 'sha256');
|
||||
const macsEqual = await this.cryptoFunctionService.timeSafeEqualFast(fastParams.mac, computedMac);
|
||||
const macsEqual = await this.cryptoFunctionService.compareFast(fastParams.mac, computedMac);
|
||||
if (!macsEqual) {
|
||||
// tslint:disable-next-line
|
||||
console.error('mac failed.');
|
||||
@ -463,7 +463,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
return null;
|
||||
}
|
||||
|
||||
const macsMatch = await this.cryptoFunctionService.timeSafeEqual(mac, computedMac);
|
||||
const macsMatch = await this.cryptoFunctionService.compare(mac, computedMac);
|
||||
if (!macsMatch) {
|
||||
// tslint:disable-next-line
|
||||
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> {
|
||||
@ -515,7 +515,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
if (key != null && key.macKey != null && encPieces.length > 1) {
|
||||
const mac = Utils.fromB64ToArray(encPieces[1]).buffer;
|
||||
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) {
|
||||
throw new Error('MAC failed.');
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ export class NodeCryptoFunctionService implements CryptoFunctionService {
|
||||
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 mac1 = await this.hmac(a, 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);
|
||||
}
|
||||
|
||||
timeSafeEqualFast(a: ArrayBuffer, b: ArrayBuffer): Promise<boolean> {
|
||||
return this.timeSafeEqual(a, b);
|
||||
compareFast(a: ArrayBuffer, b: ArrayBuffer): Promise<boolean> {
|
||||
return this.compare(a, b);
|
||||
}
|
||||
|
||||
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> {
|
||||
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);
|
||||
}
|
||||
|
||||
aesDecryptLarge(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise<ArrayBuffer> {
|
||||
aesDecrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise<ArrayBuffer> {
|
||||
const nodeData = this.toNodeBuffer(data);
|
||||
const nodeIv = this.toNodeBuffer(iv);
|
||||
const nodeKey = this.toNodeBuffer(key);
|
||||
|
@ -69,7 +69,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
// 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://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 signingAlgorithm = {
|
||||
name: 'HMAC',
|
||||
@ -102,7 +102,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
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 bytes = new Uint32Array(rand);
|
||||
const buffer = forge.util.createBuffer();
|
||||
@ -155,7 +155,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
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']);
|
||||
return await this.subtle.decrypt({ name: 'AES-CBC', iv: iv }, impKey, data);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user