2

This whole cryptology thing is a lot to swallow, but it's really interesting and I've been reading about it lately.

My question is about using blowfish to hash your passwords for storage. I know a salt is needed, but I'm not exactly sure what to do for it. I have some questions.

  1. Many tutorials I read people just seemingly randomly come up with one like "oidsjf03" and use it for all their salts. Do they just mash their keyboard or what?

  2. I've also read a lot that says each password should have a unique hash. So I generate a separate salt for each password I store. Then I'd have to store that somewhere. Where, however? If I just store it as an entry in the user's row, if the database was compromised could they not just generate rainbow tables with that salt?

    Would I be correct in saying this isn't viable, as they'd need to generate a rainbow table for every password, and with blowfish creating each hash would take awhile, so this wouldn't be practical?

  3. Why is having a unique one for each user so important? Say you're using blowfish and your database is compromised, and your salt gets captured as well. The hacker could create a rainbow table to test your passwords, but with a good amount of rounds on the hash, it may take 0.1 seconds per password, for instance. If they want to create a rainbow table with 1 billion entries, that's 100 million seconds to create it (or around 3 years).

    If you used unique salts and had say 1000 passwords, they'd have to create 1000 rainbow tables, increasing the amount of time to 3000 years. Is this why? The amount of time goes up per password stored?

  4. How do you generate this salt for the hash? Is PHP's uniqid() function enough or should I be doing some fancy stuff?

  5. Do I really need to create a full out class et al, or can I create a simple function?

  6. Lastly, I've heard phpass mentioned a lot for its security and how users should just use that instead of potentially making errors themselves. Is this really the recommended practice?

halfer
  • 19,824
  • 17
  • 99
  • 186
Doug Smith
  • 29,668
  • 57
  • 204
  • 388
  • 1
    Re: #3, the reason salt should be separate per-user is so that if multiple users use the same password ("secret1") they won't have the same hash - an attacker can't tell they're all using the same password, they'll have to crack each one individually. And re: #6, YES. It is a fundamental rule of Security that you're better off using code that someone else wrote and many else's have tested than to do it from scratch and repeat their mistakes. – gowenfawr Feb 20 '13 at 23:17
  • And read http://security.stackexchange.com/questions/211/how-to-securely-hash-passwords – Michael Berkowski Feb 20 '13 at 23:19

2 Answers2

4

1- Many tutorials I read people just seemingly randomly come up with one like "oidsjf03" and use it for all their salts. Do they just mash their keyboard or what?

Using the same salt for everything is a bad idea. Period.

2- I've also read a lot that says each password should have a unique hash. So I generate a separate salt for each password I store. Then I'd have to store that somewhere. Where, however? If I just store it as an entry in the user's row, if the database was compromised could they not just generate rainbow tables with that salt?

The salt is part of the hash. Rainbow tables only work when you have multiple users with the same salt. But they are all unique, right? So storing it with the hash is fine. Same goes for #3.

4- How do you generate this salt for the hash? Is PHP's uniqid() function enough or should I be doing some fancy stuff?

As of PHP 5.5, password hashing functions have been built directly into PHP. In the meantime, see the aforementioned link and in the comments is a link to a Github project that is forward compatible with these functions and available for PHP >= 5.3.7.

6- Lastly, I've heard phpass mentioned a lot for its security and how users should just use that instead of potentially making errors themselves. Is this really the recommended practice?

The built-in PHP functions are better because they will always be kept up-to-date should any security vulnerability become known. I would use them instead. However phpass is a very good alternative.

Mike
  • 23,542
  • 14
  • 76
  • 87
  • I too have been reading a lot about it. Here is an old post from SO: http://stackoverflow.com/questions/4795385/how-do-you-use-bcrypt-for-hashing-passwords-in-php. As shown in Jon Hulka's answer, you can randomize the salt every time you compare encryptions. – Sablefoste Feb 20 '13 at 23:29
0

In addition to above answer you can save salt with hash in DB brcause if your DB was compromised attaker needs to know your salt algorithm. Like hash($pass.$salt) or hash(hash($pass).$salt) etc.

Yaroslav
  • 2,338
  • 26
  • 37
  • I'm using blowfish, so I'd only need to hash it once, so to speak. But isn't the amount of times hashed in the hashed password? $2x$07 or whatever, 7 being the hash amount. – Doug Smith Feb 20 '13 at 23:45
  • I actually disagree with this point. In order to verify a password against a hash, you *need* to rehash the password using exactly the same parameters. Therefore everything needs to be stored, including the algorithm used, salt, number of rounds, etc. If you are using `crypt`, everything is stored right in the computed string (the algorithm, the cost parameter, the salt and the actual hashed string). The secret is to use enough rounds/cost that it would take an infeasibly long time to brute force it, but unnoticeably short to the end user (e.g. ~250 ms). – Mike Feb 21 '13 at 01:50
  • @DougSmith it is preferable to use `$2y$`, not `$2x$`. And yes, the `07` part is the two-digit cost parameter, which has to be between `04` and `31`. The idea is to keep this is high as possible without being an inconvenience to your users. This will, of course, depend on the hardware it is being calculated on. I currently have mine set to `12` and it takes around 250 ms to calculate, but if your server is less powerful, you might want to set it to `10` or `11` or more if it is more powerful or if you would prefer to have it take longer to calculate the hashes. – Mike Feb 21 '13 at 01:58
  • @Mike I'm just talking about even if DB was stolen (with hashes and salts) stole programm files somethig harder usually. So hash algorithm and its parameters remains unknown to attaker. Therefore we don't need to keep salts more secure than passwords or in different place. – Yaroslav Feb 26 '13 at 11:59
  • @Yaroslav, I think it's a fair assumption to make that if someone is able to steal your database files, they are very likely to also have access to your program's source code. However even if they don't, there is one huge problem with this - if your hashing parameters are stored in the source code, you are then locked in to only using those parameters forever. You may some day upgrade your server hardware and decide that instead of doing `$2y$10$` you can now do `$2y$13$`, but you won't be able to because the parameters aren't stored in the hash, but in your program's source code. – Mike Feb 26 '13 at 19:16
  • @Yaroslav not to mention that it seems like you might be trying to invent your own type of hash algorithm. It's always better stick to an accepted and tested algorithm than some `hash(hash($salt.hash($salt.$pass).hash($salt)))` sort of thing you can think up on your own. Something like this could be absolutely atrocious with collisions, but you will never know because it "works", so you assume it's also secure. This is merely security by obscurity. Don't do that. – Mike Feb 26 '13 at 19:21