Skip to content

Instantly share code, notes, and snippets.

@dmh2000
Last active May 18, 2021 09:58
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save dmh2000/1609820c17c5daf95298f54324360950 to your computer and use it in GitHub Desktop.
Save dmh2000/1609820c17c5daf95298f54324360950 to your computer and use it in GitHub Desktop.
Using bcrypt with promises to hash a password and then verify it
const bcrypt = require("bcrypt");
// use this library in case your version of node doesn't support Promise
// const Promise = require("promise");
let password = "hello";
let stored_hash = "";
// first generate a random salt
function genSalt(password) {
return new Promise((resolve, reject) => {
bcrypt.genSalt(10, function(err, salt) {
if (err) {
reject(err);
} else {
resolve({
salt: salt,
password: password
});
}
});
});
}
// hash the password with the salt
function genHash(salt, password) {
return new Promise((resolve, reject) => {
bcrypt.hash(password, salt, function(err, hash) {
if (err) {
reject(err);
} else {
resolve({
salt: salt,
password: password,
hash: hash
});
}
});
});
}
// execute in sequence
console.log("store");
genSalt(password)
.then(function(result) {
return genHash(result.salt, result.password);
})
.then(function(result) {
console.log("store hash in user profile :", result);
stored_hash = result.hash;
})
.catch(function(err) {
console.log(err);
});
// =====================================================
function lookupUser(user, passwd) {
return new Promise((resolve, reject) => {
// lookup the user in the stored database
// in this case its not async so just resolve with the stored hash
resolve({
user: user,
password: passwd,
hash1: stored_hash
});
});
}
function reHash(user, password, hash1) {
// extract salt from existing has (30 characters)
let salt = hash1.substr(0, 30);
return new Promise((resolve, reject) => {
bcrypt.hash(password, salt, function(err, hash2) {
if (err) {
reject({
err,
user: user,
salt: salt,
password: password,
hash1: hash1, // stored hash
hash2: hash2 // generated hash
});
} else {
resolve({
user: user,
salt: salt,
password: password,
hash1: hash1, // stored hash
hash2: hash2 // generated hash
});
}
});
});
}
// lookup and verify
setTimeout(function() {
console.log("verify");
lookupUser("joe", password)
.then(function(result) {
return reHash(result.user, result.password, result.hash1);
})
.then(function(result) {
console.log(result.hash1);
console.log(result.hash2);
if (result.hash1 === result.hash2) {
console.log("verified");
} else {
console.log("failed");
}
})
.catch(function(err) {
console.log(err);
});
}, 1000);
@Katamori
Copy link

Katamori commented Oct 9, 2019

This is ungodly awesome, thank you!

Turns out, if you want to use bcrypt and sequelize simultaneously, you rely on such solution much more intensely, given that the latter uses a lot of Promises.

@yahayaohinoyi
Copy link

I love this man.

@Sirius-Coder
Copy link

Thanks for this ... Helped a ton

@dmh2000
Copy link
Author

dmh2000 commented Jan 16, 2020

glad i could help. I worked this up after I failed horribly on an interview question about bcrypt.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment