使用password_verify()验证MD5密码


Verifying MD5 passwords using password_verify()

是否有办法将MD5的密码转换为可以由password_verify()验证的密码?

我在Crypt维基百科页面上读到"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
}

你不能那样做。

您可以做的是通过password_hash()已经md5哈希的密码进行哈希,并在数据库中为这些旧密码添加额外的标志,以便您知道之后要对它们进行双重验证。

示例代码:

<>之前$passwordCompare = ($passwordIsOldFlag === true)? md5 (passwordInput美元): $ passwordInput;if (password_verify($passwordCompare, $ passworddhash)){if ($passwordisOldFlag === true){$ passwordnewwhash = password_hash($ passworddinput, PASSWORD_DEFAULT);//在这里,您将使用新的纯bcrypt散列更新数据库//也将passwordIsOldFlag设置为0}}之前

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

阅读手册:

  • http://php.net/manual/en/function.password-hash.php

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

您需要更改列的长度并重新使用新的散列以使其生效。

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'

所以一个hash_verify_kind_function()只需要password_hash()的哈希,因为你可以用md5(或任何)哈希你的字符串,只是检查它是否都等于这是非常愚蠢的工作,因为在这种情况下,你不需要先用md5哈希它!因为实际上md5哈希并没有用于密码哈希(因此验证)