111 lines
2.4 KiB
JavaScript
111 lines
2.4 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
const crypto = require ('crypto');
|
||
|
|
||
|
const encryption_mode_cbc_256 = {
|
||
|
algorithm: 'aes-256-cbc',
|
||
|
nonce_size: 16,
|
||
|
key_size: 32,
|
||
|
hash: 'sha256',
|
||
|
salt_size: 16,
|
||
|
iterations: 32767
|
||
|
};
|
||
|
|
||
|
const encryption_mode_cbc_256_quick = {
|
||
|
algorithm: 'aes-256-cbc',
|
||
|
nonce_size: 16,
|
||
|
key_size: 32,
|
||
|
hash: 'sha256',
|
||
|
salt_size: 16,
|
||
|
iterations: 32
|
||
|
};
|
||
|
|
||
|
const encryption_mode_cbc_128 = {
|
||
|
algorithm: 'aes-128-cbc',
|
||
|
nonce_size: 16,
|
||
|
key_size: 16,
|
||
|
hash: 'sha256',
|
||
|
salt_size: 16,
|
||
|
iterations: 40
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* encrypt plain text with aes
|
||
|
*
|
||
|
* @param {string} text plaintext
|
||
|
* @param {string} pass password
|
||
|
* @param {object} mode encryption mode
|
||
|
* @returns {string} encrypted
|
||
|
*/
|
||
|
function encrypt_aes (text, pass, mode = encryption_mode_cbc_256) {
|
||
|
const salt = crypto.randomBytes (mode.salt_size);
|
||
|
// eslint-disable-next-line no-sync
|
||
|
const key = crypto.pbkdf2Sync (
|
||
|
Buffer.from (pass),
|
||
|
salt,
|
||
|
mode.iterations,
|
||
|
mode.key_size,
|
||
|
mode.hash
|
||
|
);
|
||
|
const nonce = crypto.randomBytes (mode.nonce_size);
|
||
|
const cipher = crypto.createCipheriv (mode.algorithm, key, nonce);
|
||
|
return Buffer.concat ([
|
||
|
salt,
|
||
|
nonce,
|
||
|
cipher.update (Buffer.from (text)),
|
||
|
cipher.final ()
|
||
|
])
|
||
|
.toString ('base64');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* decrypt an aes string
|
||
|
*
|
||
|
* @param {string} ciphertext encrypted text
|
||
|
* @param {string} pass password
|
||
|
* @param {object} mode encryption mode
|
||
|
* @param {boolean} rethrow rethrow exceptions instead of returning null
|
||
|
* @returns {string} plaintext
|
||
|
*/
|
||
|
function decrypt_aes (
|
||
|
ciphertext,
|
||
|
pass,
|
||
|
mode = encryption_mode_cbc_256,
|
||
|
rethrow = false
|
||
|
) {
|
||
|
try {
|
||
|
let buf = Buffer.from (ciphertext, 'base64');
|
||
|
const salt = buf.slice (0, mode.salt_size);
|
||
|
buf = buf.slice (mode.salt_size);
|
||
|
// eslint-disable-next-line no-sync
|
||
|
const key = crypto.pbkdf2Sync (
|
||
|
Buffer.from (pass),
|
||
|
salt,
|
||
|
mode.iterations,
|
||
|
mode.key_size,
|
||
|
mode.hash
|
||
|
);
|
||
|
const nonce = buf.slice (0, mode.nonce_size);
|
||
|
buf = buf.slice (mode.nonce_size);
|
||
|
const cipher = crypto.createDecipheriv (mode.algorithm, key, nonce);
|
||
|
return Buffer.concat ([
|
||
|
cipher.update (buf),
|
||
|
cipher.final ()
|
||
|
])
|
||
|
.toString ();
|
||
|
}
|
||
|
catch (e) {
|
||
|
if (rethrow)
|
||
|
throw e;
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
decrypt_aes,
|
||
|
encrypt_aes,
|
||
|
encryption_mode_cbc_128,
|
||
|
encryption_mode_cbc_256,
|
||
|
encryption_mode_cbc_256_quick
|
||
|
};
|