提问人:Zakaria 提问时间:9/15/2010 最后编辑:dimo414Zakaria 更新时间:6/4/2022 访问量:120253
是否值得在客户端对密码进行哈希处理
Is it worth hashing passwords on the client side
问:
当我想安装登录系统时,我总是将给定密码的 MD5 与其在服务器端用户表中的值进行比较。
但是,我的一个朋友告诉我,“清除”密码可能会被网络软件嗅探。
所以我的问题是:在客户端对密码进行哈希处理是个好主意吗?它比在服务器端散列它更好吗?
答:
基本上,你的朋友是对的。但是,简单地在客户端对密码进行哈希处理,只比将其作为纯文本提交给服务器要好。可以监听您的纯文本密码的人当然也能够监听哈希密码,并使用这些捕获的哈希来对您的服务器进行身份验证。
就此而言,更安全的身份验证协议通常会跳过许多障碍,以确保这种重放攻击无法奏效,通常允许客户端选择一堆随机位,这些随机位与密码一起散列,并以明文形式提交给服务器。
在服务器上:
- 生成几位随机数
- 将这些位(以明文形式)发送到客户端
在客户端上:
- 生成一些随机位
- 连接密码、服务器的随机位和客户端的随机位
- 生成上述的哈希值
- 向服务器提交随机位(明文)和哈希值
由于服务器知道自己的随机信息以及客户端的随机位(它以明文形式获取它们),因此它可以执行基本相同的转换。该协议确保,在此对话中监听的任何人都不能稍后使用信息使用记录的信息进行错误身份验证(除非使用了非常弱的算法......),只要双方每次产生不同的“噪声位”,就会执行握手。
编辑所有这些都容易出错且乏味,而且有些难以正确(阅读:安全)。如果可能的话,可以考虑使用已经由知识渊博的人编写的身份验证协议实现(与我不同!以上只是我前段时间读过的一本书的记忆。你通常真的不想自己写这个。
评论
你可能不用担心这一点 - 正如 Dirk 所提到的,即使你对密码进行哈希处理,恶意用户也可能在网络上并看到哈希被发送,并且可能只是自己发送相同的哈希。
它稍微好一点,因为它可以防止恶意用户知道密码是什么,但由于他们仍然可以登录(或可能重建原始密码),因此这并没有那么有用。
一般来说,如果您担心用户密码和数据的安全性(您应该这样做!),则需要使用安全的SSL服务器。如果出于某种原因,这不是您关心的问题,您最好不要为散列而烦恼;这只是通过默默无闻获得安全。
编辑 2014 年 8 月:谷歌越来越强烈地推动网站在任何地方都切换到HTTPS,因为保护通信本身是防止网络嗅探攻击的唯一方法。试图混淆传输的数据只会阻碍而不是阻止专门的攻击者,并可能给开发人员带来危险的虚假安全感。
评论
x
这取决于,您可以使用客户端哈希,但服务器端盐是不可能的。
我最近在这方面做了很多工作,IRL 客户端哈希/对称加密有两个问题,真正扼杀了这个想法: 1.你必须以某种方式将盐带回服务器......要在客户端加密它,您需要一个密码......这违背了目的。 2. 你暴露了你的哈希实现(这不是一个大问题,因为大多数网站使用 3 或 4 个哈希算法之一),这使得攻击更容易(因为只需要尝试一个而不是 n)。
我最终去的是使用 OpenPGP.js 或类似工具在客户端上进行非对称加密...... 这依赖于客户端上导入的或客户端生成的密钥以及发送其公钥的服务器。只有客户端的公钥才能发送回服务器。 这可以防止 MIM 攻击,并且与设备一样安全(我目前默认将客户端的私钥存储在 localStore 中,这是一个演示)。
这样做的主要优点是,我永远不必将用户数据存储在服务器/数据存储上未加密的内存中(并且我服务器的私钥在物理上是独立的)
其基础是为人们提供一种在HTTPS受到限制的情况下进行安全通信的方法(例如,伊朗/朝鲜atc...),也只是一个有趣的实验。
我远不是第一个想到这一点的人,http://www.mailvelope.com/ 使用它
如果有人可以在您的连接上看到数据传入和传出,则身份验证不会保存您。 相反,我会为超级秘密的东西做以下事情。
在发送到服务器之前在客户端预先哈希的密码。 (服务器存储从浏览器发送的该哈希值的另一个哈希值和加盐值)。
因此,中间人攻击可以允许他们发送与他们相同的哈希值来登录,但用户密码不会被知道。这将阻止他们尝试使用相同凭据的其他服务在其他地方登录。
用户数据在浏览器端也是加密的。
啊,所以中间人攻击会得到加密数据,但如果没有用于登录的实际密码,就无法解密它。(用户登录时存储在浏览器的 DOM 中的密码)。 因此,真正的用户会看到解密的内容,但中间人不能。 这也意味着任何 NSA 或其他机构都无法要求您/公司/托管服务提供商解密这些数据,因为他们也不可能这样做。
这两种方法的一些小例子在我的博客上 http://glynrob.com/javascript/client-side-hashing-and-encryption/
实际上,我不同意在这种情况下客户端哈希更安全。我认为它不太安全。
在数据库中存储密码的哈希值而不是真实密码(甚至是加密密码)的全部意义在于,从哈希值中获取原始密码在数学上是不可能的(尽管理论上可以获得冲突哈希输入,其难度取决于哈希算法的安全强度)。这里可能的攻击媒介是,如果潜在的攻击者以某种方式破坏了您的密码存储数据库,他/她仍然无法获取您用户的原始密码。
如果您的身份验证机制发送密码的哈希值,那么在“安全漏洞”场景中(即攻击者以某种方式获得了您的密码数据库的副本),攻击者不需要知道真实密码 - 他们只需发送他们从漏洞中获得的哈希密码,嘿,他们有权访问该用户的帐户。这完全违背了首先存储散列密码的意义!
真正安全的方法是向客户端发送一次性公钥,让他们加密密码,然后在服务器端解密并重新散列。
顺便说一句,这种问题可能会在Security StackExchange上得到更多专家的回答。
评论
首先,这不会提高应用程序的安全性(假设它是一个 Web 应用程序)。
使用 SSL(或者实际上是 TLS,通常称为 SSL)。使用 Certbot 进行设置是免费且简单的。
原因很简单。TLS 解决了一个在加密学中非常大的问题(当与证书颁发机构的证书一起使用时,而不是自签名):我如何知道我正在与之交谈的服务器是我认为我正在与之交谈的服务器?TLS证书是一种说法:“我,证书颁发机构,受您的浏览器信任,证明[url]的网站具有此公钥,并具有相应的私钥,只有服务器知道(私钥),看我在整个文档上签名了我的签名,如果有人更改了它,您可以看到”。
没有TLS,任何加密都变得毫无意义,因为如果我在咖啡店里坐在你旁边,我可以让你的笔记本电脑/智能手机认为我是服务器和MiTM(中间人)你。使用 TLS,您的笔记本电脑/智能手机会尖叫“不受信任的连接”,因为我没有与您的站点匹配的证书颁发机构签名证书。(加密与身份验证)。
免责声明:用户倾向于直接点击这些警告:“不受信任的连接?什么?我只想要我的小猫照片!添加例外 点击确认 点击YAY!小猫!
但是,如果您真的不想使用证书,请仍然实现客户端 Javascript 哈希(并使用斯坦福库 (SJCL),切勿自己实现加密)。
为什么?密码重用!我可以在没有 HTTPS 的情况下轻松窃取您的会话 cookie(这允许我向您的服务器假装我是您)(参见 Firesheep)。但是,如果您将 Javascript 添加到登录页面,在发送之前,它会对您的密码进行哈希处理(使用 SHA256,或者更好的是,使用 SHA256,向他们发送您生成的公钥,然后用它加密哈希密码,您不能使用盐),然后将哈希/加密密码发送到服务器。用盐重新散列服务器上的哈希值,并将其与数据库中存储的内容进行比较(像这样存储密码:
(SHA256(SHA256(password)+salt))
(将盐也保存为数据库中的纯文本))。并像这样发送您的密码:
RSA_With_Public_Key(SHA256(password))
并像这样检查您的密码:
if SHA256(RSA_With_Private_Key(SHA256(sent_password))+salt_for_username) == stored_pass: login = ok
因为,如果有人嗅探您的客户端,他们将能够以您的客户端身份登录(会话劫持),但他们永远不会看到明文密码(除非他们更改了您的 Javascript。但是,星巴克黑客可能不知道如何或对此不感兴趣。因此,他们将访问您的 Web 应用程序,但不能访问他们的电子邮件/Facebook/等(您的用户可能会使用相同的密码)。(电子邮件地址要么是他们的登录名,要么是他们的个人资料/设置中的 Web 应用)。
评论
考虑一下:-
客户端向服务器发送请求“我有要验证的密码”。
服务器向客户端发送一次性随机字符串。雷亚尔
客户端将用户的密码嵌入到此字符串中(基于您希望应用的任何(变量)规则)。
客户端将字符串发送到服务器,如果密码正常,则服务器将用户登录。
如果服务器收到另一个使用 R$ 的登录请求,用户将被注销,帐户将被冻结,等待调查。
显然,将采取所有其他(正常)安全预防措施。
最近,GitHub和Twitter都宣布将密码存储在内部日志中。我在错误报告和其他日志中无意中发生了这种情况,这些日志进入了 splunk 等。对于Twitter来说,如果特朗普的密码在日志中,那么管理员“看到”它可能是一件大事,对于其他网站来说,可能没什么大不了的,因为管理员对它没有太大用处。无论如何,作为管理员,我们不喜欢看到密码,不是吗。
因此,问题在于是否应该在客户端进行哈希以确保安全,但是我们如何在密码最终被服务器端进行哈希和比较之前保护密码,以免以某种方式被记录下来。
加密并不是一个坏主意,因为开发人员至少必须跳过一些障碍,如果您发现密码进入了日志,您可以更改加密密钥,销毁原始密钥,然后数据变得毫无用处。更好的是每晚轮换钥匙,它可以大大减少窗户。
您还可以在用户记录中对哈希进行哈希处理。泄露的密码将是散列的纯文本密码。服务器将存储哈希的哈希版本。当然,哈希会成为密码,但除非你有照相记忆,否则你不会记住 60 个字符的密码。Salt 替换为用户名。如果你能在登录过程中收集一些关于用户的信息(同时不暴露用户记录的存在),你也可以用它来创建一个更强大的哈希值,不能在站点之间共享。中间的任何人都无法在站点之间剪切和粘贴捕获的哈希值。
结合一个没有被提交回服务器的cookie,你可能会遇到一些事情。在第一次请求时,使用密钥向客户端提交一个 cookie,然后确保该 cookie 不会返回登录服务,因此它被记录的可能性很小。将密钥存储在会话存储中,然后在登录发生后或会话过期后立即将其删除...这需要你们 JWT 家伙的状态,但也许只是使用 nosql 服务。
因此,在这条路上,管理员会在 splunk 或错误报告工具中遇到这些散列和加密的密码之一。这对他们来说应该是无用的,因为他们再也找不到加密密钥了,即使他们找到了,他们也必须暴力破解哈希。此外,最终用户没有发送任何明文,所以中间的任何人至少都有更困难的时间,你不能只是跳到另一个网站并登录。
评论
请注意,保护密码免受第三方侵害并不是全部。
一旦涉及隐私(现在什么时候不涉及隐私?您不想知道密码。你不能滥用或泄露你没有的东西,所以如果你从来没有看到他们的明文密码,你和你的客户都可以睡得更好。
因此,对客户端进行哈希/加密是有意义的。
评论
x
n
这种客户端哈希的想法是为了保护用户,而不是您的网站。如前所述,纯文本或散列密码都可以平等地访问您的网站。您不会获得安全权益。
但是您的用户实际的纯文本密码应该只有他们自己知道。知道他们选择的密码是可以在其他站点和系统上对他们使用的信息。您是一个以客户为中心的网站,通过保护他们的密码选择不被您的服务器开发人员或第三方发现。
我想出的方法是使用 SHA-256 进行多轮和随机盐......
salt = generate random salt
hash = sha256(password)
for (i = 0 to rounds)
hash = sha256(hash + salt)
这将以只有用户知道密码是什么的方式对密码进行加密。salt 和 hash 都存储在数据库中。我还使用服务器生成的随机字符串在客户端实现了这一点。
server_data = {
algorithm,
rounds,
salt,
string
}
hash = hash(server_data.algorithm, password)
for (i = 0 to server_data.rounds)
hash = hash(server_data.algorithm, hash + salt)
hash = hash(server_data.algorithm, hash + server_data.string)
在加密课上,我们被教导攻击者可以知道算法、盐、回合等......但在这种情况下,永远不会发送实际的哈希密码。服务器知道它发送的随机字符串是什么,因此在客户端上生成完整的哈希值,最后部分是使用随机字符串对结果进行哈希处理。这是发送到服务器的结果。结果实际上是一个一次性密码,在重放攻击中毫无用处。用户的密码永远不会以明文形式发送,如果攻击者获得了密码哈希,则对他们来说毫无用处,因为服务器不会以这种形式接受它。黑客可能能够计算出盐的彩虹表和轮数来尝试暴力破解密码,但是任何使用至少 8 个字符长的 ASCII 符号 32-126 的足够复杂的密码通常需要很长时间才能破解......这是针对每个密码的。我为之编写的站点的密码长度最多为 128 个字符。
至于会话劫持,可以通过每 30 秒左右重新生成会话 ID 来合理缓解这种风险。我还包含一个嵌入在页面本身的 HTML 中的令牌。在服务器端,一些客户端信息(如客户端的 IP 地址和用户代理字符串)也会被哈希处理并存储在用户的会话数据中。
因此,在每个请求中,服务器都会获取 cookie 会话 ID 和令牌。令牌将与会话数据中的内容进行比较。其他信息(如 IP 地址和用户代理)也会进行哈希处理,并与会话中的信息进行比较。如果全部匹配,那么这很有可能是真正的用户,而不是入侵者。
我可以看到这种情况发生的唯一方法是,如果攻击者拥有嵌入式令牌、相同的 IP 地址和相同的用户代理。这一切都与概率有关。此外,任何时候您都在处理加密货币,可能很难做对。所以正如其他人所说,不要自己动手。
现在是 2022 年。随着黑客攻击变得越来越复杂,幸运的是也有浏览器标准。事实上的传输协议是加密的 (https),使用内容安全策略和 CORS 系统地进行跨站点脚本或重放攻击更加困难。
我相信您的时间将花在熟悉这些技术上。
我不是安全专家,把它交给更有能力的工程师。
评论