2012-04-27 58 views
0

因此,我正在学习PHP并正在登录页面上工作。我已经想出了如何使用SHA256注册新用户来散列$ salt + $密码。我知道像bcrypt这样的加密方法较慢,但为了学习目的,我只使用SHA256。我的问题是,使用这种加密后:从数据库检索salt + hash进行验证

function HashPassword($password) { 
    $salt = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)); 
    $hash = hash("sha256", $salt . $password); column 
    $final = $salt . $hash; 
    return $final; 
} 

使用准备好的语句,什么是从数据库中检索哈希密码的最好办法,所以我可以使用这样的功能验证呢?

function ValidatePassword($password, $hash_pass) { 

    $salt = substr($hash_pass, 0, 64); 
    $trueHash = substr($hash_pass, 64, 64); 
    $reHash = hash("sha256" , $salt . $password); 

    return $reHash == $trueHash; 
} 

回答

1

你基本上保存密码哈希与盐,使其不能识别。

如果您的数据库在某些时候被黑客攻击,黑客无法直接读取密码。相反,他将不得不重新创建哈希值。

如果你不为每个用户使用不同的(随机)salt,黑客只需要创建一个包含所有可能的散列值的表并将其与你保存的散列密码进行比较。

但是,如果每个密码在密码之前添加了一个不同的salt,那么在哈希之前,黑客必须为每个密码创建一个新表,从而增加获取真实密码所需的工作量。人们希望这会导致黑客效率低下或代价过高。

对于您为要验证你必须遵循下面的模式登录凭证编码器:

  1. 获取保存在数据库中的盐。
  2. 计算具有的级联hash = salt + password
  3. 值进行比较计算与保存的一个hash === savedHash
  4. 如果它们是相同的,这是有效的密码。如果不是,那是一个错误的密码。
+0

是的,我理解这个概念,并感谢你的额外澄清。绊倒我的是我如何访问我的数据库中的串联散列。从用户密码中选择username ='$ username'? – Jukodan 2012-04-27 07:38:59

+0

@Jukodan你可以做一个单一的查询来检索salt和散列密码:'SELECT hashedPW,salt FROM users WHERE username ='$ username''。然后用PHP完成比较。重要的一点是为每个用户使用不同的盐,而不是全球用户(对另一个答案的评论听起来像对所有用户只有一个“盐”)。 – Sirko 2012-04-27 07:41:40

+0

啊!我一直在想它,主要是因为当我查询数据库并回应我收到“资源ID#2”的结果而不是预期的散列密码时。目前我正在使用: $ salt = bin2hex(mcrypt_create_iv(32,MCRYPT_DEV_URANDOM)); 为每个用户生成一个随机salt,然后将hash = salt + password存储在一列中。 – Jukodan 2012-04-27 07:46:18

5

的原则是,你找回密码;而是使用相同的HashPassword函数计算密码尝试的散列值,然后查询数据库以查找匹配的记录。


编辑

HashPassword功能再来看,我知道你不希望在其中生成随机盐,而是采取$salt作为参数;您将传入现有数据库记录的值,或者根据需要传入随机生成的值。

+0

虽然盐呢?我知道人们能够验证使用盐进行散列的登录。在这种情况下,由于它是随机生成的,我可以如何验证...我有点迷路。 – Jukodan 2012-04-27 07:27:54

+3

@Jukodan:你的盐应该和你的记录一起存放。 – eggyal 2012-04-27 07:28:15

+0

我把我的salt作为一个全局类变量(私有)放在包含我需要hash + salt的脚本中。只需输入他们输入的密码,添加盐,将其存储在变量中,从数据库中检索已经哈希的密码并比较两者。如果他们匹配,那么你是金,如果没有,那么他们输入了错误的密码 – 2012-04-27 07:31:51