Skip to main content

Storing User Credentials

For the most part, this is about storing passwords, and understanding how to secure them properly.

Password encryption algorithms

When it comes to storing user passwords, the algorithm you use for doing so is always going to be a tradeoff between security strength and the time and processing power required to hash a given password with that algorithm.

For instance, the most robust and secure algorithms can take significant CPU and memory to run (in order to be further hardened against attacks that brute-force passwords at speed, they forcibly take up an amount of memory to avoid an attacker being able to run many at the same time). The webservers of most websites are not designed to handle this kind of load and would buckle quickly under this much pressure.

As a result, for websites - you usually need an algorithm that is strong enough to be secure, but not strong enough to bring your servers to a halt. Many languages and frameworks have defaults set for them that represent current security practices, but it is always good to be aware of these considerations, just in case.

In PHP, the password_hash function has several algorithms that can be used, and defaults to bcrypt at the time of writing, which is perfectly fine for a normal website as of the time of writing. Often, the default (as is the case in PHP) will change to use a more secure standard if needed in future, and if this is the case for your language or framework, you should use the default instead of managing it yourself. If the default changes in future, you don't need to worry about changing anything in your code, as the hash generated by functions usually includes a substring that indicates which algorithm was used to encrypt it (so that the function knows which algorithm is needed to verify it).

Storing passwords correctly

This generally isn't difficult - you just need to make sure you do not make any big errors. For instance, if you have several pages on which a user might sign up, change their password or otherwise set their security credentials, it's good practice to use one centralised function to actually hash the password and upload it to your database - if there is more than one function doing this, you run the risk of accidentally forgetting to update one with the others, introducing a potential vulnerability.

Storing 2FA secrets

Unlike passwords, users' 2FA secret keys are generally stored unencrypted. This is because unlike the password, the server needs to know the original value of the key to check if the user's inputted 2FA passcode is valid or not, making encryption a fairly difficult option to actually use here. Two-way encryption wouldn't help: after all, you have to store the decryption key somewhere in a manner specific to that user... which is usually going to be the database itself.

2FA is not designed to protect against server breaches. Keeping your database safe from prying eyes is the most practical way to secure 2FA secrets.