How can I vendorize bcrypt in a PHP application (a

2019-02-22 04:10发布

问题:

I am contributing to a relatively mature open-source PHP project. Recently, I discovered that it stores passwords as plain MD5 hashes, which is quite bothersome to me. I figured that if I was going to fix it, I might as well Do It Right(tm), so I wanted to use bcrypt.

First, what I have found for other languages: bcrypt-ruby appears to use either the original C code from OpenBSD or jBCrypt's java code. py-bcrypt is a thin wrapper around the BSD code. BCrypt.net is a direct port of jBCrypt.

Now, PHP itself supports bcrypt (albeit, misleadingly called simply 'blowfish') in the crypt function. However, versions prior to 5.3 require support on the system itself, generally provided by crypt_blowfish. phpass is the same, and recommends installing either PHP 5.3 or Suhosin.

Since many users of the application use standard shared hosting, I don't want to require any special configuration of the server. I was hoping to just steal the code from PHP's 5.3 release, but it is in C, and (from the small bit of reading I've just done) I cannot require the use of a C-extension for the project's users.

I thought of just creating a pure-PHP port of bcrypt, but looking at the source of jBCrypt, I am not sure that I should, given that I'm not incredibly familiar with either PHP or blowfish, and a mistake here could be simultaneously dangerous and difficult to detect in the first place.

So, I present to you two (multipart) questions:

  1. Is my lack of PHP knowledge getting the best of me? Can I really use one of the already-created implementations?
  2. Should I instead just create a simple loooping function that calls sha1() or md5() repeatedly for some configurable number of times?

回答1:

Is my lack of PHP knowledge getting the best of me? Can I really use one of the already-created implementations?

Unfortunately, you are correct. Prior to 5.3.0 PHP didn't support bcrypt by default. Instead, it relied on the OS's support (check the CRYPT_BLOWFISH constant). As you've pointed out Suhosin is an option in that case.

Should I instead just create a simple loooping function that calls sha1() or md5() repeatedly for some configurable number of times?

The best advice when it comes to cryptography is "don't roll your own." Repeated calls to sha1() or md5() may or may not increase security.

The authors of bcrypt on the other hand explain their design decisions on this paper.



回答2:

Unfortunately you can't use bcrypt with Blowfish unless you're on PHP 5.3 or using the Suhosin extension or possibly that the operating system has support for Blowfish in its bcrypt implementation.

So your best bet in this case would be to use SHA-256 or SHA-512 with key stretching (and of course, salt). But rolling your own solution is never a good idea when it comes to security.



回答3:

One of the benefits of phpass that you didn't touch upon was that it automatically falls back to using DES and finally MD5 as an underlying cipher if CRYPT_BLOWFISH is not available. The wrapper uses these in such a way that even the md5 implementation is significantly more secure than a simple hash.