使用password_verify()验证MD5密码

时间:2015-07-30 10:30:34

标签: php hash passwords php-password-hash

有没有办法将MD5密码转换为可由password_verify()验证的内容?

我在Crypt Wikipedia page上看到" MD5密码哈希值的可打印格式以$1$开头。"

因此我给了他一个机会(没有任何运气):

$password = "abcd1234";
$md5hash = "$1$".md5($password);
var_dump(password_verify($password, $md5hash));

有没有办法让password_verify()使用MD5密码?

问题原因:我有一个旧系统,密码存储为MD5哈希。我想开始使用更安全的Password Hashing API。如果我能够将现有密码哈希值转换为适用于password_verify()的内容,我可以更新数据库条目(将$1$添加到所有密码哈希值之前),我的程序可以很好地工作使用以下代码(我不必为旧MD5密码设置特殊情况):

$password; // Provided by user when trying to log in
$hash; // Loaded from database based on username provided by user
if(password_verify($password, $hash)) {
   // The following lines will both update the MD5 passwords
   // and all passwords whenever the default hashing algorithm is updated
   if(password_needs_rehash($hash, PASSWORD_DEFAULT)) {
      $hash = password_hash($password, PASSWORD_DEFAULT);
      // Store the new hash in database
   }
   // User is logged in
} else {
   // User is not logged in
}

2 个答案:

答案 0 :(得分:3)

你做不到。

您可以做的是通过password_hash()散列已经MD5哈希的密码,并在数据库中为这些旧密码添加一个额外标志,因此您需要对它们进行双重验证之后。

一些示例代码:

$passwordCompare = ($passwordIsOldFlag === true)
    ? md5($passwordInput)
    : $passwordInput;

if (password_verify($passwordCompare, $passwordHash))
{
    if ($passwordisOldFlag === true)
    {
        $passwordNewHash = password_hash($passwordInput, PASSWORD_DEFAULT);

        // Here, you'd update the database with the new, purely bcrypt hash
        // and set your passwordIsOldFlag to 0 as well
    }
}

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

阅读手册:

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

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

答案 1 :(得分:0)

md5(或任何其他哈希算法-查看包含hash_algos()的完整列表)每次都会将某事物哈希为一个常数(相同),换句话说:

'1234' ---md5---> '81dc9bdb52d04dc20036dbd8313ed055'
'1234' ---md5---> '81dc9bdb52d04dc20036dbd8313ed055'
'1234' ---md5---> '81dc9bdb52d04dc20036dbd8313ed055'
'1234' ---md5---> '81dc9bdb52d04dc20036dbd8313ed055'
...

但是password_hash($password, $algo)每次都会将某事物散列为新事物,换句话说:

'1234' ---password_hash---> '$2y$10$VXj5/N79aVolZQHJa.wdUub4C1uifXCNGRVKVUIYnsuRGs/wnXU/S'
'1234' ---password_hash---> '$2y$10$BjSPyCyZU2Rui5MtL5MLC.bkLGbUxf/f9NshALvTc39lhemoWZFC6'
'1234' ---password_hash---> '$2y$10$WXGX/6dCLbJN77MKNNVbCej9Fya2fQGvPjAMLuU3a6zGCDuBMisbm'
'1234' ---password_hash---> '$2y$10$sqkB2ZK7BanIHTRZIKUHi.TVdseZE.GSMghBhuT7mDC9GrjW9g6Ky'

所以只需要password_hash()产生的哈希值就需要hash_verify_kind_function(),因为您可以使用md5(或任意值)对字符串进行哈希处理,并检查它们是否相等,这非常愚蠢之所以可以工作,是因为在这种情况下,您不需要先使用md5对其进行哈希处理!因为实际上md5哈希没有用于密码哈希(因此需要进行验证)