将md5密码哈希转换为PHP 5.5 password_hash()

时间:2013-09-19 23:38:40

标签: php security hash passwords php-password-hash

PHP 5.5中的新password_hash API很不错,我想开始在任何地方使用它。鉴于较旧的项目具有较旧的数据库,其中密码存储在md5哈希中,将旧用户密码迁移到新的更安全的API的最佳方法是什么?

除了简单地提示用户在下次登录时重置密码(这对用户来说这是不切实际和恼人的)我已经考虑过使用当前md5哈希作为所有现有用户的password_hash()输入的可能性。为了验证这些用户的密码(在登录期间),我将他们的输入转换为md5哈希,然后将其用于password_verify()。新用户将免于这一额外的步骤。

这是一个值得这样做的方法吗?有没有更好的透明迁移方式,用户不会因为密码重置而烦恼,但我可以立即享受更安全的哈希带来的好处吗?

最重要的是,在使用现有的md5哈希值(易于暴力)和使用password_hash()API来“双重哈希”时,是否有安全优势呢?

3 个答案:

答案 0 :(得分:11)

login.php(?)中,您将旧密码从MD5转换为bcrypt,并用新的密码替换数据库中的旧MD5哈希值。

伪代码:

$password = $_POST["password"];

if (substr($pwInDatabase, 0, 1) == "$")
{
    // Password already converted, verify using password_verify
}
else
{
    // User still using the old MD5, update it!

    if (md5($password) == $pwInDatabase)
    {
        $db->storePw(password_hash($password));
    }
}

双重散列不会增加bcrypt的安全性,因为bcrypt itsef是一种单向散列函数。

Nota:MD5生成一个32个字符长度的字符串,而password_hash()最少生成60个字符串。

阅读手册:

如果您决定使用password_hash()或兼容包(如果PHP <5.5)https://github.com/ircmaxell/password_compat/,请务必注意,如果您当前的密码列的长度低于60 ,它需要更改为(或更高)。手册建议长度为255。

您需要更改列的长度并重新开始使用新哈希才能使其生效。否则,MySQL将无声地失败。

答案 1 :(得分:2)

由于它是单向加密,除非您希望登录页面上的用户密码不安全,否则您可以让用户重新输入其密码。另一个选项是在password_hash()散列密码的基础上用md5()重新加密所有数据库记录并将这些值存储到数据库中,然后在登录PHP页面上放置password_hash()你的md5(),有点像:

password_hash(md5($_POST['password']));

使用第二种方式,您无需让用户重置密码。

答案 2 :(得分:0)

这里还没有提到非常具体的用例,那就是你已经迈出了第一步并开始使用crypt函数,但仍然使用MD5算法。

在这种情况下,注册/密码更改时的密码哈希值如下:

$pass_hash = crypt($pass, '$1$salthere');
// store $pass_hash in database

然后你会比较:

if(hash_equals($pass_hash_from_db, crypt($user_input, '$1$salthere')))
{
  // user logged in
}

这种转变的美妙之处在于您的数据库已经处于准备好使用的状态password_verify

注册/密码更改将变为:

 $pass_hash = password_hash($pass);
 // store $pass_hash in database

你可以用以下方法代替比较:

if(password_verify($user_input, $pass_hash_from_db))
{
  // user logged in
}

这只是开箱即用,并在下次更改密码时升级所有用户的密码。但是我们不需要等待,也可以做@Fabian在这里的答案。

这里我们只需要更改登录名:

if(password_verify($user_input, $pass_hash_from_db))
{
  // user logged in
  if(password_needs_rehash($pass_hash_from_db, PASSWORD_DEFAULT))
  {
    $pass_hash = password_hash($user_input);
    // store $pass_hash in database
  }
}

一旦新密码算法成为PHP的默认密码算法,这将有助于升级用户密码。你真的不得不做任何事。

如果您希望为密码散列函数使用其他参数(例如更改“费用”),则应查看password_hashpassword_needs_rehash文档,注意可选的最后一个参数{{ 1}}。