SSL/TLS 握手过程
传输层安全协议
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
完整握手
基于 RSA 的完整握手
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 验证客户端的完整握手
有时候客户端需要验证,这就导致比基本的TLS握手多了两个步骤。客户端在 ServerHelloDone 消息之后发送 Certificate 消息,携带自己的证书。并且发送 CertificateVerify 消息,携带经过自己私钥加密的签名。服务器收到证书和签名之后用客户端的公钥做验证。
基于 Diffie-Hellman 的完整握手
迪菲-赫尔曼密钥交换
这里其实主要是多了一个步骤,ServerKeyExchange 交换 DH parameter,使用 Diffie-Hellman parameters 生成 PreMasterSecret
简易握手
Session ID
一般现在Web服务器的架构是Nginx+OpenSSL(假设是),Nginx只支持单机多进程间共享的Session Cache,所以为了可靠性一般需要有全局的分布式Session Cache,这样就能保证在多台Web服务器之间共享使用Session ID。
Session Cache 的方案需要在服务器做缓存,会导致服务端需要较大的内存。
Session Ticket
TLS 协议
参考 Wiki: TLS RecordOptimizing the TLS record size: Optimizing TLS Record Size & Buffering Latency
加密套件
几种常见的加密套件: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,其中参数使用了证书中公钥对应的私钥进行了签名。
因为使用了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 后,立即发送加密的应用层数据,而无需等待服务器端的确认。客户端在发送 ChangeCipherSpec 和 Finished 后,并没有等待服务器端的确认就立即发送了加密应用数据。这样就省去了一个RT。