Don't use hash algorithm
I mean, not only.
MD5, SHA1, SHA256, SHA512, SHA-3,...
These are all general purpose hash functions, designed to calculate a digest of huge amounts of data in as short a time as possible.
This means that they are fantastic for ensuring the integrity of data and utterly rubbish for storing passwords.
Salt for prevent brute force attacks
A salt is a random value that is generally not a secret, which is used to make some precomputed attacks harder.
Salts are closely related to the concept of nonce.
The primary function of salts is to defend against dictionary attacks versus a list of password hashes and against pre-computed rainbow table attacks.
NOTE: A seed is a random value which generally has to be kept secret or the encryption is broken, don't confuse with salt!
Use strong salt rounds
Bcrypt is an adaptative password hashing function: over time, the iteration count can be increased to make it slower, so it remains resistant to brute-force search attacks even with increasing computation power.
How much slower is bcrypt than, say, MD5? Depends on the work factor. Using a work factor of 12, bcrypt hashes the password yaaa in about 0.3 seconds on my laptop. MD5, on the other hand, takes less than a microsecond.
So weâ€™re talking about 5 or so orders of magnitude. Instead of cracking a password every 40 seconds, Iâ€™d be cracking them every 12 years or so. Your passwords might not need that kind of security and you might need a faster comparison algorithm, but bcrypt allows you to choose your balance of speed and security. Use it.
That's little benchmark to know how salt rounds affect:
rounds=8 : ~40 hashes/sec rounds=9 : ~20 hashes/sec rounds=10: ~10 hashes/sec rounds=11: ~5 hashes/sec rounds=12: 2-3 hashes/sec rounds=13: ~1 sec/hash rounds=14: ~1.5 sec/hash rounds=15: ~3 sec/hash rounds=25: ~1 hour/hash rounds=31: 2-3 days/hash
Saving password on database
Always store the hashed password.
About store the salt, exists different approach about what store:
- A fix salt for all the user passwords.
- A salt per each user password.
- In the same database than password.
- In a different database.
In the case of bcrypt, it explore A salt per each password and In the same database than password:
var hash = bcrypt.hashSync(myPlaintextPassword, saltRounds); bcrypt.compareSync(myPlaintextPassword, hash); // true
Let's see how looks the hash has been generated:
> bcrypt.genSaltSync(10) // $2a$10$Yq0.l.cOsImF1s1kJL2IOe > bcrypt.genSaltSync(10) // $2a$10$Rtqb0Kjma5W93bDDJRUdO. > bcrypt.genSaltSync(11) // $2a$11$/7YSZ7uZH0ouTTDl4BAGve
The salt is part of the final hash.
As you can see, it stores both the salt, and the hashed output in the string.
Strong password in the user side
All this is useless if the input password is 12345.
Best trick that I know for that: auto-generate strong password per service using 1Password: