Forum Moderators: coopster

Message Too Old, No Replies

Need help with MD5 problem

The MD5 hash is not matching up with stored hash

         

Baron Higbee

2:11 am on Oct 12, 2007 (gmt 0)

10+ Year Member



Hello there all!

Been designing and coding a long time but have only recently started messing with encryption. Let me briefly describe the problem:

I am storing passwords in a MySQL database as MD5 hashes. If a person loses or forgets their password, I need to be able to create a new password and email it to them with the click of a button. Seems simple enough, but for some reason the emailed password is not matching the stored hash.

I did notice in this process that the input fields for initial registration and login had to be identical in size or it changes the MD5 hash; i.e. <input type="password" value="pswd" size="12" maxlength="12"> for both usages.

However, in order to create the password with the click of a button I have a function that is creating the password, updating the database, and sending the email with the new password. Since I discovered this prior issue I thought that logically the password length being created should also be 12 characters. No matter what size I alter the creation function to, it fails. Please help me! My head is bloody from banging it against the keyoard lol

*************************************
Here is the function:
*************************************


function generate_password($length=8) { // note when in use I am passing a length of 12 (see below)
$password = "";
mt_srand ((double) microtime() * 1000000);
$char = "A,B,C,D,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,m,n, o,p,q,r,s,t,u,v,w,x,y,z,1,2,3,4,5,6,7,8,9";
$char = explode(",", $char);
$n = count($char);
while (strlen($password) < $length) {
for ($i=0; $i<$n; $i++) {
$r = mt_rand(0, $n-1);
$temp = $char[$i];
$char[$i] = $char[$r];
$char[$r] = $temp;
}
$r = mt_rand(0, $n-1);
$password .= $char[$r];
}
return $password;
}

***********************************
And this is the function that calls it:
***********************************

function update_password() {
$new_password = $this->generate_password(12);
$query = "UPDATE TABLE_NAME SET password=MD5('$new_password') WHERE EMAIL='$email'";
mysql_query($query);
if (mysql_errno()) {
$this->ERRSTR = "Could not update password (".mysql_error().").";
return;
}
$subject = "Your New Password";
$headers = "From:user@somewebsite.com\r\n";
$body = "
Your pasword has been reset!

Your new password is:

{$new_password}";

mail($email, $subject, $body, $headers);
return 1;
}

As I said the functions work, but logging in with the new password does not :( Any insight would be a great help! Thanks in advance :)

[edited by: dreamcatcher at 7:25 am (utc) on Oct. 12, 2007]
[edit reason] Fixed side scroll. [/edit]

mooger35

4:21 am on Oct 12, 2007 (gmt 0)

10+ Year Member



I think it's the quotes...

$query = "UPDATE TABLE_NAME SET password=MD5('$new_password') WHERE EMAIL='$email'";

try switching it to this:

$query = "UPDATE TABLE_NAME SET password=MD5($new_password) WHERE EMAIL='$email'";

At first glance it looks like you've been storing the MD5 of "$new_password" instead of the variable.

Baron Higbee

5:10 am on Oct 12, 2007 (gmt 0)

10+ Year Member



Sadly that didn't work. When I do that the server thinks $new_password is a column name and fails to UPDATE. I would have been surprised if it had since I need to use the quotes everywhere else. Thanks tho :)

mooger35

6:17 am on Oct 12, 2007 (gmt 0)

10+ Year Member



what about setting the password before the query.

$db_password = MD5($new_password);

$query = "UPDATE TABLE_NAME SET password='$db_password' WHERE EMAIL='$email'";

dreamcatcher

7:28 am on Oct 12, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



or:

password='".md5($new_password)."'

dc

PHP_Chimp

9:36 am on Oct 12, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member




$char = "A,B,C,D,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,m,n, o,p,q,r,s,t,u,v,w,x,y,z,1,2,3,4,5,6,7,8,9";

There is a space before your o so when you explode them all of the others will be a single character...however you will have ' o'. That may not be helping. As the result will give you 2 different hashes.

whoisgregg

6:23 pm on Oct 12, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I think that extra space was added by dc to fix the side scroll.

Baron Higbee

7:16 pm on Oct 12, 2007 (gmt 0)

10+ Year Member



Yea I checked the function and there is not space in it :) I am going to try these other options in the script right now, and I'll report my findings. I will say...even if one of these other options works, it doesn't explain "why" they worked as opposed to the way I was doing it. Well let me give them a whirl before I go there :)

dreamcatcher

7:23 pm on Oct 12, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I think that extra space was added by dc to fix the side scroll.

Indeed it was. Sorry for the confusion. Thanks for pointing that out whoisgregg. :)

dc

Baron Higbee

11:30 pm on Oct 12, 2007 (gmt 0)

10+ Year Member



Ooooo K...

So after numerous attempts with these suggestions. I finally decided to make a test page that contained only the problematic functions. At first I had a problem with none of the hashes matching up; including the way I knew they had matched successfully.

After removing the single quotes from the MD5() functions. I got the test page to work perfectly in both scenarios.

So I attempted to apply this information to the page where I update the user's password with the generated one using:

password='".MD5($password)."'

It still did not work. So then I applied this same method to the login function and BLAM! It worked! WOOT!

Now here's the kicker...

The Admin page is still using: password=MD5('$password') as the login syntax and it works just fine. Even on the passwords that are generated. Additionally, the initially created password are sent to MySQL using:

INSERT INTO TABLE (password) VALUES (MD5('$password'))

and these passwords still work fine as well! I'm glad I got it to work but I am still mystified as to what the REAL problem is.

Is this an issue of the UPDATE constant sometimes corrupting information? Is this an issue of MD5 use within literal strings being unpredictable? Is this the real reason why I needed to make sure that the INPUT box sizes were identical?

Thanks to all who have helped, it was driving me bonkers, but I still don't get it. I've been reading up on MD5, but I can't find this kind of behavior really documented anywhere.

Baron Higbee

6:06 am on Oct 14, 2007 (gmt 0)

10+ Year Member



One more follow-up question...

I've been using the syntax as previously stated for another part of these functions and have never had a problem with it. Creating and storing an authorization code using: auth=MD5('$auth').

Should I change it over to this syntax to be safe from future problems? Or if it ain't broke don't fix it?

P.S. I would still love to have any insight on the questions from the post above :)

PHP_Chimp

9:15 pm on Oct 14, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Although I cant tel you why your variables are performing as they are my personal preference is to do the same thing the same way each time.
So if you are not using auth=MD5('$auth') in a 1/a few places then change them all to the same format. Otherwise when you get another problem in a year or so, you look back having forgotten this and think 'Why is that one different?' change it and its all broken again. There is of course the magic of // for your notes on why this one is different..I guess which one you decide to do depends on the amount of work involved with changing everything to the same format.

Baron Higbee

9:59 pm on Nov 4, 2007 (gmt 0)

10+ Year Member



Just wanted to do a quick follow-up post to this, so everyone knows the final situation/solution...

#1 - Though you cast variables in any and/or all of the ways posted in this thread, using the same variable casting technique throughout your entire script avoids confusion (so tru thank u for that reply)

#2 - MD5 does NOT have different results for an identical string, so if this appears to be occurring, look for the answer somewhere else in the script

#3 - when using preg_match(), be certain that it is covering all of the necessary characters that could appear

When I tell you what happened you will laugh...I did, eventhough it drove me insane and after I cursed for 20 minutes lol

The problem was not in my variable declarations, or the functions I posted in this thread. It turns out that the problem was in my preg_match() function that was confirming the validity of the password being entered. It wasn't looking for capital letters. Magically once I added them in, everything worked like a charm. The reason I was having intermittent problems is because some of the MD5() conversions happened to be all lowercase, so I was just getting around the preg_match() problem by sheer luck. *sigh* I love coding lol

Hope this helps somebody else before it drives them as nuts as it drove me :)