Using crypt() across systems

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
griffinmt
Forum Commoner
Posts: 35
Joined: Sun Jul 16, 2006 8:37 pm
Location: Michigan

Using crypt() across systems

Post 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,
griffinmt
Forum Commoner
Posts: 35
Joined: Sun Jul 16, 2006 8:37 pm
Location: Michigan

Post by griffinmt »

A small :roll: 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 :evil:
griffinmt
Forum Commoner
Posts: 35
Joined: Sun Jul 16, 2006 8:37 pm
Location: Michigan

Post 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?
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

How about you post your code?
griffinmt
Forum Commoner
Posts: 35
Joined: Sun Jul 16, 2006 8:37 pm
Location: Michigan

Post 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
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post 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?
griffinmt
Forum Commoner
Posts: 35
Joined: Sun Jul 16, 2006 8:37 pm
Location: Michigan

Post 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.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post 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.
griffinmt
Forum Commoner
Posts: 35
Joined: Sun Jul 16, 2006 8:37 pm
Location: Michigan

Post 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.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post 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. Image (I wrote a pure PHP version of it.)
griffinmt
Forum Commoner
Posts: 35
Joined: Sun Jul 16, 2006 8:37 pm
Location: Michigan

Post 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).
Post Reply