I need to secure the user input password of an electron app to create a key for crypto AES ancryption. As suggested here on SO I've replaced the createHash function with scryptSync function. I'm not sure about the salt.
// this is the old method I've used to hash the password to obtain the correct lenght for aes-256-gcm
// let key = crypto.createHash('sha256')
// .update(data.password)
// .digest();
// salt creation
let salt = crypto.randomBytes(64);
let key = crypto.scryptSync(data.password, salt, 32);
Is there a predefined size that I need to pass to randomBytes function for aes-256-gcm encryption algo?
Also when I attach the salt to the encrypted output I'm using this code
let encryptedData = Buffer.concat([cipher.update(base64, 'utf8'), cipher.final()]);
let payload = `${salt.toString('base64')}:${iv.toString('base64')}:${encryptedData.toString('base64')}`;
Since I'm using the join() function to merge multiple encoded strings, I need a way to split them when the encrypted output file needs to be decoded. At the moment I'm using this way, but I've figured out that I need to extract the salt to check the password. Is there a way to do it better?
const decryptData = (data) => {
let output = [];
// I need the salt here but the file needs to be splitted before
let key = crypto.scryptSync(data.password, 'salt', 32);
return new Promise( (resolve, reject) => {
fs.readFile(data.path, 'utf8', (err, content) => {
if(err) return reject(err);
let fileContents = content.split(' ');
output = fileContents.map( (file) => {
let [salt, iv, content] = file.split(':');
let cipher = crypto.createDecipheriv('aes-256-gcm', key, Buffer.from(iv, 'base64'));
let decrypted = cipher.update(content, 'base64', 'utf8');
return decryptedData;
});
resolve(output);
});
});
}