纸上得来终觉浅,绝知此事要躬行。
1. HTTPS 简介
HTTPS
,也称作HTTP over TLS
。TLS
的前身是SSL
,因为早期的SSL
存在设计缺陷导致未能广泛使用。TLS 1.0
通常被标示为SSL 3.1
,TLS 1.1
为SSL 3.2
,TLS 1.2
为SSL 3.3
。
设计目的
- (1) 所有信息都是加密传播,第三方无法窃听
- (2) 具有校验机制,一旦被篡改,通信双方会立刻发现
- (3) 配备身份证书,防止身份被冒充
耗时
HTTP耗时 = TCP握手
HTTPs耗时 = TCP握手 + SSL握手
2. HTTPS 事务
3. SSL 会话握手
SSL/TLS
协议的基本思路是采用公钥加密算法,默认使用RSA
。
公钥加密/私钥解密: 客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。
3.1 产生的问题
- (1)如何保证公钥不被篡改?
- 解决方法:将公钥放在数字证书中。只要证书是可信的,公钥就是可信的。
- (2)公钥加密计算量太大,如何减少耗用的时间?
- 解决方法:每一次对话(session),客户端和服务器端都生成一个”对话密钥”(session key),用它来加密信息。
- 由于”对话密钥”是对称加密,所以运算速度非常快,而服务器公钥只用于加密”对话密钥”本身,这样就减少了加密运算的消耗时间。
3.2 SSL 握手
使用
RSA
算法的SSL
握手过程
- (1) [明文] 客户端发送随机数
client_random
和支持的加密方式列表- 客户端支持的协议版本,比如
TLS 1.0
版本 - 客户端生成一个用于生成”对话密钥”的随机数
- 客户端支持的加密方法,比如
RSA
公钥加密 - 客户端支持的压缩方法
- 客户端支持的协议版本,比如
- (2) [明文] 服务器返回随机数
server_random
,选择的加密方式和服务器证书- 确认使用的加密通信协议版本,比如
TLS 1.0
版本 - 生成一个用于生成”对话密钥”的随机数
- 确认使用的加密方法,比如 RSA 公钥加密
- 发送服务器证书
- 确认使用的加密通信协议版本,比如
- (3) [RSA] 客户端验证服务器证书,使用证书中的公钥加密
premaster secret
发送给服务端- 验证服务器证书
- 发送一个用服务器公钥加密随机数,防止被窃听
- 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送
- 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的
hash
值,用来供服务器校验。
- (4) 服务端使用私钥解密
premaster secret
- 服务端使用自己的私钥解密客户端通过公钥加密的随机数
- (5) 两端分别通过
client_random
,server_random
和premaster secret
生成master secret
,用于对称加密后续通信内容- 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送
- 服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的
hash
值,用来供客户端校验。
3.3 DH 算法的握手阶段
整个握手阶段都不加密(也没法加密),都是明文的。因此,如果有人窃听通信,他可以知道双方选择的加密方法,以及三个随机数中的两个。整个通话的安全,只取决于第三个随机数(Premaster secret
)能不能被破解。
虽然理论上,只要服务器的公钥足够长(比如2048
位),那么Premaster secret
可以保证不被破解。但是为了足够安全,我们可以考虑把握手阶段的算法从默认的RSA
算法,改为Diffie-Hellman
算法。
采用DH
算法后,Premaster secret
不需要传递,双方只要交换各自的参数,就可以算出这个随机数。
- 上图中,第三步和第四步由传递
Premaster secret
变成了传递DH
算法所需的参数,然后双方各自算出Premaster secret
。这样就提高了安全性。
3.4 session 的恢复
握手阶段用来建立
SSL
连接。如果出于某种原因,对话中断,就需要重新握手。这时有两种方法可以恢复原来的session
:一种叫做session ID
,另一种叫做session ticket
。
session ID
session ID
的思想很简单,就是每一次对话都有一个编号(session ID
)。如果对话中断,下次重连的时候,只要客户端给出这个编号,且服务器有这个编号的记录,双方就可以重新使用已有的对话密钥,而不必重新生成一把。
- 上图中,客户端给出
session ID
,服务器确认该编号存在,双方就不再进行握手阶段剩余的步骤,而直接用已有的对话密钥进行加密通信。
session ticket
session ID
是目前所有浏览器都支持的方法,但是它的缺点在于session ID
往往只保留在一台服务器上。所以,如果客户端的请求发到另一台服务器,就无法恢复对话。session ticket
就是为了解决这个问题而诞生的,目前只有Firefox
和Chrome
浏览器支持。
- 上图中,客户端不再发送
session ID
,而是发送一个服务器在上一次对话中发送过来的session ticket
。这个session ticket
是加密的,只有服务器才能解密,其中包括本次对话的主要信息,比如对话密钥和加密方法。当服务器收到session ticket
以后,解密后就不必重新生成对话密钥了。
4. HTTPS 相关问题
- 误解:HTTPS 无法缓存
- 只要在
HTTP
头中使用特定命令,HTTPS
是可以缓存的 Firefox
默认只在内存中缓存HTTPS
。但是只要头命令中有Cache-Control: Public
缓存就会被写到硬盘上
- 只要在
- 误解:SSL 证书很贵
- 在效力上,便宜的证书当然会比大机构颁发的证书差一点,但是几乎所有的主流浏览器都接受这些证书
- 误解:HTTPS 站点必须有独享的 IP 地址
- 使用子域名通配符
SSL
证书,就能在一个IP
地址上部署多个HTTPS
子域名 - 统一通信证书(
UCC
)支持一张证书同时匹配多个站点,可以是完全不同的域名 - 服务器名称指示(
SNI
)允许一个IP
地址上多个域名安装多张证书
- 使用子域名通配符
- 误解:HTTPS 太慢
- 使用
HTTPS
不会使你的网站变得更快,但是有一些技巧可以大大减少额外开销 - 同一张网页使用 HTTPS 协议之后打开时间变长,一旦有效的 HTTPS 连接建立起来,两种协议几乎没有区别
- 使用
- 误解:只有注册登录页才需要 HTTPS
- 需要保护的信息都需要
HTTPS
- 需要保护的信息都需要