HTTPS 看这篇就够了
HTTPS 看这篇就够了
我们之前讲解过了 HTTP,如果面看过的建议先去看看 HTTP(传送门),我们知道 HTTP 有三大缺点:通信使用明文、不验证通信方的身份、无法证明报文的完整性。今天,我就来带你看看 HTTPS 相比 HTTP 有哪些优点,是如何解决这些问题的,话不多说,直接开干。
不安全的 HTTP
在上篇文章中我们只是简单的介绍了 HTTP 不安全的几点,并没有详细分析,今天我们就来详细的分析 HTTP 在不安全方面的三个缺点,如下所示:
- 通信使用明文( 不加密) , 内容可能会被窃听
- 不验证通信方的身份, 因此有可能遭遇伪装
- 无法证明报文的完整性, 所以有可能已遭篡改
通信使用明文可能会被窃听
由于 HTTP 本身不具备加密的功能, 所以也无法做到对通信整体(使用 HTTP 协议通信的请求和响应的内容) 进行加密。 即, HTTP 报文使用明文(指未经过加密的报文)方式发送。
不仅是 HTTP 传输的内容会被窃听,其他的 TCP/IP 都可能被窃听,通信内容在所有的通信线路上都有可能遭到窃听。即使已经过加密处理的通信, 也会被窥视到通信内容, 这点和未加密的通信是相同的。 只是说如果通信经过加密, 就有可能让人无法破解报文信息的含义, 但加密处理后的报文信息本身还是会被看到的。
不验证通信方的身份就可能遭遇伪装
HTTP 的请求和响应不会对通信方进行确认,也就是说任何人都可以发起请求,而服务器对请求者来者不拒,只要接收到请求,就会返回一个响应。
显然,正是由于 HTTP 的这种简单性,导致了如下隐患:
1)客户端发送的 HTTP 请求报文可能到达的并非真正的目的服务器,可能是已伪装的服务器。
2)服务器返回的 HTTP 响应报文可能也并没有被正确的客户端所接收,可能是已伪装的客户端。
3)无法确定正在通信的对方是否具备访问权限。
4)无法判定请求来自何方,出自谁手。
5)即使是无意义的请求也会照单全收。
无法证明报文的完整性可能报文被篡改
HTTP 无法证明报文的完整性,所谓完整性就是指信息的准确度。若无法证明完整性,在 HTTP 请求或响应 送出之后直到对方接收的这段时间内,即使请求或响应的内容遭到攻击者篡改,也没有办法获悉。通俗来说,HTTP 没有办法确认发送出去的请求和接收到的请求是否一致。
举个例子,你从某个使用 HTTP 的非正规网站上下载QQ,存放在服务器上的文件确实是QQ,但是,在你下载的过程当中,攻击者攻击了这个网站,你正在传输的文件内容被篡改成了其他文件,而在这个过程中,你是完全察觉不到的。
像这样的在请求或响应在传输途中,遭受攻击者拦截并篡改内容的攻击称为中间人攻击。
安全的 HTTPS
HTTPS 协议并非应用层的一个新协议,只是 HTTP 通信接口部分用 SSL(Secure Socket Layer)和 TLS(Transport Layer Security)协议代替而已。
通常 HTTP 是直接和 TCP 进行通信的,当使用 SSL 时,则演变成先和 SSL 通信,再由 SSL 和 TCP 进行通信。简而言之。所谓 HTTPS,就是身批 SSL 协议外壳的 HTTP。如下图所示:
在采用 SSL 后,HTTP 就拥有了加密、证书和完整性保护等功能,而这些功能正是用来解决我们上述所说的 HTTP 不安全问题的。另外,SSL 是独立于 HTTP 协议的,所有运行在应用层的协议都可以配合 SSL 协议使用。可以说,SSL 协议是当今世界上应用最为广泛的网络安全技术。
那么,针对上述 HTTP 的三个安全性问题,我们来看看 HTTPS 或者说 SSL 到底提供了哪些解决方案。
加密
既然无法阻止被窃听,那么我就把我的内容加密起来,让你无法破解。那么,既然发送方对通信内容进行了加密,接收方接收到这个被加密过的内容,一定要知道对应的解密手段。主要的加密方式有下面这几种:
共享密钥加密
加密和解密使用同一密钥的方式称为共享密钥加密(Common Key crypto system),也称做对称密钥加密。
这里简单的说一下秘钥是啥?所谓密钥,就是钥匙,加密方有一把密钥,用来上锁,解密方也拥有一把密钥,用来解锁。而且加密方和解密方使用的密钥不一定是同一把。
以共享密钥加密时必须将密钥也发送给对方。显然,如果通信双方都各自持有同一个密钥,且没有别人知道,则两方的通信安全是可以被保证的(除非密钥被破解)。
那么,最大的问题就是如何保证这个密钥的安全传输,不被外部攻击者知道。如果由服务器生成一个密钥并传输给浏览器,这个传输过程中密钥被攻击者劫持,那么之后攻击者就能用这把密钥解开双方传输的任何内容。
发送密钥就有被窃听的危险,但不发送,对方就不能解密。怎么样才能安全的发送密钥?解决这个问题,我们就需要公开密钥加密(非对称密钥加密)。
公开密钥加密
公开密钥加密很好的解决了共享密钥加密的困难。
公开密钥加密需要一组非对称的密钥对,分别是公钥 public key 和私钥 private key。顾名思义,公钥可以随意发布,任何人都可以获得,而私钥不能让除通信双方外的其他任何人知道。这两个密钥是成对出现的,公钥加密的内容需要对应的私钥解密。
举个例子:客户端(浏览器)想要给网站服务器发送消息
- 首先,网站服务器持有一组公钥和私有,它会把自己的公钥明文传输给客户端。
- 客户端利用这个公钥给自己的消息进行加密,然后传输给服务器,这时候就算被攻击者截获,由于攻击者没有对应的私钥也无法解密该内容。
- 网站服务器收到后,使用这个公钥对应的私钥进行解密。
利用这种方式,不需要发送解密需要的私钥,也就不必担心私钥被攻击者盗走。
混合加密方式
上述公开密钥加密的方式虽然安全,但是相比于不那么安全的共享密钥加密方式来说,其处理速度要慢很多。HTTPS 综合这两种加密方式的优势,使用共享密钥加密要发送的信息,使用公开密钥加密这个共享密钥,这样就减少了公开加密的次数。举个例子:
- 某网站服务器拥有一组用于公开密钥加密的非对称密钥:公钥 A1、私钥 A2
- 浏览器向网站服务器请求,服务器把公钥 A1 明文给传输浏览器
- 接收到这把公钥 A1 后,浏览器随机生成一个用于共享密钥加密(对称加密)的密钥 X,用公钥 A1 加密后传给服务器。这个阶段,即便被攻击者截获,由于攻击者没有对应的私钥也无法解密该内容
- 服务器拿到后用对应的私钥 A2 解密得到密钥 X(以上这些阶段就是公开密钥加密)
- 这样双方就都拥有密钥 X 了,且别人无法知道它。之后双方之间所有的数据传输都使用密钥 X 进行加密和解密即可(这个阶段就是共享密钥加密)
数字证书
遗憾的是,上述混合加密的方式仍然还是有漏洞的。攻击者(中间人)的确无法得到浏览器生成的对称密钥 X,这个密钥本身被公钥 A1 加密,只有使用服务器拥有的私钥 A2 才能解密。但是攻击者完全不需要拿到服务器私有的私钥 A2 就能劫持信息。举个例子:
- 某网站服务器拥有一组用于公开密钥加密的非对称密钥:公钥 A1、私钥 A2。
- 浏览器向网站服务器请求,服务器把公钥 A1 明文给传输浏览器。
- 攻击者劫持到公钥 A1,保存下来,把数据包中的公钥 A1 替换成自己伪造的公钥 B1(它当然也拥有公钥 B1 对应的私钥 B2)。
- 浏览器随机生成一个用于对称加密的密钥 X,用攻击者的公钥 B1(服务器此时不知道自己的公钥被替换了)加密后传给服务器。
- 攻击者劫持后用自己的私钥 B2 解密就得到了密钥 X。然后再用服务器的公钥 A1 加密后传给服务器。
- 服务器接收到攻击者用公钥 A1 加密的信息后,用对应的私钥 A2 解密得到密钥 X。
这样在客户端浏览器和网站服务器都没有发现异常的情况下,攻击者得到了对称密钥 X。此后客户端和浏览器双方通过对称密钥 X 加密发送的任何内容,攻击者都可以轻松破解。
上述过程就是典型的中间人攻击,其根本原因是浏览器客户端无法确认自己收到的公钥是不是真正的网站服务器的。那么下一步就是解决这个问题:如何证明浏览器客户端收到的公钥一定是该网站服务器的公钥?防止服务器和客户端的身份被伪装。
其实很简单,大家想一下在现实生活中,如何证明小明说出的身份证号确实是它自己的,怎么办?看看小明的身份证就可以了。身份证是由谁颁发的?政府机构。那么这里政府机构就起到了公信的作用,它本身的权威可以对一个人的身份信息作出证明。
对应的,互联网中也有这么一个公信机构,数字证书认证机构 Certificate Authority, CA。所谓公信机构,就是客户端和浏览器都信赖的第三方机构。
网站服务器在使用 HTTPS 前,需要向 CA 申请颁发数字证书,数字证书里有证书持有者、证书持有者的公钥等信息。服务器把数字证书明文传输给浏览器客户端,然后浏览器从证书里取出服务器的公钥就可以了。
然而这里又有一个显而易见的问题:证书本身的传输过程中,如何防止被篡改?即如何证明证书本身的真实性?数字证书怎么防伪呢?
数字签名
数字证书认证机构 CA 在判明提出申请者的身份之后,会对其申请的公开密钥做数字签名,然后将数字签名和公开密钥放入数字证书。而客户端在收到服务器发送来的数字证书后,对证书上面的数字签名进行验证,如果这个数字签名和证书上的原始公开密钥 Hash 后的结果一致,那么客户端便可明确两件事情:
- 认证服务器的公开密钥的是真实有效的数字证书认证机构
- 服务器的公开密钥是值得信赖的
OK,这么说还不太清楚,我们先来了解什么是数字签名?
数字证书认证机构 CA 把要传送的明文信息(也就是申请认证的网站服务器的公钥)通过 Hash 算法得出摘录信息 MIC(摘录技术),再用自己的私钥对 MIC 值进行加密,就得到了得到数字签名。
解释一下:认证机构一般会持有一组公钥 A1 和私钥 A2,为了确保证书的安全性,浏览器客户端通常会在内部事先植入常用认证机构的公钥 A1,认证机构在颁发数字证书的时候,会用自己的私钥 A2 对 MIC 进行加密得到数字签名。而浏览器接收到数字证书后,先利用事先存储好的公钥 A1 解密数字签名,再对数字签名进行验证。
总结过程如下:
1)CA 颁发数字证书给网站的过程:
- CA 拥有非对称加密的私钥和公钥。
- 网站申请数字证书,并发送自己的公开密钥 A。
- CA 对网站的公开密钥 A 进行 Hash 得到摘录信息 MIC。
- 对 MIC 值用 CA 的私钥加密,继而得到数字签名。
- 将数字签名和网站的公开密钥 A 放进数字证书发放给网站。
2)浏览器客户端验证网站数字证书的过程:
- 浏览器客户端接收到网站服务器发来的数字证书,得到网站的公钥 A 和数字签名 S1。
- 浏览器使用事先植入的 CA 机构的公钥对 S1 进行解密,得到 S2。
- 用数字证书里说明的 Hash 算法对网站的公钥 A 进行 Hash 得到 A2。
- 比较 S2 是否等于 A2,若相等则表示证书可信。于是浏览器就可以放心的取出数字证书中的网站公钥 A 进行使用。
HTTPS 真的无敌吗
由于使用了加密通信, 相比于纯文本通信的 HTTP 来说,HTTPS 会消耗掉更多的 CPU 及内存资源,如果每次通信都加密,会消耗掉非常多的资源,平摊到一台计算机上时,能够处理的请求数量必定也会随之减少。一些国际大型网站比如维基百科等,在启用 HTTPS 前都会先考虑自己服务器资源和计算能力是否可以承载 HTTPS。因此,如果是非敏感信息,使用 HTTP 通信也无妨。只有在涉及个人敏感信息等数据时,才需要使用 HTTPS。
另外,开启 HTTPS 需要申请 SSL 证书,高额的证书申购费用会让很多网站开发者望而却步。
引用:
《图解 HTTP 》