6

I am working on a script and need to save passwords. For development purposes, I have been using the crypt() function because it was easy and available. Now that I am mostly done, I want to replace it with something a little better and more consistent.

Some of the concerns I have are:

  • not all algorithms are supported on every system
  • sometimes the salt is pre-pended to the result (seems like a security problem)

I want something that works with PHP 4.3+.

Is there anything available, or should I stick with crypt()? I thought about using md5(md5($password).$salt). Thanks for the insight.

steveo225
  • 11,394
  • 16
  • 62
  • 114
  • 5
    You want something "better than `crypt()`" and you're proposing double md5? – ceejayoz Dec 28 '11 at 22:57
  • I've worked on projects where md5 and sha1 were used (not together). More info on sha1: http://us.php.net/sha1 – Mike Purcell Dec 28 '11 at 22:58
  • your confusing encryption (2 way) with hashing (1 way) –  Dec 28 '11 at 22:59
  • 1
    The salt is prepended because without it, you can't use the same salt to hash a password you want to check. It's not a security problem; in fact, it has to be there if your hashes are uniquely salted (which they should be). – cHao Dec 28 '11 at 23:00
  • I don't know if [scrypt](http://www.tarsnap.com/scrypt.html) has been ported to PHP yet, but it is memory-hard. Which means that even high-end parallel computation systems will have a difficult time cracking any compromised digests efficiently. – cdhowie Dec 28 '11 at 23:02
  • @cHao: I have a known randomly generated salt for each user, so I do not need them remembered in the hash. – steveo225 Dec 28 '11 at 23:03
  • @steveo225: Consider that anyone who can get the hash, can also get the salt. You don't gain anything by storing them separately. – cHao Dec 28 '11 at 23:04
  • 3
    If you *ever* have to use PHP4 you or your bosses are doing something very, *very* wrong! – ThiefMaster Dec 28 '11 at 23:05
  • @cdhowie there is no scrypt implementation for PHP (I have looked), and also I would not use scrypt yet primarily because it is too young. – Petah Dec 28 '11 at 23:09
  • @cHao: I didn't say I was storing the salt either, how the salts are maintained in not of concern, but I don't need them in the hash itself – steveo225 Dec 28 '11 at 23:11
  • @cHao You might get something by storing them separately... if they are stored in two different database columns then you can authenticate a user entirely in the database without any complicated parsing. `... WHERE hashed_password = SHA1(SHA1(@password) || password_salt)` – cdhowie Dec 28 '11 at 23:12
  • @steveo: It's important if people knowing the salt is a security problem. If i can figure out the salt, then you have gained nothing by not having it in the hash. And if you're hashing per user, i can figure it out. – cHao Dec 28 '11 at 23:17
  • @cHao: What makes you think you could easily figure out the salt? That's why I don't want it in the hash... if it isn't known, isn't static, and isn't saved in the database, it is that much tougher to brute force the password. – steveo225 Dec 28 '11 at 23:26
  • @cdhowie: You've just sent the password, unhashed and quite possibly unencrypted, over the SQL connection. – cHao Dec 28 '11 at 23:27
  • @cHao: If the connection to the database server is not encrypted or at least on a private network (loopback included), there are more problems here. This can be mitigated somewhat by performing the initial SHA1 round in the application and passing that to the database. – cdhowie Dec 28 '11 at 23:31
  • 1
    @steveo: I can figure it out because you have to figure it out in order to authenticate the user. And if i have access to your database, then it's likely i own your server already. – cHao Dec 28 '11 at 23:33

2 Answers2

6

There is nothing wrong with crypt

If your server does not support it, use another server.

You should NEVER use MD5 for hashing passwords (or even SHA1 for that matter)

Use either bcrypt (the blowfish method of crypt) or pbkdf2

There is an implementation of pbkdf2 here: Encrypting Passwords with PHP for Storage Using the RSA PBKDF2 Standard

More information on why and how here:

Community
  • 1
  • 1
Petah
  • 45,477
  • 28
  • 157
  • 213
  • Problem is, I am trying to make this work for other users where I do not have control of their systems and not all crypt methods are available, in fact blowfish is not on mine, although it has sha512, whereas another server I play on is just the opposite. – steveo225 Dec 28 '11 at 23:05
  • @steveo225 well if you want to sacrifice security for portability, I'm sorry for your customers. – Petah Dec 28 '11 at 23:07
  • What is wrong with md5? I have seen many other known script systems use it, like vBulletin? – steveo225 Dec 28 '11 at 23:09
  • @steveo225: Just make it configureable with a good default value. In case on some system it does not exist, another algo can be used. Additionally make the whole authentication part configureable so it's possible to integrate your application into SSO systems. – hakre Dec 28 '11 at 23:09
  • @steveo225 on just our computers at my work, using CUDA I can crack ***1.5 billion*** MD5 passwords per second http://www.tomshardware.com/reviews/password-recovery-gpu,2945.html – Petah Dec 28 '11 at 23:11
  • @hakre: Luckily the system is configurable that way already, so users can override it to their liking. Its just in the setup script, I am having trouble getting all the rules in the event certain methods or functions don't exist. – steveo225 Dec 28 '11 at 23:19
  • Don't write a routine that will always works (then use PHPASS instead, it's made for that purpose, works on PHP 3 systems, too). Instead write a clean implementation (seriously, that part of your application is crucial) and in case some users can't have it, offer a way in your program to replace the whole function. – hakre Dec 28 '11 at 23:22
  • @hakre: I know how crucial it is, hence the question, I want something that is going to be as difficult as possible, but still useable by the users. And it is completely replaceable, there is an internal encrypt function (bad name since it hashes) that can be overridden or completely replaced, but I have to provide a default. – steveo225 Dec 28 '11 at 23:40
  • @Petah: You posted links to why PBKDF and bcrypt are strong solutions, but you stated "You should NEVER use MD5 for hashing passwords (or even SHA1 for that matter)", can you post a link or two describing why these hashing solutions should not be considered? – Mike Purcell Dec 28 '11 at 23:56
  • @DigitalPrecision The last link in the answer has some information on why SHA is weak (or rather too fast to be secure) and in the comments I posted a link to Tom's Hardware which has information on how fast weak hashing algorithms are bad – Petah Jan 10 '12 at 00:49
4

First of all: Prepending the salt is not a security problem. Having a per-password salt is a big goodie, and it's perfectly OK to it being store alongside the pw.

Now: As long as you don't transport password hashes from one system to another, and the latter not supporting the default algorithm of the first, nothing bad will happen by definition. Since PHP 5.3 there are built-in algorithms in PHP such as Blowfish, that are guaranteed to be available.

Eugen Rieck
  • 64,175
  • 10
  • 70
  • 92