const crypto = require('crypto');
// Function to generate a random salt of given length
function generateSalt(length) {
return crypto.randomBytes(Math.ceil(length / 2)).toString('hex').slice(0, length);
}
// Function to hash the password using SHA-256 and the provided salt
function hash(password, salt) {
const hash = crypto.createHmac('sha256', salt);
hash.update(password);
const hashedPassword = hash.digest('hex');
return salt + hashedPassword; // Combining salt and hashed password
}
// Function to compare the plain password with the hashed password
function compare(password, hashed) {
const salt = hashed.substr(0, 16); // Extracting the salt from the hashed password
const hashedPassword = hash(password, salt); // Hashing the plain password with extracted salt
return hashed === hashedPassword;
}
// Example usage
const plainPassword = 'mySecurePassword';
const salt = generateSalt(16); // Generating a random salt
const hashedPassword = hash(plainPassword, salt); // Hashing the password with the generated salt
console.log("Hashed Password:", hashedPassword);
// Bonus: Comparing the plain password with the hashed password
const isMatch = compare(plainPassword, hashedPassword);
console.log("Password Match:", isMatch);
Y29uc3QgY3J5cHRvID0gcmVxdWlyZSgnY3J5cHRvJyk7CgovLyBGdW5jdGlvbiB0byBnZW5lcmF0ZSBhIHJhbmRvbSBzYWx0IG9mIGdpdmVuIGxlbmd0aApmdW5jdGlvbiBnZW5lcmF0ZVNhbHQobGVuZ3RoKSB7CiAgICByZXR1cm4gY3J5cHRvLnJhbmRvbUJ5dGVzKE1hdGguY2VpbChsZW5ndGggLyAyKSkudG9TdHJpbmcoJ2hleCcpLnNsaWNlKDAsIGxlbmd0aCk7Cn0KCi8vIEZ1bmN0aW9uIHRvIGhhc2ggdGhlIHBhc3N3b3JkIHVzaW5nIFNIQS0yNTYgYW5kIHRoZSBwcm92aWRlZCBzYWx0CmZ1bmN0aW9uIGhhc2gocGFzc3dvcmQsIHNhbHQpIHsKICAgIGNvbnN0IGhhc2ggPSBjcnlwdG8uY3JlYXRlSG1hYygnc2hhMjU2Jywgc2FsdCk7CiAgICBoYXNoLnVwZGF0ZShwYXNzd29yZCk7CiAgICBjb25zdCBoYXNoZWRQYXNzd29yZCA9IGhhc2guZGlnZXN0KCdoZXgnKTsKICAgIHJldHVybiBzYWx0ICsgaGFzaGVkUGFzc3dvcmQ7IC8vIENvbWJpbmluZyBzYWx0IGFuZCBoYXNoZWQgcGFzc3dvcmQKfQoKLy8gRnVuY3Rpb24gdG8gY29tcGFyZSB0aGUgcGxhaW4gcGFzc3dvcmQgd2l0aCB0aGUgaGFzaGVkIHBhc3N3b3JkCmZ1bmN0aW9uIGNvbXBhcmUocGFzc3dvcmQsIGhhc2hlZCkgewogICAgY29uc3Qgc2FsdCA9IGhhc2hlZC5zdWJzdHIoMCwgMTYpOyAvLyBFeHRyYWN0aW5nIHRoZSBzYWx0IGZyb20gdGhlIGhhc2hlZCBwYXNzd29yZAogICAgY29uc3QgaGFzaGVkUGFzc3dvcmQgPSBoYXNoKHBhc3N3b3JkLCBzYWx0KTsgLy8gSGFzaGluZyB0aGUgcGxhaW4gcGFzc3dvcmQgd2l0aCBleHRyYWN0ZWQgc2FsdAogICAgcmV0dXJuIGhhc2hlZCA9PT0gaGFzaGVkUGFzc3dvcmQ7Cn0KCi8vIEV4YW1wbGUgdXNhZ2UKY29uc3QgcGxhaW5QYXNzd29yZCA9ICdteVNlY3VyZVBhc3N3b3JkJzsKY29uc3Qgc2FsdCA9IGdlbmVyYXRlU2FsdCgxNik7IC8vIEdlbmVyYXRpbmcgYSByYW5kb20gc2FsdApjb25zdCBoYXNoZWRQYXNzd29yZCA9IGhhc2gocGxhaW5QYXNzd29yZCwgc2FsdCk7IC8vIEhhc2hpbmcgdGhlIHBhc3N3b3JkIHdpdGggdGhlIGdlbmVyYXRlZCBzYWx0Cgpjb25zb2xlLmxvZygiSGFzaGVkIFBhc3N3b3JkOiIsIGhhc2hlZFBhc3N3b3JkKTsKCi8vIEJvbnVzOiBDb21wYXJpbmcgdGhlIHBsYWluIHBhc3N3b3JkIHdpdGggdGhlIGhhc2hlZCBwYXNzd29yZApjb25zdCBpc01hdGNoID0gY29tcGFyZShwbGFpblBhc3N3b3JkLCBoYXNoZWRQYXNzd29yZCk7CmNvbnNvbGUubG9nKCJQYXNzd29yZCBNYXRjaDoiLCBpc01hdGNoKTsK