3

I have read tons of questions and tutorials about encrypting a password, and while I've learned a lot, nowhere did I find an answer to this.

I want to use crypt() for hashing a password that I will store on Database. I also know I need to use a salt so it works properly, and I've read that the best way to generate a random salt is by using this or something similar.

If I understood correctly the process is this:

  1. User enters a password
  2. Random create a salt
  3. Hash password and salt
  4. Store result in database

But then how do I recover the salt when user tries to login?

  1. User enters his password
  2. I somehow add his own unique randomly generated salt
  3. Hash both of them together
  4. Compare it to hashed salted password stored in Database.

In a few questions I've found, one of the answers was to store the randomly generated salt on the database. But I thought the whole purpose of salting was to be more secure, if an attacker got access to my DB he would see the 'salt' fields and even if my passwords are encrypted he would gain easy access to accounts.

Other answers said that the 'salt' is prepended to the password when using crypt() so there is no need to store it in a separate field. My question is, how do I get access to it? Is there some function that does this and I'm totally missing?

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
Ant100
  • 403
  • 1
  • 8
  • 26
  • 2
    store salt in db, it does NOT decrees security doing this, septate or with password, your call, i have done both –  Jan 23 '14 at 20:25
  • @Dagon Doesn't it? Surely the point of a salt is to add some unknown into the hash, doesn't just putting the key right next to it make it useless? – Niet the Dark Absol Jan 23 '14 at 20:26
  • 1
    no salt stops rainbow table attacks, knowing the salt, you have to recreate an entire rainbow table with each salt –  Jan 23 '14 at 20:27
  • It doesn't? Okay, it's easier that way. I am curious about how to get the prepended salt from hashed password though. Do you know how to do this? – Ant100 Jan 23 '14 at 20:27
  • You don't get it from the hash, you store it in a separate field. – Digital Chris Jan 23 '14 at 20:28
  • 1
    PHP has a great password mechanism built in, that handles all this stuff for you (and gloms the hash and salt into a single field): http://www.php.net/manual/en/ref.password.php – Digital Chris Jan 23 '14 at 20:30
  • @DigitalChris you don't store the salt separately. If you're doing things right (see jterry's answer) it is stored right in the hash. – Mike Jan 23 '14 at 20:31
  • No, it's not "in" the hash, and that confuses many people. PHP's implementation just stores the hash and salt together in a single field, but it is just as appropriate to have a salt field. – Digital Chris Jan 23 '14 at 20:32
  • @DigitalChris if you store it separately, you're either not using the password hashing functions you referenced above, OR you're using some sort of string splitting thing to separate it. Either way whatever you're doing is prone to error. – Mike Jan 23 '14 at 20:33
  • @Mike I got lost, so what should I do? :S – Ant100 Jan 23 '14 at 20:34
  • I see what you're saying. Yes. there are two options: 1 is to let PHP handle salting for you. However, if you are using a standard password scheme, you would have a salt in a separate field; having a single field makes it "user friendly" and is part of the password_hash() magic. – Digital Chris Jan 23 '14 at 20:35
  • @DigitalChris as far as I know, PHP's implementation is based off Unix Crypt and the hashes are compatible with each other. Both will create a string with the hashing algorithm, the salt, and the actual hashed password all concatenated together. – Mike Jan 23 '14 at 20:41
  • 3
    Ant100 - if you're still unsure: since you're using an older PHP, use [PHPass](http://www.openwall.com/phpass/). If you upgrade you can use [password_hash()](http://www.php.net/manual/en/ref.password.php) – Digital Chris Jan 23 '14 at 20:42
  • In this [answer](http://stackoverflow.com/a/20399775/575765), i tried to explain, how the salt can be extracted from the hash-value. The crypt function will extract this automatically. – martinstoeckli Jan 23 '14 at 20:44
  • @Mike you're thinking of [crypt()](http://us2.php.net/crypt) which uses a separately-stored salt to decrypt. – Digital Chris Jan 23 '14 at 20:46
  • @DigitalChris password_hash() is based on [crypt](http://us2.php.net/crypt). Check out the code from ircmaxell's [compatibility library](https://github.com/ircmaxell/password_compat). – Mike Jan 23 '14 at 20:57
  • @Mike... yes... it based on crypt and uses crypt but adds NEW things like the unified hash/salt in one field and automatic salt generation. They are not the same. This has become fairly esoteric and not useful for Ant100 who just wants to implement a password scheme so this will be last comment here. – Digital Chris Jan 23 '14 at 21:15
  • thank you all for your help. At the end I decided to add a new field called 'salt' in database and stored salt there. I store it as a type binary(16), do you know what type should my hashed password be for mysql? – Ant100 Jan 23 '14 at 22:37
  • 2
    @Ant100, go with what jterry and DigitalChris say and use either password_hash or PHPass (links above). Don't roll your own password hashing mechanisms because you WILL get it wrong. Let people who are smarter than you and I handle it instead. You don't need to store the salt separately. It is contained within the output string. See [this question](http://stackoverflow.com/questions/5881169/storing-a-hashed-password-bcrypt-in-a-database-type-length-of-column) for how to store the whole thing in your database. – Mike Jan 24 '14 at 03:39
  • @Mike thank you, I will use PHPass! I'm actually checking it out, and looks quite simple to implement. One quick question though, nowhere does it ask me for a salt, so this means it is automatically implemented? -- Nevermind, just read it does. Awesome! – Ant100 Jan 24 '14 at 15:48

3 Answers3

4

You store the salt in your db, along with the hashed password, i.e. hash(salt+password).

If your database gets compromised and someone gets all the hashes and the salts, they cannot run a rainbow table attack against your hashes - they will need to brute force each hash. With a good hashing algorithm, the brute force attack is unfeasible.

What is a rainbow table attack?

Lets assume a generic hashing algorithm, hash(f).

I, as an attacker, precalculate common passwords (f) and their hashes (hash(f)). Now, when I get your unsalted database of hashes, I just need to look through your database for hashes that match my precalculated table (rainbow table).

For example, if my rainbow table stores that for f = qwerty, hash(f) = someRandomHash, I look through your database for someRandomHash and as soon as I find it, I know that user's password is qwerty.

However, if you salted your passwords, when a user set his password as qwerty, you calculated his hash as hash('saltqwerty), which means, you did not calculate his hash as someRandomHash but instead as someRandomSaltedHash. This renders my rainbow table completely useless.

I am left with no choice but to brute force your table. I know the salt, but I don't know the password, so I have to calculate hash(salt+password) for every possible permutation and combination of password. With a slow enough hashing algorithm, this can take centuries (worst case).

How do you login a user?

User submit his user_id and password. You query the database for the salt for that user. Then you compute hash(salt+password) and compare against the hash stored in your database.

Ayush
  • 41,754
  • 51
  • 164
  • 239
  • yes I hash both the salt and the password. But when user logins he will only type the password, how do I get the salt and add it? – Ant100 Jan 23 '14 at 20:29
  • Edited answer to explain that – Ayush Jan 23 '14 at 20:34
  • Thank you so much for the explanation! I will save salt in separate field then. Is crypt() a good enough hash? – Ant100 Jan 23 '14 at 20:43
  • That’s not a [rainbow table](http://en.wikipedia.org/wiki/Rainbow_table) but a simple [lookup table](http://en.wikipedia.org/wiki/Lookup_table). – Gumbo Jan 23 '14 at 21:24
  • @Gumbo: It is still a rainbow table, although highly inefficient (in space). From the wikipedia page: "The goal is to precompute a data structure that, given any output h of the hash function, can either locate an element p in P such that H(p) = h, or determine that there is no such p in P. The simplest way to do this is compute H(p) for all p in P". A lookup table would be an in-memory data structure such as an array, hashtable etc.. – Ayush Jan 24 '14 at 10:25
3

You can safely store a hashed password and a salt in the same database - the idea is that since the salt is different every time, even the exact same passwords will be stored differently in the database, which virtually eliminates brute-force lookup weaknesses associated with things like md5-encoded passwords.

Out of an obvious mass confusion, if you're able to use PHP v5.5.0 or higher, password storage has become remarkably easier with the use of password_hash and password_verify.

As an additional benefit, these functions don't require you to have separate password and salt fields in your database - you can simply store the returned password_hash value and use password_verify with the clear-text password to validate.

jterry
  • 6,209
  • 2
  • 30
  • 36
  • 2
    There is a compatibility library to make those functions available for php < 5.5 on the links above. – Mike Jan 23 '14 at 20:30
  • Thank you I did read about this, unfortunately I believe current project is using either PHP 5.2 or PHP 5.3 – Ant100 Jan 23 '14 at 20:31
  • 1
    Definitely check out the links on the PHP manual pages per @Mike's comment... they'll cover you for versions < `5.5.0`! – jterry Jan 23 '14 at 20:33
0

I don't know a lot about high level security DB, but how about this?:

hashedPassword = hash(UsurID+GivenPassword)

So, at logon time, youget first the User Login, and his ID, and then the given password to compare with the hashedPassword tha is already in DB. As I said, I dont know if this will increase security, but at least it makes all passwords differents, doesn't?

Anyway, I'm still learning too.

Jorge Santos
  • 51
  • 1
  • 5