views:

120

answers:

3
+2  Q: 

php encryption sql

I want a form where user can change password. I am able to encrypt a password, however when it is selected from the database(the original password say 'test') it does not recognise it.

This is when the password has been encrypted in db. i am checking to see if the typed password in form matches the one in the db:

SELECT * from table where password = md5('$typed_password')

This is how it is encrypted:

UPDATE table set field = md5('$typed_password' )

How can my select work so that when a user types it in the form the original one is recognied?

+4  A: 

firstly: MD5 is a cryptographic hash function, not necessarily an encryption method. A hash is designed to only be performed in one direction, and cannot be reversed. (this is a good thing)

MD5 is however cryptographically broken (not considered secure anymore); you should use another hash function (preferable Bcrypt-hash or at least SHA256)

Looking at the code, I can see several things wrong:

  1. your password is not salted
  2. I really hope that $typed_password is properly sanitized or you are in for SQL-injection.
  3. You try to select all users from the table with the same password.

The easiest (and probably best) way of doing passwords is by using a standard library: the Portable PHP password hashing framework and make sure you use the CRYPT_BLOWFISH algorithm.

require('PasswordHash.php');

$pwdHasher = new PasswordHash(8, FALSE);

// $hash is what you would store in your database
$hash = $pwdHasher->HashPassword( $password );

// $hash would be the $hash stored in your database for this user
$checked = $pwdHasher->CheckPassword($password, $hash);
if ($checked) {
    echo 'password correct';
} else {
    echo 'wrong credentials';
}

the store/check/update queries should be bound to the user's Id:

// Insert query
$query = "INSERT INTO users VALUES({$userId}, '{$username}', '{$hash}')";

// Select query
$query = "SELECT hash FROM users WHERE userId = {$userId}";

// Update query
$query = "UPDATE users SET hash = '{$hash}' WHERE userId = {$userId}";

And then, you should use parametrised queries instead of directly passing the variable values into the query.

I realise this is a lot of info at once, but it is vital learn this if you do not want your script to be hackable by almost every programmer out there.

Jacco
if ok could you elaborate on point 1 and 3. I don't quite understand what you mean. Thanks
Thanks for all the info i will look into it. The reason why i am doing this is because if a user relogins into the system, they are expected to log in with a password that they typed within the form. This password can only be recognised if it is converted back into the original format. Is this correct what i am thinking? Please correct me if i am wrong, i have not read into cryptographic hash function at the moment.
This works, without ever knowing what the password was via a hash. You hash their original password, and rehash it again and compare the hashes instead of the passwords.
Daren Schwenke
`$typed_password` needs not to be sanitized, since it's hashed anyway. and hashes are almost certainly no possible to use in sql injection
knittl
`md5('$typed_password')` with $typed_password set as: `x') AND 1=1 --` would nicely break the system.
Jacco
+1  A: 

Why not encrypt the password in PHP and then INSERT already encrypted one.
Same with SELECT.

So:

$enc_passwd = md($typed_password);
$sql = "SELECT * FROM table WHERE password = '$enc_passwd')";

similar with UPDATE

(why not INSERT?)

Michal M
You are still selecting every user with a certain password, the password Hash is not salted and the hashfunction (MD5) is cryptographically broken.
Jacco
@jacco. While that is true, the point he's trying to make is, why not let php do the work instead of mysql? He doesn't have to use md5. PHP supports 34 other hash algorithms and has since 5.1.2. http://us3.php.net/manual/en/function.hash-algos.php
txyoji
A: 

A recent post on passwords I got a little off topic and covered a lot of this. A tidbit:

Once you are happy with the password they have picked encrypt it with PHP first, then store. The following password encryption function is not my idea either, but solves a number of problems. Encrypting within PHP prevents people on a shared server from intercepting your unencrypted passwords. Adding something per user that won't change (I use email as this is the username for my sites) and add a hash (SALT is a short constant string I change per site) increases resistance to attacks. Because the SALT is located within the password, and the password can be any length, it becomes almost impossible to attack this with a rainbow table. Alternately it also means that people can't change their email and you can't change the SALT without invalidating everyone's password though.

function password_crypt($email,$toHash) {
   $password = str_split($toHash,(strlen($toHash)/2)+1);
   return hash('sha256', $email.$password[0].SALT.$password[1]); 
}

So on first input of the user password, in pseudo code:

define(SALT,'blah');
$hashed_password = password_crypt($email,$password);
INSERT INTO users (email,hashed_password) VALUES ($email,$hashed_password);

Then to check a subsequent login in pseudo code:

define(SALT,'blah');
$user_hashed_password = password_crypt($_POST['username'],$_POST['password']);
SELECT email FROM users WHERE email = ? AND hashed_password = $user_hashed_password LIMIT 1

If you get a row back, valid login.

Daren Schwenke
thanks for th suggestions, i will read into this and try it out. Thanks once again everyone
The salt should change for every hashed password. Using a constant value per site is not correct.
Jacco
I'm guessing you never read it. It does change per every hashed password. I'm using two salts. One that changes per site to prevent cross site rainbowing, and one that changes per user.
Daren Schwenke
A salt should be random to be effective, not derived from some sort of user-related data. Using a random salt makes sure the hashed value is effectively different for each stored hash, be it on your own system or across systems. This would also make sure that an e-mail change does not invalidate the password. In short: recommend/use a proven library because there are just to many possibilities to fail.
Jacco
I used to use a random string generated when the users joined. It was stored in their user record. In either case if an attacker can get at my hashed passwords, they are going to get at my first salt, be it email or random. I agree entropy goes up a little with random. What proven library would you be referring to?
Daren Schwenke
Portable PHP password hashing framework: PHPass: http://www.openwall.com/phpass/
Jacco
Ok I'm sold. :) Good hashing, small size, definable computational cost and backwards compatibility if I turn it up.
Daren Schwenke
Thanks Daren and Jacco, both provided helpful feedback.