2009-10-24 53 views
2

我想要一个用户可以更改密码的表单。我可以加密密码,但是当它从数据库中选择时(原始密码称为“测试”),它不能识别它。php加密sql

这是密码在db中被加密的时候。我检查,看看是否在形式上键入密码相匹配的在DB:

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

这是它是如何加密:

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

哪有我选择的工作,这样当用户键入它以原来的形式被识别?

回答

4

首先:MD5是cryptographic hash function,不一定是加密方法。散列被设计为仅在一个方向上执行,并且不能被颠倒。 (这是件好事)

然而,MD5被密码破坏(不再被认为是安全的)。你应该使用其他散列函数(最好Bcrypt散列或至少SHA256)

看代码,我可以看到几件事情错:

  1. 你的密码是不salted
  2. 我真的希望$typed_password已经过正确的消毒处理,或者您处于SQL-injection
  3. 您尝试从表中选择具有相同密码的所有用户。

做密码的最简单的(也可能是最好的)方法是使用一个标准库:在Portable PHP password hashing framework,并确保您使用CRYPT_BLOWFISH算法。

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'; 
} 

店/检查/更新查询应该被绑定到用户的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}"; 

然后,你应该使用parametrised queries,而不是直接传递变量值到查询。

我意识到这是一次很多的信息,但重要的是要学习这一点,如果你不希望你的脚本几乎每个程序员都可以破解。

+0

如果还好,你能否详细说明第1点和第3点。我不太明白你的意思。谢谢 – user179780 2009-10-24 23:06:24

+0

感谢所有的信息,我会研究它。我这样做的原因是因为如果用户重新登录到系统中,他们需要使用他们在表单中键入的密码登录。只有在将密码转换回原始格式时才能识别该密码。这是正确的我在想什么?如果我错了,请纠正我,我目前还没有读入密码散列函数。 – user179780 2009-10-24 23:40:45

+1

这可以工作,而不需要知道密码是通过散列表得到的。你哈希他们的原始密码,并重新哈希它再次比较哈希而不是密码。 – 2009-10-24 23:45:52

1

为什么不用PHP加密密码,然后INSERT已经加密了。
SELECT相同。

所以:(为什么不呢?INSERT

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

类似与UPDATE

+2

您仍在选择每个使用某个密码的用户,密码哈希不会被腌制,散列函数(MD5)会被加密破坏。 – Jacco 2009-10-24 23:23:19

+0

@jacco。虽然这是真的,但他试图做的一点是,为什么不让php做这个工作而不是mysql?他不必使用md5。 PHP支持另外34个哈希算法,并且自5.1.2开始。 http://us3.php.net/manual/en/function.hash-algos.php – txyoji 2009-10-25 03:10:17

0

A recent post on passwords 我有点偏离主题,并覆盖了很多本。一个珍闻:

一旦你对他们选择的密码感到满意,先用PHP加密,然后存储。下面的密码加密功能也不是我的想法,但解决了一些问题。 PHP中的加密可防止共享服务器上的人员拦截未加密的密码。每个用户添加一些不会改变的东西(我使用电子邮件,因为这是我的网站的用户名),并添加一个散列(SALT是一个简短的常量字符串,我改变每个网站)增加抵抗攻击。由于SALT位于密码中,并且密码可以是任意长度,所以用彩虹表进行攻击几乎是不可能的。或者,这也意味着人们不能更改他们的电子邮件,并且您不能更改SALT而不会破坏每个人的密码。

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

因此,对用户密码的第一个输入,在伪代码:

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

那就要检查一下在伪代码随后登录:

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 

如果你得到一个行回来,有效登录。

+0

谢谢你的建议,我会读入此并尝试一下。再次感谢所有人 – user179780 2009-10-24 23:58:13

+1

盐应该改变为每个哈希密码。每个站点使用不变的值是不正确的。 – Jacco 2009-10-25 11:55:26

+0

我猜你从未读过它。它每改变一次密码都会改变。我正在使用两种盐。每个站点更改以防止跨站点彩虹化,并且每个用户更改一个。 – 2009-10-25 13:16:36