在客户端哈希密码值得吗

当我想要设置一个登录系统时,我总是将给定密码的 MD5与服务器端的 users 表中的值进行比较。

然而,我的一个朋友告诉我,一个“明确”的密码可以嗅到一个网络软件。

所以我的问题是: 在客户端散列密码是一个好主意吗?比在服务器端散列好吗?

111970 次浏览

基本上,你朋友是对的。但是在客户端对密码进行哈希处理只比将其作为纯文本提交给服务器好一些。有些人,谁可以监听您的纯文本密码当然也能够监听哈希密码,并使用这些捕获的哈希他/她对您的服务器进行身份验证。

对于这个问题,更安全的认证协议通常会跳过许多环节,以确保这样的重播攻击不能正常工作,通常是通过允许客户端选择一组随机位,这些随机位与密码一起散列,并且也清楚地提交给服务器。

在服务器上:

  • 产生一些随机的比特
  • 将这些位(以明文形式)发送给客户端

关于客户:

  • 产生一些随机位
  • 连接密码、服务器的随机位和客户端的随机位
  • 生成上面的散列
  • 向服务器提交随机位(明文)和散列

由于服务器知道自己的随机信息以及客户机的随机位(它得到的是明文) ,它可以执行基本上相同的转换。这个协议确保,在这次谈话中,没有人可以使用后来记录的信息进行虚假的认证(除非使用了一个非常弱的算法... ...) ,只要双方每次产生不同的“噪音位”,握手就会执行。

编辑 所有这些都是容易出错的、单调乏味的,并且有些难以正确处理(读: 安全)。如果可能的话,考虑使用已经由知识渊博的人编写的身份验证协议实现(不像我!以上内容仅仅来自我不久前读过的一本书。)你一般不会想自己写的。

你可能不用担心这个问题——正如 Dirk 提到的,即使你对密码进行哈希处理,恶意用户也可能在网络上看到哈希被发送,并且可以简单地发送相同的哈希本身。

它比 有点更好,因为它可以防止恶意用户知道密码是什么,但是因为他们仍然可以登录(或者可能是 重建原始密码) ,所以这没有多大帮助。

一般来说,如果您担心用户的密码和数据的安全(您应该担心!),您将需要使用一个安全的 SSL 服务器。如果出于某种原因,您不必担心这个问题,那么最好不要使用散列; 它只是 隐晦式安全


编辑2014年8月: 谷歌正在越来越强烈地推动网站到 切换到 HTTPS 无处不在,因为保护通信本身是防止网络嗅探攻击的唯一方法。试图混淆传输的数据只会阻碍而不是阻止专门的攻击者,并且会给开发人员一种危险的错误的安全感。

这取决于,您可以使用客户端散列,但是不可能使用服务器端 salt。

看看链接 客户端的密码加密

我最近在这方面做了很多工作,IRL 客户端 hash/对称的加密有两个问题,真正扼杀了这个想法: 1.你得想办法把盐带回服务器,客户端需要密码才能加密,这样就达不到目的了。 2.你暴露了你的哈希实现(不是一个巨大的交易,因为大多数网站使用3或4个哈希算法之一) ,这使得攻击更容易(只需要尝试一个而不是 n)。

我最终在客户端上使用 OpenPGP.js 或类似的非对称加密技术。 这依赖于客户端上导入的或客户端生成的密钥以及发送它的公钥的服务器。只能将客户端的公钥发送回服务器。 这样可以防止 MIM 攻击,并且和设备一样安全(我目前默认在 localStore 中存储客户端的私钥,这是一个演示)。

这样做的主要优点是,我从来不需要将用户数据存储在服务器/数据存储区中,即使在内存中也不需要对数据进行加密(而且我的服务器的私钥在物理上是独立的)

这样做的基础是为人们提供一种在 HTTPS 受到限制的情况下(例如,伊朗/朝鲜等等)进行安全通信的方法,同时也是一个有趣的实验。

我远不是第一个想到这个的人,http://www.mailvelope.com/使用这个

如果有人可以看到数据在您的连接上进出,那么身份验证将不会保存您。 相反,我会做以下超级秘密的东西。

发送到服务器之前在客户端预处理的密码。 (服务器存储从浏览器发送的该散列的另一个散列值和已加盐值)。

因此,中间人攻击可以允许他们发送相同的散列值来登录,但用户的密码不会被知道。这将阻止他们尝试使用其他具有相同凭证的服务在其他地方登录。

用户数据在浏览器端也是加密的。

所以中间人攻击可以得到加密的数据但是没有用于登录的真实密码就无法解密。(用户登录时将密码存储在浏览器的 DOM 中)。 所以真正的用户可以看到解密的内容,但中间人看不到。 这也意味着任何国家安全局或其他机构将无法要求您/公司/托管服务提供商解密这些数据,因为这将是不可能的,他们也这样做。

这两种方法的一些小例子都在我的博客上 Http://glynrob.com/javascript/client-side-hashing-and-encryption/

事实上,我不同意客户端散列在这种情况下更安全,我认为它不那么安全。

在数据库中存储密码的哈希值而不是真正的密码(甚至是加密的密码)的关键在于,从哈希值中获得原始密码在数学上是不可能的(尽管理论上可以获得碰撞的哈希输入,其难度取决于哈希算法的安全强度)。这里可能的攻击向量是,如果潜在的攻击者以某种方式破坏了您的密码存储数据库,他/她仍然无法获得您的用户的原始密码。

如果你的身份验证机制发送了一个密码的散列,那么在“安全漏洞”的情况下(即攻击者以某种方式获得了你的密码数据库的副本) ,攻击者不需要知道真正的密码-他们只需发送他们从漏洞中获得的散列密码,然后他们就可以访问那个用户的帐户。这完全打破了存储哈希密码的要点摆在首位!

真正安全的方法是向客户机发送一个一次性公钥,让客户机加密密码,然后在服务器端解密并重新散列密码。

顺便说一下,这类问题在 SecurityStackExchange 上可能会得到更多专家的回答。

首先,没有确实提高了应用程序的安全性(假设它是一个 web 应用程序)。

使用 SSL (或者实际上是 TLS,通常称为 SSL)。

原因很简单。TLS 解决了一个在密码学中非常重要的问题(当与证书颁发机构的证书一起使用时,而不是自签名的) : 我如何知道我正在与之交谈的服务器就是我认为正在与之交谈的服务器?TLS 证书是这样一种说法: “我,你们浏览器信任的证书颁发机构,证明[ url ]网站有这个公钥,还有一个相应的私钥,这个私钥只有服务器知道,看,我在整个文档上签了名,如果有人修改了它,你们可以看到。”。

没有 TLS,任何加密都变得毫无意义,因为如果我在咖啡馆坐在你旁边,我可以让你的笔记本电脑/智能手机认为我是服务器,而 MiTM (中间人)是你。使用 TLS 时,您的笔记本电脑/智能手机会发出“ UNTRUSTED CONNECTION”的尖叫,因为我没有与您的站点匹配的证书颁发机构签名证书。(加密与认证)。

免责声明: 用户倾向于点击右键通过这些警告: “不可信连接?什么?我只想要小猫的照片!太棒了!小猫咪!”

但是,如果您确实不想使用证书,那么仍然使用 实现客户端的 Javascript 散列(并使用 Stanford 库(SJCL) 永远不要自己实现加密)。

为什么?重用密码!我可以偷你的会话 cookie (它允许我假装你的服务器,我是你)没有 HTTPS 很容易(见火羊)。然而,如果你将 Javascript 添加到你的登录页面,在发送之前,散列你的密码(使用 SHA256,或者更好,使用 SHA256,发送一个你生成的公钥,然后用它加密散列密码,你不能使用 salt) ,然后发送散列/加密密码到服务器。用 salt 重新 HASH 服务器上的散列,并将其与数据库中存储的内容进行比较(存储密码如下:

(SHA256(SHA256(password)+salt))

(在数据库中也将 salt 保存为明文):

RSA_With_Public_Key(SHA256(password))

然后像这样检查你的密码:

if SHA256(RSA_With_Private_Key(SHA256(sent_password))+salt_for_username) == stored_pass: login = ok

因为,有人嗅探你的客户端,他们将能够作为你的客户端登录(会话劫持) ,但他们会看到明文密码(除非他们改变你的 Javascript。然而,星巴克的黑客可能不知道怎么做,也不会对此感兴趣。)所以他们可以访问你的网络应用,但不能访问他们的电子邮件/Facebook 等(你的用户可能会使用相同的密码)。(电子邮件地址可以是他们的登录名,也可以在你的 web 应用程序中找到他们的个人资料/设置)。

考虑一下:-

客户端向服务器发送请求“我有一个密码要验证”。

服务器向客户端发送一次性的随机字符串

客户端将用户的密码嵌入到此字符串中(基于您希望应用的任何(变量)规则)。

客户端将字符串发送到服务器,如果密码确定,服务器将用户登录。

如果服务器收到另一个使用 R $的登录请求,用户将被注销,帐户将被冻结,等待调查。

显然,所有其他(正常的)安全预防措施将被采取。

最近 GitHub 和 Twitter 都公布了存储在内部日志中的密码。我曾经在错误报告和其他日志中无意中发生过这种情况,这些日志被记录到 Splunk 等文件中。对于 Twitter 来说,如果特朗普的密码被记录在日志中,管理员“看到”可能是件大事,而对于其他网站来说,可能没有管理员使用它那么重要。不管怎样,管理员都不喜欢看到密码,不是吗。

所以问题在于,为了安全起见,是否应该在客户端进行哈希处理,但是我们如何在密码最终被服务器端进行哈希处理和比较之前保护它,使它不会以某种方式被记录下来。

加密并不是一个坏主意,因为开发者至少要经历一些考验,如果你发现密码进入了日志,你只需要改变加密密钥,破坏原始数据,那些数据就会变得毫无用处。更好的方法是每晚旋转钥匙,这样可以大大减少窗户。

您还可以在用户记录中散列一个散列。泄露的密码将是散列纯文本密码。服务器将存储散列的散列版本。当然,哈希变成了密码,但是除非你有过目不忘的记忆力,否则你不会记住一个60字符的 bcyrpt。用户名是 Salt。如果您可以在登录过程中收集一些关于用户的信息(同时不暴露用户记录的存在) ,那么您可以添加这些信息,同时创建一个更健壮的散列,这个散列不能在站点之间共享。没有中间人能够只是剪切和粘贴站点之间捕获的散列。

结合一个不会被提交回服务器的 cookie,您可能会发现一些问题。在第一次请求时,用一个密钥向客户端提交一个 cookie,然后确保 cookie 不会返回到登录服务,因此被记录的可能性很小。将密钥存储在一个会话存储中,然后在登录发生或会话过期后立即删除它... ... 这需要 JWT 用户的状态,但也许只需要使用 nosql 服务即可。

所以在路上,一个管理员偶然发现了这些散列和加密的密码之一,或者一个错误报告工具。这对他们来说应该是无用的,因为他们再也找不到加密密钥了,即使他们找到了,他们也不得不强行破解。此外,最终用户没有发送任何明文沿线,所以任何人在中间至少有一个更困难的时间,你不能只是跳到另一个网站和登录。

请注意,保持密码针对第三方的安全性并不是它的全部。

一旦涉及到隐私(现在什么时候不是了?)不想知道密码。你不能滥用或泄露你不 ,所以你和你的客户都可以睡得更好,如果你从来没有看到他们的明文密码。

因此,对客户端进行哈希/加密是有意义的。

客户端散列的这个想法是为了保护用户,而不是您的站点。正如已经多次提到的,纯文本或哈希密码都有访问您的网站平等。你没有安全福利。

但您的用户实际上,纯文本,密码应该只有他们知道。知道他们选择什么作为密码是可以在其他站点和系统上用来对付他们的信息。您正在成为一个以客户为中心的网站,通过保护他们的密码选择不会被您的服务器开发人员或第三方发现。

我想到的方法是使用 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)

在加密课上,我们被告知攻击者可以知道算法、 salt、 round 等等... 但是在这种情况下,实际的散列密码永远不会被发送。服务器知道它发送的随机字符串是什么,所以在客户机上生成完整的散列,最后一步是用随机字符串散列结果。这是发送到服务器的结果。结果就是一个一次性密码,在重播攻击时毫无用处。用户的密码永远不会以明文形式发送,如果攻击者获得了密码散列,那么对他们来说就没有用了,因为服务器不会接受这种形式的密码。黑客 五月能够计算出一个彩虹表中的盐和子弹的数量来尝试强行破解密码,但是任何使用 ASCII 符号32-126至少8个字符长的足够复杂的密码通常需要很长时间才能破解... 这就是 每个人密码。我写的网站可以有长达128个字符的密码。

至于会话劫持,通过每30秒左右重新生成会话 ID,可以合理地降低这种风险。我还包含了一个嵌入在页面本身的 HTML 中的标记。在服务器端,一些客户机信息(如客户机的 IP 地址和用户代理字符串)也被散列,并存储在用户的会话数据中。

因此,对于每个请求,服务器都会获得 Cookie 会话 ID 和令牌。将令牌与会话数据中的内容进行比较。其他信息,例如 IP 地址和用户代理,也被散列,并与会话中的内容进行比较。如果全部匹配,那么很有可能这是真正的用户,而不是入侵者。

我能看到这种情况发生的唯一方法是,如果攻击者拥有嵌入式令牌、相同的 IP 地址和相同的用户代理。都是概率问题。此外,任何时候你处理加密,可能很难得到正确的。所以就像别人说的,不要自己动手。

现在是2022年了。随着黑客攻击越来越复杂,幸运的是也有浏览器标准。事实上的传输协议是经过加密的(https) ,而跨网站脚本攻击或重播攻击在使用 内容安全策略CORS时更加困难。

我相信你的时间将会很好地花在熟悉这些技术上。

我不是安全专家,把它交给更有能力的工程师。