如何通过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为您开箱即用。
有几个很好的理由你应该使用授权标题
- 这是一个标准
- 这很简单(在学习如何使用它们之后)
- 它将允许您在URL级别login,例如:
https://user:password@your.domain.com/login
(例如,Chrome会自动将其转换为Authorization
标头)
重要:
正如@zaph在他下面的评论中所指出的那样,将敏感信息作为GET查询发送并不是一个好主意,因为它很可能最终会出现在服务器日志中。
您可以使用质询响应scheme。 假设客户端和服务器都知道一个秘密S.然后服务器可以确定客户端知道密码(没有泄露):
- 服务器向客户端发送一个随机数R。
- 客户端将H(R,S)发送回服务器(其中H是encryption散列函数,如SHA-256)
- 服务器计算H(R,S)并将其与客户端的响应进行比较。 如果它们匹配,服务器知道客户端知道密码。
编辑:
R的新鲜度和HTTP是无状态的这个问题有一个问题。 这可以通过让服务器创build一个秘密来处理,称之为Q, 只有服务器知道 。 然后协议是这样的:
- 服务器生成随机数R,然后发送给客户端H(R,Q)(客户端不能伪造)。
- 客户端发送R,H(R,Q),并计算H(R,S)并将其全部发送回服务器(其中H是encryption散列函数,如SHA-256)
- 服务器计算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做些什么。 我会做这样的事情。
- 服务器将其公钥embeddedlogin页面。
- 客户端填写login表单并点击提交。
- AJAX请求从服务器获取当前时间戳。
- 客户端脚本连接证书,时间戳和盐(来自模拟数据的散列,例如鼠标移动,按键事件),使用公钥对其进行encryption。
- 提交结果散列。
- 服务器解密散列
- 检查时间戳是否足够短(仅允许短5-10秒的窗口)。 如果时间戳太旧,拒绝login。
- 存储哈希20秒。 在此间隔期间拒绝login相同的散列。
- validation用户。
所以这样密码被保护,同样的validation哈希不能重播。
关于会话令牌的安全性。 这有点困难。 但有可能使被盗的会话令牌重复使用有点困难。
- 服务器设置一个包含随机string的额外会话cookie。
- 浏览器在下一个请求中发回这个cookie。
- 服务器检查cookie中的值,如果不同则破坏会话,否则一切正常。
- 服务器再次用不同的文本设置cookie。
因此,如果会话令牌被盗,并且其他人发送请求,则在原始用户的下一个请求中会话将被销毁。 因此,如果用户主动浏览网站,经常点击链接,那么盗贼不会与盗取的令牌走得太远。 该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/