I've implemented my first data encryption / decryption methods on Node.js. Although it might look similar to hundreds of sample implementations available online, I'm curious to get a feedback.
I'm particularly interested in:
- some flaw points, potential security, and performance issues
- In
encrypt()
I return anENCRYPTED
object with encrypted data after being freezed byObject.freeze()
, are there any drawbacks/pitfalls of returning a freezed object besides the read-only status of the object?
const CRYPTO = require("crypto");
const ALG_CIPHER = "aes-256-gcm";
const ENC_IN = "utf8";
const ENC_OUT = "base64";
const BUFFER_SIZE = 16;
const KEY = Buffer.from("…", ENC_IN);
/**
* Encrypt data using an initialisation vector
*
* @param {string} data - data to be encrypted
* @returns {Promise<{authTag: Buffer, data: string, iv: Buffer}>} encrypted - encrypted data with decryption parameters
*/
const encrypt = async function encrypt(data) {
const IV = Buffer.from(CRYPTO.randomBytes(BUFFER_SIZE));
const CIPHER = CRYPTO.createCipheriv(ALG_CIPHER, KEY, IV);
let enc = CIPHER.update(data, ENC_IN, ENC_OUT);
enc += CIPHER.final(ENC_OUT);
const ENCRYPTED = Object.freeze({
data: enc,
iv: IV,
authTag: CIPHER.getAuthTag()
});
return ENCRYPTED;
};
/**
* Decrypt data using an initialisation vector
*
* @param {string} data - data to be decrypted
* @param {string} iv - initialisation vector
* @param {Buffer} authTag - authentication tag
* @returns {Promise<string>} decrypted - decrypted data
*/
const decrypt = async function decrypt(data, iv, authTag) {
const DECIPHER = CRYPTO.createDecipheriv(ALG_CIPHER, KEY, iv);
DECIPHER.setAuthTag(authTag);
let decrypted = DECIPHER.update(data, ENC_OUT, ENC_IN);
decrypted += DECIPHER.final(ENC_IN);
return decrypted;
};