Better Password Peppering

Epistemic status: confidant. I’m not a cryptographer, but no one raised strong objections and I thought about it a bunch since first thinking about it.

Everyone talking about password peppering is missing a better method to implement it.

whether you think peppers are good or bad, knowing this is valuable. If you think they’re good, this is a better method to use them. If you think they’re bad, this is a stronger version to argue against. The main point of this post isn’t to endorse peppers (though I do think they’re good), but to compare the common methods to an alternative one.

Terms and background, in short

Skip if you’re familiar

Hash: Secure password storage doesn’t store passwords, so if the database leaks, the passwords aren’t revealed. Instead you use a hashing function, which takes any password, and turns it into a seemingly random (very large) number, this is your hash, and this is what you store instead of the password. Hashes are hard to reverse, and unlike encryption, hashes don’t have keys to decrypt them. When the user logs in, the password is hashed again and compared to the stored hash.

Salt: A random string that is added to to the password before it’s hashed, and is usually stored in plain text near the now salted hash (so each salt is connected to a user). When the user logs in the salt is again hashed with their password and compared to the stored hash. Salts prevent rainbow table attacks, and make the hashes of passwords shared by multiple users unique so each password has to be cracked individually. However, if an attacker targets a specific user and is willing to bruteforce their password, a salt will do nothing to stop them, and the user will have to rely on the strength of their own password.

Pepper: A pepper is a secret salt that is stored without connection to a user (for example at the top of the database[1]), or not stored at all. Peppers make it harder to crack individual passwords even in the case of a leak. Peppers should always be used together with salts.

Common Approaches

There’s two main approaches to peppering, both should be in addition to salts.

  1. You generate a really long number (128+ bits) and store it outside the database, then whenever you need to hash a user’s password you add it to the password before hashing.

    • Pros: if attackers don’t know the pepper it’s impossible to crack any of the passwords.

    • Cons: If the attackers find the pepper it becomes useless, and if they know the salt and plain text password of some user (could even be themselves), and which hashing algorithm was used, they can potentially use that to brute force the pepper.

  2. You pick a string at random and use it a the pepper, but don’t store it at all, so every time the user logs in you basically have to brute force all the peppers until you find the right one. For it to not take ages, you use a small string, say 1-2 characters.

    • Pros: It makes the attackers X times slower because they have to try every possible pepper on each password.

    • Cons: the attackers will likely know which peppers are possible, since it’s likely 1-2 characters out of the allowed character set. And users that got letters that hackers are likely to start with just out of convenience are at a serious disadvantage.

My method is a combination of the two:

Do note that I’m not saying no one has come up with this before, just that I didn’t see it.

Generate some (say, ~100) really long numbers, and store them outside the database. When a user registers, you pick one of them at random and use it as their pepper. Whenever they login you try each of the stored peppers until one works.

Pros over #1:

  • Your peppers aren’t easy to crack anymore, even if one pepper is brute forced, there’s still all the other that remain unknown.

  • If the peppers leak, then the attackers still don’t know which pepper is used for which user, and so are still slowed down by the amount of peppers you chose to generate.

Pros over 2#:

  • The peppers are practically impossible to guess, while still giving the benefit of having a lot of different ones.

  • This makes cracking even a weak password like ’123′ impossible without already knowing the pepper used or which peppers to check.

  • Authentication isn’t slower since appending is quick and you choose the amount of peppers you use.

  • You don’t lose much security from stored peppers since the possible peppers were already quite predictable with the common method.

  • You have better control over the amount of possible peppers, and it’s easy to gradually add more peppers with time.

I think this should be more secure than both methods, with little downside, and barely any increased complexity—Yet I wasn’t able to find any source that describes something similar.

  1. ^

    Many sources talk of storing the pepper “outside the database”, and a previous version of this article used this phrasing as well (though did mention it’s not strictly necessary). The reason that, as the rest of the article explains, conventional implementations require a secrecy assumption. Though storing it “outside the database” does make it less likely the pepper would leak if the database leaks, assuming that you can keep the pepper secret if you can’t keep the passwords secret is just a bad and insecure assumption. The method I suggest still benefits from secrecy (so storing “outside the database” won’t hurt), but doesn’t require it.