PROTECTING USER PASSWORDS
Note: This post was originally written in 2016 and imported from my old blog. Unfortunately, this post is still very relevant even today as unsalted passwords still get leaked.
When creating a user account system, protecting user passwords is a very important aspect. If your database containing user account information is ever hacked, the best case scenario is that hackers have a hard time decrypting the data.
For this reason, you should never store unencrypted passwords. Anyone who has access to the data (ex. Administrators) can immediately know how to log in as that user. This would definitely be the worst case scenario if your data ever leaks.
Another option such as encrypting passwords is also a bad practice. Encrypted passwords can simply be displayed if the encryption is ever reversed with the password. If the encryption is every unlocked, all the passwords will also be available.
The best way to protect your user passwords is to use a cryptographic algorithm like bcrypt and to hash your user passwords using a separate salt.
Bcrypt is a slow cryptographic algorithm that allows many rounds of hashing and also hashes passwords with a salt. The slowness is one of the main reasons why Bcrypt is a cryptographic algorithm still used 17 years after its creation.
Slowness is a good feature because computers become faster over time. If Bcrypt hashed passwords fast, that would give hackers with powerful hardware more options to try to decrypt your passwords. Bcrypt is inherently slow but is not noticeable to users logging in with their credentials. Bcrypt also allows us to administer specific rounds of hashing passwords.
Salting a hash is when an algorithm hashes the user’s entered password with a random string of bytes. Using a separate salt for each user protects dictionary attacks, which use common pass-phrases to create a hash.
Example User table with made up Salts and Hashes below:
1Users | Password | Salt | Hash
2------------------------------------------------------
3Jon | Sn0w! | 1#*...^Fsd | *&5SDa...DF(ASl
4
5Annie | r@men1 | s2j...51l@* | (S$Dfj...y183sd
6
7Alex | Sn0w! | 7s#...8Sj | )fd6l2...515/*s
Even though Jon and Alex have the same password, the hash is totally different because of the salt. If there was no salt added to the hash on creation, the hash for Jon and Alex would be the same. Finding one hash combination for a password would unlock all users with that same password. That is why you need to have separate hashes per user!
Because we have a different salt for each user, a hacker would need to generate new password hashes separately for each user. Again, Bcrypt is inherently slow, finding passwords for the whole database would be a very time expensive task.
Storing the salt in the database along with the username is also not an issue because the salt’s purpose is to protect users with the same password.
If you want to protect your users’ passwords, use a hashing algorithm with separate salts!