关于安全性:如何通过HTTP安全地发送密码?

How to send password securely over HTTP?

如果在登录屏幕上,用户提交带有用户名和密码的表单,则密码以纯文本形式发送(即使使用Post,如果我出错,请更正我的错误)。

所以问题是,什么是保护用户及其密码不受可能窃听通信数据的第三方攻击的正确方法?

我知道HTTPS解决了这个问题,但是是否有任何方法可以使用标准HTTP协议(POST请求)来确保至少某种程度的安全性?(可能以某种方式使用javascript)

编辑我可能遗漏了一些重要的事情。

我所说的是一个页面——这是由PHP生成的登录页面,它当然以HTML文件的形式发送给HTTP GET请求中的用户。服务器和客户机之间没有(@jeremy powell)连接,因此我无法创建这种握手协议。我希望整个过程对用户是透明的——他想提交一个密码,而不是处理密码。

谢谢。


将HTTP与SSL结合使用将使您的生活更加轻松,您可以轻松地休息,非常聪明的人(至少比我聪明!)多年来一直在仔细研究这种保密通信方法。


安全认证是一个广泛的话题。简而言之,正如@jeremy powell提到的,总是倾向于通过HTTPS而不是HTTP发送凭证。它将消除许多与安全相关的头痛。

TSL/SSL证书现在很便宜。事实上,如果你根本不想花钱,有一个免费的letsencrypt.org——自动证书颁发机构。

您可以进一步使用caddyserver.com,它在后台调用letsencrypt。

现在,一旦我们把https排除在外…

您不应该通过post-payload或get参数发送登录名和密码。使用授权头(基本访问认证方案),其构造如下:

  • The username and password are combined into a string separated by a
    colon, e.g.: username:password
  • The resulting string is encoded using
    the RFC2045-MIME variant of Base64, except not limited to 76
    char/line.
  • The authorization method and a space i.e."Basic" is then
    put before the encoded string.

source: Wikipedia: Authorization header

这看起来有点复杂,但事实并非如此。有很多好的库可以为您提供开箱即用的功能。

您应该使用授权头有几个很好的理由

  • 这是一个标准
  • 这很简单(在你学会如何使用它们之后)
  • 它允许您在URL级别登录,如:https://user:[email protected]/login(例如chrome会自动将其转换为Authorization头文件)
  • 重要提示:正如@zaph在下面的评论中指出的那样,将敏感信息作为get查询发送不是一个好主意,因为它很可能最终会出现在服务器日志中。

    enter image description here


    您可以使用挑战响应方案。假设客户机和服务器都知道一个秘密,那么服务器可以通过以下方式确保客户机知道密码(而不泄露):

  • 服务器向客户机发送随机数r。
  • 客户机将h(r,s)发送回服务器(其中h是加密散列函数,如s h a-256)
  • 服务器计算h(r,s)并将其与客户机的响应进行比较。如果匹配,服务器知道客户机知道密码。
  • 编辑:

    这里有一个关于r的新鲜度和HTTP是无状态的事实的问题。这可以通过让服务器创建一个只有服务器知道的秘密(称为q)来处理。然后协议如下:

  • 服务器生成随机数r,然后发送给客户机h(r,q)(客户机不能伪造)。
  • 客户机发送r,h(r,q),并计算h(r,s),然后将其全部发送回服务器(其中h是一个加密散列函数,如s h a-256)
  • 服务器计算h(r,s)并将其与客户机的响应进行比较。然后它需要r并计算(再次)h(r,q)。如果客户机的h(r,q)和h(r,s)版本与服务器的重新计算匹配,则服务器认为客户机已通过身份验证。
  • 要注意,由于客户端不能伪造h(r,q),h(r,q)充当cookie(因此可以实际实现为cookie)。

    另一个编辑:

    以前对协议的编辑是不正确的,因为任何观察到h(r,q)的人似乎都能用正确的散列值重放它。服务器必须记住哪些R不再是新的。我在写这个答案,所以你们可以编辑一下,找出一些好的答案。


    如果你的网络主机允许,或者你需要处理敏感数据,那么使用https,period。(阿法克法律经常要求这样做)。

    否则,如果您想通过HTTP做一些事情。我会这样做的。

  • 服务器将其公钥嵌入登录页。
  • 客户机填充登录表单并单击提交。
  • Ajax请求从服务器获取当前时间戳。
  • 客户端脚本连接凭证、时间戳和salt(从模拟数据(如鼠标移动、按键事件)散列),并使用公钥对其进行加密。
  • 提交结果哈希。
  • 服务器解密哈希
  • 检查时间戳是否足够新(仅允许5-10秒的短窗口)。如果时间戳太旧,则拒绝登录。
  • 将哈希存储20秒。在此时间间隔内拒绝登录的相同哈希。
  • 对用户进行身份验证。
  • 这样就可以保护密码,并且不能重播相同的身份验证哈希。

    关于会话令牌的安全性。这有点难。但有可能使重用被盗会话令牌变得更加困难。

  • 服务器设置一个包含随机字符串的额外会话cookie。
  • 浏览器在下一次请求时发送回此cookie。
  • 服务器检查cookie中的值,如果它不同,则会破坏会话,否则一切正常。
  • 服务器用不同的文本再次设置cookie。
  • 因此,如果会话令牌被盗,并且其他人发送了一个请求,那么在原始用户的下一个请求中,会话将被销毁。所以如果用户主动浏览站点,经常点击链接,那么窃贼就不会带着偷来的令牌走得太远。此方案可以通过对敏感操作(如帐户删除)要求另一个身份验证来加强。

    编辑:请注意,如果攻击者使用不同的公钥设置自己的页面,并将请求代理到服务器,这不会阻止MITM攻击。为了防止出现这种情况,必须将公钥固定在浏览器的本地存储中或应用程序中,以检测这些技巧。

    关于实现:RSA可能是最著名的算法,但是对于长密钥来说,它是相当慢的。我不知道的PHP或JavaScript实现有多快。但可能有更快的算法。


    我将使用带有Ajax或多表单提交的服务器端和客户端Diffie-Hellman密钥交换系统(我推荐前者),尽管我在Internet上没有看到任何好的实现。记住,JS库总是可以被MITM损坏或更改。在某种程度上,本地存储可以用来帮助解决这一问题。


    您可以使用SRP在不安全的通道上使用安全密码。其优点是,即使攻击者嗅探流量或破坏服务器,他们也不能在不同的服务器上使用密码。https://github.com/alax/jsrp是一个javascript库,支持浏览器或服务器端(通过节点)的HTTP安全密码。


    HTTPS非常强大,因为它使用了非对称加密技术。这种类型的加密技术不仅允许您创建加密的隧道,而且可以验证您与正确的人交谈,而不是黑客。

    这里是Java源代码,它使用非对称密码RSA(由PGP使用)进行通信:http://www.hushmail.com/services/downloads(服务/下载)/


    你可以为你的主机使用ssl。有免费的ssl项目,比如letsencrypt。https://letsencrypt.org网站/