From f361b1607a7a61b7e9acb892f2ff29fd1ae38d0e Mon Sep 17 00:00:00 2001 From: CeciliaAvila Date: Thu, 28 Nov 2024 14:58:23 -0300 Subject: [PATCH] Throw error on crypto.createDecipher for node 22 --- .../src/botConfiguration.ts | 5 +- libraries/botframework-config/src/encrypt.ts | 29 +++++++++-- .../tests/loadAndSave.test.js | 51 ++++++++++++------- 3 files changed, 61 insertions(+), 24 deletions(-) diff --git a/libraries/botframework-config/src/botConfiguration.ts b/libraries/botframework-config/src/botConfiguration.ts index 94fa77452a..a39ee7fad5 100644 --- a/libraries/botframework-config/src/botConfiguration.ts +++ b/libraries/botframework-config/src/botConfiguration.ts @@ -304,7 +304,10 @@ export class BotConfiguration extends BotConfigurationBase { } } } - } catch { + } catch (legacyErr) { + if (legacyErr.message.includes('Node.js versions')) { + throw legacyErr; + } throw err; } } diff --git a/libraries/botframework-config/src/encrypt.ts b/libraries/botframework-config/src/encrypt.ts index 52a0686ddd..73e9b06fdf 100644 --- a/libraries/botframework-config/src/encrypt.ts +++ b/libraries/botframework-config/src/encrypt.ts @@ -6,6 +6,7 @@ */ import crypto from 'crypto'; +import { version as nodeVersion } from 'process'; /** * @private @@ -100,10 +101,28 @@ export function decryptString(encryptedValue: string, secret: string): string { * @param secret */ export function legacyDecrypt(encryptedValue: string, secret: string): string { - // LEGACY for pre standardized SHA256 encryption, this uses some undocumented nodejs MD5 hash internally and is deprecated - const decipher: crypto.Decipher = crypto.createDecipher('aes192', secret); - let value: string = decipher.update(encryptedValue, 'hex', 'utf8'); - value += decipher.final('utf8'); + const UNSUPPORTED_VERSION = '22.0.0'; + if (!isNodeCompatible(nodeVersion, UNSUPPORTED_VERSION)) { + throw new Error(`This method is not available for Node.js versions over ${UNSUPPORTED_VERSION}.`); + } else { + // LEGACY for pre standardized SHA256 encryption, this uses some undocumented nodejs MD5 hash internally and is deprecated + const decipher: crypto.Decipher = crypto.createDecipher('aes192', secret); + let value: string = decipher.update(encryptedValue, 'hex', 'utf8'); + value += decipher.final('utf8'); + + return value; + } +} - return value; +/** + * private + * + * @param currentVersion The current version of Node.js. + * @param minVersion The minimum unsupported version. + * @returns true if the current version of Node is lower than the unsupported version. + */ +function isNodeCompatible(currentVersion: string, minVersion: string): boolean { + const [currentMajor] = currentVersion.replace('v', '').split('.').map(Number); + const [minMajor] = minVersion.split('.').map(Number); + return currentMajor < minMajor; } diff --git a/libraries/botframework-config/tests/loadAndSave.test.js b/libraries/botframework-config/tests/loadAndSave.test.js index 11c887e27e..16080c4dc9 100644 --- a/libraries/botframework-config/tests/loadAndSave.test.js +++ b/libraries/botframework-config/tests/loadAndSave.test.js @@ -8,6 +8,7 @@ const testBotPath = require.resolve('./test.bot'); const govTestBotPath = require.resolve('./govTest.bot'); const legacyBotPath = require.resolve('./legacy.bot'); const saveBotPath = testBotPath.replace('test.bot', 'save.bot'); +const [nodeVersion] = process.version.replace('v', '').split('.').map(Number); describe('LoadAndSaveTests', function () { it('DeserializeBotFile', async function () { @@ -89,12 +90,19 @@ describe('LoadAndSaveTests', function () { const config = await bf.BotConfiguration.load(testBotPath); await config.saveAs(saveBotPath, secret); - await assert.rejects( - bf.BotConfiguration.load(saveBotPath), - new Error( - 'You are attempting to perform an operation which needs access to the secret and --secret is missing' - ) - ); + if (nodeVersion >= 22) { + await assert.rejects( + bf.BotConfiguration.load(saveBotPath), + new Error('This method is not available for Node.js versions over 22.0.0.'), + ); + } else { + await assert.rejects( + bf.BotConfiguration.load(saveBotPath), + new Error( + 'You are attempting to perform an operation which needs access to the secret and --secret is missing' + ), + ); + } }); it('LoadAndVerifyChannelServiceSync', async function () { @@ -354,17 +362,24 @@ describe('LoadAndSaveTests', function () { }); it('LegacyEncryption', async function () { - let config = await bf.BotConfiguration.load(legacyBotPath, 'password'); - assert.equal(config.services[0].appPassword, 'xyzpdq', 'value should be unencrypted'); - assert.ok(config.padlock != null, 'padlock should exist'); - assert.ok(!config.secretKey, 'secretKey should not exist'); - - const secret = bf.BotConfiguration.generateKey(); - await config.saveAs(saveBotPath, secret); - config = await bf.BotConfiguration.load(saveBotPath, secret); - fs.unlinkSync(saveBotPath); - assert.ok(config.padlock != null, 'padlock should exist'); - assert.ok(config.padlock.length > 0, 'padlock should not be empty'); - assert.ok(!config.secretKey, 'secretKey should not exist'); + if (nodeVersion >= 22) { + await assert.rejects( + bf.BotConfiguration.load(legacyBotPath, 'password'), + new Error('This method is not available for Node.js versions over 22.0.0.'), + ); + } else { + let config = await bf.BotConfiguration.load(legacyBotPath, 'password'); + assert.equal(config.services[0].appPassword, 'xyzpdq', 'value should be unencrypted'); + assert.ok(config.padlock != null, 'padlock should exist'); + assert.ok(!config.secretKey, 'secretKey should not exist'); + + const secret = bf.BotConfiguration.generateKey(); + await config.saveAs(saveBotPath, secret); + config = await bf.BotConfiguration.load(saveBotPath, secret); + fs.unlinkSync(saveBotPath); + assert.ok(config.padlock != null, 'padlock should exist'); + assert.ok(config.padlock.length > 0, 'padlock should not be empty'); + assert.ok(!config.secretKey, 'secretKey should not exist'); + } }); });