如何通过HTTP安全地发送密码?

如果在login屏幕上用户使用他的用户名和密码提交表单,密码将以纯文本forms发送(即使使用POST,如果我错了,也要纠正)。

所以问题在于保护用户和密码的方法是什么?对于可能窃听通信数据的第三方?

我知道HTTPS是解决问题的方法,但有什么办法可以保证使用标准的HTTP协议(POST请求)至less有一定程度的安全性吗? (可能以某种方式使用JavaScript)

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

我所讲的是一个页面 – 那就是PHP生成的login页面,当然这个页面是通过HTTP GET请求作为HTML文件发送给用户的。 服务器和客户端之间没有(@Jeremy Powel)连接,所以我不能创build这样的握手协议。 我希望完整的过程对用户是透明的 – 他想提交密码,而不是密码处理。

谢谢。

通过SSL使用HTTP可以让你的生活变得更轻松,而且你可以放心,很聪明的人(至less比我聪明!)已经仔细审视了这种保密通信方法多年。

安全authentication是一个广泛的话题。 简而言之,就像@ jeremy-powell所说的那样,总是希望通过HTTPS而不是HTTP来发送证书。 它会带走很多安全相关的麻烦。

TSL / SSL证书现在相当便宜。 事实上,如果你不想花钱,那么有一个免费的letsencrypt.org – 自动authentication机构。

你可以走一步,使用后台调用letsencrypt的caddyserver.com。

现在,一旦我们得到了HTTPS …

您不应通过POST载荷或GET参数发送login名和密码。 使用授权标头(基本访问authenticationscheme),其结构如下:

  • 用户名和密码组合成一个用冒号分隔的string,例如:username:password
  • 生成的string使用Base64的RFC2045-MIME变体进行编码,但不限于76字符/行。
  • 然后把授权方法和一个空格即“Basic”放在编码的string之前。

来源: 维基百科:授权标题

这看起来可能有些复杂,但事实并非如此。 有很多好的图书馆,将提供这种function为您开箱即用。

有几个很好的理由你应该使用授权标题

  1. 这是一个标准
  2. 这很简单(在学习如何使用它们之后)
  3. 它将允许您在URL级别login,例如: https://user:password@your.domain.com/login (例如,Chrome会自动将其转换为Authorization标头)

重要:
正如@zaph在他下面的评论中所指出的那样,将敏感信息作为GET查询发送并不是一个好主意,因为它很可能最终会出现在服务器日志中。

在这里输入图像描述

您可以使用质询响应scheme。 假设客户端和服务器都知道一个秘密S.然后服务器可以确定客户端知道密码(没有泄露):

  1. 服务器向客户端发送一个随机数R。
  2. 客户端将H(R,S)发送回服务器(其中H是encryption散列函数,如SHA-256)
  3. 服务器计算H(R,S)并将其与客户端的响应进行比较。 如果它们匹配,服务器知道客户端知道密码。

编辑:

R的新鲜度和HTTP是无状态的这个问题有一个问题。 这可以通过让服务器创build一个秘密来处理,称之为Q, 只有服务器知道 然后协议是这样的:

  1. 服务器生成随机数R,然后发送给客户端H(R,Q)(客户端不能伪造)。
  2. 客户端发送R,H(R,Q),并计算H(R,S)并将其全部发送回服务器(其中H是encryption散列函数,如SHA-256)
  3. 服务器计算H(R,S)并将其与客户端的响应进行比较。 然后它需要R并再次计算H(R,Q)。 如果客户端版本H(R,Q)和H(R,S)与服务器的重新计算匹配,则服务器认为客户端已authentication。

注意,由于H(R,Q)不能被客户伪造,所以H(R,Q)充当cookie(因此可以实际上被实现为cookie)。

另一个编辑:

以前对协议的编辑是不正确的,因为任何观察到H(R,Q)的人似乎都可以用正确的哈希来重放它。 服务器必须记住哪个R不再新鲜。 我CW'ing这个答案,所以你们可以在这个编辑和工作出好东西。

如果您的虚拟主机允许它,或者您将需要处理敏感数据,那么请使用HTTPS。 (这是法律惯例所要求的)。

否则,如果你想通过HTTP做些什么。 我会做这样的事情。

  1. 服务器将其公钥embeddedlogin页面。
  2. 客户端填写login表单并点击提交。
  3. AJAX请求从服务器获取当前时间戳。
  4. 客户端脚本连接证书,时间戳和盐(来自模拟数据的散列,例如鼠标移动,按键事件),使用公钥对其进行encryption。
  5. 提交结果散列。
  6. 服务器解密散列
  7. 检查时间戳是否足够短(仅允许短5-10秒的窗口)。 如果时间戳太旧,拒绝login。
  8. 存储哈希20秒。 在此间隔期间拒绝login相同的散列。
  9. validation用户。

所以这样密码被保护,同样的validation哈希不能重播。

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

  1. 服务器设置一个包含随机string的额外会话cookie。
  2. 浏览器在下一个请求中发回这个cookie。
  3. 服务器检查cookie中的值,如果不同则破坏会话,否则一切正常。
  4. 服务器再次用不同的文本设置co​​okie。

因此,如果会话令牌被盗,并且其他人发送请求,则在原始用户的下一个请求中会话将被销毁。 因此,如果用户主动浏览网站,经常点击链接,那么盗贼不会与盗取的令牌走得太远。 该scheme可以通过对敏感操作(如账户删除)要求另外的authentication来加强。

关于实现:RSA可能是最知名的algorithm,但是它对于长密钥来说相当慢。 我不知道PHP或Javascript的执行速度有多快。 但可能有一个更快的algorithm。

我会使用服务器端和客户端的Diffie-Hellman密钥交换系统与AJAX或多个表单提交(我推荐前者),虽然我没有看到在互联网上的任何好的实施。 请记住,一个JS库总是可以被MITM破坏或改变。 本地存储可以用来在一定程度上帮助解决这个问题。

HTTPS非常强大,因为它使用非对称密码学。 这种types的密码不仅可以让你创build一个encryption的隧道,但你可以validation你正在对正确的人,而不是黑客。

以下是使用非对称密码RSA(由PGP使用)进行通信的Java源代码: http : //www.hushmail.com/services/downloads/

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

你可以使用ssl为你的主机有免费的SSL项目像letsencrypt https://letsencrypt.org/