1

由于无法找到可工作的河豚的 php/javascript 实现,我现在正在考虑使用 SHA1 哈希来实现基于 Web 的身份验证,但由于缺乏对这一特定领域的了解,我不确定所选择的方法是否足够安全。

计划路线图:

  1. 用户的密码作为 MD5 哈希值存储在服务器上。
  2. 服务器发出一个公钥(当前时间的 MD5 哈希,以毫秒为单位)
  3. 客户端javascript函数将用户密码作为输入,并计算其MD5哈希
  4. 客户端然后从上面连接公钥和密码哈希,并计算结果字符串的 SHA1
  5. 客户端向服务器发送 SHA1 哈希,服务器使用公钥和用户密码 MD5 哈希执行类似的计算
  6. 服务器比较哈希值,匹配表示身份验证成功。
  7. 不匹配表示身份验证失败,服务器发布一个新的公钥,有效地使已经使用的公钥失效。

现在,有问题的部分是关于在 SHA1 之前连接两个密钥,这是否容易受到某种统计或其他攻击?

是否有任何特定顺序应该连接密钥以提高整体质量(即更高的位对加密的可靠性更重要)?

先感谢您。

4

2 回答 2

6

如果您只使用“公钥”(实际上不是公钥,它是一个随机数,并且应该是随机的,除非您真的希望它在某个时间范围内可用,在这种情况下,请确保您使用带有密钥的HMAC来生成它,因此对手无法预测 nonce ) 以防止重放攻击,并且它是固定大小的,那么连接可能不是问题。

也就是说,我有点担心您可能没有经过深思熟虑的安全模型。无论如何,这试图阻止什么攻击?用户的密码哈希是未加盐的,因此密码数据库的破解无论如何都会很容易地揭示明文密码,虽然有时间限制的随机数可以减轻来自被动嗅探器的重放攻击,但这样的被动嗅探器可能只会窃取用户的会话密钥反正。说到这里,为什么不直接使用会话密钥作为 nonce 而不是基于时间戳的系统呢?

但实际上,为什么不直接使用 SSL?密码学真的很难做到正确,比你或我聪明得多的人花了几十年的时间审查 SSL 的安全性以使其正确。

编辑:如果您担心 MITM 攻击,那么 SSL 将拯救您。时期。Mallory 可以将您的超级安全登录表单替换为以明文形式向他发送密码的表单。游戏结束。即使是被动的攻击者也可以通过网络看到一切——包括您的会话 cookie。一旦 Eve 获得会话 cookie,她只需将其注入浏览器并已登录。游戏结束。

如果您说您不能使用 SSL,那么您需要非常仔细地查看您要保护的确切内容,以及您将缓解哪些类型的攻击。您可能需要实现某种桌面应用程序来进行加密 - 如果 MITM 正在流行,那么您将无法信任您的任何 HTML 或 Javascript - Mallory 可以随意替换它们。当然,您的桌面应用程序将需要对数据流实施密钥交换、加密和身份验证,以及远程主机的身份验证——这正是 SSL 所做的。如果你做对了,你可能会使用与 SSL 几乎相同的算法来做到这一点。

如果您决定 MITM 不在范围内,但您想防止被动攻击,您可能需要在 Javascript 中实现一些严格的密码学 - 我们正在讨论Diffie-Hellman交换以生成永远不会发生的会话密钥通过网络发送HTML5 Web 存储等),在 Javascript 中使用 AES 来保护密钥等。此时您基本上已经在 J​​avascript 中实现了一半的 SSL,只有其中可能存在更多错误 - 尤其是这是在Javascript中很难获得安全随机数的问题。

基本上,您可以选择:

  1. 没有实现任何真正的加密安全(显然不是一种选择,因为您正在实现所有这些复杂的身份验证协议)
  2. 实现一些看起来很像 SSL 的东西,只是可能没有那么好
  3. 使用 SSL。

简而言之 - 如果安全很重要,请使用 SSL。如果您没有 SSL,请安装它。我知道的每个可以运行 JS 的平台也可以处理 SSL,所以真的没有任何借口。

于 2011-01-09T13:08:00.367 回答
1

bdonlan 是绝对正确的。正如所指出的,对手只需要用恶意代码替换您的 Javascript 表单,这对 HTTP 来说是微不足道的。然后游戏结束。

我还建议考虑使用盐将您的密码移动到 SHA-2,使用合适的加密随机数生成器生成(即不使用服务器的时钟播种)。此外,多次执行散列。请参阅http://www.jasypt.org/howtoencryptuserpasswords.html第 2 节和第 3 节。

MD5 坏了。不要使用 MD5。

您的安全方案需要类似于以下内容:

  1. 一切都发生在 SSL 上。身份验证表单、验证表单的服务器端脚本、图像等。这里不需要做任何花哨的事情,因为 SSL 会为您完成所有艰苦的工作。真正需要的只是一个简单的 HTML 表单,它以“纯文本”形式提交用户名/密码,因为 SSL 将加密所有内容。

  2. 用户创建新密码:您生成一个随机盐(不是基于服务器时间,而是来自良好的加密随机源)。多次散列盐 + 新密码,并将盐和生成的散列存储在您的数据库中。

  3. 验证密码:您的脚本为用户查找盐,并多次散列盐 + 输入的密码。检查数据库中的匹配。

唯一应该存储在数据库中的是盐和哈希/摘要。

假设您有一个需要支持的 MD5 哈希数据库,那么解决方案可能是为新的 SHA-2 哈希和盐添加数据库列。当用户登录时,您可以像以前一样检查 MD5 哈希。如果有效,则按照“用户创建新密码”中的步骤将其转换为 SHA-2 & salt,然后删除旧的 MD5 哈希。用户不会知道发生了什么。

任何真正偏离这一点的东西都可能存在一些安全漏洞。

于 2011-01-11T17:22:16.747 回答