PeterScott/pwstore — pull request #6 by adinapoli (2013-09-16 07:30:41+00:00)
Title: Pbkdf2

Hi!

First of all, I do really apologise for the big PR, I really wanted to make a tinier one, but a lot of function I've introduced wouldn't have made sense in the overall picture. Let me try to explain what this patch tries to solve.

A week ago I had the need of migrating some password from a legacy webapp of mine, written in Django, in a new REST server written in Haskell. The first idea I had was to use your library to compute the very same "auth string" that Django generates, in order to have all the password migrated for free. Despite your library is awesome, I found it limiting, because:

* It was using pbkdf1, whereas Django was using pbkdf2
* It was not possible to explicitly set the strength for the password, because the value you feed in is automatically used to compute the strength as 2^strength.

In case you are wondering, the following changes does not break the API, so they are *fully backward compatible*. This means that, if you merge this patch now, nobody will have his password routine broke, which is a big deal because also Snap is using your library for his `Auth` snaplet. But in a nutshell, what does this PR ship?

* A sane, fast and RFC compliant pbkdf2 algorithm. On my old 2009 macbook the generation for a new password takes 300ms with 10000 iterations, on my new 2011 macbook just 160ms. I've tested the functions
against the RFC vectors, and it's generating indeed the correct results.

* It exposes helper functions which allow the programmer to have the full control over the password generation, in terms of which algorithm to use (they can now choose between pbkdf1 or pbkdf2), the number of iterations and so on and so forth.

* As I told you, it doesn't brake existing code; The "old" functions are still there and takes sensible defaults. As a proof for that, I've run `Tests.hs` and everything was fine.

* The code is extremely well documented, I've really tried to keep up with existing coding style and documentations.

Overall, I really think it's a good patch; I know, it basically scratches my own itches, but it now gives more control to the programmer, just if he wants it. I had to use Galois' `SHA` library, which ships which a sane version of `hmac` function.

Last but not least, at the moment this is the *only* SANE pbkdf2 algorithm on Hackage. There is another package, called pbkdf2 by Silkapp, but it's broken in the implementation, just looking at the code reveals it (for example the author is using `or` instead of appending in a couple of places), so I think this addition could be really helpful for the whole Haskell community!

I'm really sorry for the lengthy writeup, but I really think having a lot of information is definitely better than having none!
If you have any enquiry/concern please tell me, I can modify the code accordingly :)

Thanks!
Alfredo