How to hash, store and validate a password
Banner source: https://blog.emsisoft.com/en/29524/how-to-create-manage-store-passwords/
Rule #1: Never ever invent your own crypto algorithm.
What makes a good hashing algorithm?
A good algorithm for hashing passwords:
- Is deterministic: the same plaintext will always produce the same hash;
- Produces a completely different result if a single bit of the plaintext is
changed; - Is resistant to collision attacks. Two different plaintexts can sometimes produce the same hash, however, if the method to create this same hash is known, the algorithm shouldn't be used;
- Is resistant to Rainbow Table attacks by using salts;
- Is compatible with performance requirements: always check benchmarks;
- Allows parallelism in order to prevent the server from becoming
unresponsive during hashing; - Doesn't have other known vulnerabilities: Google is your friend.
tl;dr use Bcrypt
Coda Hale's How To Safely Store A Password provides an excellent explanation as to why Bcrypt is currently preferred to all the other popular hashing algorithms.
Also, this is the hashing algorithm recommended by OWASP:
Use Bcrypt unless you have a good reason not to.
If you really can't use Bcrypt:
- remember to always add a salt to your hash in order to prevent rainbow-table attacks (you can even add a pepper);
- make sure you're using an appropriate number of hashing rounds.
NodeJS Example
If you're developing a NodeJS application, the bcrypt package is a great library to:
- hash the plaintext passwords you receive from the front-end during the user registration process;
- compare the plaintext passwords entered by the user during login with the hash previously stored in the DB.
Note: make sure you're using at least 12 rounds.
import bcrypt from 'bcrypt'
const password = 'myv3rys3cr3tp@ssw0rd'
const rounds = 12
bcrypt.hash(password, rounds, (err, hash) => {
if (err) {
console.error(err)
return
}
console.log(hash)
})
bcrypt.compare(password, hash, (err, res) => {
if (err) {
console.error(err)
return
}
console.log(res) //true or false
})