user-key-crypto
Version:
A simple and secure Node.js library to encrypt and decrypt data using user-defined secret keys. Perfect for privacy-focused applications.
64 lines (49 loc) • 2.13 kB
JavaScript
const crypto = require('crypto');
const config = {
algorithm: 'aes-256-gcm',
keyLength: 32,
ivLength: 12,
saltLength: 16,
tagLength: 16,
iterations: 100_000,
digest: 'sha256',
};
function deriveKey(password, salt) {
if (typeof password !== 'string') throw new Error('Secret must be a string');
return crypto.pbkdf2Sync(password, salt, config.iterations, config.keyLength, config.digest);
}
function encrypt(data, secret) {
if (typeof data !== 'string') throw new Error('Data must be a string');
if (typeof secret !== 'string') throw new Error('Secret must be a string');
const salt = crypto.randomBytes(config.saltLength);
const iv = crypto.randomBytes(config.ivLength);
const key = deriveKey(secret, salt);
const cipher = crypto.createCipheriv(config.algorithm, key, iv);
const encrypted = Buffer.concat([cipher.update(data, 'utf8'), cipher.final()]);
const tag = cipher.getAuthTag();
const payload = Buffer.concat([salt, iv, tag, encrypted]);
return payload.toString('base64');
}
function decrypt(encryptedData, secret) {
if (typeof encryptedData !== 'string') throw new Error('Encrypted data must be a string');
if (typeof secret !== 'string') throw new Error('Secret must be a string');
const data = Buffer.from(encryptedData, 'base64');
const { saltLength, ivLength, tagLength } = config;
if (data.length < saltLength + ivLength + tagLength) {
throw new Error('Invalid encrypted payload');
}
const salt = data.slice(0, saltLength);
const iv = data.slice(saltLength, saltLength + ivLength);
const tag = data.slice(saltLength + ivLength, saltLength + ivLength + tagLength);
const encrypted = data.slice(saltLength + ivLength + tagLength);
const key = deriveKey(secret, salt);
const decipher = crypto.createDecipheriv(config.algorithm, key, iv);
decipher.setAuthTag(tag);
try {
const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);
return decrypted.toString('utf8');
} catch {
throw new Error('Failed to decrypt. Possibly wrong password or corrupted data.');
}
}
module.exports = { encrypt, decrypt };