mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-01-26 22:23:14 -05:00
Changed database file encryption to pbkdf2 for key derivation and aes-256-gcm for encryption (#6296)
* Added pbkdf2 and aes-256-gcm options for database file encryption * Added dbCipherAlgorithm option * Changed pbkdf2 to default Maintains backward compatibility, but will require a manual repush to update to the new version * Removed dbkeyderivationiterations option, as this branch is to be more opinionated
This commit is contained in:
parent
41e4213fc5
commit
5b76a31644
58
db.js
58
db.js
@ -417,34 +417,72 @@ module.exports.CreateDB = function (parent, func) {
|
||||
};
|
||||
|
||||
// Get encryption key
|
||||
obj.getEncryptDataKey = function (password) {
|
||||
obj.getEncryptDataKey = function (password, salt, iterations) {
|
||||
if (typeof password != 'string') return null;
|
||||
let key;
|
||||
try {
|
||||
key = parent.crypto.pbkdf2Sync(password, salt, iterations, 32, 'sha384');
|
||||
} catch (e) {
|
||||
// If this previous call fails, it's probably because older pbkdf2 did not specify the hashing function, just use the default.
|
||||
key = parent.crypto.pbkdf2Sync(password, salt, iterations, 32);
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
obj.oldGetEncryptDataKey = function (password) {
|
||||
if (typeof password != 'string') return null;
|
||||
return parent.crypto.createHash('sha384').update(password).digest("raw").slice(0, 32);
|
||||
}
|
||||
|
||||
// Encrypt data
|
||||
obj.encryptData = function (password, plaintext) {
|
||||
var key = obj.getEncryptDataKey(password);
|
||||
if (key == null) return null;
|
||||
let encryptionVersion = 0x1;
|
||||
let iterations = 100000
|
||||
const iv = parent.crypto.randomBytes(16);
|
||||
const aes = parent.crypto.createCipheriv('aes-256-cbc', key, iv);
|
||||
var key = obj.getEncryptDataKey(password, iv, iterations);
|
||||
if (key == null) return null;
|
||||
const aes = parent.crypto.createCipheriv("aes-256-gcm", key, iv);
|
||||
var ciphertext = aes.update(plaintext);
|
||||
ciphertext = Buffer.concat([iv, ciphertext, aes.final()]);
|
||||
let versionbuf = Buffer.allocUnsafe(2);
|
||||
versionbuf.writeUInt16BE(encryptionVersion);
|
||||
let iterbuf = Buffer.allocUnsafe(4);
|
||||
iterbuf.writeUInt32BE(iterations);
|
||||
let encryptedBuf = aes.final();
|
||||
ciphertext = Buffer.concat([versionbuf, iterbuf, aes.getAuthTag(), iv, ciphertext, encryptedBuf]);
|
||||
return ciphertext.toString('base64');
|
||||
}
|
||||
|
||||
// Decrypt data
|
||||
obj.decryptData = function (password, ciphertext) {
|
||||
let ciphertextBytes = Buffer.from(ciphertext, 'base64');
|
||||
try {
|
||||
var key = obj.getEncryptDataKey(password);
|
||||
if (key == null) return null;
|
||||
const ciphertextBytes = Buffer.from(ciphertext, 'base64');
|
||||
const iv = ciphertextBytes.slice(0, 16);
|
||||
const data = ciphertextBytes.slice(16);
|
||||
const aes = parent.crypto.createDecipheriv('aes-256-cbc', key, iv);
|
||||
var plaintextBytes = Buffer.from(aes.update(data));
|
||||
let key = obj.oldGetEncryptDataKey(password);
|
||||
const aes = parent.crypto.createDecipheriv("aes-256-cbc", key, iv);
|
||||
let plaintextBytes = Buffer.from(aes.update(data));
|
||||
plaintextBytes = Buffer.concat([plaintextBytes, aes.final()]);
|
||||
return plaintextBytes;
|
||||
} catch (e) {}
|
||||
// Adding an encryption version lets us avoid try catching in the future
|
||||
let encryptionVersion = ciphertextBytes.readUInt16BE(0);
|
||||
try {
|
||||
switch (encryptionVersion) {
|
||||
case 0x1:
|
||||
let iterations = ciphertextBytes.readUInt32BE(2);
|
||||
let authTag = ciphertextBytes.slice(6, 22);
|
||||
const iv = ciphertextBytes.slice(22, 38);
|
||||
const data = ciphertextBytes.slice(38);
|
||||
let key = obj.getEncryptDataKey(password, iv, iterations);
|
||||
if (key == null) return null;
|
||||
const aes = parent.crypto.createDecipheriv("aes-256-gcm", key, iv);
|
||||
aes.setAuthTag(authTag);
|
||||
let plaintextBytes = Buffer.from(aes.update(data));
|
||||
plaintextBytes = Buffer.concat([plaintextBytes, aes.final()]);
|
||||
return plaintextBytes;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
} catch (ex) { return null; }
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user