113 lines
3.6 KiB
JavaScript
113 lines
3.6 KiB
JavaScript
const crypto = require('crypto');
|
|
const logger = require('./logger');
|
|
|
|
class Encryption {
|
|
constructor() {
|
|
this.algorithm = 'aes-256-gcm';
|
|
this.key = Buffer.from(process.env.ENCRYPTION_KEY || '', 'hex');
|
|
this.ivLength = 16;
|
|
this.saltLength = 64;
|
|
this.tagLength = 16;
|
|
}
|
|
|
|
encrypt(text) {
|
|
try {
|
|
if (!text) return null;
|
|
|
|
// Generate a random initialization vector
|
|
const iv = crypto.randomBytes(this.ivLength);
|
|
|
|
// Generate a random salt
|
|
const salt = crypto.randomBytes(this.saltLength);
|
|
|
|
// Create cipher
|
|
const cipher = crypto.createCipheriv(this.algorithm, this.key, iv);
|
|
|
|
// Encrypt the text
|
|
let encrypted = cipher.update(text, 'utf8', 'hex');
|
|
encrypted += cipher.final('hex');
|
|
|
|
// Get the auth tag
|
|
const tag = cipher.getAuthTag();
|
|
|
|
// Combine IV, salt, tag, and encrypted text
|
|
return Buffer.concat([
|
|
iv,
|
|
salt,
|
|
tag,
|
|
Buffer.from(encrypted, 'hex')
|
|
]).toString('base64');
|
|
} catch (error) {
|
|
logger.error('Encryption error:', error);
|
|
throw new Error('Encryption failed');
|
|
}
|
|
}
|
|
|
|
decrypt(encryptedData) {
|
|
try {
|
|
if (!encryptedData) return null;
|
|
|
|
// Convert from base64
|
|
const buffer = Buffer.from(encryptedData, 'base64');
|
|
|
|
// Extract IV, salt, tag, and encrypted text
|
|
const iv = buffer.slice(0, this.ivLength);
|
|
const salt = buffer.slice(this.ivLength, this.ivLength + this.saltLength);
|
|
const tag = buffer.slice(this.ivLength + this.saltLength, this.ivLength + this.saltLength + this.tagLength);
|
|
const encrypted = buffer.slice(this.ivLength + this.saltLength + this.tagLength);
|
|
|
|
// Create decipher
|
|
const decipher = crypto.createDecipheriv(this.algorithm, this.key, iv);
|
|
decipher.setAuthTag(tag);
|
|
|
|
// Decrypt the text
|
|
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
|
|
decrypted += decipher.final('utf8');
|
|
|
|
return decrypted;
|
|
} catch (error) {
|
|
logger.error('Decryption error:', error);
|
|
throw new Error('Decryption failed');
|
|
}
|
|
}
|
|
|
|
// Hash function for passwords
|
|
hashPassword(password) {
|
|
try {
|
|
const salt = crypto.randomBytes(16).toString('hex');
|
|
const hash = crypto.pbkdf2Sync(
|
|
password,
|
|
salt,
|
|
1000,
|
|
64,
|
|
'sha512'
|
|
).toString('hex');
|
|
|
|
return `${salt}:${hash}`;
|
|
} catch (error) {
|
|
logger.error('Password hashing error:', error);
|
|
throw new Error('Password hashing failed');
|
|
}
|
|
}
|
|
|
|
// Verify password against hash
|
|
verifyPassword(password, hashedPassword) {
|
|
try {
|
|
const [salt, hash] = hashedPassword.split(':');
|
|
const verifyHash = crypto.pbkdf2Sync(
|
|
password,
|
|
salt,
|
|
1000,
|
|
64,
|
|
'sha512'
|
|
).toString('hex');
|
|
|
|
return hash === verifyHash;
|
|
} catch (error) {
|
|
logger.error('Password verification error:', error);
|
|
throw new Error('Password verification failed');
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = new Encryption();
|