我应该在客户端还是主机端进行密码加盐和哈希处理?

4
我认为在客户端的机器上直接进行密码加盐和哈希会更明智。原因是,我实际上从不想获取用户的密码。它是一个应该对他保密而不是我们两个都知道的字符串。现在有人争论说,您想保持盐的秘密,所以不能在通道上以明文发送它。 显然不是这样。所以现在我不明白为什么我不应该只请求客户端的哈希值。你怎么看?
编辑讨论将客户端密码发送到主机实际上并不是直接的问题。对于客户端来说,问题是根本不要将密码发送出计算机。乐观的客户端可能会认为他的计算机是安全的领土。但是从那条电缆(或天线)出去的一切都是Eve的领土。在安全场景中,您永远无法过于偏执。所以再次强调:密码永远不应离开客户端计算机!

3
即使你收到了密码的哈希值(也可能是加盐的),仍应该通过加密连接发送,以防止重放攻击。 - Mike Daniels
@Mike,当然是的。它应该始终通过加密连接发送。谢谢你澄清。我会删除之前的评论以防止混淆。 - tjm
@Mike:仅仅加密并不能防止重放攻击。在典型情况下,你只会在建立账户时发送经过哈希和加密的口令一次。这意味着即使有人试图重放它,也只是创建了另一个使用相同密码的账户,或者因为他们试图创建已经存在的账户而被拒绝尝试。 - Jerry Coffin
你可能会发现,如果密码从未离开客户端计算机,服务器将永远不会让客户端连接 - 服务器没有理由信任客户端。 - Jonathan Leffler
3个回答

12

发送口令或其哈希值中的任何一个都会让攻击者记录哈希值,并在重放攻击中使用。

通常情况下,您需要使用挑战/响应协议,这意味着您会发送一个随机数。客户端使用其口令的哈希值作为密钥对该随机数进行加密(或进行密钥散列运算),然后将结果发送回来。你也这样做,看两个是否匹配。

这样可以在不通过不安全的渠道发送密钥本身的情况下验证匹配的密钥。

至于如何最初获取数据以能够进行比较,是的,通常您希望客户端对口令进行哈希处理,然后使用服务器的公共密钥对其进行加密,并发送该加密结果。


@Jerry Coffin:像 asket 一样 @Jonathan Leffler:你所描述的“salt”不是被称为“nonce”吗? - Heisenbug
@Jerry Coffin:这是第一次有人让我相信,无需交换核心机密即可实现双方确保他们正在交谈的安全性的需求。我认为,这包括您应该将盐发送给客户端,因为它必须在他开始哈希之前应用。您如何做到这一点?纯文本是否足够? - erikbstack
@Overbose:我不认为我把任何东西都描述为salt,但是没错,nonce是challenge的另一个说法(但nonce是更通用的术语——例如,nonce也可用作IV或加密密钥)。 - Jerry Coffin
2
@erikb:是的——通常情况下,盐值被认为是公开信息;它不需要保密才能发挥作用。 - Jerry Coffin
@@Jerry Coffin:不,你不需要 :) 抱歉。但是你描述了一种挑战-响应机制。我在对Jonathan Leffler的评论中写道,我习惯称之为“盐”。我认为这与挑战-响应的nonce有些不同。 - Heisenbug
@Overbose:是的——你在那里的描述符合我通常使用“salt”的方式,我相信这是相当标准的(例如,在《应用密码学》和《应用密码学手册》中使用)。 - Jerry Coffin

2
那样做的问题在于,经过盐值加密的密码会在网络上传输,如果有人拦截了它,他们就可以使用它。
可能可行的方法是,服务器将用于客户端的盐值发送到客户端,然后客户端使用服务器创建的盐值返回经过盐值加密的密码。攻击者可能能够捕获回复,但这并没有帮助,因为服务器的盐值每次都不同,因此客户端的响应也每次不同。然而,这需要服务器知道密码,以便可以使用盐值重新计算它,从而实现您的一个目标。
从根本上讲,服务器必须最终知道某些内容,以确保客户端没有欺骗它;而经典的方法是让服务器存储经过盐值加密的密码,客户端将密码发送到服务器,服务器通过给发送的密码加盐和加密来验证客户端发送的内容,并将结果与其存储的内容进行比较。这避免了服务器明文存储密码,但确实意味着密码会通过网络传输。因此,在发送前务必对密码进行加密。

Leffler:你所描述的“nonce”不是被称为“盐”吗?我的意思不是反对,只是一个问题。我认为盐是另一回事。 - Heisenbug
@0verbose: 是的,在“服务器发送挑战”的变体中,我所称之为“salt”(盐)的另一个名称是“nonce”(一次性数字)。它基本上与“salt”(盐)是相同的。无论如何,客户端都必须使用服务器发送的值对密码进行哈希处理,并且服务器必须知道密码以便能够重复哈希处理并检查是否从客户端获得了正确的值。 - Jonathan Leffler
Leffler @Jerry Coffin:好的,知道了。我以为盐是另一种东西。就像在Unix密码文件中一样,它被连接到密码中,以防止使用相同短语的不同用户生成相同的哈希密码。还可以增加密钥空间和计算时间,最终打破密码。 - Heisenbug
@Jonathan Leffler:不需要密码,服务器只需要盐哈希。他只需要确保首先获得真正的盐哈希。然后,他就有了一些东西可以用来比较以后的哈希值。如果他真的需要密码做什么事情,他实际上需要以明文或至少可解密的方式存储它。 - erikbstack

2

通常情况下,哈希是用来混淆实际密码的,不会保护免受重放攻击的影响。您需要使用安全套接字层来确保频道受到保护。

哈希的好处在于可以防止信息泄漏。例如,假设有人掌握了您的用户表,现在他们拥有大量账户。由于人们经常重复使用密码,这些账户可以被用于攻击其他网站。哈希使得反向哈希成密码变得困难。

仅当您要本地存储密码(如移动设备)时,才需要在客户端对密码进行哈希。通常情况下,您需要在服务器级别执行哈希操作。


你可能认为作为软件工程师,你是客户的朋友。但事实并非如此。在他看来,你只是另一个可能利用他秘密的人。至少他不能信任你在安全方面做得足够好,就像Sony这样的公司已经证明了一样。 - erikbstack
本地存储的哈希密码如何使用?您无法反转该哈希。 - Jonathan Leffler
你可以使用本地存储的哈希作为缓存,以验证移动应用程序中的连接是否断开。这样,您就有了一种允许用户离线使用应用程序的方式,同时仍然提供一定程度的保护。 - Candide

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接