php - 在 PHP7+MySQL 中从 SHA256 哈希密码迁移到 BCRYPT

标签 php mysql passwords bcrypt sha256

我有一个注册了几个用户的旧 Web 应用程序,它使用不安全的 hash("sha256", trim($_POST["password"])) 将散列密码存储在 MySQL 中数据库。现在我想更新 Web 应用程序以使用更安全的 BCRYPT password_hash() 但是我不想给所有注册用户发送电子邮件提醒他们更改密码。所以我正在考虑以这种方式在 sha256() 散列密码上实现 BCRYPT:

为了保存密码,我将使用 sha256() 散列用户密码:

$hashed_password = password_hash(hash("sha256", trim($_POST["password"])), PASSWORD_BCRYPT);

然后我会将BCRYPT散列密码保存在数据库中。

为了验证用户的密码,我只需这样做:

$hashed_password = "select hashed_password from users where email = 'abc@email.com'";

if(password_verify(hash("sha256", trim($_POST["password"])), $hashed_password))
{
    echo "Welcome";
}
else
{
    echo "Wrong Password!";
}

这样我将通过循环每个注册用户来更新 MYSQL 数据库中的用户密码,然后我将检索 sha256() 散列密码,最后我将在使用 password_hash( ):

$new_password = password_hash($old_sha256_hashed_password, PASSWORD_BCRYPT);

$mysql->save_user_password($new_password, $user_id);

因此用户仍然可以使用他们的旧密码登录。

您如何看待这个解决方案?

即使我在 BCRYPT 之前对密码进行 sha256() 哈希,它仍然安全吗?

最佳答案

由于您当前的散列系统(未加盐的 SHA256)确实非常不安全,您可以使用双重散列立即保护密码。尽快,当用户下次登录时,我会切换到新算法并删除双重哈希。

使旧哈希更安全:

$doubleHashToStoreInDb = password_hash($oldUnsaltedSha256HashFromDb, PASSWORD_DEFAULT);

对每一行执行此操作将保护以其他方式不安全地存储的密码。请注意 PASSWORD_DEFAULT 参数,它应该优先于特定算法,因为它是面向 future 的。并标记双哈希,这样你就可以区分双哈希和已经转换的哈希,see why .

处理新用户注册:

$hashToStoreInDb = password_hash($_POST['password'], PASSWORD_DEFAULT);

只需使用新算法,无需双重哈希。

验证登录:

if (checkIfDoubleHash($storedHash))
{
  $correctPassword = password_verify(oldPasswordHash($_POST["password"]), $storedHash);
  if ($correctPassword)
    storeConvertedHash(password_hash($_POST['password'], PASSWORD_DEFAULT));
}
else
{
  $correctPassword = password_verify($_POST['password'], $storedHash);
}

// Hashes the user password with a deprecated hashing scheme
function oldPasswordHash($password)
{
  return hash("sha256", trim($password));
}

双重哈希将转换为新的密码哈希函数,这是可能的,因为此时我们拥有原始用户密码。使用 password_verify() 验证新的哈希值这是面向 future 和向后兼容的功能。

使密码算法适应 future 的硬件不是一次性的任务,一旦新硬件变得更快,这将是必要的。 PHP 提供函数 password_needs_rehash()找出是否需要重新散列,然后您还可以计算一个新的散列并存储它。

关于php - 在 PHP7+MySQL 中从 SHA256 哈希密码迁移到 BCRYPT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56621046/

相关文章:

php - 检查日期是否在当前时间的 7 天内

MySQL JSON 数组用于 "IN"子句?

php - 将 X 数组变成单个数组

sockets -/etc/init.d 中缺少 mysqld.sock 和 mysqld

javascript - 告诉浏览器为同一域下的每个路径单独存储不同的密码

php - 在 Smarty 模板中运行 MySQL 查询

php - 当月的唯一文件编号

php - "Heartbeats"在 PHP/JS 中从客户端到服务器

php - Golang 和 Phpass (Php) 怎么办?

security - 可以存储可以检索的密码吗?