后端密码加密与哈希的区别

3

我有关于保护用户身份认证的最佳方法的问题。

我遇到了一个Web应用程序,它在后端使用相同的密钥对用户密码进行加密。此外,这个密钥是在后端“硬编码”的。

应用程序开发人员声称这是完全安全的。然而,我有我的疑虑。我认为这种方法可能会导致两个问题:

  • 加密密码的原因是为了避免在未经授权的数据库访问事件中访问密码。但是,如果您将密钥存储在同一服务器上,则有机会获取该密钥。

  • 相同的密码将产生相同的加密值,因此更容易攻击系统。

我的问题如下:

  • 我的观点是否正确?如果它真的不安全,我应该警告他们可能存在的威胁吗?

  • 使用哈希+盐方法的优缺点是什么?

谢谢!


是的,加密的密码可以被解密,因此如果系统被访问,它们就会变得容易受攻击。而经过盐值处理和哈希的密码则不会有这种风险。 - dbugger
1
你的批评完全正确。你已经警告过他们了。是否坚持取决于上下文,只有你能够充分评估。使用加盐哈希没有任何缺点。这是执行密码认证的正确方式。存储加密密码是一种特殊情况,就像密码管理器一样,其中个人使用主密钥加密自己的凭据。这绝对不是身份验证的正确解决方案。 - erickson
谢谢@erickson。我看到使用哈希+盐确实是最好的解决方案,而且实现起来并不比加密方案更复杂。 - Felipe Sulser
@FelipeSulser 那确实是正确的方法 :-) - Juxhin
2个回答

4
我不确定你是否混淆了加密和哈希。如果用户的密码被 加密 而不是 哈希,那么在数据泄露事件中攻击者有可能窃取所有用户密码。
当涉及身份验证时,有一些因素似乎被忽略了。首先,任何哈希都应该在后端完成,而不是在前端完成。在前端进行哈希仍然会使您容易受到哈希攻击。
一些开发人员采用双重哈希方法,即在前端哈希密码,然后在后端重新哈希密码。我认为这是不必要的,前端密码应该由 HTTPS 层 (TLS) 进行覆盖,但这是有待讨论的。
首先,让我们澄清两个关键术语,然后解释如何安全地存储和验证用户。

加密

你指定用户的密码被 加密 而不是哈希。加密函数将输入(用户密码)映射到输出(加密密码),这意味着这是 可逆的
这意味着如果黑客获取了加密密钥(私钥),他们可以轻松地反转整个过程。
散列值
相反,用户的密码应该在服务器端进行哈希。为什么?因为你可以通过比较两个哈希值来检查它们是否匹配而不必存储该值的明文表示形式。
再次提醒,你可能会问,“为什么”? 嗯,因为哈希函数是单向的,这意味着无法将明文值反转(好吧,它们很难),我不会详细介绍。
我该怎么做?
用户的密码永远不应以明文形式存储在Web服务器的任何部分中。相反,应该存储用户的哈希值。当用户尝试登录时,你通过HTTPS / TLS安全地接收其明文密码,对其进行哈希,如果两个哈希匹配,则认证用户。
因此,数据库表可能如下所示:
+--------------------------------------+
|  ID  |  Username  |   Password Hash  |       
+--------------------------------------+
|  1   | foo        | $2a$04$/JicM     |
|  2   | bar        | $2a$04$cxZWT     |
+--------------------------------------+
  • 注意,哈希值是使用4轮(也称为无效)截断的BCrypt哈希值

现在让我们以Alice和我们的服务器之间的示例为例。不要过于字面理解数据。

Alice使用她的凭据发送登录请求,首先通过我们的安全传输层:

{username: "foo", password: "bar"} -> TLS() -> ZwUlLviJjtCgc1B4DlFnK -> | Server |

我们的服务器接收到这个请求后,使用它的证书密钥来解密:

ZwUlLviJjtCgc1B4DlFnK -> KEY() -> {username: "foo", password: "bar"} -> Web Application

太好了!我们的凭据已经安全传递了,那么接下来呢?对密码进行哈希处理并与我们在数据库中得到的进行比较。

BCRYPT('bar') -> $2a$04$/JicM

if ($2a$04$/JicM == user.get_password_hash) {
    authenticate();
}
else {
    return status_code(401);
}

我们现在已经能够验证用户身份,存储一个不可逆的哈希值,而无需存储明文值。这应该已经回答了您的第一个和第二个问题。

很好的且详尽的定义。尽管我已了解哈希和加密的概念,但这是一个完整的定义,并介绍了哈希的主要优势。谢谢! - Felipe Sulser
@FelipeSulser - 非常好,很多人经常混淆这两个概念,我认为在直接回答你的问题之前解释一下它们之间的主要区别会很有益。很高兴你觉得有帮助 :-) - Juxhin

0

是的,你的分析是正确的,这是不安全的。

它肯定无法通过任何正式的审计,例如PCI-DSS。开发人员/运营人员可能会辩称,这些账户提供的资产价值很小,因此他们没有必要提供如此高级别的保护措施,然而他们仍然有责任对客户负责 - 而且大多数人会在不同的网站/服务上使用相同的密码。

它确实为用户提供了一种“恢复”密码的方式,而无需创建一个过期的一次性密码 - 然而,发送明文密码进一步削弱了安全性。

事实上,即使攻击者只能访问加密的密码数据(特别是如果它包含已知的加密值/不使用初始化向量),也可能可以推导出加密密钥。


2
虽然我同意你的回答,但最后一段是错误的(你使用了“可能”,但实际上高度不可能)。如果从许多明文密文对中可以推导出密钥,则此对称密码已被破解,并且在任何情况下都不应使用。AES是最常用的密码之一,但并非这样的密码。 - Artjom B.
同意密码的选择会产生影响 - 但我们不知道这里使用的是什么密码。此外,由于没有 IV 和多个短消息,加密实际上是在 ECB 模式下进行的。 - symcbean
但是,如果我们把它分解开来不是更容易吗?例如,如果表中的两行包含加密密码x,其中一行的密码提示是“狗的名字”,另一行的密码提示是“最喜欢的餐点”,那么你可以假设答案是“肉丸子”。这样可能更容易破解,对吧? - Felipe Sulser
@FelipeSulser 猜测这两个密码可能更容易,但使用它们无法恢复密钥并解密所有其他密码。您所描述的漏洞在任何密码身份验证方案中都是可能的,这就是为什么密码提示不安全的原因。 - erickson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接