add encryption mode choice
This commit is contained in:
		
							
								
								
									
										52
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								index.js
									
									
									
									
									
								
							@@ -10,7 +10,7 @@
 | 
			
		||||
const crypto = require ('crypto');
 | 
			
		||||
const encoding = require ('@scode/encoding-helper');
 | 
			
		||||
 | 
			
		||||
const encryption = {
 | 
			
		||||
const encryption_mode_cbc_256 = {
 | 
			
		||||
  algorithm:  'aes-256-cbc',
 | 
			
		||||
  nonce_size: 16,
 | 
			
		||||
  key_size:   32,
 | 
			
		||||
@@ -19,6 +19,15 @@ const encryption = {
 | 
			
		||||
  iterations: 32767
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const encryption_mode_cbc_128 = {
 | 
			
		||||
  algorithm:  'aes-128-cbc',
 | 
			
		||||
  nonce_size: 16,
 | 
			
		||||
  key_size:   16,
 | 
			
		||||
  hash:       'sha256',
 | 
			
		||||
  salt_size:  16,
 | 
			
		||||
  iterations: 40
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * creates a random string
 | 
			
		||||
 *
 | 
			
		||||
@@ -149,20 +158,21 @@ function checksum (data) {
 | 
			
		||||
 *
 | 
			
		||||
 * @param {string} text plaintext
 | 
			
		||||
 * @param {string} pass password
 | 
			
		||||
 * @param {object} mode encryption mode
 | 
			
		||||
 * @returns {string} encrypted
 | 
			
		||||
 */
 | 
			
		||||
function encrypt_aes (text, pass) {
 | 
			
		||||
  const salt = crypto.randomBytes (encryption.salt_size);
 | 
			
		||||
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, 'utf-8'),
 | 
			
		||||
    salt,
 | 
			
		||||
    encryption.iterations,
 | 
			
		||||
    encryption.key_size,
 | 
			
		||||
    encryption.hash
 | 
			
		||||
    mode.iterations,
 | 
			
		||||
    mode.key_size,
 | 
			
		||||
    mode.hash
 | 
			
		||||
  );
 | 
			
		||||
  const nonce = crypto.randomBytes (encryption.nonce_size);
 | 
			
		||||
  const cipher = crypto.createCipheriv (encryption.algorithm, key, nonce);
 | 
			
		||||
  const nonce = crypto.randomBytes (mode.nonce_size);
 | 
			
		||||
  const cipher = crypto.createCipheriv (mode.algorithm, key, nonce);
 | 
			
		||||
  return Buffer.concat ([
 | 
			
		||||
    salt,
 | 
			
		||||
    nonce,
 | 
			
		||||
@@ -177,25 +187,31 @@ function encrypt_aes (text, pass) {
 | 
			
		||||
 *
 | 
			
		||||
 * @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, rethrow = false) {
 | 
			
		||||
function decrypt_aes (
 | 
			
		||||
  ciphertext,
 | 
			
		||||
  pass,
 | 
			
		||||
  mode = encryption_mode_cbc_256,
 | 
			
		||||
  rethrow = false
 | 
			
		||||
) {
 | 
			
		||||
  try {
 | 
			
		||||
    let buf = Buffer.from (ciphertext, 'base64');
 | 
			
		||||
    const salt = buf.slice (0, encryption.salt_size);
 | 
			
		||||
    buf = buf.slice (encryption.salt_size);
 | 
			
		||||
    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, 'utf-8'),
 | 
			
		||||
      salt,
 | 
			
		||||
      encryption.iterations,
 | 
			
		||||
      encryption.key_size,
 | 
			
		||||
      encryption.hash
 | 
			
		||||
      mode.iterations,
 | 
			
		||||
      mode.key_size,
 | 
			
		||||
      mode.hash
 | 
			
		||||
    );
 | 
			
		||||
    const nonce = buf.slice (0, encryption.nonce_size);
 | 
			
		||||
    buf = buf.slice (encryption.nonce_size);
 | 
			
		||||
    const cipher = crypto.createDecipheriv (encryption.algorithm, key, nonce);
 | 
			
		||||
    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 ()
 | 
			
		||||
@@ -215,6 +231,8 @@ module.exports = {
 | 
			
		||||
  decode_signed,
 | 
			
		||||
  decrypt_aes,
 | 
			
		||||
  encrypt_aes,
 | 
			
		||||
  encryption_mode_cbc_128,
 | 
			
		||||
  encryption_mode_cbc_256,
 | 
			
		||||
  get_signature_info,
 | 
			
		||||
  hash_sha512,
 | 
			
		||||
  random_hex,
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,12 @@ test ('fail decryption', (t) => {
 | 
			
		||||
test ('rethrow decryption', (t) => {
 | 
			
		||||
  const enc = crypto.encrypt_aes ('foo', 'bar');
 | 
			
		||||
  t.throws (() => {
 | 
			
		||||
    crypto.decrypt_aes (enc, 'baz', true);
 | 
			
		||||
    crypto.decrypt_aes (
 | 
			
		||||
      enc,
 | 
			
		||||
      'baz',
 | 
			
		||||
      crypto.encryption_mode_cbc_256,
 | 
			
		||||
      true
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user