使用 password_verify() 验证 MD5 密码
Verifying MD5 passwords using password_verify()
有没有办法将 MD5
密码转换为 password_verify()
可以验证的密码?
我在 Crypt Wikipedia page 上看到 "The printable form of MD5
password hashes starts with $
."
因此我试一试(没有任何运气):
$password = "abcd1234";
$md5hash = "$".md5($password);
var_dump(password_verify($password, $md5hash));
有什么方法可以让 password_verify()
使用 MD5
密码吗?
提问原因:我有一个旧系统,其中密码存储为 MD5
哈希。我想开始使用更安全的 Password Hashing API
。如果我能够将现有的密码哈希值转换为适用于 password_verify()
的内容,我只需更新数据库条目(将 $
添加到所有密码哈希值之前),我的程序将使用以下代码(我不必为旧的 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, $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 将默默地失败。
md5
(或任何其他散列算法 - 请参阅 hash_algos()
的完整列表)每次都会将某些内容散列为一个常量(相同)的东西,换句话说:
'1234' ---md5---> '81dc9bdb52d04dc20036dbd8313ed055'
'1234' ---md5---> '81dc9bdb52d04dc20036dbd8313ed055'
'1234' ---md5---> '81dc9bdb52d04dc20036dbd8313ed055'
'1234' ---md5---> '81dc9bdb52d04dc20036dbd8313ed055'
...
但是password_hash($password, $algo)
每次都会将一些东西散列成新的东西,换句话说:
'1234' ---password_hash---> 'y$VXj5/N79aVolZQHJa.wdUub4C1uifXCNGRVKVUIYnsuRGs/wnXU/S'
'1234' ---password_hash---> 'y$BjSPyCyZU2Rui5MtL5MLC.bkLGbUxf/f9NshALvTc39lhemoWZFC6'
'1234' ---password_hash---> 'y$WXGX/6dCLbJN77MKNNVbCej9Fya2fQGvPjAMLuU3a6zGCDuBMisbm'
'1234' ---password_hash---> 'y$sqkB2ZK7BanIHTRZIKUHi.TVdseZE.GSMghBhuT7mDC9GrjW9g6Ky'
所以 hash_verify_kind_function() 只需要 password_hash()
生成的散列,因为你可以用 md5(或任何)散列你的字符串,然后检查它们是否相等 这是非常愚蠢的工作,因为在这种情况下你不需要先用 md5 散列它!因为实际上 md5 哈希并未用于密码哈希(以及验证)
有没有办法将 MD5
密码转换为 password_verify()
可以验证的密码?
我在 Crypt Wikipedia page 上看到 "The printable form of MD5
password hashes starts with $
."
因此我试一试(没有任何运气):
$password = "abcd1234";
$md5hash = "$".md5($password);
var_dump(password_verify($password, $md5hash));
有什么方法可以让 password_verify()
使用 MD5
密码吗?
提问原因:我有一个旧系统,其中密码存储为 MD5
哈希。我想开始使用更安全的 Password Hashing API
。如果我能够将现有的密码哈希值转换为适用于 password_verify()
的内容,我只需更新数据库条目(将 $
添加到所有密码哈希值之前),我的程序将使用以下代码(我不必为旧的 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, $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 将默默地失败。
md5
(或任何其他散列算法 - 请参阅 hash_algos()
的完整列表)每次都会将某些内容散列为一个常量(相同)的东西,换句话说:
'1234' ---md5---> '81dc9bdb52d04dc20036dbd8313ed055'
'1234' ---md5---> '81dc9bdb52d04dc20036dbd8313ed055'
'1234' ---md5---> '81dc9bdb52d04dc20036dbd8313ed055'
'1234' ---md5---> '81dc9bdb52d04dc20036dbd8313ed055'
...
但是password_hash($password, $algo)
每次都会将一些东西散列成新的东西,换句话说:
'1234' ---password_hash---> 'y$VXj5/N79aVolZQHJa.wdUub4C1uifXCNGRVKVUIYnsuRGs/wnXU/S'
'1234' ---password_hash---> 'y$BjSPyCyZU2Rui5MtL5MLC.bkLGbUxf/f9NshALvTc39lhemoWZFC6'
'1234' ---password_hash---> 'y$WXGX/6dCLbJN77MKNNVbCej9Fya2fQGvPjAMLuU3a6zGCDuBMisbm'
'1234' ---password_hash---> 'y$sqkB2ZK7BanIHTRZIKUHi.TVdseZE.GSMghBhuT7mDC9GrjW9g6Ky'
所以 hash_verify_kind_function() 只需要 password_hash()
生成的散列,因为你可以用 md5(或任何)散列你的字符串,然后检查它们是否相等 这是非常愚蠢的工作,因为在这种情况下你不需要先用 md5 散列它!因为实际上 md5 哈希并未用于密码哈希(以及验证)