HTTPS 建立连接

SSL/TLS 握手过程

Transport Layer Security
传输层安全协议
High Performance Browser Networking  |  O'Reilly: Transport Layer Security (TLS)

发展历史

Defined
Protocol Year
SSL 1.0 n/a
SSL 2.0 1995
SSL 3.0 1996
TLS 1.0 1999
TLS 1.1 2006
TLS 1.2 2008
TLS 1.3 TBD

对于 TLS 的发展过程以及涉及的基本概念可以参考 Wiki 

完整握手

HTTPS 建立连接

基于 RSA 的完整握手

HTTPS 建立连接

1、客户端发送 ClientHello 消息,包括 最高支持的 TLS 协议版本,随机数,加密套件,压缩算法。如果希望下次重用握手,可以包含 session id。如果客户端使用 ALPN,可以包括应用层的协议列表,比如http2

2、服务器回一个 SeverHello 消息,包括选择的协议版本,随机数,选择的加密套件和压缩算法。服务器确认或者允许重用握手可能需要发送一个 session id。选择的协议版本应该是客户端和服务端都支持的最高版本

3、服务端发送 Certificate 消息

4、服务器发送 ServerKeyExchange 消息,使用RSA进行密钥交换无需交换任何临时参数,所以可以没有 ServerKeyExchange 阶段,

5、服务器发送 ServerHelloDone 消息,表示握手协议完成

6、客户端生成 PreMasterSecret 并用服务器的公钥加密,回应 ClientKeyExchange 消息,包括 PreMasterSecret,可能包括客户端的公钥。

7、客户端和服务端利用两个随机数和 PreMasterSecret 生成 master secret,也就是接下来使用的对称秘钥(Session Key)

8、客户端发送 ChangeCipherSpec 告诉对方接下来所有的消息都是经过加密的

9、最后客户端发送加密的 Finished 消息,并且包含 MAC。服务器解密并且验证 MAC,如果解密或者验证失败,握手失败

10、服务端发送 ChangeCipherSpec 告诉对方接下来所有的消息都是经过加密的

11、服务端发送加密的 Finished 消息,客户端解密并验证

12、握手完成

基于 RSA 验证客户端的完整握手


HTTPS 建立连接

有时候客户端需要验证,这就导致比基本的TLS握手多了两个步骤。客户端在 ServerHelloDone 消息之后发送 Certificate 消息,携带自己的证书。并且发送 CertificateVerify 消息,携带经过自己私钥加密的签名。服务器收到证书和签名之后用客户端的公钥做验证。

基于 Diffie-Hellman 的完整握手
HTTPS 建立连接

迪菲-赫尔曼密钥交换   
这里其实主要是多了一个步骤,ServerKeyExchange 交换 DH parameter,使用 Diffie-Hellman parameters 生成 PreMasterSecret

简易握手

HTTPS 建立连接

Session ID 

HTTPS 建立连接

一般现在Web服务器的架构是Nginx+OpenSSL(假设是),Nginx只支持单机多进程间共享的Session Cache,所以为了可靠性一般需要有全局的分布式Session Cache,这样就能保证在多台Web服务器之间共享使用Session ID。

Session Cache 的方案需要在服务器做缓存,会导致服务端需要较大的内存。

Session Ticket 

HTTPS 建立连接
Session Ticket  是不需要消耗服务器的内存的,但必须保证 Nginx 集群使用相同的 Session Ticket 加解密算法,不然就会导致 Session Ticket 在不同的 Nginx 机器上解密错误而不能重用。
Session Ticket 也是现在主流使用的快速握手方案,但是在应用重启就会导致 Session Ticket 丢失的问题,就必须要重新走完整握手的方案。对这一问题腾讯提出了一个解决方案,参考:腾讯HTTPS性能优化实践

TLS 协议

参考 Wiki: TLS Record

Optimizing the TLS record size:Optimizing TLS Record Size & Buffering Latency

加密套件

几种常见的加密套件:
HTTPS 建立连接

Kx 为 RSA 时候,Au 也必须为 RSA,且可以省略

KX 密钥交换算法

RSA:由client生成 premaster secrete,用 server 的公钥加密后在 ClientKeyExchange 包中传给 server,server再用自己的私钥解密。RSA秘钥的长度,至少应大于2048位才是安全的,较长的秘钥使得RSA解密一个256位的 premaster secrete 需要2ms左右,比较消耗服务端CPU资源。

ECDHE (Elliptic Curve Diffie–Hellman Exchange) = ECC + DH + E,是在DH算法的基础上,加入了椭圆曲线算法,使得所需秘钥的长度变短,最后的E表示每次动态生成参数和key,其中参数使用了证书中公钥对应的私钥进行了签名。
HTTPS 建立连接

因为使用了RSA 2048位的私钥进行签名,参数签名后长度变成了256字节。如果使用密钥为256位的ECDSA证书,则只需32个字节。

client 使用动态参数、自己的临时私钥和server的临时公钥来生成一个premaster secret。

server 使用动态参数、自己的临时私钥和client的临时公钥(在ClientKeyExchange包中传出)生成相同的premaster secret。

ECDHE 算法有更短的密钥,能更快地得到对称加密的密钥,相比RSA消耗更少的服务端CPU资源。而且搭配ECDSA证书会有更好的效果。

Au 签名认证算法

待续~~~

Enc 对称加密算法

交互应用层数据时使用的对称加密算法

MAC 检验算法

Message authentication code 交互应用层数据时使用的Hash算法,检验数据的完整性
MD5 以及 SHA-1 已被攻破

TLS False Start

TLS False Start是Google提出来的优化方法,其做法是:在TLS协商阶段,客户端发送 ChangeCipherSpec 和 Finished 后,立即发送加密的应用层数据,而无需等待服务器端的确认。
HTTPS 建立连接

客户端在发送 ChangeCipherSpec 和 Finished 后,并没有等待服务器端的确认就立即发送了加密应用数据。这样就省去了一个RT。

HTTPS 建立连接
上一篇:Dart API 扩展


下一篇:Android多个网络连接