1

I've been reading a bunch of stuff about security and I'm just now starting to try and play around with the code. I want to use MD5 encryption with a salt. I ran across this nifty PHP script with random salt:

substr(str_shuffle(str_repeat('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',5)),0,10);

It randomly generates some characters as salt, but then I was thinking: How would I go about checking logins? Do I remove the salt, or should I store it in the database?

user229044
  • 232,980
  • 40
  • 330
  • 338
Howdy_McGee
  • 10,422
  • 29
  • 111
  • 186
  • 4
    MD5 is absolutely broken for password hashing purposes, regardless of salt. Use a dedicated library like [phpass](http://www.openwall.com/phpass/). – user229044 Aug 12 '11 at 18:16
  • 1
    @Buddy SHA512 is also a poor choice for password hashing. – user229044 Aug 12 '11 at 18:16
  • @Buddy SQL Injection and PDO aren't relevant to anything in this question... – user229044 Aug 12 '11 at 18:25
  • @Buddy That makes no sense. PDO prevents SQL injection, and using a library like phpass to hash passwords prevents passwords from being compromised. But your sentence seems to imply that using PDO for preventing SQL injection is somehow related to hashing passwords. – Jared Ng Aug 12 '11 at 18:27
  • 1
    PDO does not prevent SQL injection. Prepared statements do (and only if used correctly). – Mchl Aug 12 '11 at 18:32
  • @Mchl Sorry, I was generalizing too much. You're absolutely right. – Jared Ng Aug 12 '11 at 18:36
  • No need to be sorry. People say this all the time (just look at comments above), and I always try to correct them. – Mchl Aug 12 '11 at 18:43
  • I just trying to say that people often do unnecessary things with hashes and think that will help improve security. You can still see absurd things like `base64_encode(md5(sha1(crc32($string))))`. – Buddy Aug 12 '11 at 18:48
  • @meagar first comment, I would think that getting a dedicated library would depend on your system, but I do not think that is for this purpose. Thanks though. – Howdy_McGee Aug 12 '11 at 18:49
  • @Howdy The library I linked you to will almost certainly work for your platform (note the giant bold word **portable** in the title), and it's absolutely applicable. Whatever password hashing scheme you come up with, it is *guaranteed* to be less secure than simply using phpass. – user229044 Aug 12 '11 at 19:15
  • 1
    I don't know, I personally do not trust anything that can be decrypt. – Howdy_McGee Aug 12 '11 at 19:36
  • Those algorithms cannot be decrypted. They do use cyphers, but both the plaintext to encrypt and the encryption key are derived from the given password; therefore they cannot be decrypted. – Blaisorblade Aug 12 '11 at 22:18

5 Answers5

6

You shouldn't be using MD5 for password hashing. See How can I store my users' passwords safely?

To answer your original question, the salt is stored alongside the HASHED password in the database. The salt is not meant to be secret if the hashed password is discovered. Its purpose is to prevent attackers from using rainbow tables.

Community
  • 1
  • 1
Jared Ng
  • 4,891
  • 2
  • 19
  • 18
4

Store it in database. Otherwise you can't compare password provided by user with hashed one.

Some even regenerate hash (with new salt) upon each successful login of given user, although commenters below argue this is not the best idea (see comments)

Mchl
  • 61,444
  • 9
  • 118
  • 120
  • Dittoed. That is the common practice. – Jeremy Holovacs Aug 12 '11 at 18:14
  • 3
    @Mchi, regenerating the hash on each login seems like a terrible idea. The point of the salt is to mandate a brute-force attack by minimizing the information available to the attacker. If the attacker has access to the DB and can watch it over time, then regenerating the hash with a new salt after each login can only add to the information available to the attacker; if the hacker doesn't have such access, then regeneration is completely pointless. – Richard Aug 12 '11 at 18:25
  • Regenrating hash on each login always seemed a bit overkill for me, but I never considered it this way. Thanks for the insight. – Mchl Aug 12 '11 at 18:30
  • 1
    Agreed; regenerating the salt on login *only* weakens the system. There is demonstrably no benefit. – user229044 Aug 12 '11 at 18:32
2

Okay, so salts are used for both one-way hashes and encryption. They make it harder to reverse the encryption or the hash. I think it's easier to draw the point out with hashes, so I'll write from that point of view, but the principles apply to encryption in general.

Imagine that you're saving passwords. One of your users chooses the word "kiwi" as a password. Because storing passwords in plain-text is stupid, you don't want to do that. You want to hash the password.

But, those pesky hackers out there have compiled huge databases of hash look-up tables. (Check this one out!)

So, how do we foil the hackers? By salting the user's input! The salt is a random string (or set of bits, properly) that is cryptographically combined with the user's input to produce a more secure hash.

For example, if the string to be hashed is still "kiwi" and our salt is "5m3d", a simple salt mechanism might concatenate the two into: "kiwi5m3d". The hackers probably have "kiwi" in their database, but probably don't have "kiwi5m3d". A good salting system will probably perform a much more complicated function than this.

So now the hackers need a new look-up database for each possible salt. Using a random salt means that the hacker will have to do a full-on brute force attack, rather than recycling previous computations or using someone else's look-up table.

You could choose a different salt for everything, or the same salt for all the things on your site. A different salt of each entity necessitates a new brute force attack for each entity, but it can make implementation more difficult because each salt must be saved, rather than having one global salt (which, for data which is already somewhat random, e.g. passwords, should be sufficient).

In the case of encryption, look-up tables are still a possibility, but the data to be encrypted is generally varied enough that they're not feasible. So it becomes a game of playing "guess the password". It's easy to guess "kiwi" and hard to guess "kiwi5m3d".

You will have to save the salt somewhere, because it's the only way to "know" what's been hashed or encrypted. In the case of a hashed, you compare the user's original hash against the salted hash of their input. In the case of encryption, you need the salt to decrypt the data.

Where do you go from here? First, don't use MD5. I gave you a link to an MD5 look-up database above. The function's increasingly considered to be weak. The sha class of algorithms is a better choice.

Second, make sure you choose a good salt. Longer and randomer is better. Computers are kind of bad at generating random data. This site could be one good choice and has a pretty good break-down of how it generates its random numbers.

Third, consider salt algorithms. Simple concatenation should work, but maybe HMAC (something I don't know much about) would be better.

Richard
  • 56,349
  • 34
  • 180
  • 251
  • @meagar, the principle of salting applies to both hashing and to encryption. The last paragraph makes that difference explicit. You compare hashes, because they can't be decrypted. Or, if you are working with encrypted data, you can decrypt the data. – Richard Aug 12 '11 at 18:32
  • @meagar, give me a moment, I'm cleaning it now. – Richard Aug 12 '11 at 18:34
1

You would have to store it in the database, otherwise you would not have anything to compare it to. The thing to remember with using a salt, is that the complexity can vary and without knowing what the salt is, the likelihood of it being brute forced hack is dramtically decreased.

Example:

$password = "banana";
$salt = "a12dsfg33B1cD2eF3G"; # Can be any assortment of characters
$password = md5($salt.$password);

Then you would just attach the same salt (would have to match to work) and pass the same function to your login script that combines the salt and the supplied password. You would then check that to the value in your database to authenticate the user.

Robert
  • 8,717
  • 2
  • 27
  • 34
  • A salt is a random value (if it is not random, it's called a key). And there is no need for the salt to be secret. – Jacco Aug 17 '11 at 08:33
1

Do not invent your own password-hashing scheme, however nifty it may look. Having a secure system is hard because you cannot really test for security. What you need is the following:

  • For each password instance, a random salt of sufficient length is created.
  • The random salt is stored along the hashed value; you will need it to verify the password afterward.
  • The password hashing process must be (configurably) slow, with many (many) nested invocation of whatever hash function is internally used.
  • Preferably, the internal hash function should use operations which are efficient on a PC but slow on a parallel architecture (a GPU).

Such a thing exists, it is called bcrypt and you can get it in PHP with the portable PHP password hashing framework.

Thomas Pornin
  • 72,986
  • 14
  • 147
  • 189