import { compactDecrypt, importJWK } from 'jose'; import { createDecipheriv } from 'crypto'; import { Keys } from '@models'; // Types import type { ICryptoObjData, IDecryptFunction } from './types'; /** * Crypto - Decrypt Helpers */ const decrypt: IDecryptFunction = { aes: { /** * Decrypt String Encrypted with AES Algorithm * * @param {string} encryptedStr - Data to be Decrypted * @returns {string} - Decrypted String */ str: (encryptedStr: string): string => { const { GLOBAL_PASSPHRASE, IV } = process.env; if (GLOBAL_PASSPHRASE && IV) { const algorithm = 'aes-256-cbc'; const [iv, secret] = [ Buffer.from(IV, 'hex'), Buffer.from(GLOBAL_PASSPHRASE, 'hex'), ]; const decipher = createDecipheriv(algorithm, secret, iv); let decryptedData = decipher.update(encryptedStr, 'hex', 'utf-8'); decryptedData += decipher.final('utf8'); return decryptedData; } else { throw new Error( 'GLOBAL_PASSPHRASE, IV not found in Environment Variables, Kindly Setup', ); } }, /** * Decrypt Object Encrypted with AES Algorithm * * @param {string} encryptedStr - Data to be Decrypted * @returns {Object} - Decrypted Object */ obj: <T>(encryptedStr: string): T => { const { GLOBAL_PASSPHRASE, IV } = process.env; if (GLOBAL_PASSPHRASE && IV) { const algorithm = 'aes-256-cbc'; const [iv, secret] = [ Buffer.from(IV, 'hex'), Buffer.from(GLOBAL_PASSPHRASE, 'hex'), ]; const decipher = createDecipheriv(algorithm, secret, iv); let decryptedData = decipher.update(encryptedStr, 'hex', 'utf-8'); decryptedData += decipher.final('utf8'); const jsonData: ICryptoObjData<T> = JSON.parse(decryptedData); return jsonData.data; } else { throw new Error( 'GLOBAL_PASSPHRASE, IV not found in Environment Variables, Kindly Setup', ); } }, }, rsa: { /** * Decrypt String Encrypted with RSA Algorithm * * @param {string} encryptedStr - Data to be Decrypted * @returns {Promise<string>} - Decrypted String */ str: async (encryptedStr: string): Promise<string> => { const privateKey = await Keys.findOne({ type: 'privatekey' }).exec(); if (privateKey) { const pvtKey = await importJWK(privateKey.key, 'PS256'); const { plaintext } = await compactDecrypt(encryptedStr, pvtKey); const decodedText = new TextDecoder().decode(plaintext); return decodedText; } else { throw new Error( 'Private Key Not Available in the Database, Please Setup first, then try this', ); } }, /** * Decrypt Object Encrypted with RSA Algorithm * * @param {string} encryptedStr - Data to be Decrypted * @returns {Promise<Object>} - Decrypted Object */ obj: async <T>(encryptedStr: string): Promise<T> => { const privateKey = await Keys.findOne({ type: 'privatekey' }).exec(); if (privateKey) { const pvtKey = await importJWK(privateKey.key, 'PS256'); const { plaintext } = await compactDecrypt(encryptedStr, pvtKey); const decodedText = new TextDecoder().decode(plaintext); const objectData: ICryptoObjData<T> = JSON.parse(decodedText); return objectData.data; } else { throw new Error( 'Private Key Not Available in the Database, Please Setup first, then try this', ); } }, }, }; export default decrypt;