The Python “crypt” module, which wraps the C library crypt(3) function, requires that you provide it with a “salt” argument, which should be a random string of certain characters in most cases. However, the Python library doesn't provide a helper for building such a salt. Not a big deal to write code to generate in a world of PDP-11s where you only need 2 salt characters. But in today's world, you probably want to be using SHA512-based password hashing in Modular Crypt Format, which is hard to find documentation on.
So I just submitted a patch to the Python bug tracker, and asked for comments, on a patch to add a “mksalt()” helper to the crypt library, and make a strong salt be selected if no salt argument is passed to “crypt.crypt()”. Read on for more information.
As you may know, this library routine is used for dealing with passwords as stored in the Unix “/etc/shadow” file. Additionally, it's just a really good way of storing a password on a server, in such a way that you can check user entry for validity, without storing the unencrypted password. This has come quite into the public view with the recent exposure of many users passwords on a large public website.
But as part of that discussion, there was also discussion about the difficulty of cracking passwords that are stored hashed. A 2TB hard drive can store quite a large database of common passwords, including all 4096 (12 bits) of salted variants in the traditional 2-character salt.
My searching for documentation of the more secure salting formats, called “Modular Crypt Format”, found very little of use. So not only is it something that just seems to be missing from the Python standard library, it's something that's hard to reproduce independently, and critical to security.
So I've added a method called “mksalt()”, which you can specify a method to, or if you don't specify a method it will select the strongest one available to your platform. Additionally, I made it so that if no salt is specified to the “crypt.crypt()” call, it will get a strong salt for you. For example:
>>> crypt.mksalt() '$6$4mBq.NeN.spzJc05' >>> crypt.crypt('password')[:50] '$6$usWKuYEDojaq4VlW$XoBub1UOCuVNyx19idUu5rDqaxQ67b' >>> crypt.crypt('password', crypt.METHOD_MD5) '$1$0QgCN7u0$SH7RE0rMiSDkzqx59GAoj.' >>> crypt.crypt('password', crypt.mksalt(crypt.METHOD_CRYPT)) 'vdcJejnZUluPo'
So it's now easy to create very secure hashes of passwords for storage in your user databases.comments powered by Disqus