Password Hashing Techniques in PHP

This post started as part of yesterday’s post on encrypting passwords as a subsection labeled “Salt? Pepper? When did this become a cooking blog?” The fact is, I felt that the section was a bit long-winded and warranted a dedicated post. Without further ado let’s talk about some techniques for generating secure password hashes.

If you’re not familiar with salts and such, let me go into a bit more detail for you. Please note, that for the sake of the examples I’ll be using the SHA-1 function. I don’t recommend using these as copy and paste examples but more for the logic being demonstrated. More information about why you shouldn’t use sha1() for securing passwords is available here.

Salted Hashes

A salt is a string (usually on the short side) that is appended (or prepended) to the string you are about to generate a hash for. The salt itself is stored either as part of the hash or it could live in a separate column in your database on the user’s table. The salt itself should be randomly generated for each user as well as regenerated during password changes.

$salt	 = 'salt'
$password = 'abc123'
$hash	 = sha1($salt . $password

Peppered Hashes

Peppered hashes are similar to salted hashes as they contain a string that is appended or prepended to the plaintext password before hashing. Unlike a salt, the pepper is stored at the application level (in your code) and not the database or in the hash. This creates another touch point that a potential attacker would have to compromise to be able to accurately crack the password hashes.

$pepper   = 'cayenne'
$password = 'abc123'
$hash	 = sha1($pepper . $password

Generally speaking, pepper values are somewhat of a static solution. You could easily implement multiple pepper values based on what the user’s unique ID is in the database or some other value like the first character of their email.

Key Stretching

Key stretching adds complexity by hashing the password multiple times, usually at least 1,000 times or more. The most simple implementation would be to apply the same function multiple times in a loop:

$password = 'abc123'

for ($i $i < 1000 $++)
{
	$password = sha1($password
}

By doing this you’re increasing the time it takes to generate the password hash and thus slowing down any brute force attacks against the hash. You can expand upon this by adding in the salt and/or pepper to each iteration. I’ve seen this referred to as “spicy hashing” because of all of the pepper that’s being added 😉

$password = 'abc123'

for ($i $i < 1000 $++)
{
	$password = sha1($pepper . $password
}

Conclusion

How you hash your stored passwords is just as important as which hashing function you choose to use. Salting, peppering or key stretching on their own can add enough complexity to avoid having your password hashes susceptible to rainbow table attacks. Combine all of the techniques (and making sure to use a unique salt per user) will make it nearly impossible to crack your hashes if you’re using a stronger hashing function like Blowfish or SHA-512.

Keep in mind that these techniques may stand the test of time but the hashing functions themselves can be compromised in the future. The faster computers become, the easier it will become to crack the algorithms that we consider secure today.

Josh Sherman - The Man, The Myth, The Avatar

About Josh

Husband. Father. Pug dad. Musician. Founder of Holiday API, Head of Engineering and Emoji Specialist at Mailshake, and author of the best damn Lorem Ipsum Library for PHP.


If you found this article helpful, please consider buying me a coffee.