计网学习笔记应用层篇3-HTTPS
前言
之前在写HTTP/2的时候,其实HTTP/2是的二进制分帧层就是建立在SSL\TSL上的,所以应用层篇的最后一篇笔记想写一写的就是HTTPS的学习
HTTPS
[Q1:为什么要引入HTTPS的机制?]
采取未加密的协议进行通信有如下弊端:
-
通信使用明文,内容可能被窃听
-
不验证通讯方的身份,可能遭遇伪装.(任何人都能发送请求,不管对方是谁都会返回响应)
-
无法证明报文的完整性,可能会遭篡改.(没有办法确认发出的请求/响应和接收到的请求/响应前后一致)
[Q2:什么是HTTPS?]
- HTTP+加密+认证+完整性保护 = HTTPS:HTTPS就是在HTTP上再加入加密处理和认证等机制
- HTTPS是身披SSL保护外衣的HTTP: HTTPS并非应用层的一种新协议,只是HTTP通讯接口部分用SSL和TLS协议代替,所以HTTPS其实就是身披SSL保护外衣的HTTP
[Q3:HTTPS是如何实现加密的?]
记录下当时看这个知识的时候印象很深刻的程序员小灰漫画讲解:https://blog.csdn.net/bjweimengshu/article/details/87706654
SSL/TLS协议运行机制
和漫画中的流程一致:SSL/TLS协议的基本过程是:
- 客户端向服务端索取并验证公钥
- 双方协商生成对话秘钥
- 双方采用对话秘钥进行加密通信
具体的握手阶段流程
-
客户端发出请求(ClientHello)
客户端向服务器发出加密通信的请求
客户端向服务器提供的信息:
- 支持的协议版本,比如TLS 1.0版
- 一个客户端生成的随机数,稍后用于生成”对话密钥”
- 支持的加密方法,比如RSA公钥加密
- 支持的压缩方法
-
服务器回应(SeverHello)
服务器收到客户端请求后,向客户端发出回应
回应信息:
- 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信
- 一个服务器生成的随机数,稍后用于生成”对话密钥”
- 确认使用的加密方法,比如RSA公钥加密
- 服务器证书
- 需要确认客户端身份情况:会再包含一项请求,要求客户端提供”客户端证书”
-
客户端回应
客户端收到服务器回应以后,首先验证服务器证书。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信
如果证书没有问题,客户端就会从证书中取出服务器的公钥。然后,向服务器发送下面三项信息
- 一个随机数。该随机数用服务器公钥加密,防止被窃听
- 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送
- 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验
-
服务器最后回应
- 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送
- 服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供客户端校验
[Q:为什么需要3个随机数来生成一个对话秘钥?]
“不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。
对于RSA密钥交换算法来说,pre-master-key本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。
pre master的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre master secret就有可能被猜出来,那么仅适用pre master secret作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。”
[Q:Android如何实现HTTPS?]
优化演进
[Q:HTTPS的弊端?]
- 2-RTT的延时:一次普通的HTTP请求,除了真实数据传输的耗时,实际上很多耗时存在于TCP连接的三次握手(1.5个RTT)的耗时上。而对于一次HTTPS的安全连接,则还需要花费时间在前期的会话密钥建立上,这里面存在1~2个RTT
- 非对称加密CPU开销:非对称加密组件计算效率往往远低于对称加密组件,直接使用非对称加密组件加密业务数据,这样的性能损耗任何Server都是无法承受的
Session ID
Session ID是HTTPS加速的一种方式,TLS里提出的session cache机制,通过保存上一次握手后的会话状态,在下一次连接是继续复用
上一次的握手结果,而无需进行新的握手流程
在HTTPS的握手过程中,服务器会为这一次连接生成一个会话ID(Session_id),同时端会为这个session_id保存相关的会话状态,比如协商好的会话密钥等
然后,服务器会把这个session_id回传给客户端,客户端收到后保存下来。在下一次建立Https连接时,直接把session_id传给服务器,服务器收到后会在本地查找之前保存的会话状态,如果找到,就直接回传给客户端,并发送握手结束事件。然后,双方就可以使用之前协商好的密钥直接开始通信了
不过,session_id保存session cache这种方式存在一个问题:如果同时有多台TLS服务器,而这个session cache默认只存在于最初协商的那台机器上,这就意味着没法在多台机器间共享
Session Ticket
Session ID存在的问题就是多台TLS服务器session_id无法共享,而解决的方案就是采用Session Ticket,这种方案的思路,就是将上面提到的session cache加密成一个Session Ticket,转存到客户端。下次建立连接时,客户端把Session Ticket带回给服务器,这个Ticket只有服务器能够解密,如果解密成功,说明Session未被篡改,那么就可以从中读取session信息并进行恢复,结束握手
这种方式就不存在多台服务器session共享的问题,另外,服务器也可以选择忽略这个Ticker,并启动一次完整的握手流程。
而且这个Session Ticket内部有一个缓存失效时间,如果客户端发现该Ticket已过期,则自动删除
感谢: