主页

引言

TLS作为保证网络通信安全的关键技术和基石被广泛应用,但目前主流国内外网站仍然使用国际TLS协议,即:TLS1.2TLS1.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,加密模式涉及两种方式:CBCGCM
  • 校验算法/哈希算法包含: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不同的地方。

在示例中,涉及到的工具有:

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请求 # 查看国密证书生成脚本
➜ practical-crypto git:(master) cat openssl/generate_sm2_cert.sh
#!/bin/sh
# 1. 设置证书主体subject
SUBJ="/C=CN/ST=BeiJing/L=BeiJing/O=warm3snow/OU=Server/CN=localhost" # 2. 生成签名证书 (openssl 1.1.x以上版本支持sm2, 或者tassl、gmssl)
gmssl ecparam -genkey -name SM2 -text -out ./gmcerts/server_sign.key
gmssl req -new -key ./gmcerts/server_sign.key -out ./gmcerts/server.csr -subj $SUBJ
gmssl x509 -req -days 3650 -sm3 -in ./gmcerts/server.csr -signkey ./gmcerts/server_sign.key -out ./gmcerts/server_sign.crt \
-extfile ./openssl.cnf -extensions v3_req_sign # 3. 生成加密证书
gmssl ecparam -genkey -name SM2 -text -out ./gmcerts/server_enc.key
gmssl req -new -key ./gmcerts/server_enc.key -out ./gmcerts/server.csr -subj $SUBJ
gmssl x509 -req -days 3650 -sm3 -in ./gmcerts/server.csr -signkey ./gmcerts/server_enc.key -out ./gmcerts/server_enc.crt \
-extfile ./openssl.cnf -extensions v3_req_enc

注意在支持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{signKeyPair, encKeyPair},
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需要设置两个证书,一个是签名证书,用于签名验证;一个是加密证书,用于数据加密(这里指的是握手过程中涉及到的加密)。这种双证书体系使得证书的这两种功能(加密和签名验证)能够使用不同证书来单独处理,提高了安全性。

启动服务并进行抓包

  • 启动https服务,并使用tlsClient客户端发送请求

  • 打开wireshark并进行抓包设置

从左上角图的最后输出我们可以看到,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字段对应,都为签名证书。(实际上我们这里想要说明的是发送的签名证书无误,由于签名证书和加密证书的证书主体Subject字段是一致的,我们这里用证书KeyUsage进行区分)

服务端加密证书

Wireshark抓包详情(Certificate消息)

practical-crypto测试程序服务端使用的加密证书

从上面两张图可以看出:抓包显示证书的KeyUage - keyEncipherment字段,和服务端启动设置证书的X509v3 Key Usage -KeyEncipherment字段对应,都为加密证书。(实际上我们这里想要说明的是发送的加密证书无误,由于签名证书和加密证书的证书主体Subject字段是一致的,我们这里用证书KeyUsage进行区分)*

结论

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

参考资料

TLS原理与实践(四)国密TLS的更多相关文章

  1. WebSocket原理与实践(四)--生成数据帧

    WebSocket原理与实践(四)--生成数据帧 从服务器发往客户端的数据也是同样的数据帧,但是从服务器发送到客户端的数据帧不需要掩码的.我们自己需要去生成数据帧,解析数据帧的时候我们需要分片. 消息 ...

  2. OpenSSL 1.1.1 国密算法支持

    OpenSSL 1.1.1 国密算法支持 https://www.openssl.org/ https://github.com/openssl/openssl OpenSSL 1.1.1 新特性: ...

  3. SSL/TLS 原理详解

    本文大部分整理自网络,相关文章请见文后参考. SSL/TLS作为一种互联网安全加密技术,原理较为复杂,枯燥而无味,我也是试图理解之后重新整理,尽量做到层次清晰.正文开始. 1. SSL/TLS概览 1 ...

  4. SSL/TLS原理详解

    本文大部分整理自网络,相关文章请见文后参考. 关于证书授权中心CA以及数字证书等概念,请移步 OpenSSL 与 SSL 数字证书概念贴 ,如果你想快速自建CA然后签发数字证书,请移步 基于OpenS ...

  5. [No0000126]SSL/TLS原理详解与WCF中的WS-Security

    SSL/TLS作为一种互联网安全加密技术 1. SSL/TLS概览 1.1 整体结构 SSL是一个介于HTTP协议与TCP之间的一个可选层,其位置大致如下: SSL:(Secure Socket La ...

  6. 2017-2018-2 20179204《网络攻防实践》第十三周学习总结 python实现国密算法

    国密商用算法是指国密SM系列算法,包括基于椭圆曲线的非对称公钥密码SM2算法.密码杂凑SM3算法.分组密码SM4算法,还有只以IP核形式提供的非公开算法流程的对称密码SM1算法等. 第1节 SM2非对 ...

  7. 开源项目SMSS发开指南(四)——SSL/TLS加密通信详解

    本文将详细介绍如何在Java端.C++端和NodeJs端实现基于SSL/TLS的加密通信,重点分析Java端利用SocketChannel和SSLEngine从握手到数据发送/接收的完整过程.本文也涵 ...

  8. kafka原理和实践(四)spring-kafka消费者源码

    系列目录 kafka原理和实践(一)原理:10分钟入门 kafka原理和实践(二)spring-kafka简单实践 kafka原理和实践(三)spring-kafka生产者源码 kafka原理和实践( ...

  9. 图解ARP协议(四)代理ARP原理与实践(“善意的欺骗”)

    一.代理ARP概述 我:当电脑要访问互联网上的服务器,目标MAC是什么? 很多小伙伴在刚学习网络协议的时候,经常这样直接回应:不就是服务器的MAC嘛! 这时我会反问:那电脑怎么拿到这个服务器的MAC地 ...

  10. Hyperledger Fabric国密改造

    Fabric国密改造是个什么概念?我们来思考以下4个问题: 为什么偏偏是密码算法?(WHY?) 什么是国密算法?(WHAT?) 改造切入点什么?(WHERE?) 如何实现国密支持?(HOW?) 1.为 ...

随机推荐

  1. Windows10磁盘占用100%和内存占用高

    前言 公司配备了两台电脑,两台电脑都是安装的win10系统,一台是磁盘占用高,另一台是内存可用低. 具体情况如下: 一台外网机 8g内存,安装win10 专业版,开机一天后经常出现内存不够用,但其实都 ...

  2. 我手写了一个RPC框架。成功帮助读者斩获字节、阿里等大厂offer。

    本着开源精神,本项目README已经同步了英文版本.另外,项目的源代码的注释大部分也修改为了英文. 如访问速度不佳,可放在 Gitee 地址:https://gitee.com/SnailClimb/ ...

  3. 操作系统开发:BIOS/MBR基础与调试

    这里在实验之前需要下载 Bochs-win32-2.6.11 作者使用的是Linux版本的,在Linux写代码不太舒服,所以最好在Windows上做实验,下载好虚拟机以后还需要下载Nasm汇编器,以及 ...

  4. Mygin中间件优化及日志中间件

    本篇是mygin的第七篇,参照gin框架,感兴趣的可以从 Mygin第一篇 开始看,Mygin从零开始完全手写,在实现的同时,带你一窥gin框架的核心原理实现. 目的 中间件Middleware优化 ...

  5. 图(树)的广度优先遍历bfs

    图的广度优先遍历 广度优先遍历,就是在遍历时优先考虑遍历的广度,不像深度优先那样一条路径遍历到底,而是一层一层的遍历. 由于广度优先是一层一层节点的遍历,在图的边权值都为1的情况下,若我们要求出节点a ...

  6. Linux-sshpass(shell脚本使用ssh远程执行命令通过密码的方式登录)

    1. sshpass简介 sshpass 是一个在非交互式 ssh 会话中自动输入密码的工具.它可以直接在命令行中指定密码,因此可以用于 Shell 脚本等自动化场景.在 Red Hat 系统中,可以 ...

  7. Go 之烧脑的接口

    基本定义 Go 官方对于接口的定义是一句话:An interface type is defined as a set of method signatures. 翻译过来就是,一个接口定义了一组方法 ...

  8. NC24858 [USACO 2009 Nov S]Job Hunt

    题目链接 题目 题目描述 Bessie is running out of money and is searching for jobs. Farmer John knows this and wa ...

  9. NVME(学习杂谈)—Asynchronous Event

    Asynchronous Event Request Host Software Recommendations 当一个异步事件请求完成(提供Event Type,Event Information, ...

  10. Java 递归的方式将list集合的某一字段拼接单个String

    场景介绍 要将list 集合中的某一个字段合并成一个字符串,并且要用符号 "|" 分割开每个拼接后的字段. 一个例子胜于一切的文字表达,拼接后的结果如下 str1|str2|str ...