This is how i Hash and store my password in the Database.
NEWUSER FUNCTION
var salt = bcrypt.genSaltSync(10);
var hash = bcrypt.hashSync(password, salt);
var query="INSERT into user(email,firstname,lastname,logintime,gender,password) VALUES('"+email+"','"+firstname+"','"+lastname+"','"+logintime+"','"+gender+"','"+hash+"')";
This is how i retrieve and check to authenticate
VALIDATE FUNCTION
var query = "SELECT password from user where email='" + email + "'";
connection.query(query,function(err,result){
if(err)
{
console.log("ERROR:"+err.message);
}
else
{
if(result.length!==0)
{
var hash=JSON.stringify(result[0].password); console.log(hash);
console.log(bcrypt.compareSync(password,hash ));
if(bcrypt.compareSync(password, hash)) { callback(err, result); }
This always shows false but if i do it this way it shows the expected result
var hash = bcrypt.hashSync("sacjap", 8);
//var hash=JSON.stringify(result[0].password);
console.log(hash);
console.log(bcrypt.compareSync(password,hash ));
if(bcrypt.compareSync(password, hash))
{
callback(err, result);
}
So the problem is that whenever i get the password from the database its not working. PLZ Help
First of all, my answer is based on the documentation I found here:
https://github.com/davidwood/node-password-hash
It seems that the password-hash module tries to call the 'split' function on the second argument you provided to the 'verify' function, assuming it is a string (JavaScript String split function on MDN). I think you should check the type of your 'result' variable, it looks to me like a more complex query result object returned by your database. Your provided code doesn't give me more information about what type of connection you are using here, so I can't give you a more specific answer. My approach would be to find out how to get a plain string from your 'result' variable, which then would represent the hashed password you can hand over to 'verify'. This is just a wild guess, I hope this little hint helps you to solve your problem.
Side note: The module you are using for password hashing appears to be deprecated, maybe you should look out for an alternative.
Related
Let's imagine I have an MongoDB document that includes the following data:
{
"username": "test123",
"password": "$2b$10$M2Y3ELsgfvA4KHxdCJkezeHZ1kKgtOA2Jiq4kuwqcRJSovGBu9nLm"
}
The password is hashed using bcrypt. Using MongoDB's official Node driver, I can find the username with:
collection.findOne({ username: req.body.username });
But how can I find the username, then check the password value of the same document (the password related to the username), and finally return the password?
PS. I know the title is very confusing, if you can think of a better way to express it, please comment below.
It's bad practice to send encrypted passwords to the database. It has some security issues. I guess you want to get the user by its username, figure out if it's the right user that you fetched by comparing its password also (password hashes), then do something with that user - for example, return password or so, as you mentioned (I don't see why would you expose password back to anyone).
For encryption, I'm using bcryptjs package, but it's pretty similar. Its function compare() takes the raw password for the first argument, and takes hashed password from the database as the second argument. It hashes the raw password and compares it with the given hash. If hashes match, the password is valid. For a code, you would have something like:
const bcrypt = require('bcryptjs');
// ...
const user = await collection.findOne({ username: req.body.username });
if (!user) throw new Error('User doesn\'t exist');
// first argument "password" is a raw password to compare with the one in the document
const passwordValid = await bcrypt.compare(password, user.password);
if (!passwordValid) throw new Error('Invalid password');
// do whatever you want to do with validated user
// if you want password to return, raw "password" is the one that's in the database also (hash)
I'm trying to launch a really basic chat app for myself and a few friends and wanted to include a password check upon loading the site by using a prompt + socket.emit:
var username = prompt('password:');
socket.emit('password', password);
I wanted to insert a function that checks their input against whatever I define as the answer. Something like this:
var codeword = prompt('password:', function checkPrompt(password) {
if (prompt.password.length === 0) {
return false;
}
if (password.value !== answer.value) {
return false;
}
return true;
});
But I get ERR_INVALID_ARG_TYPE(name, 'Function', value); once I run the app. How can I implement this?
Sidenote: I know this is super insecure. I'll implement a real password check once I have a DB set up but until then I just wanted a simple placeholder.
prompt is a "blocking" method, so there is no need for a callback. Callbacks are needed when you are uncertain when code within the callback will be executed. This is not the case here. You can work with the returned result in a do...while loop for example.
Dummy example with static password check:
// We will keep the user in the loop until the password is correct...
do {
var password = prompt('Password:');
} while (password !== 'abcd');
// At this point we know the password was correct.
alert('Password was correct!');
Dummy example with dedicated auth method:
function authenticate(username, password) {
if (username == 'john' && password == 'abcd') {
return true;
}
return false;
}
// We will keep the user in the loop until the password is correct...
do {
var username = prompt('Username:');
var password = prompt('Password:');
var loginSuccessful = authenticate(username, password);
} while (!loginSuccessful);
// At this point we know the password was correct.
alert('Password was correct!');
From the security point of view, it only makes sense to have the authentication logic on server-side, so you'll most probably will want to make an AJAX call from within the above authenticate function (using the Fetch API for example or jQuery.post - if you're using jQuery). Then the method would return true or false based on the response of the server-side call.
I'll try and word this question as short and clear as possible. I have a node.js project that connects to a non local instance of MongoDB using mongoose. I have written code for a user to login using passport module. I create a JSON file as a users collection. When I go to sign in I get this error
throw "Not a valid BCrypt hash."
So If I wanted to just create a JSON file of Users to work with this how would I go about it? My end goal is to convert RDBMS to MongoDB. Just starting with the users table. I understand that if I was registering new users I could just make a function that would hash their password like
newUser.password= createHash(password)
var createHash = function(password){
return bCrypt.hashSync(password, bCrypt.genSaltSync(10), null);
}
or something along those lines. Summary: How do I make a JSON file of user info for MongoDB that'll work with bcrypt hash and passport?
var fs = require('fs');
var bc = require('bcrypt-nodejs')
fs.readFile('users.txt',function(err,data){
var x = [];
if(err) throw err;
var buf = new Buffer(data);
x = buf.toString();
x = JSON.parse(x);
//console.log(x);
for(var a in x){
x[a].password=createHash(x[a].password);
}
x = JSON.stringify(x);
fs.writeFile('users.txt',x,callback()); //or just push directly to db?
});
var createHash = function(password){
return bc.hashSync(password, bc.genSaltSync(10), null);
}
function callback(){
console.log('finished');
}
Just read in my User Info , Bcrypted the passwords and made a new file. Put it in Mongo. Hopefully this helps someone else. If anyone has a better solution for me I'd appreciate it.
I am trying to figure out how to salt and hash a password in nodejs using the crypto module. I am able to create the hashed password doing this:
UserSchema.pre('save', function(next) {
var user = this;
var salt = crypto.randomBytes(128).toString('base64');
crypto.pbkdf2(user.password, salt, 10000, 512, function(err, derivedKey) {
user.password = derivedKey;
next();
});
});
However I am confused about how to later validate the password.
UserSchema.methods.validPassword = function(password) {
// need to salt and hash this password I think to compare
// how to I get the salt?
}
In whatever persistence mechanism (database) you're using, you would store the resulting hash alongside the salt and number of iterations, both of which would be plaintext. If each password uses different salt (which you should do), you must also save that information.
You would then compare the new plain text password, hash that using the same salt (and iterations), then compare the byte sequence with the stored one.
To generate the password (pseudo)
function hashPassword(password) {
var salt = crypto.randomBytes(128).toString('base64');
var iterations = 10000;
var hash = pbkdf2(password, salt, iterations);
return {
salt: salt,
hash: hash,
iterations: iterations
};
}
To validate password (pseudo)
function isPasswordCorrect(savedHash, savedSalt, savedIterations, passwordAttempt) {
return savedHash == pbkdf2(passwordAttempt, savedSalt, savedIterations);
}
Based on the nodejs documentation (http://nodejs.org/api/crypto.html), it doesn't look like there is a specific method that will validate a password for you. To validate it manually, you will need to compute the hash of the currently provided password and compare it to the stored one for equality. Basically, you will do the same thing with the challenge password that you did with the original, but use the salt stored in the database instead of generating a new one, and then compare the two hashes.
If you aren't too committed to using the built in crypto library, I might recommend using bcrypt instead. The two are about equal on the security front, but I think bcrypt has a more user-friendly interface. An example of how to use it (taken directly from the bcrypt docs on the page linked above) would be this:
Create a hash:
var bcrypt = require('bcrypt');
var salt = bcrypt.genSaltSync(10);
var hash = bcrypt.hashSync("B4c0/\/", salt);
// Store hash in your password DB.
To check a password:
// Load hash from your password DB.
bcrypt.compareSync("B4c0/\/", hash); // true
bcrypt.compareSync("not_bacon", hash); // false
Edit to add:
Another advantage of bcrypt is that the output of the genSalt function contains both the hash and the salt in one string. This means that you can store just the single item in your database, instead of two. There is also a method provided that will generate a salt at the same time that the hashing occurs, so you don't have to worry about managing the salt at all.
Edit to update:
In response to the comment from Peter Lyons: you're 100% correct. I had assumed that the bcrypt module that I had recommended was a javascript implementation, and therefor using it asynchronously wouldn't really speed things up on node's single threaded model. It turns out that this is not the case; the bcrypt module uses native c++ code for it's computations and will run faster asynchronously. Peter Lyons is right, you should use the asynchronous version of the method first and only pick the synchronous one when necessary. The asynchronous method might be as slow as the synchronous one, but the synchronous one will always be slow.
Either store password and salt in separate columns in your database, or (my preferred method), store your passwords in your database in a format that's compatible with RFC 2307 section 5.3. An example would be {X-PBKDF2}base64salt:base64digest. You could also store your iteration count in there, which allows you to increase the iteration count in the future for new accounts and accounts that update your passwords, without breaking logins for everyone else.
An example hash from my own PBKDF2 module for Perl looks like
{X-PBKDF2}HMACSHA1:AAAD6A:8ODUPA==:1HSdSVVwlWSZhbPGO7GIZ4iUbrk= which includes the specific hash algorithm used, as well as the number of iterations, the salt, and the resulting key.
This is a modified version of #Matthews answer, using TypeScript
import * as crypto from "crypto";
const PASSWORD_LENGTH = 256;
const SALT_LENGTH = 64;
const ITERATIONS = 10000;
const DIGEST = "sha256";
const BYTE_TO_STRING_ENCODING = "hex"; // this could be base64, for instance
/**
* The information about the password that is stored in the database
*/
interface PersistedPassword {
salt: string;
hash: string;
iterations: number;
}
/**
* Generates a PersistedPassword given the password provided by the user.
* This should be called when creating a user or redefining the password
*/
export function generateHashPassword(
password: string
): Promise<PersistedPassword> {
return new Promise<PersistedPassword>((accept, reject) => {
const salt = crypto
.randomBytes(SALT_LENGTH)
.toString(BYTE_TO_STRING_ENCODING);
crypto.pbkdf2(
password,
salt,
ITERATIONS,
PASSWORD_LENGTH,
DIGEST,
(error, hash) => {
if (error) {
return reject(error);
}
accept({
salt,
hash: hash.toString(BYTE_TO_STRING_ENCODING),
iterations: ITERATIONS,
});
}
);
});
}
/**
* Verifies the attempted password against the password information saved in
* the database. This should be called when
* the user tries to log in.
*/
export function verifyPassword(
persistedPassword: PersistedPassword,
passwordAttempt: string
): Promise<boolean> {
return new Promise<boolean>((accept, reject) => {
crypto.pbkdf2(
passwordAttempt,
persistedPassword.salt,
persistedPassword.iterations,
PASSWORD_LENGTH,
DIGEST,
(error, hash) => {
if (error) {
return reject(error);
}
accept(
persistedPassword.hash === hash.toString(BYTE_TO_STRING_ENCODING)
);
}
);
});
}
Faced with the same question I brought everything together into one module: https://www.npmjs.org/package/password-hash-and-salt
It uses pbkdf2 and stores hash, salt, algorithm, and iterations in a single field. Hope it helps.
There are two major steps involved in this scenario
1) Creating and Storing password
Here you will have to do the following.
Take the user password
Generate a string of random chars (salt)
Combine the salt with the user entered password
Hash the combined string.
Store the hash and the salt in the database.
2) Validating user password
This step would be required to authenticate the user.
The user will enter the username/email and the password.
Fetch the hash and the salt based on the username entered
Combine the salt with the user password
Hash the combination with the same hashing algorithm.
Compare the result.
This tutorial has a detailed explaination on how to do it with nodejs crypto. Exactly what you are looking for.
Salt Hash passwords using NodeJS crypto
From github:
To hash a password:
var bcrypt = require('bcrypt');
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash("B4c0/\/", salt, function(err, hash) {
// Store hash in your password DB.
});
});
To check a password:
// Load hash from your password DB.
bcrypt.compare("B4c0/\/", hash, function(err, res) {
// res == true
});
bcrypt.compare("not_bacon", hash, function(err, res) {
// res = false
});
From above, how can there be no salt values involved in the comparisons? What am I missing here?
The salt is incorporated into the hash (as plaintext). The compare function simply pulls the salt out of the hash and then uses it to hash the password and perform the comparison.
Bcrypt compare hashed and plaintext passwords without the salt string because the hashed password contains the salt string which we created at the time of hashing.
For example :
Take this Plain Password :
546456546456546456456546111
Hashed Password of above plain text using Bcrypt :
$2b$10$uuIKmW3Pvme9tH8qOn/H7uZqlv9ENS7zlIbkMvCSDIv7aup3WNH9W
So in the above hashed password, There are three fields delimited by $ symbol.
i) First Part $2b$ identifies the bcrypt algorithm version used.
ii) Second Part $10$ 10 is the cost factor (nothing but salt rounds while we creating the salt string. If we do 15 rounds, then the value will be $15$
iii) Third Part is first 22 characters (that is nothing but salt string)
In this case it is
uuIKmW3Pvme9tH8qOn/H7u
The remaining string is hashed password.
So basically, the saltedHash = salt string + hashedPassword to protect from rainbow table attacks.
I had the same question too as the original poster and it took a look bit of looking around and trying different things to understand the mechanism. As has already been pointed out by others, the salt is concatenated to the final hash. So this means a couple of things:
The algorithm must know the length of the salt
Must also know the position of the salt in the final string. e.g. if offset by a specific number from left or right.
These two things are usually hard coded in the implementation e.g. the bcrypt implementation source for bcryptjs defines the salt length as 16
/**
* #type {number}
* #const
* #private
*/
var BCRYPT_SALT_LEN = 16;
So to illustrate the basic concept behind the idea if one wanted to do it manually, It would look similar to the below. I do not recommend implementing stuff like this yourself when there are libraries that you can get to do it.
var salt_length = 16;
var salt_offset = 0;
var genSalt = function(callback)
{
var alphaNum = '0123456789abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ';
var salt = '';
for (var i = 0; i < salt_length; i++) {
var j = Math.floor(Math.random() * alphaNum.length);
salt += alphaNum[j];
}
callback(salt);
}
// cryptographic hash function of your choice e.g. shar2
// preferably included from an External Library (dont reinvent the wheel)
var shar2 = function(str) {
// shar2 logic here
// return hashed string;
}
var hash = function(passwordText, callback)
{
var passwordHash = null;
genSalt(function(salt){
passwordHash = salt + shar2(passwordText + salt);
});
callback(null, passwordHash);
}
var compare = function(passwordText, passwordHash, callback)
{
var salt = passwordHash.substr(salt_offset, salt_length);
validatedHash = salt + shar2(passwordText + salt);
callback(passwordHash === validatedHash);
}
// sample usage
var encryptPassword = function(user)
{
// user is an object with fields like username, pass, email
hash(user.pass, function(err, passwordHash){
// use the hashed password here
user.pass = passwordHash;
});
return user;
}
var checkPassword = function(passwordText, user)
{
// user has been returned from database with a hashed password
compare(passwordText, user.pass, function(result){
// result will be true if the two are equal
if (result){
// succeeded
console.log('Correct Password');
}
else {
// failed
console.log('Incorrect Password');
}
});
}
Because I had the same question myself, I know exactly what you are thinking about.
You have a misconception between "Secret Key" which is used in Cryptographic algorithms and "Salt" which is used to slow down the encryption process and make it harder for hackers to use brute force.
When you use the plain password and the salt to generate the hash, this hash uses as secret key the password itself! So the next time you will try to compare it with a plain password, this plain password must be the exact same one you used to generate the hash! So this is why you don't have to store it somewhere else because it is always provided by the user on both register and login steps!
It is just a fixed length string.
console.log("");
var salt = bcrypt.genSaltSync(10);
console.log(salt);
hash = bcrypt.hashSync("foobar", salt);
console.log(hash);
console.log("");
var salt = bcrypt.genSaltSync(10);
console.log(salt);
hash = bcrypt.hashSync("foobar", salt);
console.log(hash);
console.log("");
var salt = bcrypt.genSaltSync(10);
console.log(salt);
hash = bcrypt.hashSync("foobar", salt);
console.log(hash);
$2a$10$onmcKV.USxnoQAsQwBFB3e
$2a$10$onmcKV.USxnoQAsQwBFB3eytL3UZvZ5v/SudaWyaB9Vuq9buUqGO2
$2a$10$mwQfdyVS9dsO4SuxoR5Ime
$2a$10$mwQfdyVS9dsO4SuxoR5ImeG7atz7RXGRXb.c0VHp5zSn1N2VOA.Vq
$2a$10$uVUuJr6LryjchhKEg6PH7u
$2a$10$uVUuJr6LryjchhKEg6PH7unTw8aJGK0i3266c5kqDBLJkf80RHEpq
$2a$10$Y.upG5/54zvJyZacRxP17O
$2a$10$Y.upG5/54zvJyZacRxP17OH60BC0hQRMNfQjJxSWE77fyBrbzalmS
The salt is incorporated into the hash. The compare function simply pulls the salt out of the hash and then uses it to hash the password and perform the comparison.
When a user will log into our system, we should check the password entered is correct or not. Unlike other systems that would decrypt the password in the database (if it is encrypted), and compare it with the one entered by the user, what I do with bcrypt ( given it implements one-way hashing) is encrypt the one entered by the user. To do this, I will pass the password to bcrypt to calculate the hash, but also the password stored in the database associated with the user (hash). This is because, as mentioned before, the bcrypt algorithm used a random segment (salt) to generate the hash associated with the pasword. This was stored along with the password, and you need it to recalculate the hash of the password entered by the user and finally compare with the one entered when registering and see if they match.