Go中TLS源码学习(6)之Server端第3次TLS握手

Go中TLS源码学习(6)之Server端第3次TLS握手

​“我正在参加「启航计划」”


SSL/TLS专栏导航
1. SSL/TLS原理常识
2. Go源码中TLS完结
3. openssl中TLS完结
4. SSL卸载
5. SSL署理
6. SSL V.P.N
7. SSL 与 IPSec
8. 其他
获取PDF版本请查找关键字:“TLS详解”

@[toc]


通常情况下,第三次握手报文的载荷包含:

  • 可选的Certificate载荷
  • ClientKeyExchange载荷
  • 可选的CertificateVerify载荷
  • ChangeCipherSpec载荷
  • Finished载荷 但是在ECDHE办法的TLS握手流程中,首要有:ClientKeyExchange、ChangeCipherSpec、Finished载荷。第三次握手报文如下:

Go中TLS源码学习(6)之Server端第3次TLS握手
ClientKeyExchange载荷无论在ECDHE密钥交流流程中,还是在RSA密钥交流流程中,都是个非常重要的交互载荷:在RSA流程中,ClientKeyExchange用来传递通过服务端公钥加密的预主密钥; 在ECDHE流程中,ClientKeyExchange载荷用来传递客户端的公钥信息。在ECDHE密钥交流过程中,正是通过该载荷的交流,服务端和客户端一起拥有了两个随机数、两个公钥以及各自的私钥,这便具备了生成TLS密钥的一切资料。之后就是预主密钥、主密钥、会话密钥,最终进行加密通讯。

1. 验证客户端证书

2. 核算预主密钥、主密钥

预主密钥和主密钥的核算办法涉及如下几个参数,通过TLS的握手报文,客户端和服务端都现已拥有下面的密钥资料,客户端和服务端各自核算出相同的预主密钥、主密钥以及会话密钥。

Go中TLS源码学习(6)之Server端第3次TLS握手
预主密钥的核算有两种办法:

当选用RSA算法进行密钥交流时,则在客户端通过随机产生;然后通过服务端证书的公钥进行加密,最终通过ClientKeyExchange载荷发送到服务端;

当选用ECDHE算法进行密钥交流时,则需求运用对端的公钥、本端的私钥、以及选用的椭圆曲线函数别离核算生成预主密钥。

Go中生成预主密钥的流程如下:

Go中TLS源码学习(6)之Server端第3次TLS握手
通过第Client Hello和Server Hello报文的交互,客户端和服务端现已确定了选用的算法套件,从而也就是确定了ServerKeyExchange和ClientKeyExchange载荷的内容以及处理办法。在第二个握手报文的“疑问”小结中,现已列出了算法套件与对应的密钥交流结构。因为此次TLS握手选用的是ECDHE的办法进行密钥配送,因此对应的密钥交流结构为ecdheKeyAgreement

ecdheKeyAgreement结构的SharedKey()办法中能够看出,预主密钥的核算涉及:对端的公钥,本端的私钥,以及选用的椭圆曲线

Go中TLS源码学习(6)之Server端第3次TLS握手
预主密钥核算结束后,便能够生成主密钥。主密钥的核算办法比较简单:

Go中TLS源码学习(6)之Server端第3次TLS握手
到目前为止,预主密钥、主密钥都现已得到。后边就是能够生成6把会话密钥了

3. 制造会话密钥

会话密钥有3类合计6把:

密钥名称 效果
client MAC 客户端音讯认证码密钥
server MAC 服务端音讯认证码密钥
client KEY 客户端对称加密密钥
server KEY 服务端对称加密密钥
client IV 客户端初始向量,对称加密时运用
server IV 服务端支持向量,对称加密时运用

会话密钥的制造是在RFC2246(TLS1.0)中**“6.3. Key calculation”**定义的,它的核算办法如下:

Go中TLS源码学习(6)之Server端第3次TLS握手
Go中核算会话密钥的函数如下:
Go中TLS源码学习(6)之Server端第3次TLS握手
6把会话密钥核算结束后,后边便应该将生成的密钥存储到对应的衔接上供业务通讯时运用。这儿还有需求注意的当地:

TLS协议能够完结对报文机密性、完整性、认证的功用;机密性则是通过运用对称密码加密来完结的(此刻会运用到6把密钥中的后4把);完整性和认证功用则是通过音讯认证码来完结的(此刻会用到6把密钥的前2把)。但是除此之外,还有一种愈加高档的算法:AE(Authenticated Encryption)或者AEAD(Authenticated Encryption with Associated Data ),中文成为认证加密认证加密是一种将音讯认证码和对称加密算法相结合,能够一起满意机密性、完整性、认证三大功用的机制。关于认证加密相关常识在“密码学常识”中进行介绍,这儿不再赘述。

Go中的TLS源码当然也支持这种比较新颖的办法(2000年今后开始出现认证加密机制)。

Go中TLS源码学习(6)之Server端第3次TLS握手
假如加密套件中存在AEAD(认证加密)算法,则只需求运用到6把密钥中的后4把,MAC密钥不再需求。假如不存在AEAD则选用独立加密算法和音讯认证算法,此刻6把密钥会悉数参加后续加密通讯。

关于TLS服务端而言,ClientCipher套件用来解析运用;ServerCipher套件用来加密运用。别离存在TLS衔接的两个半衔接上(in半衔接用来读取客户端加密信息,存储ClientCipher套件; out半衔接用来加密服务端信息,存储ServerCipher套件)

密钥信息目前并不能立刻投入运用,而是在收到对方的ChangeCipherSpec报文后,再切换运用新洽谈的密钥。在go源码的完结中,将cipher, mac别离对应的nextCipher,nextMac结构中。

Go中TLS源码学习(6)之Server端第3次TLS握手

4. 读取Change Cipher Spec报文

client的Client Key Exchange载荷处理结束后,洽谈两边现已完结了互相认证,预主密钥和会话密钥都现已核算结束,之后便能够进行加密通讯。但是在加密通讯之前,TLS协议有着愈加完备的处理机制:通过Change Cipher Spec载荷来告诉洽谈两边一起完结密钥切换;通过Finished报文来查验洽谈出的密钥是否能够正常通讯

CCS载荷的效果就是告诉对方开始切换密钥,今后通讯均运用新洽谈的密钥进行加密通讯。CCS载荷内容很简单:只要1字节长度,值为1。

Go中TLS源码学习(6)之Server端第3次TLS握手
go源码中运用readChangeCipherSpec()函数处理CCS报文。在函数中通过一系列的校验之后,最终调用如下函数完结密钥的切换:

Go中TLS源码学习(6)之Server端第3次TLS握手

5. 读取Finished报文

Finished报文首要用来查验两边洽谈的密钥信息是否能够进行正常通讯。Finished载荷核算办法如下(RFC5246:”7.4.9. Finished”小节):

PRF(master_secret, finished_label, Hash(handshake_messages))

从这儿能够看出:参加Finished载荷内容核算的包含:主密钥、Finish标签、一切的握手音讯的摘要。之前每一个握手函数都会存储到到hs.finishedHash上,就是为了此刻运用。 关于finished_label,客户端为“client finished”;服务端为”server finished”。这三个数据洽谈两边都悉数拥有,各自独立核算,然后比较是否相同;假如相同,则两边洽谈出的密钥均准确无误,能够用来加密通讯;假如校验失败,阐明洽谈有误,应立即停止洽谈。

Go中TLS源码学习(6)之Server端第3次TLS握手
通过该载荷完结对两边洽谈出的密钥的校验。