How I should have done password crypto for DWiki

January 24, 2010

DWiki (the software behind WanderingThoughts) uses cryptography for the traditional web application things, namely login passwords and login cookies; it stores hashed versions of login passwords, and it signs its login cookies. I had very little idea what I was doing when I wrote that code, so DWiki's current use of cryptography is better off not discussed in polite company; instead, let's discuss how it should work.

(I was so stupid that I didn't use HMAC, despite it being in the Python library, because I thought it was too complicated and I preferred something simpler that I could fully understand. Well, the joke's on me.)

First, you need to store encrypted passwords. The basic minimum requirement is to generate a unique per-password salt with os.urandom(), do, passwd, hashlib.sha1), and store both the HMAC output and the salt. Per Matasano Chargen, using bcrypt is much better; however, there is no Python module for it in the standard library, so if you're that worried you'd need to build the bcrypt module from pypi. As far as I know, there is no standard library support for better (ie significantly slower) hashes than SHA1.

(You might ask why not SHA512? According to openssl speed, it's only two to three times slower than SHA1, ie still pretty fast, and it means you have very large password hashes. If you're worried that much about security, go with bcrypt. Also, I lack enough crypto knowledge to know if repeatedly SHA1-ing the HMAC digest result will damage your security. If it doesn't, adding some extra SHA1 rounds will at least vaguely mimic some of bcrypt's advantages and completely erase SHA512's.)

To sign and authenticate cookies, use HMAC (with SHA1) on anything you need to authenticate plus a global secret key (any random value will do; I got DWiki's from /dev/urandom), and put in the login cookie both the plaintext and the authenticator digest. If you don't care about how long people have valid cookies, you can just sign the login name; if you do care, you need to sign both the login name and the expiry time. Make sure to sign exactly what you put in the login cookie (minus the signature, obviously).

(By now I am sufficiently paranoid that I would include the delimiter between the plaintext and the signature in what I sign, just in case.)

(Disclaimer: this may turn out to be horribly naive in N years, just like the last time around.)

Written on 24 January 2010.
« A Python safety tip: Do notice that things can throw exceptions
You can only really expire cookies on the server »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Sun Jan 24 00:22:01 2010
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.