双重哈希密码 - 客户端&服务器

时间:2010-06-10 20:20:26

标签: security passwords hash design-patterns hmac

嘿,首先,让我说,我不是在问md5之类的东西(md5(......,已经有关于它的话题。

我的问题是:

我们允许客户在本地存储密码。当然,我们不希望它们存储在计划文本中,因此我们在存储和/或发送之前将它们本地hmac。现在,这很好,但如果这就是我们所做的全部,那么服务器将拥有存储的hmac,并且由于客户端只需要发送hmac而不是纯文本密码,攻击者可以使用服务器中存储的哈希值访问任何人的帐户(在灾难性的情况下,当然有人会获得对数据库的访问权限。)

所以,我们的想法是通过hmac在客户端上编码一次密码,将其发送到服务器,然后通过hmac对其进行第二次编码,并将其与存储的两次hmac密码进行匹配。这将确保:

  • 客户端可以在本地存储密码,而无需将其存储为纯文本
  • 客户端可以发送密码,而不必担心(太多)其他网络方
  • 服务器可以存储密码,而无需担心有人从服务器上窃取密码并使用它来登录。

当然,所有其他事情(强密码,复盐等)也适用,但与问题无关。

实际问题是:这听起来像一个坚实的安全设计吗?我们是否忽略了以这种方式做事的任何缺陷?是否有类似这样的安全模式?

附录:我们不希望在客户端上以纯文本本地存储密码的原因是因为很多人仍然使用相同的密码进行多项服务,因此获取“真实”密码会对于用户来说,这比对他的哈希被盗更严重。

7 个答案:

答案 0 :(得分:11)

我正在跑出门,但是Skeet砰的一声,你不会对Skeet感到沮丧。

您正在做的是用另一个常量值替换密码。这里没有任何收获,唯一的安全措施是无法在客户端计算机上发现纯文本密码。

您接下来要做的是处理HMAC(您确定您的意思是HMAC吗?如果是这样,密钥来自哪里,并存储?)作为密码本身的密码 - 您将其从客户端发送到用于进行身份验证的服务器。第二个HMAC或散列是没有意义的 - 您正在与发送的值进行比较 - 它是任何其他名称的密码。因此,作为攻击者,我只需要窃取存储在客户端计算机上的HMAC,而不是窃取密码。这里什么都没有。

答案 1 :(得分:6)

警告:我不是安全专家。我会ping blowdart,看看他是否喜欢加入。

如果客户端只是存储哈希值,并根据哈希值有效地传输 ,那么他们有效以纯文本格式存储它。第一个哈希提供的唯一好处是,如果他们在不同的系统上使用相同的密码,那么如果显示哈希,则其他系统不会受到损害。

换句话说:如果有人能够掌握存储在服务器上的哈希值,那就是他们登录系统所需的全部内容......就像纯文本存储一样。

答案 2 :(得分:6)

正如其他人所说的那样,将客户端和你的系统隔离开来并没有真正为你买任何东西 - 第一个哈希就变成了密码。

如果(很可能)客户端在其他系统上使用相同的密码,则会出现该值。在这种情况下,如果客户端计算机受到危害,那么至少您的哈希密码的本地副本不允许攻击者访问其他系统。显然,客户端的攻击者现在能够访问您的服务器了 - 毕竟他们已经获得了密码。

有权访问服务器上的双哈希值的攻击者不会购买任何东西,因为他们无法反转它以获得单个哈希值(即“密码”)。当然,如果攻击者能够读取您的安全数据库,那么我怀疑他们还有其他可用的攻击媒介:)

另外,正如另一张海报所说,确保你在两个哈希上使用盐。如果不这样做,如果密码不强,反转哈希实际上可能非常简单。

编辑 - 实际上,考虑一下,因为你使用哈希作为密码,你真的不需要在服务器上使用盐。没有人能够创建一个有效的彩虹表:)尽管在客户端仍然需要一个。

答案 3 :(得分:3)

不,这不安全。散列值实际上是密码。密码是从用户认为是 密码的其他内容派生的,这一事实并不重要。这是验证用户身份的秘密值,对吧?听起来像是我的密码。

我认为这取决于声明,“当然,我们不希望它们存储在计划文本中,因此我们在存储和/或发送之前将它们本地化。”如果系统被更改以使哈希密码现在具有密码曾经具有的相同功率,则应使用哈希密码同样谨慎。

答案 4 :(得分:1)

吹笛击中了头上的钉子 - 你只是改变了secet偷窃,没有保护任何东西。您正在尝试复制的内容是一种旧的身份验证协议,我无法为我的生活记住其名称。以下是它的工作原理:

初始化后,服务器获取密码,迭代散列n次,由F n (pass)表示。客户端有密码,编号为n。

您进行身份验证,然后发送服务器F n-1 (pass) - 即密码哈希n-1次。服务器再次对其进行哈希处理,将其与F n (pass)进行比较,如果匹配,则可以访问。然后服务器用F n-1 (pass)替换F n (pass),然后递减n。

下次进行身份验证时,您发送F n-2 (通过)并重复该过程。

让我们检查安全性:

  • MITM:协议中没有内置抗拒,你必须将它分层在SSL中
  • 重播攻击:它们不起作用,因为服务器已经减少了哈希迭代次数。
  • 窃听:下一次身份验证将使用F n-1 (pass)完成。你有F n (通过)。根据散列函数的定义,从F n (传递)到F n-1 (pass)是不可行的
  • 拥有服务器:您不知道客户端的密码,也不能像他们一样进行身份验证,因为当您只有F 时,您还需要F n-1 (pass) ñ
  • 拥有客户端:由于您存储F n-1 (传递)(因此他们不必输入密码) - 然后拥有客户端会让攻击者登录。如果您只存储n而不是密码,则会阻止此密码,但您显然希望保存密码。

这就是你想要完成的事情。然而,这个协议没有被使用是有原因的 - 它是一个同步的巨大婊子。如果客户端和服务器因半步完成而不同步,则表示您已被锁定。您为避免这种情况而构建的任何弹性都可能降低重放或窃听的安全性。

答案 5 :(得分:0)

我不确定这会以明文本地存储密码为止。

本地加密的目的是防止黑客将密码发送到您的服务器。但是,如果您打算将加密表单发送到......那么,您还没有购买任何东西。

相反,本地计算机应以双向加密格式存储密码。这意味着它可以被解密。你在传递之前做了哪些事。 db可以存储单向加密格式(甚至使用单独的加密机制)。在比较之前,您加密收到的内容然后检查。

答案 6 :(得分:0)

要实现的密码的初始哈希是什么?它将防止发现密码的纯文本版本。它不会阻止使用该哈希值来计算双重散列值。