上一篇文章: Https之(三)TLS双向认证
简介
国密TLS,又称GMTLS
,其最新的标准是国家标准|GB/T 38636-2020
《信息安全技术 传输层密码协议(TLCP)》,即
GB/T 38636-2020
所以我们也可以称他为TLCP(Transport layer cryptography protocol),抓包软件wireshark里面对他的标记就是TLCP,后面我们统一叫他TLCP,我们后面介绍的内容也都是基于这个最新标准。
TLCP支持的密码套件如下:
从图中可以看到这些套件和我们之前说的标准版TLS一样,也是由密钥交换算法,对称加密算法,摘要算法组成,就是这些算法替换成了国密算法,目前我所知的广泛使用的是ECC_SM4_CBC_SM3,这个套件和我们第一篇文章介绍的TLS_RSA_WITH_AES_128_GCM_SHA256类似,这里的ECC并不是用于ECDHE中密钥交换的功能,而是对应RSA的非对称加密功能,服务器发送ECC公钥(在证书中)到客户端,客户端拿ECC公钥加密随机数给服务器。下面我们就根据这个套件来介绍一下TLCP的握手过程。
流程概述
首先看一下握手消息流程图:
注:*代表可选或依赖具体密码套件,不是每次都发送。
从上图看TLCP的协议流程和TLS1.2一致,下面我们通过抓包分析每一步的具体内容,如果你对TLS不了解,建议先看之前的文章,后面我主要分析差异点,不会讲每一步的细节。
握手过程
GMSSL - 国密SSL实验室是一个免费提供国密相关内容的网站,里面有国密相关的工具可以使用,我们测试TLCP就是用的这里面的内容。
GMCURL-国密版cURL可以用来与国密https服务通信。
上面工具的具体使用方法就不详细介绍了,直接去网站里看就可以了,下面是一次TLCP握手的完整流程:
TLCP第一次握手
1.Client Hello
1.Version:0x0101就是TLCP。
2.Random:和TLS一样,用于后面计算会话密钥。
3.Cipher Suites:客户端支持的加密套件,可以看到都是国密套件。
TLCP第二次握手
2.Server Hello
1.Random是服务端生成的一个随机数,用于生成会话密钥
2.Cipher Suites是服务端选择的加密套件
3.Certificate
到这里就和TLS有很大不同了,TLCP使用的是双证书体系,有两个证书,一个加密证书负责进行密钥交换,一个签名证书负责进行身份认证。
- 加密证书的公私钥是CA生成的,之后CA把公钥制作成证书给到服务端。
- 签名证书和TLS中的证书一样,服务器生成公私钥,将公钥给CA生成证书。
客户端在加密预主密钥时使用服务端加密证书中的公钥,为什么要这么做呢,因为加密证书的公钥和私钥都是CA生成的,这也就意味着CA拥有私钥可以解密得到会话密钥,进而可以在必要时解密数据。
可以看到上图有四个证书,分别是加密证书、签名证书、三级CA证书、二级CA证书,可以通过扩展字段keyUsage来区分他们。
4.Server Key Exchange
这一步和TLS也不一样,第一篇文章介绍的TLS的RSA密钥交换是没有这一步的,只有第二篇DH密钥协商才使用了这一步传递密钥协商的参数,按理说TLCP的ECC是和TLS的RSA一样的,并不需要这一步,老实说我也不知道ECC_SM4_CBC_SM3为什么有这一步,下面介绍一下这一步做了什么:
DH密钥协商中会在这一步传递协商会话密钥所需的服务端的公钥pubkey和证书私钥对公钥pubkey的签名,而ECC中不需要协商密钥,故没有pubkey以及签名,取而代之的是签名证书私钥 对(client_random + server_random + 加密证书)摘要 的加密值,客户端可以通过签名证书的公钥来解密验证这个值是否正确。
我问了一下deepseek这一步的作用,下面是他的回答:
国密GMTLS通过Server Key Exchange的签名机制,实现了身份认证、参数完整性、双证书联动和抗中间人攻击的多重安全目标。其核心是将会话密钥生成过程中的关键参数(随机数和加密证书)与服务端身份强绑定,确保ECC_SM4_CBC_SM3套件在静态密钥交换场景下的安全性。这一设计是国密协议对传统TLS的优化
5.Server Hello Done
和TLS一样,代表服务器这一步握手结束。
TLCP第三次握手
6.Client Key Exchange
和TLS相同,将用加密证书公钥加密的pre-master传递给服务端,服务端拿到直接用私钥解密就可以拿到pre-master,加上client的random和server的radom就可以得到回话密钥。
客户端随机数 + 服务端随机数 + 预主密钥 = 主密钥 ==> 会话密钥
7.Change Cipher Spec 8.Encrypted Handshake Message
告诉服务端开始用会话密钥进行加密通讯了
把客户端之前所有发送的数据做个摘要,再用会话密钥(master secret)加密一下,让服务器做个验证,验证加密通信是否可用和之前握手信息是否有被中途篡改过。
TLCP第四次握手
9.Change Cipher Spec 10.Encrypted Handshake Message
和客户端发送的Change Cipher Spec操作相同,告诉客户端我准备好使用会话密钥了
把服务端之前所有发送的数据做个摘要,再用会话密钥(master secret)加密一下,让客户端做个验证,验证加密通信是否可用和之前握手信息是否有被中途篡改过。
到这里国密TLCP就介绍完了,可以看到大部分步骤和TLS还是相同的,只是替换了国密的算法和引入了双证书体系,下面再介绍一下国密的双向认证过程,看看和TLS有什么区别。
双向认证
国密的双向认证和标准TLS基本一致,区别在于算法和双证书体系,建议先看Https之(三)TLS双向认证-CSDN博客。
我们通过GMCURL-国密版cURL模拟双向认证通信,
gmcurl_linux_x64 --gmssl --cacert ./sm2.ca.pem --cert ./sm2.user1.sig.crt.pem --key ./sm2.user1.sig.key.pem --cert2 ./sm2.user1.enc.crt.pem --key2 ./sm2.user1.enc.key.pem https://demo.gmssl.cn:2443/
1)–cert表示指定用户签名证书(pem格式)
2)–key表示指定用户签名私钥(pem格式)
3)–cert2表示指定用户加密证书(pem格式)
4)–key2表示指定用户加密私钥(pem格式)
由于国密是双证书体系,所以这里客户端证书提供了两个,一个签名证书,一个加密证书。
到这里你可能会有疑问,服务端使用两个证书是为了CA在必要时可以解密通讯内容,但是客户端证书又不参与加密消息内容,只是为了验证身份,为什么要两个证书呢?其实在ECC密钥交换模式下确实不需要双证书,这时候加密证书是用不到的,因此实际使用时,客户端只发送签名证书,也可以握手成功,除非服务端作了强制校验。但是在ECDHE密钥协商的模式下必须使用双证书,这时候加密证书是参与密钥协商的。
我们直接通过TLS握手的抓包来分析双向认证的过程,下面是双向认证完整的握手图:
和上面的单向认证相比多了服务端发给客户端的Certificate Request、客户端发给服务端的Certificate和Certificate Verify,我们就看这三步做了什么。
Certificate Request
这一步是服务端向客户端请求证书,其中包含了对证书的要求,
1.Certificate types:服务器可接受的客户端证书格式。
2.Distinguished Names:只接受由指定DN对应的CA签发的客户端证书,这里有两个,其中一个MiddleCa是RootCa的二级代理,这两者签发的证书都可以。
Certificate
这个是客户端收到Certificate Request请求后向服务端发送证书,这里的证书就是我们我们前面发送请求的时候指定的证书。
Certificate Verify
这一步会对之前握手的消息和客户端加密证书进行Hash,然后使用客户端签名证书的私钥进行加密。
Signature:是加密后的内容。