应该执行密码比较的最佳做法是什么

Blo*_*tac 6 security authentication web

在对网站进行用户身份验证时,是否应在数据库或网站中进行哈希生成和比较?

我的论点是网站应该将用户提供的密码(可能由Web服务器加密)传递给数据库.然后数据库用salt重新加密它并比较哈希值.数据库响应Web服务器用户的凭据是否有效.这样,最小的数据库离开数据库,基本上是是或否,没有存储的凭证信息.缺点是,数据库必须做更多的工作.

另一个论点是工作应该在Web服务器上完成.这里,Web服务器将创建哈希并从数据库请求存储的哈希并进行比较.在这种情况下,需要将salt从数据库传递回Web服务器以创建哈希.但是,随着Web服务器数量的增加,共享工作.

我个人认为第二种方法是潜在的安全风险.如果Web服务器受到危害,可以从数据库请求salt和哈希并轻松破解.

执行上述操作的最佳做​​法是什么?我忽视/遗失了什么吗?

谢谢

Lad*_*ada 2

我怀疑您会遇到的第一个问题(这是一个大问题)是您的数据库没有密码哈希函数。当然,它可能有 MD5() 和 SHA1() 但这些是加密哈希函数。它有 bcrypt() 或 scrypt() 或 PBKDF2() 吗?

使用加密哈希函数而不是密码哈希函数意味着 LinkedIn 密码可以如此快速地被破解。如果您不使用上述函数之一,那么如果您的哈希值泄露,您将同样容易受到攻击。


继续回答你的问题,假设你的数据库确实支持密码哈希算法(使用 bcrypt 只是因为我必须选择一个)。两种选择是:

数据库中的哈希值:

$db->query("SELECT COUNT(*) FROM users WHERE username = '?' AND password = BCRYPT(?, (SELECT salt FROM user WHERE username = '?'))", $username, $password, $username);
if($row['count'] != 1)
{
  // Not authenticated.  Throw exception.
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,原始密码将发送到数据库,并返回简单的是或否(1 或 0)。该数据库通信可以加密。哈希值和盐值永远不会保存在应用程序中。

应用程序中的散列:

$db->query("SELECT username, salt, password FROM users WHERE username = '?', $username);
if(bcrypt($password, $row['salt']) != $row['password'])
{
  // Not authenticated.  Throw exception.
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,哈希值和盐值从数据库提取到应用程序中,并在那里完成原始密码的哈希值和比较。与数据库的通信仍然可以加密。原始密码永远不会保存在数据库内存中。

为了提高效率,我们可以假设两种哈希算法都是用 C(或某种编译语言)编写的,并且可能由操作系统提供,因此需要相同的时间。应用程序哈希选项通过线路接收更多数据,而数据库哈希选项发送更多数据并具有更复杂的查询(本质上是两个查询,一个用于获取盐,一个用于进行比较)。可能无法按照我编写该查询的方式使用索引,但可以重写该查询。由于两种情况下数据的大小可能仍然是一个 TCP 数据包,因此速度差异可以忽略不计。由于子查询,我认为这是应用程序哈希选项的胜利。

为了曝光。我认为原始密码比哈希值和盐加在一起更敏感。因此,限制原始密码的暴露似乎是更安全的选择,使应用程序哈希成为最佳实践。