TLS原理与实践(四)国密TLS
主页
- 个人微信公众号:密码应用技术实战
- 个人博客园首页:https://www.cnblogs.com/informatics/
引言
TLS作为保证网络通信安全
的关键技术和基石被广泛应用,但目前主流国内外网站仍然使用国际TLS协议,即:TLS1.2
和TLS1.3
。随着国内《网络安全法》、《密码法》和《数据安全法》等法律法规的颁布和实施,国密TLS
在国内关键领域也逐渐被应用。
支持国密TLS具有以下重要意义:
- 数据保护:国密TLS使用了国密算法,减少了对国际密码算法的依赖,降低了使用国际算法可能造成的安全隐患
- 自主可控:技术自主可控,降低了对国际技术的依赖,提高国内密码技术的自主研发能力
- 合规要求:在某些行业,使用国际算法不符合法律法规和监管要求
国密标准GB/T 39786
对网络和通信安全
层面的密码应用提出了明确的技术要求
,涉及通信主体的各个要素, 都需要进行密码技术改造,支持国密TLS。这也是密评
中对于“网络和通信安全“的基本技术要求。
本文内容组织如下:
- 简介
- 协议原理
- wireshark抓包分析
- 总结&参考文献
简介
国密TLS,又称GMTLS1.1
,涉及的主要标准有:
- 《信息安全技术 传输层密码协议(TLCP)》,即
GB/T 38636-2020
- 《SSL VPN技术规范》,即
GM/T 0024-2014
- 上述协议关联标准:如数字证书标准
GB/T 20518
, SM2密码算法标准GB/T 35275
等
注:《SSL VPN技术规范》作为行业标准
,部分内容已上升为《信息安全技术 传输层密码协议(TLCP)》国密标准
, 后文中介绍的内容以后者为准。
GMTLS1.1
中的1.1
代表国密TLS的版本号: 0x0101。众所周知,目前TLS协议支持的版本:
VersionTLS10 = 0x0301
VersionTLS11 = 0x0302
VersionTLS12 = 0x0303
VersionTLS13 = 0x0304
目前主流的TLS软件程序实现中,通信实体在建立TLS连接时,会优先
协商使用最大版本号TLS协议
(版本号越大意味着安全性越高、性能越好),因此VersionGMSSL = 0x0101
版本号的设定增加了软件支持的复杂度,这也是阻碍GMTLS1.1广泛应用的一个重要原因。(估计国密TLS协议制定者都是一帮学术大佬,实践经验不足)。
GMTLS1.1中相关的密码套件
(图片来自GB/T 38636-2020):
从图中可以了解到GMTLS1.1:
密钥交换算法
包含ECDHE、ECC、IBSDH、IBC以及RSA,其中IBC和IBSDH主要涉及到SM9标识密码算法。- 加密算法只有
SM4
,加密模式涉及两种方式:CBC
和GCM
。 - 校验算法/哈希算法包含:SM3和SHA256
注:从上图中我们还可以了解到,在GMTLS1.1支持的套件中,包含了国际算法RSA和SHA256,这里从公开文献中未找到具体原因,大胆猜测主要是为了:
- 支持国际知名CA机构颁发的数字证书
- 作为一种切换到全国密TLS过度
协议原理
GMTLS1.1协议主要参考了TLS1.1
,并借鉴了TLS1.2
的部分内容。在关键流程上基本一致,只是在密码算法使用上用国密算法
对国际算法
j进行了替换(从这里可以看到,GMTLS1.1在协议原理上并未有太大创新,基本照搬)。 这里附一张GMTLS1.1协议流程图:
由于协议流程与TLS1.2
一致,这里不再赘述,可以参考之前的文章:《TLS原理与实践(一)》
Wireshark抓包分析
下面我们通过示例代码
和wireshark抓包分析
来详细介绍GMTLS1.1协议流程,后文Wireshark抓包分析主要介绍与TLS1.2不同的地方。
在示例中,涉及到的工具有:
- wireshark: 网络抓包和分析软件,这里使用的版本为
Version 4.0.7 (v4.0.7-0-g0ad1823cc090)
,注意4.0之前的版本可能不支持GMTLS1.1,官网为 https://www.wireshark.org - practical-crypto: 用于模拟支持GMTLS1.1协议的https服务和客户端,github仓库 https://github.com/warm3snow/practical-crypto.git
practical-crypto介绍
# 下载示例代码
➜ practical-crypto git:(master) git clone https://github.com/warm3snow/practical-crypto.git
# 查看示例代码目录结构
➜ practical-crypto git:(master) tree tls
tls
├── gmtls
│ └── gmtls1_1.go # 使用国密TLS的https服务
├── notls #无tls保护http服务
│ └── notls.go
├── readme.md #帮助文档
├── tls1.2 # 使用tls1.2协议的http服务
│ └── tls1_2.go
├── tls1.3 # 使用tls1.3协议的http服务
│ └── tls1.3.go
└── tlsclient.go # http客户端,可以发起http或https请求
注意在支持gmtls1.1的https服务中,引用了第三方实现包(golang
语言实现), 主要代码如下:
import (
tls "github.com/warm3snow/gmsm/gmtls" //1. 支持GMTLS1.1的tls协议实现包
"log"
"net/http"
)
func HelloHandler(w http.ResponseWriter, r *http.Request) { // 2. 服务端hello响应实现函数
log.Printf("Received connection: %s", r.RemoteAddr)
w.Write([]byte("Hello, world!"))
}
func main() {
// 设置handler
mux := http.NewServeMux()
mux.HandleFunc("/", HelloHandler)
// 3. 加载服务端签名证书和签名私钥
signKeyPair, err := tls.LoadX509KeyPair("../../openssl/gmcerts/server_sign.crt", "../../openssl/gmcerts/server_sign.key")
if err != nil {
log.Fatalf("LoadX509KeyPair: %v", err)
}
// 4. 加载服务端加密证书和加密私钥
encKeyPair, err := tls.LoadX509KeyPair("../../openssl/gmcerts/server_enc.crt", "../../openssl/gmcerts/server_enc.key")
if err != nil {
log.Fatalf("LoadX509KeyPair: %v", err)
}
// 5. 设置GMTLS1.1配置项
tlsCfg := &tls.Config{
GMSupport: tls.NewGMSupport(),
Certificates: []tls.Certificate{encKeyPair, signKeyPair},
MaxVersion: tls.VersionTLS12,
}
ln, err := tls.Listen("tcp", ":8443", tlsCfg)
if err != nil {
log.Fatalf("Listen: %v", err)
}
// 6. 其中https服务
err = http.Serve(ln, mux)
if err != nil {
log.Fatalf("Serve: %v", err)
}
}
从上述代码中,我们可以看到GMTLS1.1需要设置两个证书,一个是签名证书
,用于签名验证;一个是加密证书
,用于数据加密(这里指的是握手过程中涉及到的加密)。这种双证书
体系使得证书的这两种功能(加密和签名验证)能够使用不同证书来单独处理,提高了安全性。
启动服务并进行抓包
从左上角图的最后输出我们可以看到,GMTLS1.1协议执行完成,服务端最终返回了Hello world!
消息。
概览图
从概览图中,我们可以了解到:
- 客户端和服务端通信使用了
GMTLSv1协议
,即GMTLS1.1 - GMTLS1.1握手协议发送的消息类型与
TLS1.2
完全一致 - 握手完成后,进行了应用数据
Application Data
通信
Client Hello消息
从Client Hello消息中,我们可以看出:
- 协议版本号:客户端使用的协议版本号为
GMTLS(0x0101)
- 加密套件:客户端支持的GMTLS加密套件有
4
个, 并不是标准里面的12
个(这与测试程序引用的gmtls实现包有关系, 目前仅支持4个国密tls加密套件),分别为:
Cipher Suite: ECC_SM4_CBC_SM3 (0xe013)
Cipher Suite: ECC_SM4_GCM_SM3 (0xe053)
Cipher Suite: ECDHE_SM4_CBC_SM3 (0xe011)
Cipher Suite: ECDHE_SM4_GCM_SM3 (0xe051)
Server Hello消息
服务端发送ServerHello消息后,紧接着发送了Certificate消息。
从上图我们可以了解到:
- 服务端TLS版本号:服务端和客户端握手过程中使用了GMTLS1.1协议
- 协商使用的加密套件:服务端和客户端最终协商使用了
ECC_SM4_CBC_SM3
加密套件。注意我们在测试用例中并未指定使用的加密套件,服务端和客户端默认协商使用排在加密套件列表最前端
的一个,参考上文Client Hello
发送的加密套件列表。 - 服务端返回的签名证书,从图中可以看出服务端返回了我们在启动服务时在代码中设置的签名证书
- 服务端返回的加密证书,从图中可以看出服务端返回了我们在启动服务时在代码中设置的加密证书
服务端签名证书:
- Wireshark抓包详情(Certificate消息)
- practical-crypto测试程序服务端使用的签名证书
上图中抓包显示证书的KeyUage - digitalSignature
字段,和服务端启动设置证书的X509v3 Key Usage - Digital Signature
字段对应。
服务端加密证书
Wireshark抓包详情(Certificate消息)
practical-crypto测试程序服务端使用的加密证书
上图中抓包显示证书的KeyUage - keyEncipherment
字段,和服务端启动设置证书的X509v3 Key Usage -KeyEncipherment
字段对应。
结论
GMTLS1.1作为中国密码技术的重要组成部分,在国内重要领域已广泛应用,也是密评
评测指标中的关键卡点。本文结合TLS1.2协议流程以及GMTLS1.1协议demo程序和Wireshark抓包,对其进行了详细介绍。
目前主流计算机语言(JAVA、Python、NodeJs以及Golang等)官方都未支持GMTLS1.1,国密TLS协议包基本都是国内开发者基于主流语言的TLS程序报进行的二次开发,在实际应用和推广中仍然存在不少阻力,因此GMTLS1.1国际化任重道远。
顺便多一句:GMTLS1.1由于版本号的原因,够呛能够国际化。 TLS1.3支持国密算法倒是值得尝试(目前已有人提交了提案,有兴趣的可以参考 -> https://datatracker.ietf.org/doc/html/rfc8998
参考资料
- 信息安全技术 传输层密码协议(TLCP)
- SSL VPN技术规范
- wireshark: https://www.wireshark.org
- practical-crypto: https://github.com/warm3snow/practical-crypto.git
- TLS1.2 RFC: https://www.ietf.org/rfc/rfc5246.txt
- TLS1.3 RFC: https://datatracker.ietf.org/doc/html/rfc8998