Cooking with credentials – salting

Yesterday, we covered the basics of why hashing is essential for password security. Unfortunately, using a naive hash to protect passwords isn’t secure. The hash outputs of two identical input strings are, themselves, identical. If two users inadvertently use the same password, their identical hashes would leak that similarity and weaken your application.

Luckily, the cryptographic community introduced the idea of adding salt to your hash to ensure every resultant hash is a distinct value. A salt is a completely random value unrelated to the password being used – every password gets its own salt so every password+salt combination will generate a distinct hash.

Even luckier, the default password hashing mechanisms in PHP handle salting for you automatically!

$hash = password_hash(/** Some Password **/, PASSWORD_DEFAULT);

The only parameters you are required to provide are the user’s raw password and a flag to identify the algorithm you want to use. The function will create a random hash for you and returns a string that can be passed directly into password_verify() later.

While PASSWORD_DEFAULT is usually a safe default value to start with, you have the option of tuning the hashing algorithm to fit the hardware of your specific server. Some servers are better at hashing than others and you might want to slow things down a bit to prevent attackers from attempting to break their way in through brute force. Check the PHP manual for password_hash() for more details about cost factor parameters and identifying the best options to use for you system.

The resulting string will look something like:

$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

The first component (2y) identifies the algorithm you used to create the hash. The second component (10) specifies the cost factor used with the algorithm – in this case we fall back on the default parameters for the default hash (the bcrypt algorithm). The final section is the random salt concatenated with the actual hash result.

Your application should store this value (rather than the plaintext password) for use when authenticating logins in the future. When a user logs in, pass this hash and the user’s password into password_verify(). This function will recreate the user’s hash (using the same algorithm, cost factors, and random salt) and check if it matches the expected output.