(PHP) How to correctly implement crypt()
Asked Answered
S

1

7

Here is the example from the PHP manual page for crypt():

<?php
$password = crypt('mypassword'); // let the salt be automatically generated

/* You should pass the entire results of crypt() as the salt for comparing a
   password, to avoid problems when different hashing algorithms are used. (As
   it says above, standard DES-based password hashing uses a 2-character salt,
   but MD5-based hashing uses 12.) */
if (crypt($user_input, $password) == $password) {
   echo "Password verified!";
}
?>

Why does this work? I take it 'mypassword' is the password I want the actual admin to use. So I crypt that first, and set it equal to $password. Obviously, I must need to store that in the DB. But in the next lines it's being used as both the salt and what I'm comparing to, and I don't understand how crypt($user_input, $password) can possibly be equal to $password, if in this latter case I have ideally the right password as $user_input but salted with $password being compared to $password. It would make more sense to me if the last line were

if (crypt($user_input) == $password) {
   echo "Password verified!";
}

What am I not understanding?

Shoemaker answered 10/2, 2010 at 9:38 Comment(2)
you should use more advanced techniques such as md5, sha1 etc.Jason
hah. hah. hah. hahah. if only you were on this epic journey with me my friend. #2235658Shoemaker
B
8

crypt is a one-way function and returns a string that already contains the salt. The output is similar to what is stored in /etc/shadow.

Example from php.net:

<?php
echo 'result: ' . crypt('somepassword');
echo 'result: ' . crypt('somepassword');
echo 'result: ' . crypt('somepassword');
?>

result: $1$K2D8DGwq$b05uO37aMwO4rnDlB9Rsi1
result: $1$aPBvu2y.$213YVEs8/5m.jMCXSScly/
result: $1$dW3Xu2p6$nuCtJe2zzlgBMLxN2oZCx/

When comparing the user input with the crypt result, the function automatically extracts the salt from the string.

Burlburlap answered 10/2, 2010 at 9:46 Comment(6)
It answers your question perfectly. crypt() outputs a string that contains both the salt and the result of the hash. When you pass it that string as a salt, it knows to extract only the salt part and ignore the hash part. And it still returns a string containing both the salt and the hash. So these strings can be compared directly.Dicky
oh, so by giving it $password as a salt, it's extracting only the salt part, and which was the salt used for the original crypt() call, so i don't ever need to store a salt in my DB, just the hashed PW?Shoemaker
yeah sorry it didn't make sense to me when i read it but gnud rephrased it enough so that i think i got itShoemaker
@Burlburlap I know this is an old post, but I figure it makes more sense to ask here than to make my own post on it, but is doing this not insecure as someone else has the salt that is used? I am new to hashing, so I am only trying to understanding the logic behind why its done this way. I am trying to figure out whether to use crypt() or not. Thanks again.Laevorotation
@Andy: No one else gets the salt. What you get as a result from crypt is stored in a password database (like /etc/shadow) that is not accessible publically. Of course a hacker might steal it but then the salt will keep him from actually cracking a password, and definitely from cracking many passwords at once. The point is that the salt can be stored in plaintext, its purpose is to prevent against simple password attacks like bruteforcing.Burlburlap
@Burlburlap So storing the result of crypt() in the database is enough? Its very convenient to have it all together. Thanks a lot.Laevorotation

© 2022 - 2024 — McMap. All rights reserved.