是否可以散列密码并验证用户客户端?

时间:2009-07-06 16:45:10

标签: asp.net javascript silverlight authentication passwords

我经常使用默认的“散列”密码存储方法制作小型网站并在SQL Server数据库中使用内置的ASP.NET成员资格功能。

我想知道是否有办法通过在客户端上散列密码来验证用户,而不是通过网络以明文形式发送它而不使用SSL。

我意识到这只适用于启用了Javascript的用户。

或者......可能,这对Silverlight来说是一个很棒的内置功能(这是在Silverlight路线图中吗?)


编辑: 我也在寻找“安全程度”。这意味着,如果有一种方法比简单地发送明文密码具有某些优势,我想知道它们是什么以及为什么。

我知道有很多人使用登录进行小型网站(例如家庭网站或自愿为当地烹饪俱乐部制作网站)并​​且不认为需要购买SSL证书。

6 个答案:

答案 0 :(得分:6)

这是一个坏主意,安全明智。如果您发送包含散列密码的非ssl表单,那么捕获流量的任何人都需要登录。您的javascript必须导致指示成功的内容(重定向,传递给服务器的令牌等)。无论是什么,听众现在都可以在没有适当身份验证的情况下重新创建。

SSL是出于某种原因而构建的,他们尝试了很多其他Web身份验证方案。获得证书远比尝试编写自己的安全身份验证方案更加安全和便宜,而无需加密。

为清晰起见添加:

仅客户端哈希是不安全的。假设我有一个包含以下输入的表单

<form action="signin.whatever" method="post">
<input type="text" id="txtUser">
<input type="text" id="txtPass">
<input type="hidden" id="hiddenHash">
<input type="submit" onclick="hashAndSubmit()">
</form>

其中hashAndSubmit()哈希密码并将其放入hiddenHash,并清空密码字段。如果我嗅到你的提交并看到以下字段:

txtUser:joeuser
txtPass:
hiddenHash:xxx345yz   // hash result

这就是我作为攻击者所需要的一切。我用你的用户和哈希值构建了一个表单,我已经完成了设置。重放攻击不需要密码。

要解决这个问题,您必须查看一次性盐值或其他方案。所有这些都比SSL引入更多成本(不要忘记开发人员时间)和风险。在你做这样的事情之前,先问一个问题......

我是否相信自己多年来对SSL加密进行公开测试?

答案 1 :(得分:6)

这是可能的。这实际上是Kerberos身份验证所做的事情,只是添加了一点点添加剂。要确保您的身份验证机制安全,您需要以下内容:

  1. 客户端和服务器上的常见哈希算法。
  2. 在服务器上生成并与客户端共享的一次性salt值。
  3. 存储在数据库中的原始密码。
  4. 要通过哈希代码安全地对用户进行身份验证,以避免通过线路发送实际密码,请首先在服务器上生成随机的一次性salt值。将此salt值发送到客户端,并根据用户输入的密码版本生成哈希码。将生成的哈希代码发送到服务器,并将其与从存储密码的salted版本生成的哈希代码进行比较。如果比较失败,则丢弃盐,重新生成新的盐值,然后重复该过程。

    一次性使用salt的原因是为了防止任何听到对话的人捕获用户密码的哈希码,当你使用哈希码比较时,就像拥有密码一样好。

    请注意,您需要保留原始密码,不能在服务器上对其进行一次哈希并将哈希保存在数据库中。如果您需要确保存储在数据库中的密码也是安全的,那么您需要在存储它们之前加密它们。我相信ASP.NET成员资格提供程序允许您存储加密的密码,但是,如果您真的希望拥有一个黑客难以破解的安全身份验证机制,那么我建议您完全自己处理密码存储和检索。

    最后,我应该注意,如果在身份验证期间使用SSL加密连接,那么这种复杂的密码传输机制在很大程度上是不必要的。

    引用(对于那些从未听说过Kerberos或SRP的人):

    http://en.wikipedia.org/wiki/Kerberos_(protocol) http://en.wikipedia.org/wiki/Secure_remote_password_protocol

答案 2 :(得分:2)

你可以做到这一点,但这也是不安全的。问题是有人可以捕获哈希并重放它(就像他们可以使用原始密码一样)。我想你提供了一些防止暴露实际密码的保护(如果他们在其他系统上使用它),但你的系统将不再安全。

答案 3 :(得分:2)

您可以实现哈希算法客户端(在javascript中)并仅通过线路发送用户名和哈希结果。请注意,为了使其安全 ,必须使用服务器提供的字符串对哈希进行加密,并且每个请求的字符串必须是唯一的 。服务器仍然需要检查散列是否正确并验证会话。

答案 4 :(得分:1)

至少你必须使用salt来生成哈希。否则,哈希值与拦截时的普通密码一样“有价值” - 至少在您的网站上是这样。

答案 5 :(得分:1)

您可以按照HTTP Digest协议发送用户名/领域/密码哈希作为帖子字段。 AFAIK没有内置的客户端组件,也没有服务器端组件来生成/验证这一点,因此您必须手动完成所有操作。它还要求您的存储存储特定的哈希格式,请参阅Storing password in tables and Digest authentication

优势在于您遵循经过充分分析和理解的身份验证协议。不要自己动手。