From 9440afa386d6750ff806117135a5a6f54bff2c22 Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Tue, 30 May 2023 20:30:58 +0300 Subject: [PATCH] Remove re-encryption from Infisical, move to migration script --- backend/src/utils/setup/index.ts | 4 +- migration/.eslintrc.js | 8 + migration/scripts/reencrypt_under_256_key.js | 202 ++++++++----------- 3 files changed, 90 insertions(+), 124 deletions(-) create mode 100644 migration/.eslintrc.js diff --git a/backend/src/utils/setup/index.ts b/backend/src/utils/setup/index.ts index c90a94d4f..f622acce6 100644 --- a/backend/src/utils/setup/index.ts +++ b/backend/src/utils/setup/index.ts @@ -59,8 +59,8 @@ export const setup = async () => { // re-encrypt any data previously encrypted under server hex 128-bit ENCRYPTION_KEY // to base64 256-bit ROOT_ENCRYPTION_KEY - await reencryptBotPrivateKeys(); - await reencryptSecretBlindIndexDataSalts(); + // await reencryptBotPrivateKeys(); + // await reencryptSecretBlindIndexDataSalts(); // initializing Sentry Sentry.init({ diff --git a/migration/.eslintrc.js b/migration/.eslintrc.js new file mode 100644 index 000000000..cfc6baf3a --- /dev/null +++ b/migration/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + "parserOptions": { + "ecmaVersion": 2017 + }, + "env": { + "es6": true + } + } \ No newline at end of file diff --git a/migration/scripts/reencrypt_under_256_key.js b/migration/scripts/reencrypt_under_256_key.js index 6a837fddd..63b283a93 100644 --- a/migration/scripts/reencrypt_under_256_key.js +++ b/migration/scripts/reencrypt_under_256_key.js @@ -10,13 +10,6 @@ const decryptSymmetric = ({ tag, key }) => { - // console.log('decryptSymmetric arguments', { - // ciphertext, - // iv, - // tag, - // key - // }); - const decipher = crypto.createDecipheriv( 'aes-256-gcm', key, @@ -31,35 +24,10 @@ const decryptSymmetric = ({ return cleartext; } -const decryptSymmetric2 = ({ - ciphertext, - iv, - tag, - key -}) => { - - const secretKey = crypto.createSecretKey(key, 'base64'); - - const decipher = crypto.createDecipheriv( - 'aes-256-gcm', - secretKey, - Buffer.from(iv, 'base64') - ); - - decipher.setAuthTag(Buffer.from(tag, 'base64')); - - let cleartext = decipher.update(ciphertext, 'base64', 'utf8'); - cleartext += decipher.final('utf8'); - - return cleartext; -}; - const encryptSymmetric = ( plaintext, key ) => { - - console.log('encryptSymmetric arguments: ', plaintext, key); const iv = crypto.randomBytes(12); const secretKey = crypto.createSecretKey(key, 'base64'); @@ -75,116 +43,106 @@ const encryptSymmetric = ( }; }; -/** - * This script re-encrypts relevant database structures from the previous - * server ENCRYPTION_KEY to ROOT_ENCRYPTION_KEY - */ const main = async () => { console.log('main'); const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY; // 128-bit hex encryption key const ROOT_ENCRYPTION_KEY = process.env.ROOT_ENCRYPTION_KEY; // 256-bit base64 encryption key - - console.log('1: ', ENCRYPTION_KEY); - console.log('2: ', ROOT_ENCRYPTION_KEY); - - let errors = 0; - let success = 0; mongoose.connect(process.env.MONGO_URI) .then(async () => { console.log('Connected!'); if (ENCRYPTION_KEY && ROOT_ENCRYPTION_KEY) { - console.log('both ENCRYPTION_KEY and ROOT_ENCRYPTION_KEY are present'); + // re-encrypt bot private keys const bots = await Bot.find({ algorithm: 'aes-256-gcm', keyEncoding: 'utf8' }).select('+encryptedPrivateKey iv tag algorithm keyEncoding workspace'); - if (bots.length === 0) return; - - for await (const bot of bots) { - // console.log('bot: ', bot); - try { - const privateKey = decryptSymmetric({ - ciphertext: bot.encryptedPrivateKey, - iv: bot.iv, - tag: bot.tag, - key: ENCRYPTION_KEY - }); + if (bots.length > 0) { + const operationsBot = await Promise.all( + bots.map(async (bot) => { + + const privateKey = decryptSymmetric({ + ciphertext: bot.encryptedPrivateKey, + iv: bot.iv, + tag: bot.tag, + key: ENCRYPTION_KEY + }); - // console.log('privateKey: ', privateKey); - success += 1; - } catch (err) { - errors +=1; - console.error('failed to decrypt bot A: ', bot._id.toString()); - - // console.log('try'); - // const privateKey2 = decryptSymmetric({ - // ciphertext: bot.encryptedPrivateKey, - // iv: bot.iv, - // tag: bot.tag, - // key: ENCRYPTION_KEY - // }); - - // console.log('privatekey2', privateKey2); - } + const { + ciphertext: encryptedPrivateKey, + iv, + tag + } = encryptSymmetric(privateKey, ROOT_ENCRYPTION_KEY); + + return ({ + updateOne: { + filter: { + _id: bot._id + }, + update: { + encryptedPrivateKey, + iv, + tag, + algorithm: 'aes-256-gcm', + keyEncoding: 'base64' + } + } + }) + }) + ); + + const botBulkWriteResult = await Bot.bulkWrite(operationsBot); + console.log('botBulkWriteResult: ', botBulkWriteResult); } - - console.log('number of bots: ', bots.length); - console.log('num succ: ', success); - console.log('num errors: ', errors); - - // console.log('bots: ', bots); - // console.log('bots.length: ', bots.length); - - // const operationsBot = await Promise.all( - // bots.map(async (bot) => { - - // const privateKey = decryptSymmetric({ - // ciphertext: bot.encryptedPrivateKey, - // iv: bot.iv, - // tag: bot.tag, - // key: ENCRYPTION_KEY - // }); - - // console.log('privateKey: ', privateKey); - - // const { - // ciphertext: encryptedPrivateKey, - // iv, - // tag - // } = encryptSymmetric(privateKey, ROOT_ENCRYPTION_KEY); - - // console.log('re-encrypted PrivateKey: ', encryptedPrivateKey); - - // return ({ - // updateOne: { - // filter: { - // _id: bot._id - // }, - // update: { - // encryptedPrivateKey, - // iv, - // tag, - // algorithm: 'aes-256-gcm', - // keyEncoding: 'base64' - // } - // } - // }) - // }) - // ); - - // console.log('operationsBot: ', operationsBot); - } - - // const user = await Bot.findOne(); - // const secretBlindIndexData = await SecretBlindIndexData.findOne(); - // console.log('user: ', user); - // console.log('secretBlindIndexData: ', secretBlindIndexData); + // re-encrypt secret blind index data salts + const secretBlindIndexData = await SecretBlindIndexData.find({ + algorithm: 'aes-256-gcm', + keyEncoding: 'utf8' + }).select('+encryptedSaltCiphertext +saltIV +saltTag +algorithm +keyEncoding'); + + if (secretBlindIndexData.length > 0) { + const operationsSecretBlindIndexData = await Promise.all( + secretBlindIndexData.map(async (secretBlindIndexDatum) => { + + const salt = decryptSymmetric({ + ciphertext: secretBlindIndexDatum.encryptedSaltCiphertext, + iv: secretBlindIndexDatum.saltIV, + tag: secretBlindIndexDatum.saltTag, + key: ENCRYPTION_KEY + }); + + const { + ciphertext: encryptedSaltCiphertext, + iv: saltIV, + tag: saltTag + } = encryptSymmetric(salt, ROOT_ENCRYPTION_KEY); + + return ({ + updateOne: { + filter: { + _id: secretBlindIndexDatum._id + }, + update: { + encryptedSaltCiphertext, + saltIV, + saltTag, + algorithm: 'aes-256-gcm', + keyEncoding: 'base64' + } + } + }) + }) + ); + + const secretBlindIndexDataBulkWriteResult = await SecretBlindIndexData.bulkWrite(operationsSecretBlindIndexData); + console.log('secretBlindIndexDataBulkWriteResult: ', secretBlindIndexDataBulkWriteResult); + } + } }); }