Wanna know how to securely store passwords in DB?
There is a way to do it more securely than doing SHA256(salt|password)
. Recently I’ve read a great article about bcrypt and now I will definitely use it to hash passwords🔐
The trick is in ability to control the complexity of hashing passwords so even in case of DB compromise the attackers will be significantly slowed down while brutefocing your hashed passwords👾
Also your passwords will be prune to precomputed rainbow tables because all passwords have their own salt baked into password.
Checkout the structure of a bcrypt hash:
$2b$10$nOUIs5kJ7naTuTFkBy1veuK0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa
| | | |
| | | hash-value = K0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa
| | |
| | salt = nOUIs5kJ7naTuTFkBy1veu
| |
| cost-factor => 10 = 2^10 rounds
|
hash-algorithm identifier => 2b = BCrypt
The returned hash string contains the salt nOUIs5kJ7naTuTFkBy1veu
. But why? Because salt is generated randomly for every hash computation and is needed to recalculate and compare hashes from plain-text password.
Sample algorithm for Python🐍
So the algorithm for storing passwords should be like this:
- Calculate
bcrypt.generate_password_hash(password, rounds=N)
with rounds starting from 12 - Store the returned value in database:
(username, bcrypt_hash)
And on authenticating attempt do this
- Pull the
bcrypt_hash
from DB by username which is trying to authenticate - Evaluate
bcrypt.check_password_hash(bcrypt_hash, user_provided_password)
This call automatically extracts salt from the stored hash bcrypt_hash
and applies it to slowly calculate (2^12 rounds) the hash from user_provided_password
.