9

When users register on my site, I want to store their username and hashed password in my database. When I hash that password, I'm going to salt it using PHP.

The issue is, I don't want to store the salt in a database that could be compromised - that defeats the purpose of salting, doesn't it?

Instead, I want to have a unique salt per user that is stored on a separate server - say, a cloud platform?

Is this safe/the right way to go?

TildalWave
  • 10,801
  • 11
  • 46
  • 85
Prinsig
  • 214
  • 1
  • 6
  • 8
    Just use the new [secure hashing API](https://gist.github.com/nikic/3707231) in PHP 5.5. Please don't try and be creative, especially when you don't have a solid grasp of the problem space. – Stephen Touset Oct 22 '14 at 16:58
  • 1
    "The issue is, I don't want to store the salt in a database that could be compromised - that defeats the purpose of salting, doesn't it?" Nope, the purpose is to add to the amount of work that a bruteforce attack must do. It isn't even a secret you can tell your users what their salt is, but that would just be dumb. – Andrew Hoffman Oct 22 '14 at 18:49
  • 1
    How about not storing the password hash in a database that could be compromised? – Question Overflow Oct 23 '14 at 02:04
  • @QuestionOverflow I think it's foolhardy to believe we can protect a database _completely_ from compromise. My question here was aimed at minimizing the damage of such an event. – Prinsig Oct 23 '14 at 08:08

5 Answers5

28

It is not a problem if the attacker learns the salts. Salts are not meant to be secret. What is important for a salt is that it is unique for each hashed password instance (i.e. not only a unique salt per user, but the user's salt must be changed when the user changes his password).

If you think of your salt as something that may be shared between passwords, but must not be known to the attacker, then that is not a salt; that's a key. Some people call such keys "pepper" in the case of password hashing. This is a concept quite distinct from salts, and, generally speaking, it adds complexity and increases failure frequency without really improving security. Get the basics right first (i.e. using the right function with proper salts).

The normal method is to store the salt along with the hash value. Preferably, you let the password hashing library generate the salt and handle the encoding of the salt and hash value as a single string. So you make sure that you use PHP 5.5 (or newer), and you use password_hash() (and don't use the manual salt setting; the library does the right thing by default, so just let it do it). Among possible password hashing functions, bcrypt is about the best you can have right now, and that's what password_hash() will use.

Tom Leek
  • 170,038
  • 29
  • 342
  • 480
  • Can you explain why a pepper would increase failure, and not improve security? – XaolingBao Jun 03 '16 at 13:34
  • The pepper increases security only in attack contexts where the attacker can obtained the hashed passwords, but not the pepper itself. This _may_ happen (e.g. SQL injection that retrieves hashed passwords but not the server configuration) but is comparatively rare with regards to overall server hijacking. As for failures: the pepper is one extra parameter that must not be lost when upgrading software, moving to another node, or restoring from backups (lost pepper implies loss of password verification). – Tom Leek Jun 03 '16 at 14:13
  • It makes sense about 1 extra DB needed to be maintained and hopefully as secure as the main one, but if they hijack your server, is there 100% access to your code? There should be certain protections put in place so that your code isn't readable. It's interesting because some people say that knowing the SALT, or Interations/Hashing algoirthm wont increase security, but imo anything that's added should present another risk to the attacker. Knowing the salt should allow a table to be created, even if it takes time to do so. Thanks for coming back to this so late, I appreciate your answers. – XaolingBao Jun 03 '16 at 14:44
  • "Unreadable code" is also known as _obfuscation_. It does not work well in practice. If you want some information (including code) that can still be kept out of reach of an attacker who completely hijacks the server, then you need an extra piece of hardware that remains impervious to such an hijack (the expensive version of which being called a HSM). – Tom Leek Jun 07 '16 at 12:52
5

My answer is going to differ than everyone else. Tom Leek, and Xander provided good insight, so here goes my response to your initial question, expanding from this comment of yours:

"I don't want to store the salt in a database that could be compromised - that defeats the purpose of salting, doesn't it?"

Yes, and no. If someone compromised your database, you have bigger things to worry about. The mere fact they got that far opens up the potential for sniffing on the wire, where if encryption is not used, data is visible before being encrypted and shoved into a database.

Salts protect because they add a layer to counter cracking. A cracker needs to hash a password AND a salt in order to produce something to compare to a known hash to find the right password. Most salting changes, otherwise if this occurred, salting would be useless:

User1 (password) [ kitten + your_static_salt = thundercat ]
User2 (password) [ kitten + your_static_salt = thundercat ]

In the above theatrics, two users have chosen the word "kitten" as their password which is salted to produce the outcome of "thundercat." If this held true, the salting portion is sort of useless. If you're using password_hash from PHP the salt is randomly generated for you, the outcome would be the following (of course minimized for clarity):

User1 (password) [ kitten + password_hash = thundercat ]
User2 (password) [ kitten + password_hash = uppercut ]

In the above, we see same password, PHP's password_hash changes the salt every time. No need to reinvent any wheels here as you'd need to do some deep dives into crypt() to understand it. If you're really that concerned with salting, and password security, have a look at Solar Designer's phpass, however when you state you're worried about someone compromising the db itself, this changes the scope of what an attacker could do without even needing to crack passwords to begin with.

munkeyoto
  • 8,682
  • 16
  • 31
4

It would add complexity without adding much value.

It does not defeat the purpose of salting, as you feat, because a salt is not intended to be secret, just unique. The goal is not to make it impossible to figure out the password from the hash, but to make it impossible to pre-compute hashes that can then be directly compared with yours to see if any match, and to ensure that identical passwords result in different hashes.

So, to attempt to keep the salt separate and secret is not part of the design of the construction, and you would be better off using the development time and resources to harden and protect your application and database from compromise in the first place.

Xander
  • 35,616
  • 27
  • 114
  • 141
3

It's not necessary.

Think about it this way...

If your server has access to the salts and an attacker gets root on your server, he would get access to your "remotely stored salts" wherever they were located as well.

Since you're using PHP, check out the password_hash and password_verify functions.

darkAsPitch
  • 613
  • 5
  • 9
2

No, don't do that.

First: salts are not secret. They are used to make sure that reversing the hash for one password does not reveals all the copies of that password on your database. It is used to make reversing the hash more difficult.

Second: it will increase latency. Your authentication system will have to get the username and the password from the user, access a database, get the userid, ask a remote server for a salt for that userid, compute and decide if the user has the correct password or not.

Third: your script will have the credentials to access the salt database. If someone breaks into your system, they will be able to access that database as well. Even if they cannot access the database directly, they will have access to the userid database, will iterate through all userids, and get all the data from the salt database.

And all this downsides will not get you any extra security, it will not be even marginally better.

Cryptography is a solved problem. Lots and lots of expert cryptographers have already defined the best way to encrypt and hash information. Just follow the guidelines and you will be safe.

ThoriumBR
  • 51,983
  • 13
  • 131
  • 149