From 1cb0d4e1911a34158675a7ac0ad8fe255e09707d Mon Sep 17 00:00:00 2001 From: lohit Date: Wed, 20 Nov 2024 17:09:02 +0530 Subject: [PATCH] chore: node version bump -- v22.11.0 (#3508) node version bump with updates to cipher logic --- .nvmrc | 2 +- .../bruno-electron/src/utils/encryption.js | 54 ++++++++++++++++--- .../tests/utils/encryption.spec.js | 7 +++ 3 files changed, 54 insertions(+), 9 deletions(-) diff --git a/.nvmrc b/.nvmrc index 805b5a4e0..bb8c76c68 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v20.9.0 +v22.11.0 diff --git a/packages/bruno-electron/src/utils/encryption.js b/packages/bruno-electron/src/utils/encryption.js index 89e33b1f9..36c53e7ef 100644 --- a/packages/bruno-electron/src/utils/encryption.js +++ b/packages/bruno-electron/src/utils/encryption.js @@ -6,10 +6,34 @@ const { safeStorage } = require('electron'); const ELECTRONSAFESTORAGE_ALGO = '00'; const AES256_ALGO = '01'; -// AES-256 encryption and decryption functions +function deriveKeyAndIv(password, keyLength, ivLength) { + const key = Buffer.alloc(keyLength); + const iv = Buffer.alloc(ivLength); + const derivedBytes = []; + let lastHash = null; + + while (Buffer.concat(derivedBytes).length < keyLength + ivLength) { + const hash = crypto.createHash('md5'); + if (lastHash) { + hash.update(lastHash); + } + hash.update(Buffer.from(password, 'utf8')); + lastHash = hash.digest(); + derivedBytes.push(lastHash); + } + + const concatenatedBytes = Buffer.concat(derivedBytes); + concatenatedBytes.copy(key, 0, 0, keyLength); + concatenatedBytes.copy(iv, 0, keyLength, keyLength + ivLength); + + return { key, iv }; +} + function aes256Encrypt(data) { - const key = machineIdSync(); - const cipher = crypto.createCipher('aes-256-cbc', key); + const rawKey = machineIdSync(); + const iv = Buffer.alloc(16, 0); // Default IV for new encryption + const key = crypto.createHash('sha256').update(rawKey).digest(); // Derive a 32-byte key + const cipher = crypto.createCipheriv('aes-256-cbc', key, iv); let encrypted = cipher.update(data, 'utf8', 'hex'); encrypted += cipher.final('hex'); @@ -17,14 +41,28 @@ function aes256Encrypt(data) { } function aes256Decrypt(data) { - const key = machineIdSync(); - const decipher = crypto.createDecipher('aes-256-cbc', key); - let decrypted = decipher.update(data, 'hex', 'utf8'); - decrypted += decipher.final('utf8'); + const rawKey = machineIdSync(); - return decrypted; + // Attempt to decrypt using new method first + const iv = Buffer.alloc(16, 0); // Default IV for new encryption + const key = crypto.createHash('sha256').update(rawKey).digest(); // Derive a 32-byte key + + try { + const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv); + let decrypted = decipher.update(data, 'hex', 'utf8'); + decrypted += decipher.final('utf8'); + return decrypted; + } catch (err) { + // If decryption fails, fall back to old key derivation + const { key: oldKey, iv: oldIv } = deriveKeyAndIv(rawKey, 32, 16); + const decipher = crypto.createDecipheriv('aes-256-cbc', oldKey, oldIv); + let decrypted = decipher.update(data, 'hex', 'utf8'); + decrypted += decipher.final('utf8'); + return decrypted; + } } + // electron safe storage encryption and decryption functions function safeStorageEncrypt(str) { let encryptedStringBuffer = safeStorage.encryptString(str); diff --git a/packages/bruno-electron/tests/utils/encryption.spec.js b/packages/bruno-electron/tests/utils/encryption.spec.js index b7c9abcdd..44388fb07 100644 --- a/packages/bruno-electron/tests/utils/encryption.spec.js +++ b/packages/bruno-electron/tests/utils/encryption.spec.js @@ -22,6 +22,13 @@ describe('Encryption and Decryption Tests', () => { expect(() => decryptString('garbage')).toThrow('Decrypt failed: unrecognized string format'); }); + it.skip('string encrypted using createCipher (< node 20) should be decrypted properly', () => { + const encryptedString = '$01:2738e0e6a38bcde5fd80141ceadc9b67bc7b1fca7e398c552c1ca2bace28eb57'; + const decryptedValue = decryptString(encryptedString); + + expect(decryptedValue).toBe('bruno is awesome'); + }); + it('decrypt should throw an error for invalid algorithm', () => { const invalidAlgo = '$99:abcdefg';