diff --git a/spec/node/services/nodeCryptoFunction.service.spec.ts b/spec/node/services/nodeCryptoFunction.service.spec.ts index c86f97e8a2..e57527918f 100644 --- a/spec/node/services/nodeCryptoFunction.service.spec.ts +++ b/spec/node/services/nodeCryptoFunction.service.spec.ts @@ -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); }); } diff --git a/spec/web/services/webCryptoFunction.service.spec.ts b/spec/web/services/webCryptoFunction.service.spec.ts index 52422b0b86..0d2b21d0eb 100644 --- a/spec/web/services/webCryptoFunction.service.spec.ts +++ b/spec/web/services/webCryptoFunction.service.spec.ts @@ -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!'); }); }); diff --git a/src/abstractions/cryptoFunction.service.ts b/src/abstractions/cryptoFunction.service.ts index 8935d32aa7..553444b667 100644 --- a/src/abstractions/cryptoFunction.service.ts +++ b/src/abstractions/cryptoFunction.service.ts @@ -6,15 +6,15 @@ export abstract class CryptoFunctionService { iterations: number) => Promise; hash: (value: string | ArrayBuffer, algorithm: 'sha1' | 'sha256' | 'sha512') => Promise; hmac: (value: ArrayBuffer, key: ArrayBuffer, algorithm: 'sha1' | 'sha256' | 'sha512') => Promise; - timeSafeEqual: (a: ArrayBuffer, b: ArrayBuffer) => Promise; + compare: (a: ArrayBuffer, b: ArrayBuffer) => Promise; hmacFast: (value: ArrayBuffer | string, key: ArrayBuffer | string, algorithm: 'sha1' | 'sha256' | 'sha512') => Promise; - timeSafeEqualFast: (a: ArrayBuffer | string, b: ArrayBuffer | string) => Promise; + compareFast: (a: ArrayBuffer | string, b: ArrayBuffer | string) => Promise; aesEncrypt: (data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer) => Promise; aesDecryptFastParameters: (data: string, iv: string, mac: string, key: SymmetricCryptoKey) => DecryptParameters; aesDecryptFast: (parameters: DecryptParameters) => Promise; - aesDecryptLarge: (data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer) => Promise; + aesDecrypt: (data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer) => Promise; rsaEncrypt: (data: ArrayBuffer, publicKey: ArrayBuffer, algorithm: 'sha1' | 'sha256') => Promise; rsaDecrypt: (data: ArrayBuffer, key: ArrayBuffer, algorithm: 'sha1' | 'sha256') => Promise; randomBytes: (length: number) => Promise; diff --git a/src/services/crypto.service.ts b/src/services/crypto.service.ts index 7d5a56a754..7886ab4c0d 100644 --- a/src/services/crypto.service.ts +++ b/src/services/crypto.service.ts @@ -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 { @@ -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.'); } diff --git a/src/services/nodeCryptoFunction.service.ts b/src/services/nodeCryptoFunction.service.ts index c4fdc89ccd..69fb64c2e4 100644 --- a/src/services/nodeCryptoFunction.service.ts +++ b/src/services/nodeCryptoFunction.service.ts @@ -41,7 +41,7 @@ export class NodeCryptoFunctionService implements CryptoFunctionService { return Promise.resolve(this.toArrayBuffer(hmac.digest())); } - async timeSafeEqual(a: ArrayBuffer, b: ArrayBuffer): Promise { + async compare(a: ArrayBuffer, b: ArrayBuffer): Promise { 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 { - return this.timeSafeEqual(a, b); + compareFast(a: ArrayBuffer, b: ArrayBuffer): Promise { + return this.compare(a, b); } aesEncrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise { @@ -100,11 +100,11 @@ export class NodeCryptoFunctionService implements CryptoFunctionService { } async aesDecryptFast(parameters: DecryptParameters): Promise { - 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 { + aesDecrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise { const nodeData = this.toNodeBuffer(data); const nodeIv = this.toNodeBuffer(iv); const nodeKey = this.toNodeBuffer(key); diff --git a/src/services/webCryptoFunction.service.ts b/src/services/webCryptoFunction.service.ts index 8a0b169b0d..cc619e5192 100644 --- a/src/services/webCryptoFunction.service.ts +++ b/src/services/webCryptoFunction.service.ts @@ -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 { + async compare(a: ArrayBuffer, b: ArrayBuffer): Promise { 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 { + async compareFast(a: string, b: string): Promise { 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 { + async aesDecrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise { 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); }