Skip to content

Instantly share code, notes, and snippets.

@reke592
Last active November 7, 2021 13:20
Show Gist options
  • Save reke592/acd17852e132b7c8dd0174500b658f31 to your computer and use it in GitHub Desktop.
Save reke592/acd17852e132b7c8dd0174500b658f31 to your computer and use it in GitHub Desktop.

Revisions

  1. reke592 revised this gist Nov 7, 2021. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion encryption.js
    Original file line number Diff line number Diff line change
    @@ -131,7 +131,6 @@ module.exports = async function(repo) {
    }

    const createIV = async () => {
    console.log(private_key)
    return crypto.randomBytes(16).toString('hex');
    }

  2. reke592 revised this gist Nov 7, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion encryption.js
    Original file line number Diff line number Diff line change
    @@ -60,7 +60,7 @@ const crypto = require('crypto');
    // const repo = require('../repositories/repository-db-config');
    /**
    * strict different key iv per user.
    * decryption process requires the tbl_users.key
    * 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.
  3. reke592 created this gist Nov 7, 2021.
    148 changes: 148 additions & 0 deletions encryption.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,148 @@
    /** 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
    *
    * 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 () => {
    console.log(private_key)
    return crypto.randomBytes(16).toString('hex');
    }

    return {
    encrypt,
    decrypt,
    createIV
    }
    }

    return {
    configure
    }
    }