我和我的一个朋友正在讨论在将其发送到我们的服务器之前是否应该预先哈希该Web应用程序用户的密码。
我知道已经有多个问题可以解决此主题,但是它们都是关于将其安全地传输到服务器的问题。我们的想法不是关于传输安全性(我们使用SSL),我们希望对客户端进行哈希处理以防止“真实”密码到达我们的服务器。
这个主意是在Twitter宣布他们的bug导致密码以明文形式打印到日志文件时出现的。
我们目前正在讨论这个概念是否有意义,以及如果我们要使用SHA512对其进行哈希处理的话,它将如何影响密码的安全性(就Bruteforce而言)。
TL; DR:
我们要在客户端对密码进行哈希处理,以防止我们的服务器以明文形式获取密码(我们使用SSL进行传输)。
这有意义吗?
哪种算法最适合用于散列?
然后,将使用bCrypt将散列的密码再次在服务器端进行散列。
答案 0 :(得分:2)
100%有意义:实际上,这个概念已经由许多人提出,但是困难在于正确实施。如果做错了,就会有很多陷阱,最直接的陷阱就是@ swa66描述的容易受到“哈希传递”的影响。为了防止这种情况,您需要在两侧进行哈希处理。客户端哈希应较慢(bcrypt,scrypt,argon2或pbkdf2),而服务器哈希应较快(sha256)。
编辑:许多人在不了解其工作原理的情况下对其进行了否决,因此,我现在在此处包括基本细节(以前我仅链接至此工作原理)。这个想法是在客户端应用慢速哈希(例如bcrypt),然后在服务器端应用快速哈希(例如SHA256)。需要快速散列来防止散列攻击。在数据库泄漏的情况下,攻击者可以通过散列来反转快速散列(不可能-违反了密码散列函数的单向属性),也可以强行将原映像强行用于快速散列(不可能-大小为慢散列的输出长度(例如bcrypt的184位),或者蛮力组合慢散列和快速散列-使攻击者回到相同的位置,就像整个计算已经发生一样服务器端。因此,在数据库泄漏的情况下,我们不会通过将大量计算转移到客户端来降低密码攻击的安全性。
我在Method to protect passwords in databases for web applications中调查了许多类似的建议。此外,我分析了利弊,并找出了以前没有发现的弱点(帐户枚举),并提出了一种安全地做到这一点的独特方法。该研究基于许多来源,包括:
您举了Twitter的例子,GitHub也做了类似的事情。当我在上面撰写论文时,防止服务器看到明文密码的最著名示例是Heartbleed,我在论文中对此进行了评论(第1.3节的底部)。
其他人随后进行了后续研究,发现了类似的想法-Example: Client-Plus-Server Password Hashing as a Potential Way to Improve Security Against Brute Force Attacks without Overloading the Server。没有人应该得到所有的荣誉,但是主要的收获是,如果您安全地执行此操作,这是一个好主意,但是您确实需要了解风险(如果您没有阅读研究报告,很容易不安全地进行操作)。< / p>
答案 1 :(得分:1)
否!
密码学中的第一个规则:不要自己发明密码,否则会犯下可怕的错误。
这并不是对您个人不利,到目前为止,并非如此:即使是顶尖的专家在精心设计新系统时也会犯错。这就是为什么在任何事情成为标准之前,他们会多次同行评审彼此的工作。由于在同行评审中发现问题,因此专家重新制定了许多有关此类标准的建议。那么,为什么我们其他人不能仅是凡人设计:没有足够的人去做同行评审,因为专家们不会碰它。
散列密码客户端
散列客户端真的很糟糕,因为散列成为密码,现在您将其以明文形式存储在服务器上。
密码设置方法
使用SLOW哈希。即使使用盐,使用快速哈希也是一个常见的致命错误。人们知道的大多数散列函数(例如SHA-256,SHA-3等)都是快速散列,并且完全不适合对短而可预测的项(例如密码)进行散列,因为它们可以在令人惊讶的短时间内被逆转。
多么慢:尽可能地慢。缓慢散列的示例: bcrypt,PBKDF-2(实质上是 快速散列使其变慢)
有-根据您的编程环境-预制例程,请使用它们!
参考:
答案 2 :(得分:1)
@ swa66概述了如何安全地管理密码,但请注意,有一个有效的场景可以考虑客户端密码哈希,所以不要盲目地遵循“最佳实践” ,请先理解它。
假设我有一个标准的Web应用程序,用于存储来自用户的数据。在我的威胁模型中,我什至不希望自己的用户信任我,换句话说,即使我的服务器完全受损,我也希望我的用户数据是安全的。因此,我让他们选择一个密码,并在将其数据发送到应用程序之前在客户端上对其数据进行加密。他们可以使用其用户ID检索其加密数据。好吧,这听起来不太安全,我可以下载任何人的加密数据并对其进行离线攻击。因此,让他们使用其密码访问其加密数据(我不希望他们必须记住两个不同的密码)。但这不好,因为我先输入了他们的密码,然后解密了他们的数据。因此,一种简单的解决方案是使用密码对他们的数据进行加密,并将其与哈希密码一起发送到服务器,正如答案 中正确指出的那样,就算是服务器,新密码也是正确的(因此服务器应再次将其存储为散列值,依此类推)。但是,服务器无法解密客户端数据,因为它从未拥有原始密码,但是只有有效人员才能下载甚至加密的内容,而且他们只需要记住一个密码即可。 (请注意,这是一个非常简化的模型,实际上,还需要做更多的工作,例如适当的密钥派生函数,不仅是简单的散列,而且还有另外一个更长的故事。)
不要误会我的意思,我并不是说您通常应该在客户端上对密码进行哈希处理-不,另一个答案在这方面是正确的。我只是想证明至少有一个 用例,其中客户端密码哈希是有效的选择。查看著名的密码管理器,其中一些工作与此类似。