Working with Password Hashes in PHP
Every good programmer knows, that passwords should never be stored in clear text. Instead a one way hash (or digest) should be used. This way user passwords are not at risk1) in case of an intrusion.
In cryptography, a cryptographic hash function is a transformation that takes an input and returns a fixed-size string, which is called the hash value.
PHP offers a simple way to create such hashes by providing functions like md5, sha1 and crypt. Those will usually do if you are writing your application from the scratch.
But sometimes you may want to switch the used hash algorithm with keeping backwards compatibility to old hashes 2). Or you may want to authenticate against different systems all using different hashes.
DokuWiki does support a broad range of authentication backends. For creating and verifying password hashes we have two functions: auth_cryptPassword() and auth_verifyPassword(). The functions are completely self contained and can be used outside DokuWiki as well.
auth_cryptPassword() is used to create a new hash from a given plaintext password. The second argument is the wanted algorithm. Currently supported are:
- smd5 - Salted MD5 hashing
- apr1 - Apache salted MD5 hashing
- md5 - Simple MD5 hashing
- sha1 - SHA1 hashing
- ssha - Salted SHA1 hashing
- crypt - Unix crypt
- mysql - MySQL password (old method)
- my411 - MySQL 4.1.1 password
To create a hash just call it like this:
$hash = auth_cryptPassword('mypassword','smd5');
The hash can be stored in your user table. To verify a user password later, auth_veryPassword() is used:
// get stored password hash from db $hash_from_db = db_get_hash($_POST['user']); // verify the provided password $ok = auth_verifyPassword($_POST['pass'],$hash_from_db); // $ok will be true if the provided password was correct
The nice thing about auth_veryPassword() is that it will automatically determine which hash algorithm was used to create the stored password hash. This way you can have different types of password hashes in your database.
Update: All the code is now wrapped up in a class.