Page 1 of 1
Using crypt() across systems
Posted: Sun Aug 20, 2006 2:06 pm
by griffinmt
Here is my 'environment':
-WXP system with apache, php and mysql
-Fedora with apache, php, mysql
-same versions across systems
-both are on same internal lan
-database in question is replicated from WXP (master) to linux (slave)
On WXP, I add a row to the database that contains a a hashed password field. I am using crypt() with a 2 character salt, and the result is being stored in a STD_DES format. The system supports both STD_DES and MD5.
After the row is replicated across, I try to validate against the stored hash of the password (on the linux system), using the same 2 char salt with the user input, but this time it generates a MD5 hash and fails the comparison. The linux system also supports both STD_DES and MD5. The same code works as expected on the WXP system.
How can I 'force' the use of DES, or disable the MD5 option on PHP without jeopardizing other funtions??
TIA,
Posted: Sun Aug 20, 2006 2:51 pm
by griffinmt
A small

correction to what I said in my previous msg.
PHP on the Linux system was upgraded to version 5.1.4
The WXP version is still running 4.4.2
Of course, I could upgrade the WXP side to V5+, but if it starts using MD5 instead of DES, it won't function because the database field is too small (and a lot of users would be

Posted: Sun Aug 20, 2006 4:38 pm
by griffinmt
I just installed PHP 5.1.5 on the WXP system and retested.
Still works as expected on WXP and not on Linux system.
There are some obvious compile options that are different, but just what should I be looking for?
Posted: Sun Aug 20, 2006 5:07 pm
by feyd
How about you post your code?
Posted: Sun Aug 20, 2006 5:29 pm
by griffinmt
This is the way that the password was encrypted:
Code: Select all
$query = "UPDATE customer SET password='".crypt($password,$salt)."', active='Yes', activedate='".$da."' WHERE customerid='".$_POST['logonid']."'";
$password was set from some form input and $salt is a two character string randomly created by the caller.
Later, during logon, the input password is checked via:
Code: Select all
if ($row['password'] != crypt($password,substr($row['password'],0,2)))
{ // spit out error condition ....
This test is always successfull on the WXP system, but fails on the Linux system. If you echo the results of the crypt(), it is definitely MD5 format on the Linux installation.
Both systems have CRYPT_SALT_LENGTH set at 12
both have CRYPT_STD_DES and CRYPT_MD5 set to 1
Posted: Sun Aug 20, 2006 6:12 pm
by feyd
How is $salt created? Is it static or dynamically created? For giggles, because I have no other way to check, can you var_dump($salt) before running the first snippet as well please?
Posted: Sun Aug 20, 2006 6:17 pm
by griffinmt
Code: Select all
$query = "UPDATE customer SET password='".crypt($password,"Ba")."', active='Yes', activedate='".$da."' WHERE customerid='".$_POST['logonid']."'";
The results are the same if you just use a literal value as above. I tried that while debugging the problem.
And since the first two characters of the salt are all that it uses (STD_DES) and glues these to the front of the hashed value, they are easily extracted for re-use during the compare.
For example, if $password = "asdfghjkl";
then:
BaSYxv6I6Ueno
is the result.
Where as:
$1$HLQYBP6d$WMG/vEYp64p5T7V.3rWSG1
is what the login validation call generates on the Linux system.
Posted: Sun Aug 20, 2006 6:38 pm
by feyd
Reading the crypt() page:
Some operating systems support more than one type of encryption. In fact, sometimes the standard DES-based encryption is replaced by an MD5-based encryption algorithm. The encryption type is triggered by the salt argument. At install time, PHP determines the capabilities of the crypt function and will accept salts for other encryption types. If no salt is provided, PHP will auto-generate a standard two character salt by default, unless the default encryption type on the system is MD5, in which case a random MD5-compatible salt is generated. PHP sets a constant named CRYPT_SALT_LENGTH which tells you whether a regular two character salt applies to your system or the longer twelve character salt is applicable.
It would appear that your linux system has a default of using an MD5 encryption, and it would seem to be confirmed by CRYPT_SALT_LENGTH. There may not be a simple way to change it, as it apparently would require changing the OS level setting and possibly recompiling. I would suspect that because Windows doesn't have a unix crypt() function natively, PHP has to handle it.
It may be best to use a different encryption facility; one that's more reliable, controllable. What I could suggest depends on how flexible you are in changing your code.
Posted: Sun Aug 20, 2006 6:49 pm
by griffinmt
Change is not impossible, but just not preferable at this time due to the disruptive nature. This is not a business, but it is in support of a busy r/c flying club site.
However, in reading the crypt doc, and looking at some of the examples below it, it implies that the actual encryption method used is a function of the size of the salt, if supplied. Only if not supplied does it select the method itself, by way of the CRYPT_SALT_LENGTH value.
And since the flags indicate that STD_DES is indeed available for use, it should be able to be triggered.
Posted: Sun Aug 20, 2006 8:17 pm
by feyd
That doesn't necessarily mean it will be triggered. It's quite possible that, although DES is available, the server has been told not to use it. It would depend on how good PHP was at detecting the ability to use it during the build process. As I've already said, I suggest moving to some other more reliable and controllable encryption.
Since both machines are running 5.1.3+ I could suggest using the now built-in
hash() function. My personal favorite is SHA256.

(I wrote a pure PHP version of it.)
Posted: Mon Aug 21, 2006 7:04 pm
by griffinmt
I converted to use hash(), adjusting the approp. field sizes. Also set it up to force a password change for first access to create new hash values using only the WXP system.
Once changed and it replicates, logons can be handled on the Linux system as needed.
Thanks for the suggestion (although I still think this is a 'bug' with crypt's behaviour relative to its description).