Storing passwords securely

The usual advice on how to store passwords securely is "use bcrypt", but since there seem to be no Haskell bindings for bcrypt, the other good option is to iterate a salted hash function at least 1000 times. In order for people to get this right, there should be a library with a really simple API that makes it Just Work. I think I have such an API, but I'd like to hear if anybody else has suggestions before I go releasing it onto Hackage. The code is here: https://github.com/PeterScott/pwstore The part of the API that people have to care about is two functions. makePassword creates a hashed, salted password that you can store in a database. verifyPassword takes this hashed, salted password and a user's password input, and tells you if it matches. Like this: >>> makePassword (B.pack "hunter2") 12 "sha256|12|lMzlNz0XK9eiPIYPY96QCQ==|1ZJ/R3qLEF0oCBVNtvNKLwZLpXPM7bLEy/Nc6QBxWro=" >>> verifyPassword (B.pack "wrong guess") passwordHash False >>> verifyPassword (B.pack "hunter2") passwordHash True There's also a function for increasing the number of hash iterations on stored password hashes, to compensate for Moore's law. Does this sound reasonable? Also, I have a pure-Haskell version and a version which depends on some C code, for speed (about 25x difference). Does anybody care about the pure Haskell version, or should I just drop it and require the faster C/Haskell mixed version? Thanks, -Peter

Have you seen the PBKDF2 library? http://hackage.haskell.org/package/PBKDF2 Does that look like a reasonable way to store passwords securely? - jeremy On Feb 5, 2011, at 8:12 PM, Peter Scott wrote:
The usual advice on how to store passwords securely is "use bcrypt", but since there seem to be no Haskell bindings for bcrypt, the other good option is to iterate a salted hash function at least 1000 times. In order for people to get this right, there should be a library with a really simple API that makes it Just Work. I think I have such an API, but I'd like to hear if anybody else has suggestions before I go releasing it onto Hackage. The code is here:
https://github.com/PeterScott/pwstore
The part of the API that people have to care about is two functions. makePassword creates a hashed, salted password that you can store in a database. verifyPassword takes this hashed, salted password and a user's password input, and tells you if it matches. Like this:
>>> makePassword (B.pack "hunter2") 12 "sha256|12|lMzlNz0XK9eiPIYPY96QCQ==|1ZJ/ R3qLEF0oCBVNtvNKLwZLpXPM7bLEy/Nc6QBxWro="
>>> verifyPassword (B.pack "wrong guess") passwordHash False >>> verifyPassword (B.pack "hunter2") passwordHash True
There's also a function for increasing the number of hash iterations on stored password hashes, to compensate for Moore's law.
Does this sound reasonable? Also, I have a pure-Haskell version and a version which depends on some C code, for speed (about 25x difference). Does anybody care about the pure Haskell version, or should I just drop it and require the faster C/Haskell mixed version?
Thanks, -Peter _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Sat, Feb 5, 2011 at 10:54 PM, Jeremy Shaw
Have you seen the PBKDF2 library?
http://hackage.haskell.org/package/PBKDF2
http://hackage.haskell.org/package/PBKDF2 Does that look like a reasonable way to store passwords securely?
Yes, I looked at it before I started on pwstore. The code does indeed calculate the PBKDF2 key derivation function, and the documentation is terse but descriptive. It's usable, but it's not *trivial* to use. With the PBKDF2 library, a user has to: 1. Understand what PBKDF2 is, at least well enough to know what the documentation is talking about when it mentions things like "length of prf output". 2. Convert passwords to and from [Word8], which is not a very common type to have immediately on hand. 3. Generate unique salts for each user. Easy, but it would be nice if the library handled this for you. 4. Manage the salt and the hashed password separately. Again easy, but a small hassle. 5. Store the salt and hashed password as byte vectors. Some storage methods may have trouble with data that may contain (for example) the '\NUL' character. This is why my library uses base64 encoding. Some more problems are that the library is slow (thanks to the unoptimized hash functions in Crypto) and the documentation is not as clear as it could be about what a newbie needs to do. Also, if you want to extend a bunch of existing hashed passwords with more iterations as hardware gets faster, there's no obvious easy way to do that with PBKDF2. In other words, while the PBKDF2 library is technically correct, it's not as slick and easy-to-use as a password storage library should be, and *must* be, if we want everyone to store passwords properly. One of the aphorisms of cryptography is "don't roll your own", but as long as the existing code feels like it's not quite what the users are looking for, there will still be the temptation to ignore this advice and roll your own anyway. I want to make something that people can use in ten minutes and say "there, I'm done." -Peter
participants (2)
-
Jeremy Shaw
-
Peter Scott