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.
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: Don’t confuse salt and seed. A seed is a random value which generally has to be kept secret or the encryption is broken.
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 just in about 0.3 seconds on my laptop. MD5, on the other hand, takes less than a microsecond.
So weakly talking about 5 or so orders of magnitude. Instead of cracking a password every 40 seconds, We will 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
Always store the hashed password.
About store the salt, exists different approach about what store:
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.
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: