14.5.1 Problem
14.5.2 Solution
When a user signs up, encrypt her chosen password with
crypt( ) and store the encrypted password in
your database of users:
// encrypt the password
$encrypted_password = crypt($_REQUEST['password']);
// store $encrypted_password in the user database
$dbh->query('INSERT INTO users (username,password) VALUES (?,?)',
array($_REQUEST['username'],$encrypted_password));
Then, when that user attempts to log in to your web site,
encrypt the password she supplies with crypt( ) and compare it to the
stored encrypted password. If the two encrypted values match, she has supplied
the correct password:
$encrypted_password =
$dbh->getOne('SELECT password FROM users WHERE username = ?',
array($_REQUEST['username']));
if (crypt($_REQUEST['password'],$encrypted_password) == $encrypted_password) {
// successful login
} else {
// unsuccessful login
}
14.5.3 Discussion
Storing encrypted passwords prevents users' accounts from
becoming compromised if an unauthorized person gets a peek at your username and
password database. (Although such unauthorized peeks may foreshadow other
security problems.)
When the password is initially encrypted, crypt( )
supplies two randomly generated characters of salt that
get prepended to the encrypted password. Passing $encrypted_password to
crypt( ) when testing a user-supplied password tells crypt( )
to use the same salt characters again. The salt reduces your vulnerability to dictionary attacks, in which someone compares encrypted
passwords with encrypted versions of common words. Still, it's a good idea to
prevent users from choosing passwords that are simple words or other
easier-to-crack combinations. Section 14.6 provides a function to filter out easily guessable passwords.
The crypt( ) function uses a one-way algorithm. This means it's
currently impossible (or at least prohibitively computationally expensive) to
turn a crypt( )-generated ciphertext back into plain text. This makes
your stored passwords somewhat more secure, but it also means that you can't get
at the plaintext of users' passwords even if you need to. So, for example, if a
user forgets his password, you won't be able to tell him what it is. The best
you can do is to reset the password to a new value and then tell the user the
new password. A method for dealing with lost passwords is covered in Section 14.7.