PP133 Posted March 28, 2010 Share Posted March 28, 2010 Hey guys, first post here, I'm hoping you can help me out. Basically, I have two servers, one runs PHP 5.3.0 and one runs PHP 5.2.8. On each of those servers, the crypt function returns a different encrypted string, when given the same salt and input. This is causing some problems as a tool I'm developing, on the server running 5.3.0, is attempting to authenticate logins through a database whose passwords were created using the crypt function in PHP 5.2.8. Here's the code that I'm running on both servers: <?php $username = 'aardvark'; $password = 'password'; $salt = substr($username, 0, 1); $pass = crypt($password, $salt); echo "\$pass = $pass\n"; ?> Here's the output on the 5.3.0 server: $ php test23.php $pass = a$Av8awQ0AsR6 And here's the output on the 5.2.8 server: $ php test23.php $pass = a$LHSkrbhfU1. Now, if there's no other way about this, I can downgrade my PHP to 5.2.8 to play nice with the other server, but it seems odd to me that the crypt function would be upgraded, which it appears to have been for 5.3.0 and 5.3.2, but not be made backwards compatible. I guess what I'm asking here is whether there's some argument that I can give crypt so that it'll work like it did in PHP 5.2.8 from within PHP 5.3.0. Thanks in advance. Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/ Share on other sites More sharing options...
jskywalker Posted March 28, 2010 Share Posted March 28, 2010 you should read the note on http://php.net/manual/en/function.crypt.php Note: As of PHP 5.3.0, PHP contains its own implementation and will use that if the system lacks of support for one or more of the algorithms. Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033088 Share on other sites More sharing options...
PP133 Posted March 28, 2010 Author Share Posted March 28, 2010 you should read the note on http://php.net/manual/en/function.crypt.php Note: As of PHP 5.3.0, PHP contains its own implementation and will use that if the system lacks of support for one or more of the algorithms. Hey, thanks for the reply. I did actually read that but that didn't really help. I understand the crypt function in 5.3.0 is new, but is there really no way to make it backwards compatible? What about people that built databases using the crypt from 5.2.8, are they forever doomed to stay in that version because crypt is not backwards compatible? I mean, I'm sure there's a way to convert to another encryption, but you know what I mean. Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033221 Share on other sites More sharing options...
Kieran Menor Posted March 28, 2010 Share Posted March 28, 2010 That PHP contains its own implementation shouldn't make a difference. The algorithm should be the same. As far as I can tell, crypt() is a hashing function, and the algorithm it chooses depends on what is available on the system. Apparently, you can choose what algorithm to use by prefixing the salt with various things. I don't know. Anyway, any particular reason you can't use another hashing function, like sha1()? Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033224 Share on other sites More sharing options...
oni-kun Posted March 28, 2010 Share Posted March 28, 2010 I agree with Boom.dk, What on earth is encryption used for? And with a salt? Use sha1/md5 Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033244 Share on other sites More sharing options...
PP133 Posted March 29, 2010 Author Share Posted March 29, 2010 That PHP contains its own implementation shouldn't make a difference. The algorithm should be the same. As far as I can tell, crypt() is a hashing function, and the algorithm it chooses depends on what is available on the system. Apparently, you can choose what algorithm to use by prefixing the salt with various things. I don't know. Anyway, any particular reason you can't use another hashing function, like sha1()? Hey, thanks for answering. I have no problems with using another encryption algorithm, but the encrypted string the algorithm returns has to match the encrypted passwords that already exist in the database. That database, the one I'm trying to authenticate through, has a login table with passwords that were created using the crypt function in PHP 5.2.8. See what I mean? I'm authenticating kinda like this: ... $username = $_POST['username']; $password = $_POST['password']; $salt = substr($username, 0, 1); $encrypted_password = crypt($password, $salt); $query = "select firstname from logins where username = '{$username}' and password = '{$encrypted_password}'"; $result_query = mysql_query($query); ... Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033307 Share on other sites More sharing options...
oni-kun Posted March 29, 2010 Share Posted March 29, 2010 The only method you'll get to achieve compatibility is to batch decrypt the passwords and hash them like they were designed to be in the database. *SQL provides md5() and sha1() commands (without using PHP), as they're standard. If you're wanting to know the exact differences, I've made a textdiff between the two versions here: http://zwap.to/0023g Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033320 Share on other sites More sharing options...
PP133 Posted March 29, 2010 Author Share Posted March 29, 2010 The only method you'll get to achieve compatibility is to batch decrypt the passwords and hash them like they were designed to be in the database. *SQL provides md5() and sha1() commands (without using PHP), as they're standard. If you're wanting to know the exact differences, I've made a textdiff between the two versions here: http://zwap.to/0023g Hey, thanks for the help. Well, that is one thorough answer, including the library, hehe. While I'm not a stranger to C (I believe that's what that's written in) I'm having a bit of a tough time following along without more documentation. However, I do see that certain things were added, such as SHA256 and SHA512. How can I decrypt the passwords? My understanding has been that crypt creates a one-way encryption, hence the reason I'm trying to get crypt to spit out the same encrypted string in 5.3.0 as in 5.2.8, so that I can match the encrypted version of user input on 5.3.0 to the encrypted password in the database on 5.2.8. Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033348 Share on other sites More sharing options...
oni-kun Posted March 29, 2010 Share Posted March 29, 2010 Upon looking more, it looks like it's changed the way the salt is implemented in the Unix DES library, possibly using another modified algarithm. You can look online (user contrib. notes) for samples of this; I'm sure someone else has run into this problem. But you're most likely in a bad place, as you've generated defective/depricated one way hashes. Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033355 Share on other sites More sharing options...
PP133 Posted March 29, 2010 Author Share Posted March 29, 2010 Upon looking more, it looks like it's changed the way the salt is implemented in the Unix DES library, possibly using another modified algarithm. You can look online (user contrib. notes) for samples of this; I'm sure someone else has run into this problem. But you're most likely in a bad place, as you've generated defective/depricated one way hashes. I would think that others would've run into this but I didn't have much luck finding anything, that's why I came here. And don't blame me for this mess, another team decided to go about it this way, not me Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033361 Share on other sites More sharing options...
andrewgauger Posted March 29, 2010 Share Posted March 29, 2010 " As of PHP 4.1, if no salt is provided, crypt() will use MD5 encryption and randomly generate a 12-character salt. Older versions of PHP will use the first two characters of the password string as a salt if none is provided, and it uses DES-based encryption. A salt of nine or more characters will use extended DES. Use $1$ to start a 12-character salt to use MD5. Note that the last character will always be $, and extraneous characters will be ignored. An example looks like this: $1$blahblah$. Use $2$ to start a 16-character salt to use Blowfish. If anything not matching one of the above requirements is used as a salt or the relevant encryption type is not supported, the first two characters will be taken and DES will be used. " http://articles.techrepublic.com.com/5100-10878_11-1058691.html so by using the first 2 characters of the user name to generate the salt, it seems standard des will be used. To verify this use: if (CRYPT_STD_DES == 1) { echo "Standard DES: " } on your 5.2.x box. Then you are going to have to figure out how to implement standard DES in 5.3 (remember only 8 characters of the password will be relavent). It actually would be easier to bruteforce all the passwords if you really are using DES. How many users are there? Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033364 Share on other sites More sharing options...
PP133 Posted March 29, 2010 Author Share Posted March 29, 2010 " As of PHP 4.1, if no salt is provided, crypt() will use MD5 encryption and randomly generate a 12-character salt. Older versions of PHP will use the first two characters of the password string as a salt if none is provided, and it uses DES-based encryption. A salt of nine or more characters will use extended DES. Use $1$ to start a 12-character salt to use MD5. Note that the last character will always be $, and extraneous characters will be ignored. An example looks like this: $1$blahblah$. Use $2$ to start a 16-character salt to use Blowfish. If anything not matching one of the above requirements is used as a salt or the relevant encryption type is not supported, the first two characters will be taken and DES will be used. " http://articles.techrepublic.com.com/5100-10878_11-1058691.html so by using the first 2 characters of the user name to generate the salt, it seems standard des will be used. To verify this use: if (CRYPT_STD_DES == 1) echo "Standard DES: " on your 5.2.x box. Then you are going to have to figure out how to implement standard DES in 5.3 (remember only 8 characters of the password will be relavent). It actually would be easier to bruteforce all the passwords if you really are using DES. How many users are there? Hey, thanks for chiming in. Well, this is interesting, I'm learning something I wrote that is-STD-DES-available code snippet into my code, and it is available on the 5.3.0 and 5.2.8 servers (so are Blowfish and MD5). I have to correct you on one point, I'm using a one character salt, the first character of $username. Taking that into consideration, I wondered what would happen given the paragraph you quoted: "If anything not matching one of the above requirements is used as a salt or the relevant encryption type is not supported, the first two characters will be taken and DES will be used." I figured that crypt would take the first two characters of the password, but comparing the output of crypt($password, 'a') and crypt($password, 'pa'), I found they don't match. I did, however, find that crypt seems to add a $ to your salt if the salt is only one character. Once I learned this, I was able to verify that the crypt function is indeed using standard DES encryption when given a one character salt and that it is adding a $ to the salt. Take a look at the following: <?php if(CRYPT_STD_DES == 1) { echo "Standard DES is available.\n\n"; } $username = 'aardvark'; $password = 'password'; $salt = substr($username, 0, 1); echo "\$salt = $salt\n"; $pass = crypt($password, $salt); echo "Standard crypt encryption (1 char salt) = '$pass'\n"; $des_pass = crypt($password, 'a$'); echo "DES encryption (2 char salt) = '$des_pass'\n"; ?> And it's output (running PHP 5.3.0): $ php test24.php Standard DES is available. $salt = a Standard crypt encryption (1 char salt) = 'a$Av8awQ0AsR6' DES encryption (2 char salt) = 'a$Av8awQ0AsR6' And finally the output of the same code on PHP 5.2.8: $ php test24.php Standard DES is available. $salt = a Standard crypt encryption (1 char salt) = 'a$LHSkrbhfU1.' DES encryption (2 char salt) = 'a$LHSkrbhfU1.' As you can see from the output, the standard one character salt crypt function gives us the same output as the two character salt (adding a $ to our one character salt) crypt function. I suppose the findings are all good, even though we've yet to solve the problem, at least we can say that crypt is definitely using standard DES to encrypt the password, the question now stands as why the stanard DES encryptions of the same string using the same salt do not match across two servers. I should add that we've compiled 5.2.8 on the server running 5.3.0 and verified that the problem has gone away, i.e. using the PHP 5.2.8 binary on the server running 5.3.0 gives the same encrypted output as the other server running 5.2.8, just so we don't start thinking it's a problem with the servers themselves (libraries, binaries, etc.) and not the PHP version. Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033366 Share on other sites More sharing options...
PP133 Posted March 29, 2010 Author Share Posted March 29, 2010 How many users are there? Almost forgot about that question...there are over 2300 users in the database, though only a very small sub-set of those users will use this particular tool that I'm working on. I could probably trim that number down to 50 or so users that would probably use this tool but that's just a pain and doesn't work going forward (new hires). Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033373 Share on other sites More sharing options...
Mchl Posted March 29, 2010 Share Posted March 29, 2010 One way you can get around this issue is to generate new passwords for all your users and hash them using new algorithm. Send them kind emails explaining that this is to improve security of their accounts, and they should be fine with that (at least most of them). Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033379 Share on other sites More sharing options...
andrewgauger Posted March 29, 2010 Share Posted March 29, 2010 Add to and watch this: http://bugs.php.net/bug.php?id=51282&edit=1 It has to do with special characters in salt when using 5.3.2 . You may have to implement your own DES encryption function. Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033513 Share on other sites More sharing options...
PP133 Posted March 29, 2010 Author Share Posted March 29, 2010 Add to and watch this: http://bugs.php.net/bug.php?id=51282&edit=1 It has to do with special characters in salt when using 5.3.2 . You may have to implement your own DES encryption function. Just added my notes to it, thanks for the link. Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033656 Share on other sites More sharing options...
PP133 Posted March 29, 2010 Author Share Posted March 29, 2010 One way you can get around this issue is to generate new passwords for all your users and hash them using new algorithm. Send them kind emails explaining that this is to improve security of their accounts, and they should be fine with that (at least most of them). This isn't a favorable option as we're trying to make it easy for users to use this tool, not give them another password to remember (though they could just enter the same password again). They don't care if their passwords are secure, I'm sure most of them are "1234abcd" Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033660 Share on other sites More sharing options...
Zane Posted March 29, 2010 Share Posted March 29, 2010 Well, if all you have to do is put a dollar sign in at the end of the salt to make it work with 5.3, then why not do that? Or is that what you were explaining? Is this solved. is more what I'm asking. Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033746 Share on other sites More sharing options...
PP133 Posted March 29, 2010 Author Share Posted March 29, 2010 Well, if all you have to do is put a dollar sign in at the end of the salt to make it work with 5.3, then why not do that? Or is that what you were explaining? Is this solved. is more what I'm asking. Hey, no actually that doesn't fix it. With or without that additional $ in the salt, the output of crypt is different between 5.2.8 and 5.3.0: PHP 5.3.0 $ php test24.php Standard DES is available. $salt = a Standard crypt encryption (1 char salt) = 'a$Av8awQ0AsR6' DES encryption (2 char salt) = 'a$Av8awQ0AsR6' PHP 5.2.8: $ php test24.php Standard DES is available. $salt = a Standard crypt encryption (1 char salt) = 'a$LHSkrbhfU1.' DES encryption (2 char salt) = 'a$LHSkrbhfU1.' Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033763 Share on other sites More sharing options...
Zane Posted March 29, 2010 Share Posted March 29, 2010 oh.oops. I overlooked that.. Well, in my opinion, your best bet is to go with Mchl's suggestion. Send every user a link (by email) to a "login page". Then use an encryption of what they type for their password as the new password. It'd be a little less complicated that digging out the crypt function in 5.2 and merging it with your 5.3 installation. Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033769 Share on other sites More sharing options...
andrewgauger Posted March 29, 2010 Share Posted March 29, 2010 If the users don't care about their password security why not siphon them to cleartext and hash them with md5 or sha1 until you get them all? Continue using the php5.2. until sufficient users (say 90%) have logged in. The users that are left, just have them fail, roll them to the old server (you're going to have to keep this one online for a while to do this) and siphon to the new database. Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033798 Share on other sites More sharing options...
PP133 Posted March 29, 2010 Author Share Posted March 29, 2010 I may investigate this issue a little more before I give up, but I think that if I do decide to go another route, I might just have the users create the same logins on this tool as they have on the other tool running on 5.2.8. Shouldn't cause too many problems. I'll update this thread if I find anything over the next few days. Thanks for all of the suggestions guys. Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1033810 Share on other sites More sharing options...
PP133 Posted March 30, 2010 Author Share Posted March 30, 2010 Interesting development...someone replied to my bug report stating that you can only use 0-9, A-Z, a-z for a salt, so my salt including a $ might do unexpected stuff. Using the salt 'aa' with the same code, I get the same encrypted output <?php $password = 'password'; $salt = 'aa'; $des_pass = crypt($password, $salt); echo "DES encryption (salt = $salt) = $des_pass\n"; ?> PHP 5.3.0: $ php test27.php DES encryption (salt = aa) = aajfMKNH1hTm2 PHP 5.2.8: $ php test27.php DES encryption (salt = aa) = aajfMKNH1hTm2 This is good, I suppose, but I'm still having issues with the one-character-salt-created encryption not matching across 5.2.8 and 5.3.0. Reported it to the same bug place, let's see what they say. Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1034379 Share on other sites More sharing options...
andrewgauger Posted March 30, 2010 Share Posted March 30, 2010 generate a salt in your 5.2 version for a given password with salt a$ In 5.3 try a for loop($i) 0-255 and try a salt with "a"+chr($i) and see if it comes up with a different special character ?? Couldn't hurt. Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1034421 Share on other sites More sharing options...
PP133 Posted April 5, 2010 Author Share Posted April 5, 2010 generate a salt in your 5.2 version for a given password with salt a$ In 5.3 try a for loop($i) 0-255 and try a salt with "a"+chr($i) and see if it comes up with a different special character ?? Couldn't hurt. Sorry I've been a bit absent, had to work on some other stuff. This is a neat idea, but I picked up on the pattern with the two character salts way back when I first posted this: the first two characters of the encrypted output are the salt. See for your self: PHP 5.2.8 DES encryption (salt = a!) = a!sgBMFkfptE6 DES encryption (salt = a") = a"GMnFHzfE.q6 DES encryption (salt = a#) = a#Gl30xzHaZxE DES encryption (salt = a$) = a$LHSkrbhfU1. DES encryption (salt = a%) = a%2jDWNsfCiWM DES encryption (salt = a&) = a&1ozOtJW9BFA DES encryption (salt = a') = a'05n2JEUfXYI DES encryption (salt = a() = a(YCUPgS0kJzQ DES encryption (salt = a)) = a)DMOnwont4ng PHP 5.3.0 DES encryption (salt = a!) = a!Av8awQ0AsR6 DES encryption (salt = a") = a"Av8awQ0AsR6 DES encryption (salt = a#) = a#Av8awQ0AsR6 DES encryption (salt = a$) = a$Av8awQ0AsR6 DES encryption (salt = a%) = a%Av8awQ0AsR6 DES encryption (salt = a&) = a&Av8awQ0AsR6 DES encryption (salt = a') = a'Av8awQ0AsR6 DES encryption (salt = a() = a(Av8awQ0AsR6 DES encryption (salt = a)) = a)Av8awQ0AsR6 So going off of the evidence above, it appears that if you don't include a second character for a salt, crypt adds a $ to your salt. Look at the examples below, the second character is a $: PHP 5.2.8 $ php test27.php DES encryption (salt = a) = a$LHSkrbhfU1. PHP 5.3.0 $ php test27.php DES encryption (salt = a) = a$Av8awQ0AsR6 And we can verify this by explicitly making the second character in the salt a $: PHP 5.2.8 $ php test29.php DES encryption (salt = a) = a$LHSkrbhfU1. DES encryption (salt = a$) = a$LHSkrbhfU1. PHP 5.3.0 $ php test29.php DES encryption (salt = a) = a$Av8awQ0AsR6 DES encryption (salt = a$) = a$Av8awQ0AsR6 Quote Link to comment https://forums.phpfreaks.com/topic/196794-crypt-in-php-528-vs-php-530/#findComment-1037321 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.