Following this tutorial, I got a bunch of questions with this code :
const crypto = require("crypto")
async function hash(password) {
return new Promise((resolve, reject) => {
// generate random 16 bytes long salt
const salt = crypto.randomBytes(16).toString("hex")
crypto.scrypt(password, salt, 64, (err, derivedKey) => {
if (err) reject(err);
resolve(salt + ":" + derivedKey.toString('hex'))
});
})
}
Is it worth or relevant to:
- encrypt my salt before saving it to the database (with a key I have for example in a .env file to decrypt it when verifying password)
- concat a random key (another one that I keep in a .env also I guess) to the salt (but I don't add it in the db) and use it for verification also.
For example, the code above will become something like this:
const crypto = require("crypto")
async function hash(password) {
return new Promise((resolve, reject) => {
// generate random 16 bytes long salt
const generatedSalt = crypto.randomBytes(16).toString("hex")
const salt = `${generatedSalt}${process.env.BASE_SALT}`
crypto.scrypt(password, salt, 64, (err, derivedKey) => {
if (err) reject(err);
const encryptedSalt = someEncryptionfunction(generatedSalt,process.env.SALT_ENCRYPT_KEY)
resolve(encryptedSalt + ":" + derivedKey.toString('hex'))
});
})
}
And the verification function will be like:
async function verify(password, hash) {
return new Promise((resolve, reject) => {
const [encryptedSalt, key] = hash.split(":")
const generatedSalt = someDecryptionfunction(encryptedSalt,process.env.SALT_ENCRYPT_KEY)
const salt = `${generatedSalt}${process.env.BASE_SALT}`
crypto.scrypt(password, salt, 64, (err, derivedKey) => {
if (err) reject(err);
resolve(key == derivedKey.toString('hex'))
});
})
}