Monday, August 13, 2012

Muddy Waters of Crypto

After doing quite a bit of searching on the Internet, I've come up no clearer on what the state of bcrypt is relative to alternatives.  Although I did find a couple of odd complaints, which I'll take first.



Complaints

bcrypt proponents want to put load on the server, only to mitigate a bug you shouldn't have.
A bug that seems to come up with distressing frequency in the wild.  If the last sql injection that hit the news was four years ago, then I'd be somewhat okay with this argument.  But since it was last week, against AAA game developer Blizzard, and earlier this year against linkedin... not so much.
bcrypt isn't NIST approved.
Neither, to my knowledge, are md5-crypt, or Drepper's sha256/512 crypts, and it's nigh certain that you're using one of them on your Linux system; to my knowledge, there is no PBKDF2 crypt() implementation.  Remember that secure building blocks do not guarantee a secure overall system, as has been noted in HDCPv2.
You can't do bcrypt in javascript on a mobile device.
I tracked down a javascript bcrypt implementation and ran it on my 4th-gen iPod Touch.  It does run noticeably slowly, clocking in between ie8 and ie9 speeds on my desktop.  I guess you shouldn't do bcrypt in javascript on the desktop either, then?

What you don't find

Actual cryptanalysis of any crypt() implementation other than DES.  (And mschap v2.  Quit using PPTP!)

Which we've known was broken since the 1990s, which is why we have md5, bcrypt, scrypt, sha*, and PBKDF2.  md5-crypt is suspect enough that OpenBSD developed bcrypt and Drepper developed the sha* crypts.  bcrypt itself has been improved, as scrypt, to resist FPGA based attackers; but relatively speaking, nobody has heard of it.

Temptation

The result of all this is the desire to just throw all the "use bcrypt!" "don't use bcrypt!" "aaaarrrrrgh!" wars on the floor and do whatever I damn well please.  Actually, thanks to php screwing up bcrypt and "fixing" it by making the hash identifier non-interoperable, I have an easy choice: don't use bcrypt!

Ironically, the prevalence of conflicting, self-styled "expert" advice yields a solution that involves ignoring all advice, a set that includes true, accurate, expert opinions.

So yeah.  That's what I did.  I picked sha256-crypt because
  1. It's available and portable: through PHP crypt() and CPAN's Crypt::Passwd::XS.
  2. It's simple enough that even the PHP developers couldn't mess it up.
That was easy.

Side Notes

If you have the luxury of using a SRP-based system (hi again, Blizzard!) and you make 'x' expensive to compute, you can gain the benefit of brute-force resistance without paying in CPU cycles for the server to verify the password.  From the server's POV, x is pre-computed.

bcrypt only uses up to 55 characters of the password as input.

The PHP manual currently documents a hash_pbkdf2 function, which has not made it into a release yet.  The choice of sha256 might have been different if this were The Future, but it ain't.

No comments: