推荐先看下 《九个问题从入门到熟悉 HTTPS》 文章,写的很有趣~
另外,也看看 《SSL/TLS 双向认证(一) – SSL/TLS工作原理》 文章,写的更技术向~
简述
**HTTPS ,实际就是在 TCP 层与 HTTP 层之间加入了 SSL/TLS 来为上层的安全保驾护航,主要用到对称加密、非对称加密、证书,等技术进行客户端与服务器的数据加密传输,最终达到保证整个通信的安全性。**<br />[<br />](https://camo.githubusercontent.com/1e50637d97108d4c279d0b73e95ad43a843781c6/68747470733a2f2f6c6561726e696e67706963732e6f73732d636e2d7368656e7a68656e2e616c6979756e63732e636f6d2f696d616765732f61396538373830643662383939636635373039353739666339633435316664392e6a706567)<br />==一句话概括:**HTTP + 加密 + 认证 + 完整性保护 = HTTPS** 。==
SSL和TLS
官方定义,SSL 是安全套接层(secure sockets layer);TLS 是 SSL 的继任者,叫传输层安全(transport layer security)。<br /> **它们存在的唯一目的就是保证上层通讯安全的一套机制。**它的发展依次经历了下面几个时期,像手机软件升级一样,每次更新都添加或去除功能,比如引进新的加密算法,修改握手方式等。
- SSL1.0: 已废除
- SSL2.0: RFC6176 ,已废除
- SSL3.0: RFC6101 ,基本废除
- TLS1.0: RFC2246 ,目前大都采用此种方式
- TLS1.1: RFC4346
- TLS1.2: RFC5246 ,没有广泛使用
- TLS1.3: IETF 正在酝酿中
为了下面描述方便,统一先叫 SSL 。
SSL/TLS 协议作用
认证用户和服务器,确保数据发送到正确的客户机和服务器。
客户端必须避免中间人攻击,即除了真正的服务器,任何第三方都无法冒充服务器。
加密数据以防止数据中途被窃取。
- 维护数据的完整性,确保数据在传输过程中不被改变。
HTTPS实现的过程
1.建立连接获取证书
SSL 客户端通过 TCP 和服务器建立连接之后(443 端口),并且在一般的 tcp 连接协商(握 手)过程中请求证书。即客户端发出一个消息给服务器,这个消息里面包含了自己可实现的算法列表和其它一些需要的消息,SSL 的服务器端会回应一个数据包,这里面确定了这次通信所需要的算法,然后服务器向客户端返回证书。==(证书里面包含了服务器信息:域名,申请证书 的公司,公共秘钥)。==2.证书验证
Client 在收到服务器返回的证书后,判断签发这个证书的公共签发机构,并使用这个机构的公 共秘钥确认签名是否有效,客户端还会确保证书中列出的域名就是它正在连接的域名。3.数据加密和传输
如果确认证书有效,那么生成对称秘钥并使用服务器的公共秘钥进行加密。然后发送给服务器,服务器使用它的私钥对它进行解密,这样两台计算机可以开始进行对称加密进行通信。
HTTP 和 HTTPS 的区别
- 端口不同:HTTP 与 HTTPS 使用不同的连接方式,用的端口也不一样,前者是 80,后者是 443。
- 资源消耗:和 HTTP 通信相比,HTTPS 通信会由于加解密处理消耗更多的 CPU 和内存资源。
- 开销:HTTPS 通信需要证书,而证书一般需要向认证机构申请免费或者付费购买。
HTTPS 可以有效的防止运营商劫持,解决了防劫持的一个大问题。
SSL 加密方式
- 对称密钥加密,是指加密和解密使用同一个密钥的方式,这种方式存在的最大问题就是密钥发送问题,即如何安全地将密钥发给对方。
- ==非对称加密,指使用一对非对称密钥,即公钥和私钥,公钥可以随意发布,但私钥只有自己知道。发送密文的一方使用对方的公钥进行加密处理,对方接收到加密信息后,使用自己的私钥进行解密。==
SSL 协议,即用到了对称加密也用到了非对称加密,如下图所示:
在建立传输链路时,SSL 首先对对称加密的密钥使用公钥进行非对称加密。
==注意,这里 Server 返回给 Client 的不是公钥(
server.pub),而是server.crt。Client 需要使用ca.key从server.crt中解密出公钥(server.pub) 。==链路建立好之后,SSL 对传输内容使用公钥(
server.pub)对称加密。公钥传输的步骤
1.对公钥加密
每一个使用 HTTPS 的服务器都必须去专门的证书机构注册一个证书,证书中存储了用权威机构私钥加密的公钥。这样客户端用权威机构的公钥解密就可以了。
现在 HTTPS 协议的握手阶段变成了四步:
- 客户端: 你好,我要发起一个 HTTPS 请求,请给我公钥
- 服务器: 好的,这是我的证书,里面有加密后的公钥
- 客户端: 解密成功以后告诉服务器: 这是我的 (用公钥加密后的) 对称秘钥。
- 服务器: 好的,我知道你的秘钥了,后续就用它传输。
2.权威机构的公钥的传输
可以存在电脑里,这个公钥不用传输,会直接内置在各大操作系统(或者浏览器)的出厂设置里。之所以不把每个服务器的公钥内置在电脑里,一方面是因为服务器太多,存不过来。另一方面操作系统也不信任你,凭什么你说你这个就是百度/淘宝的证书呢?
所以各个公司要先去权威机构认证,申请证书,然后操作系统只会存储权威机构的公钥。因为权威机构数量有限,所以操作系统厂商相对来说容易管理。如果这个权威机构不够权威,乱发证书,就会取消他的资格,比如可怜的沃通。3. 将信息 hash 值随着信息一起传递
哈希算法的特点是它可以压缩数据,如果从函数角度来看,不管多复杂的数据(定义域可以非常大)经过哈希算法都会得到一个值,而且这个值处在某个特定(远小于定义域的范围)值域内。相同数据的哈希结果一定相同,不相同数据的哈希结果一般不同,不过也有小概率会重复,这叫哈希冲突。
为了确保原始证书没有被篡改,我们可以在传递证书的同时传递证书的哈希值。由于第三者无法解析数据,只能乱改,那么修改后的数据在解密后,就不可能通过哈希。比如说公钥就是之前的例子
Hello,我们假设哈希算法是获取字符串的最后一个字符,那么Hello的哈希值就是o,所以加密字符串是Ifmmpp。虽然公钥已知,每个人都可以解密,解密完也可以篡改,但是因为没有私钥, 所以无法正确的加密。所以它再返回给客户端的数据是无效数据,用公钥解析后会得到乱码。即使攻击者通过多次尝试碰巧能够解析,也无法通过哈希校验。
4.可以防止第三方冒充服务器
首先真正的服务器下发的内容,无法被别人篡改。他们有权威机构的公钥,所以可以解密,但是因为没有私钥,所以解密以后的信息无法加密。没有加密或者错误加密的信息被客户端用公钥解密以后,必然无法通过哈希校验。<br /> 但是,如果你一开始请求的就不是真的服务器,而是一个攻击者,此时的他完全有机会进行中间人攻击。我们知道第一次握手的时候服务器会下发用于证明自己身份的证书,这个证书会用预设在设备上的公钥来解密。所以要么是经过认证的证书用权威机构的私钥加密,再用权威机构解密,要么是用非权威机构的私钥加密,然后找不到公钥解密。<br /> **所以如果不小心安装过非权威机构的根证书,比如黑客提供的恶意证书,这时候设备上就多了一个预设的公钥,那么用恶意私钥加密的证书就能被正常解析出来。所以千万不要随便装根证书,这等于是为那些恶意证书留了一扇门。**<br /> 当然,凡是都有两面性。我们知道 Charles 可以调试 HTTPS 通信,它的原理就是需要用户安装 Charles 的根证书,然后我们的请求会被代理到 Charles 服务器,它下发的 Charles 证书才能被正确解析。另一方面,Charles 会作为客户端,从真正的服务器哪里拿到正确的 https 证书并用于后续通信。幸好 Charles 不是流氓软件,或者它的私钥一旦泄露,对用户都会造成很大的影响。<br />参照 [《九个问题从入门到熟悉 HTTPS》](http://juejin.im/post/58c5268a61ff4b005d99652a)<br />也就是说,通过 CA 来保证。至于 `server.crt` 证书是怎么申请的呢?请看 [《SSL/TLS 双向认证(一) – SSL/TLS工作原理》](https://blog.csdn.net/ustccw/article/details/76691248) 文章的 [「CA 的证书 ca.crt 和 SSL Server 的证书 server.crt 是什么关系呢? 」](http://svip.iocoder.cn/Net/Interview/#) 问题的解答。
单向认证、双向认证
单向认证,指的是只有一个对象校验对端的证书合法性。
通常都是 Client 来校验服务器的合法性。那么 Client 需要一个
ca.crt,服务器需要server.crt和server.key。双向认证,指的是相互校验,Server 需要校验每个 Client ,Client 也需要校验服务器。
- Server 需要
server.key、server.crt、ca.crt。 - Client 需要
client.key、client.crt、ca.crt。
- Server 需要
1)单向认证的过程
- 1、客户端向服务端发送 SSL 协议版本号、加密算法种类、随机数等信息。
- 2、服务端给客户端返回 SSL 协议版本号、加密算法种类、随机数等信息,同时也返回服务器端的证书,即公钥证书。
- 3、客户端使用服务端返回的信息验证服务器的合法性,包括:
- 证书是否过期。
- 发行服务器证书的 CA 是否可靠。
- 返回的公钥是否能正确解开返回证书中的数字签名。
- 服务器证书上的域名是否和服务器的实际域名相匹配
验证通过后,将继续进行通信;否则,终止通信。
4、客户端向服务端发送自己所能支持的对称加密方案,供服务器端进行选择。
5、服务器端在客户端提供的加密方案中选择加密程度最高的加密方式。
- 6、服务器将选择好的加密方案通过明文方式返回给客户端。
- 7、客户端接收到服务端返回的加密方式后,使用该加密方式生成产生随机码,用作通信过程中对称加密的密钥,使用服务端返回的公钥进行加密,将加密后的随机码发送至服务器。
- 8、服务器收到客户端返回的加密信息后,使用自己的私钥进行解密,获取对称加密密钥。
在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全。
2)双向认证的过程
双向认证和单向认证原理基本差不多,只是除了客户端需要认证服务端以外,**增加了服务端对客户端的认证**,具体过程如下:<br />[双向认证](https://img-blog.csdn.net/20160310160519781)
- 1、客户端向服务端发送 SSL 协议版本号、加密算法种类、随机数等信息。
- 2、服务端给客户端返回 SSL 协议版本号、加密算法种类、随机数等信息,同时也返回服务器端的证书,即公钥证书。
3、客户端使用服务端返回的信息验证服务器的合法性,包括:
- 证书是否过期。
- 发型服务器证书的 CA 是否可靠。
- 返回的公钥是否能正确解开返回证书中的数字签名。
服务器证书上的域名是否和服务器的实际域名相匹配
验证通过后,将继续进行通信;否则,终止通信。
【新增】4、服务端要求客户端发送客户端的证书,客户端会将自己的证书发送至服务端。
- 【新增】5、验证客户端的证书,通过验证后,会获得客户端的公钥。
- 6、客户端向服务端发送自己所能支持的对称加密方案,供服务器端进行选择。
- 7、服务器端在客户端提供的加密方案中选择加密程度最高的加密方式。
- 8、服务器将选择好的加密方案通过明文方式返回给客户端。
- 9、客户端接收到服务端返回的加密方式后,使用该加密方式生成产生随机码,用作通信过程中对称加密的密钥,使用服务端返回的公钥进行加密,将加密后的随机码发送至服务器。
- 10、服务器收到客户端返回的加密信息后,使用自己的私钥进行解密,获取对称加密密钥。
在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全。
如何选择单向认证还是双向认证
- 一般一个站点很多用户访问就用单向认证。
- 企业接口对接就用双向认证。
如果想要提高 APP 的安全级别,也可以考虑双向认证。因为,APP 天然方便放入客户端证书,从而提高安全级别。
为什么抓包工具还能抓到 HTTPS 数据包并解密成功呢
不是说HTTPS在网络中传输的是密文吗?这个问题就是中间者攻击(man in zhe middle)。
- 解决办法,就是 HTTPS 单向验证。在客户端中内置服务器公钥,在第三步服务器返回的公钥,除了验证公钥的有效性之外,再比对公钥是不是和内置的公钥一样,不一样说明被中间者攻击了,就断开链接不在请求了。
这个原理的前提是服务器的私钥没有泄露,客户端的代码不会被破解,道高一尺魔高一丈。信息安全就是在合理的范围内,选择比较合适的加密方法,没有绝对论,只有相对论。在某个范围内比较安全。
HTTPS 握手对性能的影响
TCP 有三次握手,再加上 HTTPS 的四次握手,影响肯定有,但是可以接受。
首先,HTTPS 肯定会更慢一点,时间主要花费在两组 SSL 之间的耗时和证书的读取验证上,对称算法的加解密时间几乎可以忽略不计。
- 而且如果不是首次握手,后续的请求并不需要完整的握手过程。客户端可以把上次的加密情况直接发送给服务器从而快速恢复,具体细节可以参考 《图解 SSL/TLS 协议》 。
- 除此以外,SSL 握手的时间并不是只能用来传递加密信息,还可以承担起客户端和服务器沟通 HTTP2 兼容情况的任务。因此从 HTTPS 切换到 HTTP2.0 不会有任何性能上的开销,反倒是得益于 HTTP2.0 的多路复用等技术,后续可以节约大量时间。
- 如果把 HTTPS2.0 当做目标,那么 HTTPS 的性能损耗就更小了,远远比不上它带来的安全性提升。
