599

If you expect to store user password securely, you need to do at least the following:

$pwd=hash(hash($password) + salt)

Then, you store $pwd in your system instead of the real password. I have seen some cases where $pwd contains the salt itself.

I wonder whether the salt should be stored separately, or is it OK if an attacker gets the hashed value and the salt at the same time. Why?

kc2001
  • 117
  • 6
George
  • 6,177
  • 3
  • 14
  • 10
  • Well, one thing to consider with salts. If you do manage to keep them secret, and your password hashes get leaked, it becomes completely impossible(probably) to recover a password, even with 10,000 graphics cards brute forcing it – Earlz Jul 20 '12 at 14:58
  • 14
    @Earlz That's **not** the purpose of a salt, and it's nearly impossible to keep salts hidden anyway! – Polynomial Jul 20 '12 at 15:34
  • 3
    @Polynomial Well, something to consider. I have an authentication system which uses two salts for each password, one randomly generated and stored in the database, and one which is global to the website and stored in the code. My goal was to make it so that even if the database got leaked, it's still not possible to forge a login cookie or brute force the password. – Earlz Jul 20 '12 at 15:54
  • 15
    @Earlz The second salt is called a [pepper](http://security.stackexchange.com/questions/3272/password-hashing-add-salt-pepper-or-is-salt-enough), which protects you from attackers that only have access to the database. It's useful, but since you're using parameterised queries (you *are* using them, right?) SQL injection isn't a problem, so that model of attacker is much less likely. – Polynomial Jul 20 '12 at 15:58
  • Heh I did not know there was a name for that, @Polynomial. And I'm pretty sure my database is secure, but just in case it's not. (MongoDB). I figure it can't hurt and it's not that hard to implement – Earlz Jul 20 '12 at 16:06
  • 52
    Forgive my ignorance, but is it really necessary to hash the password _before_ adding the salt? If you have a good hashing algorithm, it shouldn't make a difference, right? – Clockwork-Muse Jul 20 '12 at 16:07
  • What about $pwd=hash(hash($password) + username)? – SilverViper Jul 20 '12 at 20:20
  • 5
    @X-Zero There should be no difference at all, and it makes things more awkward when using an adaptive KDF. – Polynomial Jul 20 '12 at 22:55
  • 4
    @SilverViper That's a bad idea. It gives an attacker the salt, allowing them to compute a rainbow table ahead of time, before overtly breaching your database. In such a situation, the attacker can log in immediately after the attack and you have no time to react. See my answer for a more detailed explanation of this problem. – Polynomial Jul 20 '12 at 22:57
  • +1 for using salts, which is more than big websites seem to do usually. – Jonas Schäfer Jul 21 '12 at 11:57
  • 2
    @JonasWielicki Yup. Some even store in plaintext. See [Plaintext Offenders](http://plaintextoffenders.com/) for examples. Another large company, not listed there, is Tesco. – Polynomial Jul 29 '12 at 15:00
  • Why would you store a salt? If you could compute it using the credentials some way.. such as `$salt = base64_encode($username.$password);` then you don't have to store it, and if the username and password is correct, it will match the salt too. – code ninja Jul 02 '13 at 20:57
  • 6
    @matejkramny That's exactly equivalent to just using the username as the salt, and bad for the same reason: if the attacker knows a username they want to break into, they can just precompute the hashes for that username. Including the password in the salt doesn't change a thing. To stop them from precomputing hashes, the salt should be stored in the database, so they can't get it before getting the hashes themselves, which means they need a lot of time to break the hashes *after* they compromise the database, which gives you a chance to change passwords before they get access. – cpast Feb 04 '14 at 18:36
  • 1
    // , What containers are you using? Are you using Iodized or non-Iodized? You could wind up with a poisoned salt, so avoid metal containers, because salt leaches metals and/or elements out of the metal. Well regardless, ya don't need to use a food-saver, because salt will not go rancid even if it is exposed to air. For large amounts, I recommend scooping the salt into heavy duty gallon-sized plastic bags. Then you can put the bags in a food grade 5-gallon bucket. For all of you preppers out there, it can be used as a bartering item in time of need. – Nathan Basanese Jan 11 '19 at 02:56
  • // , https://selfreliantschool.com/how-and-why-to-store-salt – Nathan Basanese Jan 11 '19 at 03:09

7 Answers7

830

TL;DR - You can store the salt in plaintext without any form of obfuscation or encryption, but don't just give it out to anyone who wants it.


The reason we use salts is to stop precomputation attacks, such as rainbow tables. These attacks involve creating a database of hashes and their plaintexts, so that hashes can be searched for and immediately reversed into plaintext.

For example*:

86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 a
e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 b
84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 c
...
948291f2d6da8e32b007d5270a0a5d094a455a02 ZZZZZX
151bfc7ba4995bfa22c723ebe7921b6ddc6961bc ZZZZZY
18f30f1ba4c62e2b460e693306b39a0de27d747c ZZZZZZ

Most tables also include a list of common passwords:

5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8 password
e38ad214943daad1d64c102faec29de4afe9da3d password1
b7a875fc1ea228b9061041b7cec4bd3c52ab3ce3 letmein
5cec175b165e3d5e62c9e13ce848ef6feac81bff qwerty123

*I'm using SHA-1 here as an example, but I'll explain why this is a bad idea later.

So, if my password hash is 9272d183efd235a6803f595e19616c348c275055, it would be exceedingly easy to search for it in a database and find out that the plaintext is bacon4. So, instead of spending a few hours cracking the hash (ok, in this case it'd be a few minutes on a decent GPU, but we'll talk about this later) you get the result instantly.

Obviously this is bad for security! So, we use a salt. A salt is a random unique token stored with each password. Let's say the salt is 5aP3v*4!1bN<x4i&3 and the hash is 9537340ced96de413e8534b542f38089c65edff3. Now your database of passwords is useless, because nobody has rainbow tables that include that hash. It's computationally infeasible to generate rainbow tables for every possible salt.

So now we've forced the bad guys to start cracking the hashes again. In this case, it'd be pretty easy to crack since I used a bad password, but it's still better than him being able to look it up in a tenth of a second!

Now, since the goal of the salt is only to prevent pre-generated databases from being created, it doesn't need to be encrypted or obscured in the database. You can store it in plaintext. The goal is to force the attacker to have to crack the hashes once he gets the database, instead of being able to just look them all up in a rainbow table.

However, there is one caveat. If the attacker can quietly access a salt before breaking into your database, e.g. through some script that offers the salt to anyone who asks for it, he can produce a rainbow table for that salt as easily as he could if there wasn't one. This means that he could silently take your admin account's salt and produce a nice big rainbow table, then hack into your database and immediately log in as an admin. This gives you no time to spot that a breach has occurred, and no time to take action to prevent damage, e.g. change the admin password / lock privileged accounts. This doesn't mean you should obscure your salts or attempt to encrypt them, it just means you should design your system such that the only way they can get at the salts is by breaking into the database.

One other idea to consider is a pepper. A pepper is a second salt which is constant between individual passwords, but not stored in the database. We might implement it as H(salt + password + pepper), or KDF(password + pepper, salt) for a key-derivation function - we'll talk about those later. Such a value might be stored in the code. This means that the attacker has to have access to both the database and the sourcecode (or webapp binaries in the case of ASP .NET, CGI, etc.) in order to attempt to crack the hashes. This idea should only be used to supplement other security measures. A pepper is useful when you're worried about SQL injection attacks, where the attacker only has access to the database, but this model is (slowly) becoming less common as people move to parameterized queries. You are using parameterized queries, right? Some argue that a pepper constitutes security through obscurity, since you're only obscuring the pepper, which is somewhat true, but it's not to say that the idea is without merit.

Now we're at a situation where the attacker can brute-force each individual password hash, but can no longer search for all the hashes in a rainbow table and recover plaintext passwords immediately. So, how do we prevent brute-force attacks now?

Modern graphics cards include GPUs with hundreds of cores. Each core is very good at mathematics, but not very good at decision making. It can perform billions of calculations per second, but it's pretty awful at doing operations that require complex branching. Cryptographic hash algorithms fit into the first type of computation. As such, frameworks such as OpenCL and CUDA can be leveraged in order to massively accelerate the operation of hash algorithms. Run oclHashcat with a decent graphics card and you can compute an excess of 10,000,000,000 MD5 hashes per second. SHA-1 isn't much slower, either. There are people out there with dedicated GPU cracking rigs containing 6 or more top-end graphics cards, resulting in a cracking rate of over 50 billion hashes per second for MD5. Let me put that in context: such a system can brute force an 8 character alphanumeric password in less than 4 minutes.

Clearly hashes like MD5 and SHA-1 are way too fast for this kind of situation. One approach to this is to perform thousands of iterations of a cryptographic hash algorithm:

hash = H(H(H(H(H(H(H(H(H(H(H(H(H(H(H(...H(password + salt) + salt) + salt) ... )

This slows down the hash computation, but isn't perfect. Some advocate using SHA-2 family hashes, but this doesn't provide much extra security. A more solid approach is to use a key derivation function with a work factor. These functions take a password, a salt and a work factor. The work factor is a way to scale the speed of the algorithm against your hardware and security requirements:

hash = KDF(password, salt, workFactor)

The two most popular KDFs are PBKDF2 and bcrypt. PBKDF2 works by performing iterations of a keyed HMAC (though it can use block ciphers) and bcrypt works by computing and combining a large number of ciphertext blocks from the Blowfish block cipher. Both do roughly the same job. A newer variant of bcrypt called scrypt works on the same principle, but introduces a memory-hard operation that makes cracking on GPUs and FPGA-farms completely infeasible, due to memory bandwidth restrictions.


Update: As of January 2017, the state-of-the-art hashing algorithm of choice is Argon2, which won the Password Hashing Competition.


Hopefully this gives you a nice overview of the problems we face when storing passwords, and answers your question about salt storage. I highly recommend checking out the "links of interest" at the bottom of Jacco's answer for further reading, as well as these links:

Polynomial
  • 132,208
  • 43
  • 298
  • 379
  • 19
    +1, Amen. I whish we where able to create an index/directory that points to the good answers to common/popular questions such this one. Even more so, because the common/popular questions regulary also attract quite insecure answers. – Jacco Jul 21 '12 at 09:04
  • 1
    I was reading about [Scrypt](http://en.wikipedia.org/wiki/Scrypt) the other day, which is a KDF which aims to be more computationally expensive than Bcrypt and PBKDF2. It may be another option worth considering. – Garrett Albright Jul 21 '12 at 23:24
  • @GarrettAlbright I mentioned scrypt in the second-to-last paragraph. The only downside with Scrypt is that there aren't as many libraries available, and there hasn't been much study of it. Right now I'd suggest bcrypt, since FPGA-based cracking engines are not a security concern for most people, but when scrypt has been studied carefully by a few cryptographers I'd be happy to tell people to use it instead. – Polynomial Jul 22 '12 at 08:01
  • Also have a look at https://wiki.mozilla.org/Identity/CryptoIdeas/01-PBKDF-scrypt – noob Jul 24 '12 at 19:43
  • 2
    @Polynomial maybe also add a link to http://stackoverflow.com/questions/1645161/salt-generation-and-open-source-software/1645190#1645190 ? – Jacco Oct 26 '12 at 12:14
  • +1 for linking to **Links of interest** section of @Jacco's answer. – MC Emperor Dec 18 '12 at 19:11
  • However, if you implement factor such as sms code then you could even store your passwords in cleartext.. because they still got to go through the sms code. – code ninja Feb 04 '14 at 19:40
  • @matejkramny No. The primary issue is that users will ALWAYS re-use their passwords for other sites. You have a duty of care to protect any passwords given to you. – Polynomial Feb 05 '14 at 01:31
  • What is the reason to always add the salt again when re-hashing the password? – cooky451 Jul 09 '14 at 17:49
  • @cooky451 I'm not sure what you're asking, but I suggest creating a new question. – Polynomial Jul 09 '14 at 21:08
  • bcrypt also happens to be the easiest to use from a programmer's perspective. You don't even have to come up with a salt yourself because the crypto library will do it for you, since the output includes the salt (it's in the form `$$$<22 character salt><31 character hash>`). So all the information that is needed is stored in what you can think of as the hash. Doesn't get easier than this (while still being highly secure). – Kat Dec 09 '15 at 19:18
  • 22
    Just for emphasis: Make sure you use a ***different*** salt for each password! If you use the same salt for every password, the computational complexity of the brute force algorithm is significantly reduced. Furthermore, an attacker could see which users use the same password just by comparing the hashes, which could have a deanonymizing effect on users who reuse passwords across multiple accounts. – user1354557 Jun 15 '16 at 15:06
  • Bouncycastle has a scrypt implementation. – Chamila Wijayarathna Mar 01 '17 at 00:19
  • 3
    Really good answer. But you still didn't answer the question "where do I store the random salt"? You need that random salt to check if the entered password is correct... am I wrong? – Kellen Stuart Jan 09 '18 at 21:18
  • "This means that the attacker has to have access to both the database and the sourcecode" - not true for that last part. In many (if not most) cases strings are not encrypted. A hacker can easily load an executable in a hex editor and see most of the strings. They can also step through the assembly code to read values as well. In many cases source code is not required, and thus any salt and pepper value stored/calculated on the client side (i.e. desktop app) is not impossible; just hard. ;) Don't store them in plain text. Obfuscate these types of strings to make finding it harder. – James Wilkins Jan 10 '19 at 21:35
  • @JamesWilkins Yes, I was thinking of PHP/Python web applications when I wrote this. I'll edit to reflect the more diverse case where the web app is a .NET or CGI binary. – Polynomial Jan 10 '19 at 23:53
  • 2
    –1 — too much text, and doesn't actually answer the question on where to store salt (although I stopped reading midway due to the text being irrelevant to the actual question) – cnst May 23 '19 at 07:37
91

A salt is not meant to be secret, instead, a salt 'works' by making sure the hash result unique to each used instance. This is done by picking a different random salt value for each computed hash.

The intention of the salt is not compromised when it is known; the attacker still needs to attack each hash separately. Therefore, you can simply store the salt alongside the hashed password.

Links of interest:
How to securely hash passwords?
Password Hashing add salt + pepper or is salt enough?
Salt Generation and open source software

Jacco
  • 7,402
  • 4
  • 32
  • 53
  • 12
    Keep in mind that if the salt is leaked (e.g. through a flaw in your code) the attacker can build a rainbow table for that salt ahead of time. This makes it difficult for you to take preventative measures if someone steals your hashes later, because they can immediately crack the password (they already have the rainbow table!) and access the account. – Polynomial Jul 20 '12 at 07:51
  • 1
    @Polynomial You made a very good point. Perhaps you would like to write an answer that covers what you have stated? I'd certainly upvote it, and it is much easier to read that way. –  Jul 20 '12 at 13:17
  • @Terry Chia: Prepending is more common. – Piskvor left the building Jul 20 '12 at 13:41
  • 2
    Alongside the *hashed, salted, password*. – Zack Jun 28 '17 at 19:09
  • 1
    @Polynomial where do you store the salt then? It seems if the attacker finds the salt they can break into the database? – Kellen Stuart Jan 09 '18 at 21:19
44

The salt can and should be stored right next to the salted and hashed password. Additionally, the salt should be unique per password.

Its purpose is to make it unfeasible to attack a leaked password database by using precomputed tables of password-hash-pairs.

That works because the salt only becomes known to the attacker as soon as he gets the actual (hardened) passwords; thereby rendering any precomputed attack impossible. (If you don't use a unique salt per password, but a global one, precomputed tables might still be used - although they would have to be precomputed specifically for your application's salt.)

When you store the salt somewhere else than right next to the password, you might gain some additional security, but it almost defeats the purpose: Every time you want to validate a password, you need both the salt and the hashed password, so they have to be very "close" (in an arichtectural sense) anyway.

chao-mu
  • 2,801
  • 18
  • 22
lxgr
  • 4,094
  • 3
  • 28
  • 37
18

Storing your salts separately offers some extra security, but not much - after all, the database should be the best protected place of the application, so if the attacker has access to the database, chances are he has access to any other data. On the other hand, you need a different salt for each user, which means you need a lot of salt - it is just not feasible to store it outside the database.

There is a practice of using a second piece of salt (sometimes called pepper) which is the same for all users, and storing it outside the database (maybe in an environment variable, or some sort of configuration file), so the attacker does not get access to it with a simple SQL injection. This adds some security, but as said above, don't expect too much from it, and use bcrypt or some other slow hashing method to defend against stolen salts.

Tgr
  • 668
  • 3
  • 11
5

I'd like to turn your attention to an interesting article on this of the title Storing Passwords Securely

TL;DR

The author in the article explains salting and pepper. Also, he/she argues that actually you do not want to use a cryptography hashing function for storing passwords. The two main traits of a hash are that

  1. it should be one-way and.
  2. it should be cheap to compute.

Obviouslty these requirements go against each other. So a compromise is made. You do not want the attacker to be able to compute their brute-force tries cheaply. Therefore, for better security, you actually need a Key Derivation Function, something that is one-way and which takes longer to compute (eg. 0.1 s).

There are schemes/implementations how to do this, so called Adaptive Key Derivation Functions that are well studied and deemed secure (author names three: PBKDF2, bcrypt, scrypt)

user7610
  • 217
  • 1
  • 9
  • 6
    At this point your answer hasn't really bought anything to the table, so you should probably have just linked the article in a comment. It's a nice article though - very thorough and covers all the bases. I'll keep a bookmark for future reference! – Polynomial Jul 20 '12 at 16:01
  • Nice article! As far as I know, PBKDF2 is an Adaptive Key Derivation Function, but BCrypt and SCrypt are not; they are adaptive cost hashing algorithms. (The difference is subtle, but real). – Jacco Jul 21 '12 at 08:56
  • Polynomial: You are right. I was so eager to post the article (I had it in my bookmarks and got excited that its time finally came) that I just skimmed over your answer and completely missed the last paragraph. Sorry – user7610 Sep 12 '12 at 13:28
1

I have seen PBKDF2 from many companies. And they are normally formed like $variant$cost factor$22 character salt$31 character hash as @Kat commented. So they are just stored in one place.

Salt and Password can be stored together because every random salt is different and that makes attacker to brute force each password. So rainbow table also need to be created again for each salt. Same password need to be brute forced each time as well.

Hashing password is just small part of security. Every service should ask users to change their password every year or few month. Or every service should use OAuth 2.0. And best practice is using the service that is already providing best security.

-6

Well you do separate hash from salt in two different boxes - I hope you understand the correct answer. And make sure you have same amount of both, like 256bit salt, 256bit hash, you can increase security if using simple isolated salt server.

Andrew Smith
  • 1
  • 1
  • 6
  • 19