0

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

我目前的理解是:

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

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

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

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

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

问题3)服务器端收到完整哈希后会做什么?(只需将发送的完整哈希与存储的完整哈希进行比较?如果是这种情况,那么攻击者不能在闯入数据库并获取存储的完整哈希值时直接使用它们发送到服务器进行登录吗?这是基于我的假设,即登录过程本质上涉及服务器将客户端发送的完整哈希与存储在数据库中的完整哈希进行比较。

问题 4) 是否应始终通过安全连接发送密码?还是对它们进行加盐和散列处理可以让任何人看到?

4

2 回答 2

3

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

下面是一个简单的例子——正如@jhoyla 在下面的评论中指出的那样,工业级生产方案更加复杂。

要创建一个帐户:

  1. 客户端与服务器建立一个安全的(加密的,例如 SSL)连接,并发送用户名和密码,通常是明文(没关系,因为它是加密的)。

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

登录:

  1. 客户端与服务器建立一个安全的(加密的,例如 SSL)连接,并发送用户名和密码,通常是明文(没关系,因为它是加密的)。

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

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

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

于 2012-08-06T14:48:37.827 回答
2

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

于 2012-08-06T19:38:12.570 回答