excryptor
Version:
Node JS Express Framework Cryptor Tool
103 lines (79 loc) • 3.56 kB
JavaScript
// AES Encryption/Decryption with AES-256-GCM using random Initialization Vector + Salt
// ----------------------------------------------------------------------------------------
// the encrypted datablock is base64 encoded for easy data exchange.
// if you have the option to store data binary save consider to remove the encoding to reduce storage size
// ----------------------------------------------------------------------------------------
// format of encrypted data - used by this example. not an official format
//
// +--------------------+-----------------------+----------------+----------------+
// | SALT | Initialization Vector | Auth Tag | Payload |
// | Used to derive key | AES GCM XOR Init | Data Integrity | Encrypted Data |
// | 64 Bytes, random | 16 Bytes, random | 16 Bytes | (N-96) Bytes |
// +--------------------+-----------------------+----------------+----------------+
//
// ----------------------------------------------------------------------------------------
// Input/Output Vars
//
// MASTERKEY: the key used for encryption/decryption.
// it has to be cryptographic safe - this means randomBytes or derived by pbkdf2 (for example)
// TEXT: data (utf8 string) which should be encoded. modify the code to use Buffer for binary data!
// ENCDATA: encrypted data as base64 string (format mentioned on top)
const _crypto = require('crypto');
const options = {
key: "1"
};
const _default = {
length: 32, // default 32
type: 'utf8', // default utf8,
}
module.exports = master;
module.exports.encrypt = encrypt;
module.exports.decrypt = decrypt;
module.exports.ciphers = ciphers;
module.exports.hashes = hashes;
function encrypt(text) {
// random initialization vector
const iv = _crypto.randomBytes(16);
// random salt
const salt = _crypto.randomBytes(64);
// derive key: 32 byte key length - in assumption the masterkey is a cryptographic and NOT a password there is no need for
// a large number of iterations. It may can replaced by HKDF
const key = _crypto.pbkdf2Sync(options.key, salt, 2145, 32, 'sha512');
// AES 256 GCM Mode
const cipher = _crypto.createCipheriv('aes-256-gcm', key, iv);
// encrypt the given text
const encrypted = Buffer.concat([cipher.update(text, _default.type), cipher.final()]);
// extract the auth tag
const tag = cipher.getAuthTag();
// generate output
return Buffer.concat([salt, iv, tag, encrypted]).toString('base64').toString('hex');
}
function decrypt(encdata) {
// base64 decoding
const data = Buffer.from(encdata, 'base64');
// convert data to buffers
const salt = data.slice(0, 64);
const iv = data.slice(64, 80);
const tag = data.slice(80, 96);
const text = data.slice(96);
// derive key using; 32 byte key length
const key = _crypto.pbkdf2Sync(options.key, salt , 2145, 32, 'sha512');
// AES 256 GCM Mode
const decipher = _crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(tag);
// encrypt the given text
const decrypted = decipher.update(text, 'binary', _default.type) + decipher.final(_default.type);
return decrypted;
}
function master(key) {
options.key = key;
return function resolve(req, res, next) {
next();
}
}
function ciphers() {
return _crypto.getCiphers();
}
function hashes() {
return _crypto.getHashes();
}