== How I should have done password crypto for DWiki 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 http://docs.python.org/library/hmac.html]], because I thought it was too complicated and I preferred something simpler that I could fully understand. Well, [[the joke's on me ../programming/HashLengthExtAttack]].) First, you need to store encrypted passwords. The basic minimum requirement is to generate a unique per-password salt with _os.urandom()_, do _hmac.new(salt, passwd, hashlib.sha1)_, and store both the HMAC output and the salt. Per [[Matasano Chargen http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-s.html]], 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 http://pypi.python.org/pypi/bcrypt/]]. 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.)