Last active
November 7, 2021 13:20
-
-
Save reke592/acd17852e132b7c8dd0174500b658f31 to your computer and use it in GitHub Desktop.
Sample data encryption in nodejs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** Sample usage: | |
| * | |
| * let _encrypt, _decrypt, _createIV; | |
| * | |
| * repo.useEncryption = async (encryption) => { | |
| * if (!toString.call(_encrypt).match(/Function/) | |
| * && !toString.call(_decrypt).match(/Function/)) { | |
| * let config = encryption.configure([ | |
| * 'first_name', | |
| * 'last_name', | |
| * 'middle_name', | |
| * 'mobile_number' | |
| * ]); | |
| * _encrypt = config.encrypt; | |
| * _decrypt = config.decrypt; | |
| * _createIV = config.createIV; | |
| * } | |
| * } | |
| * | |
| * repo.GetEncryptionKey = async (user_id, transaction) => { | |
| * let user = await db.Users.findOne({ | |
| * where: { | |
| * id: user_id | |
| * }, | |
| * attributes: ['key_iv'], | |
| * transaction | |
| * }); | |
| * | |
| * return user.key_iv; | |
| * } | |
| * | |
| * repo.Insert = async (fields, transaction) => { | |
| * let iv = await _createIV(); | |
| * let record = await db.Users.create({ | |
| * ... await _encrypt(fields, iv), | |
| * key_iv: iv, | |
| * date_created: new Date() | |
| * }, { | |
| * transaction | |
| * }); | |
| * | |
| * return record; | |
| * } | |
| * | |
| * repo.GetById = async(id, transaction) => { | |
| * let key_iv = await repo.GetEncryptionKey(id, transaction); | |
| * let record = await db.Users.findOne({ | |
| * where: { id }, | |
| * transaction | |
| * }); | |
| * | |
| * return await _decrypt(record.dataValues, key_iv); | |
| * // return record; | |
| * } | |
| * | |
| */ | |
| const crypto = require('crypto'); | |
| // const repo = require('../repositories/repository-db-config'); | |
| /** | |
| * strict different key iv per user. | |
| * decryption process requires the tbl_users.key_iv | |
| * | |
| * on user account removal, we will delete the tbl_users.key, as a result we will not be able to recover all the private details, | |
| * but we still we preserve all the transactions made by the user for auditing purpose. | |
| */ | |
| /** | |
| * Repository plugin for encryption | |
| * @param {*} repo | |
| * @returns factory { configure } | |
| */ | |
| module.exports = async function(repo) { | |
| const algorithm = 'aes-256-cbc'; | |
| // Database private key, 32 bytes hex | |
| let private_key = await repo.db_config.GetEncryptionKey(); | |
| /** | |
| * | |
| * @param {object} private_fields entity fields to apply encryption | |
| * @param {object} repo repository implementation | |
| * @returns {object} { encrypt, decrypt, createIV } | |
| */ | |
| const configure = (private_fields) => { | |
| // key dictionary | |
| _private_fields = {} | |
| private_fields.forEach(key => { | |
| _private_fields[key] = true; | |
| }) | |
| /** | |
| * | |
| * @param {object} entity | |
| * @param {string} key_iv d | |
| * @returns {object} encrypted fields based on given private_fields in configuration | |
| */ | |
| const encrypt = async (entity, key_iv) => { | |
| if (!key_iv) return entity; | |
| Object.keys(entity).forEach(async key => { | |
| if (_private_fields[key]) { | |
| let cipher = crypto.createCipheriv(algorithm, Buffer.from(private_key, 'hex'), Buffer.from(key_iv, 'hex')); | |
| let encryptedBuffer = cipher.update(entity[key]); | |
| entity[key] = Buffer.concat([ encryptedBuffer, cipher.final() ]).toString('hex'); | |
| } | |
| }); | |
| return entity; | |
| } | |
| /** | |
| * | |
| * @param {object} entity | |
| * @param {string} key_iv | |
| * @returns {object} decrypted fields based on given private_fields in configuration | |
| */ | |
| const decrypt = async (entity, key_iv) => { | |
| if (!key_iv) return entity; | |
| Object.keys(entity).forEach(async key => { | |
| if (_private_fields[key]) { | |
| let encrpytedBuffer = Buffer.from(entity[key], 'hex'); | |
| let cipher = crypto.createDecipheriv(algorithm, Buffer.from(private_key, 'hex'), Buffer.from(key_iv, 'hex')); | |
| let decryptedBuffer = cipher.update(encrpytedBuffer); | |
| entity[key] = Buffer.concat([ decryptedBuffer, cipher.final() ]).toString(); | |
| } | |
| }); | |
| return entity; | |
| } | |
| const createIV = async () => { | |
| return crypto.randomBytes(16).toString('hex'); | |
| } | |
| return { | |
| encrypt, | |
| decrypt, | |
| createIV | |
| } | |
| } | |
| return { | |
| configure | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment