在Web应用程序中实现密码salting和散列的基本过程

时间:2012-08-06 14:06:55

标签: security hash

我一直在寻找一个很好的解释,说明如何在典型的网站环境中实施密码登录系统。我已经阅读了一些很棒的维基百科文章和SO Q& A和博客等,但他们似乎总是专注于纯粹生成哈希而不是创建哈希发送的哪个部分的整个过程,存储它的哪个部分,服务器端是什么代码用它等。如果已经有一个很好的答案,我为重新发布道歉,请链接。

我目前的理解是:

1)新用户在您的网站上创建一个新帐户。他们输入“密码”,然后客户端代码生成并在末尾附加一个长的随机字符串“salt”并生成一个哈希 - >例如,BCrypt(密码+盐)。然后,客户端代码将完整哈希加上未散列的salt发送到服务器。

2)服务器将完整哈希和未哈希的salt存储在数据库的users条目中。

3)在用户登录期间,他们输入密码,然后再用盐进行哈希

问题1)客户端代码如何为每个用户生成相同的“随机”盐值?

问题2)此时客户端代码是否只发送没有盐的完整哈希?

问题3)服务器端收到完整哈希后会做什么? (简单地将发送的完整哈希与存储的完整哈希进行比较?如果是这样的话,攻击者在攻击数据库并获取存储的完整哈希值时只能直接使用它们发送到服务器登录?这是基于我的假设,登录过程主要涉及服务器将客户端发送的完整哈希与存储在db中的完整哈希进行比较。

问题4)是否应始终通过安全连接发送密码?或者是否对它们进行腌制和散列使任何人都可以看到它?

2 个答案:

答案 0 :(得分:3)

您正在混淆散列的目的。它不是为了保护有线传输的密码。客户端不生成哈希。哈希的目的是防止攻击者破坏您的数据库,使其能够快速使用预先生成的哈希查找表来确定您的用户密码是什么。

随着@jhoyla在下面的评论中指出,工业级生产计划更加复杂。

创建帐户:

  1. 客户端与服务器建立安全(加密,例如SSL)连接,并以明文形式发送用户名和密码(这是正常的,因为它是加密的)。

  2. 服务器生成随机盐,将其附加到密码,散列结果,并存储散列和未散列的盐值。

  3. 登录:

    1. 客户端与服务器建立安全(加密,例如SSL)连接,并以明文形式发送用户名和密码(这是正常的,因为它是加密的)。

    2. 服务器从存储中检索salt,将其附加到密码,对其进行哈希处理,并将结果与​​存储中的哈希密码进行比较。如果匹配,则用户已登录。

    3. 为了确定我们这样做的原因,想象一下我成功攻击了网站的数据库服务器并下载了数据库。我现在有一个用户名列表,可能是电子邮件地址和密码哈希值。如果密码没有被腌制,那么很多哈希很可能是相同的(因为许多人使用相同的弱密码)。我知道其中一个用户在(例如)他们的电子邮件帐户上拥有相同弱密码的可能性非常高。所以我开始工作并散列整个字典,加上许多其他可能的密码,寻找与这些流行的密码相匹配的散列。如果我受到打击,我就打破了一堆密码。如果我很聪明,我会提前生成这个列表,这样我就可以快速完成。

      现在想象密码是咸的。现在,即使两个人使用相同的密码,也会为每个人生成不同的盐,并且产生的哈希值会有所不同。我无法知道哪些密码很弱,常用密码以及哪些是强密码。我可以通过将盐附加到每个可能的密码来尝试我的字典攻击,但破解密码的难度(就时间而言)现在呈指数级增长。

答案 1 :(得分:2)

永远不要自己实施!如果你需要它只是为了学习,那么@Chris回答你。但如果你需要一个正常工作的软件,那就不要这样做了。每种语言都有安全库,每个数据存储(ldap,数据库)都有已实现的密码存储机制。使用它,不要再发明轮子,因为你很可能会错过一些细节