Story continued from Page 2
Should we use password generators?
There exist password generator programs which would produce both random passphrases and random mixes of weird characters for use as short passwords. Unfortunately, many if not most of them do not use cryptographically secure sources of randomness and/or have other weaknesses. In fact, John the Ripper includes an external "cracking mode" (defined in a C-like language available for use from the configuration file) to demonstrate this kind of weakness of one such password generator ("Strip", which is short for "Secure Tool for Recalling Important Passwords"). In this cracking mode, John will try all passwords [that] certain versions of Strip could possibly generate. Although the passwords look like they are strong (weird mixes of characters), there can only be a few million of them, so John can check them all quickly (for some hash types, in a matter of seconds).
Now, this may sound like there's almost no way for an average person to pick secure passwords and for a system administrator to enforce the use of strong passwords (or passphrases). Luckily, there's a tool I wrote to help the situation. It's pam_passwdqc, a password strength checking module for the PAM (Pluggable Authentication Modules) framework. pam_passwdqc works on Linux, FreeBSD 5+ (in fact, it's been integrated into FreeBSD), Solaris, HP-UX 11+, and reportedly on recent versions of IRIX. Additionally, Damien Miller has developed a plugin password strength checker for OpenBSD's /usr/bin/passwd that uses the password complexity checking code from pam_passwdqc.
pam_passwdqc will impose reasonable restrictions on passwords and passphrases. On systems which provide a cryptographically secure source of randomness, pam_passwdqc will also offer randomly-generated combinations of words separated by punctuation for use as "passphrases". The default settings of pam_passwdqc are adequate for bcrypt hashes. If used with other (weaker) password hashing methods, the settings may need to be tweaked. In particular, if used with the traditional crypt(3), the option "max=8" must be specified, telling pam_passwdqc that passwords are truncated at 8 characters.
In practice, you can expect almost no passwords to be cracked with John the Ripper on systems which use bcrypt for password hashing and have pam_passwdqc installed (with default settings). Of course, Openwall GNU/*/Linux uses bcrypt and pam_passwdqc for users' passwords by default.
And what would you recommend to developers writing the code that manages the passwords database? Which algorithm should they use? Any trick?
Solar Designer: For C and C++ applications, I recommend my implementation of bcrypt, crypt_blowfish. When setting new passwords, the iteration counts passed into crypt_gensalt*() functions provided by crypt_blowfish should be made configurable (by the administrator, if applicable).
For PHP applications, I recommend my PHP password hashing framework, phpass. This will use a variable iteration count password hashing method that the system or the PHP interpreter might support natively (if available), with a fallback to a hashing method implemented in phpass itself (in PHP). The latter is not so great because of the slowness of PHP code. To ensure that the fallback will never occur, the PHP Hardening-Patch may be used. The Hardening-Patch integrates crypt_blowfish into the PHP interpreter such that bcrypt is available for use by PHP scripts even if the host system lacks support for it. Hopefully, future versions of PHP will do the same.
Both crypt_blowfish and phpass are in the public domain, so there are no copyrights or licensing restrictions to worry about (there can be none).
Of course, in addition to using a good password hashing method, strong passwords need to be enforced. I do not currently have a generic library for it, but the password strength checking code found in pam_passwdqc is trivial to re-use in other applications. The license for pam_passwdqc is very liberal (it is BSD and (L)GPL-compatible).
I do not currently have code for other programming languages.
I wish I could recommend something which does not include code I've written, but the very reason I did my own implementations is that I was not satisfied with whatever was available previously. For example, CrackLib and Linux-PAM pam_cracklib (with default settings) will allow most all-numeric passwords to be set (don't believe? try setting your password to "13579135"). Obviously, those passwords are easily cracked...