关于c#:危险存储一个良好的哈希密码和用于在明显的情况下散列它的方法?

Dangerous to store a well hashed password and the method used to hash it in plain sight?

我正在用C语言开发一个客户端应用程序,它将与服务器(PHP页面)通信,以获取凭证和一些关键服务。我想知道在客户机上存储散列好的密码是否危险?我所说的"hashed"是指使用一个众所周知的安全散列函数的随机种子。在本讨论中,假设源代码是免费可用的(因为所有二进制文件都可以进行反向工程)。

我的想法是将用户名和哈希密码存储在用户的计算机上,并通过未加密的HTTP连接将此用户名和哈希以纯文本形式发送到服务器进行验证。当然,这不会阻止黑客在不知道源密码的情况下使用他人的用户名和密码散列作为自己的密码(有一些代码调整)。

  • 一个恶意的人能用散列密码和产生散列的代码做什么吗?(如果获得此信息,则以其他用户身份登录除外)
  • 如果黑客没有访问源密码的权限,其他客户端应用程序如何阻止一个用户以另一个用户的身份登录?(例如蒸汽)
  • 有没有一种简单、便宜(包括成本和时间),更安全的方法来处理这个问题?
  • 黑客如何使用我当前的逻辑欺骗他人的登录凭证的示例:

  • 合法用户首次登录,凭证被存储
  • 黑客获得对文件系统的访问权,定位用户名和哈希密码
  • 黑客修改源代码(或使用代码注入)来发送获得的用户名和哈希密码,而不是程序通常做的事情。
  • 我正在生产的产品不会成为下一个eBay、Facebook或StackExchange,而且成本很低。我不需要顶级的东西,也不在乎偷窃,因为我打算用一个"按你想要的付钱"的模式。我主要是出于好奇才把这个贴出来的。


    首先,我要说的是,您没有能力安全地实施这个系统。我也不是。几乎没有人是。您需要一个安全专业人员来完成这项工作;如果您尝试滚动您自己的安全性,您会发现它是错误的,并且您将生成一个可能被攻击者破坏的系统。

    别挡道:您已经清楚地识别了系统的弱点。您正在存储一个等效密码;如果攻击者获得等效密码,那么他们是否拥有该密码并不重要;他们拥有足够的信息来模拟用户。

    解决办法很清楚。如果你这样做很痛,不要这样做。如果存储密码的系统不能可靠地抵御攻击,则不要存储等效的密码。

    如果您非常热衷于存储等效密码,那么将其存储在一个比文件系统更难被攻击者访问的存储中。如果您确实决定代表用户存储危险物品,则可以使用Windows数据保护API将其存储在使用用户凭据加密的加密存储中:

    http://msdn.microsoft.com/en-us/library/ms995355.aspx

    但最好不要首先存储等效密码。

    假设您没有存储等价的密码。你还没有完成。您仍然需要考虑重播攻击。假设攻击者窃听不安全的通道。用户输入密码,将其散列并发送到服务器。窃听者记录下哈希密码,现在他们得到了它。

    为了解决这个问题,服务器向客户机发送一个随机数。该号码将不再使用;它只是一次。客户机用随机数XORS散列密码,然后用服务器的公钥加密结果。加密的xor'd消息被发送到服务器。

    服务器使用它的私钥解密散列,用它以前发送的随机数XORS散列,并确定解密的散列与它存储的等效密码匹配。现在窃听者无法重放捕获的密码,因为他们再也看不到相同的随机数。

    现在,如果客户机不知道服务器的公钥,那么这就容易受到中间人攻击!如果服务器将公钥发送到客户机,那么中间的人可以截获服务器的公钥,并将其替换为其公钥。现在中间的人可以提供公钥和"随机"挑战,客户端将放弃等效的密码。

    就像我说的,这很难。别想自己动手。找个专业人士。


    将哈希密码存储在用户的计算机上会使他们面临(相当大的)风险——即使访问您的站点没有特别的价值,许多用户将对许多站点使用相同的用户名和密码。如果它们中的任何一个使用与您相同的(如您所说的,众所周知的)散列函数,那么对该数据的访问可以让攻击者访问其他网站。

    对于一个简单、低预算的方法,我将使用一个简单的挑战/响应系统。当用户要求登录时,向他们发送一个随机数。他们将密码输入一个客户端程序,该程序对密码进行散列,并使用散列密码作为密钥加密随机数,然后将结果发送到服务器。服务器使用其存储的用户密码散列对同一随机数进行加密。当它从用户那里得到结果时,它将两者进行比较。只有当两者匹配时,用户才有正确的密码。

    如果您的目的是避免用户一直输入密码,请将随机数和加密随机数存储在他们的计算机上。只要他们收到相同的挑战,他们就可以发送相同的响应。当/如果挑战更改时,他们需要重新输入密码以加密新挑战。恢复存储的数据使攻击者只能访问您的站点,并且只在相当短的一段时间内访问(并且更快地更改挑战也很简单)。

    这样可以避免传输密码(即使是散列形式)。唯一的例外是在初始设置期间,当您需要将哈希密码获取到服务器上时。为此,您有几个选择,但是pk密码术可能是最明显的——您向他们发送一个密钥,他们发送用该密钥加密的数据。如果有人截取了数据,那就没用了(当然,除非他们破坏了加密)。

    至于如何生成随机数,通常的方法非常简单:从服务器上的/dev/random之类的源生成一个真正的随机数。使用(散列版本)作为加密算法的密钥,该加密算法在计数器模式下运行-即,您有一个计数器(不必保密),使用该密钥加密(确实要保密)。每次你需要产生一个新的挑战时,你增加计数器,加密它,然后发送结果。


    其次,我不想在安全系统上变聪明。在我看来,最好的政策就是"拒绝"这类事情。

    好消息是,你甚至不必费心。您是否考虑过使用第三方库允许您的用户通过openid登录(stackoverflow本身似乎就是这样做的)?诚然,我以前从来没有这样做过,但我相信这可能是一个强大但轻量级的选择,可能对您很好:

    http://code.google.com/apis/accounts/docs/openid.html网站

    http://wiki.openid.net/w/page/12995176/libraries(库)

    祝你好运。


    正确存储哈希密码并不危险。在计算上,无法反转加密散列并找到将产生散列的密码。

    然而,一切都取决于"合适"这个词。首先,如果用户选择了一个糟糕的密码,那么哈希函数就不需要被反转。破解首先尝试一个常见密码列表,按流行程度排序。如果散列算法不使用某种密钥增强(数千次迭代),则可能会强制使用相当大的密码空间(8或9个字符)。如果哈希算法不使用salt,则预计算字典是可行的。

    我不确定我是否完全理解您的帖子,但听起来您知道您有效地将此哈希用作密码。中间的人,或者黑客,可以在不恢复原始密码的情况下访问您的应用程序。这样做的好处是,他们没有用户的"真实"密码,而这些密码很可能会用于许多其他应用程序。

    将密码存储在用户的大脑中,并让他们每次都输入密码,这样更安全。但是,如果您没有使用像SSL这样的安全协议,那么在其他地方花费太多的精力在安全上似乎是不值得的。合理的做法是让用户负责保护自己的设备,防止窃取存储的密码。但是他们发送信息的网络是他们无法控制的。我从交通安全开始。


    我非常不鼓励尝试创建您自己的身份验证方案。如果使用经过时间测试的模式,则更可能会覆盖未考虑的边缘情况。以下是我的建议和原因:

  • 不允许使用哈希值而不是完整密码登录。这样,即使攻击者获得了存储在服务器上的密码散列,他们也无法登录。

  • 尽量避免存储密码,甚至是哈希密码。如果您想轻松登录,@mitch的建议是一个很好的折衷方案,但我建议您加密过期令牌,并将过期令牌与其他证据绑定(例如,如果使用其他IP地址发送令牌,则该令牌将失效)。

  • 不要以纯文本形式传输凭证。即使传输的凭证被散列,如果流量被捕获,重播攻击也是可能的。SSL的实现并不十分困难,而且它会给您额外的好处,即客户机能够验证他们正在与正确的服务器通信,这有助于防止中间人攻击。

  • 永远不要在服务器上存储用户的密码。改为储存一个咸土豆泥。确保哈希值很大,以降低暴力攻击成功的可能性(例如,sha-256)。

  • 我知道你在试图寻找一个便宜、易于开发的解决方案。与其实现劣质的安全性来实现这一目标,不如尝试使用预先构建的、经过时间测试的身份验证库。这是一种在不影响质量的情况下节省时间/金钱的方法。


    这是黑客的天堂!

    任何与安全性相关的文件都只能由维护网站的人访问,无论使用何种加密方法。

    否则,你就是在招惹麻烦。

    :)