这是我参与8月更文挑战的第9天,活动详情查看:8月更文挑战
书接上回,介绍完了TLS中关键的算法:密钥协商ECDHE,身份验证RSA/ECDSA,以及最终的session key和AES对称加密。
今天让我们看看TLS1.2实际的信令流程和报文解析,我还会在下一篇中详细解析TLS1.3的报文。
流程很长,你忍一下(狗头)
TLS1.2握手整体流程
TLS1.2的初次握手确实很花时间,这是后来1.3版着重解决的问题之一。
先简单说明一下中间的session判断,判断依据是session id或session ticket,如果与服务器的session匹配上了,则可直接进入密钥协商,并开始对称加密传输数据,这是一个session resumption的流程。
这是我截取的真实的TLS握手流程:
可以看到有几条消息合并了,比如certificate, server key exchange, server hello done,但其实里面还是3条消息,由3个TCP segment进行发送.
client hello
TCP建立连接后,客户端通过随机端口向服务器443端口(HTTPS默认)发出client hello握手请求,报文详情如下:
- 关于version:TLS 1.0,注意报文开始的第一个version指的是TLS record layer记录层的版本,这个版本一直没有变过,而我们说的TLS1.2指的是TLS handshake protocol,握手协议的版本;
- Random: 客户端随机码,用于最后生成master key
- session id:用于恢复之前的会话,如果client hello携带了session ticket,则服务器会忽略这个字段,保留这个字段的目的是兼容
- Cipher Suite:报文中最重要的字段之一,告知服务器,自己支持的加密算法组,按照倾向性排序,优先级最高的排在第一,让服务器选择
- server name:因为现在一个IP可以绑定多个domain,所以TLS通过这个字段告知服务器我访问的到底是哪个域名
- supported groups: 用于协商ECC椭圆曲线参数,表明自己支持的参数组
- session ticket: 用于恢复之前的会话
- signature algorithms:客户端支持的签名算法列表,在之后的密钥协商中,服务器从中选择一种
- supported version:客户端支持的TLS握手协议版本,按照优先级排序,这个字段在1.3版本中很有用
Server Hello
服务器在收到上一条消息后,响应客户端,并发送server hello,报文详情如下:
- version:服务器选择的TLS握手协议版本
- random: 服务器随机码,用于生成master key
- session id: 0 表示这是一个新的会话,如果有值,则表示匹配成功,将使用之前会话的参数
- cipher suite:服务器选择的密码组TLS_ECDEH_RSA_WITH_AES_256_GCM_SHA384,翻译一下:
- TLS:使用版本
- ECDHE: 密钥交换方法,Elliptic Curve Diffie-Hellman Ephemeral基于椭圆曲线的DH短时加密算法。
- RSA:身份验证方法,采用非对称加密
- AES_256_GCM:用于最后的数据传输加密算法,对称加密,256bit密钥,GCM分组模式;
- SHA384:完整性保护算法,生成384bit的加密摘要
Certificate
服务器发送完响应后,接下来马上会发送证书,开始身份验证,报文如下:
服务器会发送整个证书链给客户端,我们在《当我们谈论HTTPS时,我们在谈什么(三)身份验证》中讲到过,对服务器身份的信任是基于对“root CA"的信任。
证书中的详细内容:
- serialNumber:证书序列号,这是CA机构对证书的唯一标识
- issuer:证书颁发机构,为CA机构名
- validity:证书有效期
- subject: 证书颁发对象,对于根证书来说,issuer和subject都是它自己
- subjectPublicKeyInfo: 颁发对象的公钥。证书中最关键的信息,其他所有信息都是为了验证它的真实性。
- SignedCertificateTimestampList(SCT):证书签署时间戳,可以用来审计证书的签发状态,提高证书的可信度
- encrypted: 数字签名。CA机构使用私钥对证书内容进行签名,只有用CA公钥才能验证。 最后补充一点: 证书签名算法,如上图中的"sha256WithRSAEncryption”是CA机构使用的算法,与服务器选择的身份验证算法无关。
Server Key Exchange
服务器发送了身份验证消息之后,终于到了核心环节,密钥协商,报文如下:
- ECDH Server Params: 服务器的EC参数
- Named Curve: secp256r1是服务器从客户端支持列表中选择的椭圆曲线参数组,这里面就包含了用于生成pre-master key的公共参数,我之前一直有疑问,关于双方如何同一公共参数,其实答案就在这条消息里面
- pubkey: 就是椭圆曲线算法中的dG,服务器私钥*椭圆曲线远点,作为ECDHE算法公钥发给客户端,让客户端生成pre-master key
- Signature Algorithm:服务器选择的签名算法,最底部就是服务器用自己私钥进行的签名,需要客户端使用服务器公钥验证.
Client Key Exchange
客户端在验证了服务器身份后,并收到服务器的密钥协商信息,会发送了自己的密钥参数,报文如下:
内容很简单,只有一个关键信息,ECDHE算法中客户端计算的公钥dG,发给服务器,让服务器计算pre-master key。
一般来说,在服务器没有请求客户端进行身份验证的情况下,客户端是不会发送自己的身份验证信息的。
注意一点:此时的客户端已经计算出最终传输加密需要的session key了,所以下一步,他就告知服务器,要开始进行加密传输
Change Cipher Spec
客户端发送此条消息,告知服务器,从下面开始,我要加密了!消息内容只有一个indicator指示:
Finish
这是握手流程中,客户端发送的最后一条消息,采用对称加密传输,服务器收到后,会使用同样的密钥进行验证,如果解密成功,则协商成功,双方开始数传:
new session ticket
服务器在验证了客户端加密消息之后,会发送session ticket,标识会话,并用于之后的恢复会话
关键信息包括session ticket lifetime生命周期以及id
Change Cipher Spec & Finish
服务器握手发送的最后两条信息,告知客户端开始进行加密传输,并对finish消息进行加密
以上就是TLS1.2版本中,所有的报文及其关键内容,我会在下一篇详细对比一下TLS1.3的报文。
感谢阅读,如有不准确和错误之处请留言指正,我会立即修正,感谢!
总结不易,请勿私自转载,否则别怪老大爷不客气
欢迎喜欢技术的小伙伴和我交流,微信1296386616