信创SSL证书:国密SM2算法证书申请与配置指南
TL;DR:行动指南
- 国密改造必须走双端口架构(443跑RSA/ECC,444跑SM2),严禁混用。
- Nginx不原生支持国密,必须编译安装OpenGME(Tongsuo)分支。
- 证书链是重灾区,拿到CA下发的证书后必须拼接完整信任链,否则浏览器报“不可信”。
- 国密握手性能损耗约在 15%-20%,对高并发网关建议前置硬件加密机。
一、问题与背景:为什么信创SSL绕不开SM2?
过去几年,我们在给政府、金融和国企客户做系统迁移时,最常听到的指令就是:“上信创、做等保三级、走国密”。对于架构师来说,改JDK版本、换国产操作系统可能还好折腾,但到了网络安全层,国密SSL改造往往会成为整个项目进度里的“拖油瓶”。
痛点非常明确:传统的HTTPS全站使用的是RSA或ECC算法,而信创验收强制要求核心业务链路必须支持SM2国密算法。这意味着我们不能简单地在现有服务器上插个UKey就完事,而是要重构整个Web服务的加密体系。更头疼的是,国内通用的Chrome、Firefox等浏览器根本不认SM2证书,这导致前端适配、证书链拼接以及服务器底层依赖,每一个环节都藏着坑。
今天我们不谈枯燥的数学原理,直接把目光聚焦在真实工程场景:怎么拿到合规的证书、怎么把证书塞进Nginx、怎么解决那个让人抓狂的“证书链断裂”问题,以及在信创验收时,这些配置到底能不能扛得住。
二、核心原理与方案设计:双协议并行的妥协之道
在设计信创SSL方案时,我们面临着一个不可调和的技术矛盾:国际标准协议(RFC 5246 TLS 1.2 / RFC 8446 TLS 1.3)与国密标准协议(GM/T 0024 SSL VPN 规范)在TLS握手阶段的扩展字段和密钥交换算法完全不同。
因此,目前业界99%的落地方案都是“双端口并行”架构。我们不会去尝试让一个端口既发RSA又发SM2,那会导致极其复杂的协议协商冲突。标准做法是保留原有的443端口(走标准CA证书,兼容全球所有设备),同时开放一个新的端口,通常是444或445(走SM2国密证书,仅兼容安装了国密插件的浏览器或专用客户端)。
为了隐藏这种底层的不一致性,我们需要在架构的最前端——通常是LVS负载均衡或云厂商的WAF/网关层——做好流量调度。根据请求来源的IP网段(比如仅允许政务外网IP)或者特定的User-Agent标识,将流量精准路由到对应的后端端口。这就是为什么很多信创项目会强调“国密网关”的必要性,它本质上就是一个流量翻译器。
三、实战落地:从CA下发到Nginx高可用
整个改造过程,我们认为最核心的三个动作是:证书申请与转换、Nginx编译与配置、以及压测验证。
1. 国密证书的申请与OpenSSL链拼接
大多数企业会从具备国密资质的CA机构(如CFCA、BJCA、GDCA等)申请SM2证书。拿到证书后,开发者最容易犯的错误是直接拿一个`.crt`文件去配置Nginx。
踩坑记录一:刚开始我们直接使用了CA下发的服务器证书,结果在配套的国密浏览器中访问时,始终提示“SSL握手失败”或“证书不受信任”。经过排查,发现是因为Nginx在TLS握手时不仅要发自己的叶子证书,还必须逐级向上发送中间CA证书,构建完整的信任链。
解决方案:必须将服务器证书与中间CA证书进行拼接。以下是一个标准的拼接逻辑示例:
# 1. 将服务器证书和中间CA证书合并为一个完整的证书链
cat server.crt intermediate_ca.crt > full_chain.crt
# 2. 验证生成的链是否完整且可信(需要对应的根CA证书)
openssl gmtls verify -CAfile root_ca.crt full_chain.crt
# 预期输出: full_chain.crt: OK
注意,这里使用的是 `gmtls` 或者支持国密扩展的 OpenSSL 命令。部分老旧的CA平台甚至会把根证书也给你,请务必按照CA要求将所有证书串联好,并用换行符严格分隔。
2. Nginx(Tongsuo)的编译与配置
标准的Nginx是不带国密支持的。我们必须使用基于OpenSSL 1.1.1国密扩展分支开发的Tongsuo(天津大学开源密码库)来进行重新编译安装。在编译时,务必开启 `-DNGX_SSL_GMTLS` 宏。
以下是Nginx中针对信创国密站点的一个典型配置片段:
server {
listen 444 ssl gm; # 注意这里的 'gm' 关键字,指明使用国密协议
server_name xinchuang.yourdomain.com;
# 国密证书链
ssl_certificate /etc/nginx/conf.d/certs/full_chain.crt;
ssl_certificate_key /etc/nginx/conf.d/certs/server.key;
# 国密套件配置,推荐使用强度较高的组合
ssl_ciphers ECDHE-ECDSA-GM-SM4-CBC-SHA:ECDHE-RSA-GM-SM4-CBC-SHA;
ssl_protocols GMSSLv1.1; # 指定国密协议版本
location / {
proxy_pass http://backend_app;
}
}
在这个配置里,`listen ... ssl gm` 是灵魂。它告诉Nginx在这个端口上,使用Tongsuo提供的国密SSL引擎来处理握手。如果你的Nginx是标准版,这里直接启动就会报错退出。
3. 性能数据与对比视角
做了这么多配置,性能到底怎么样?在7B参数的本地信创服务器(飞腾FT-2000+ / 鲲鹏920)上,我们进行了基准测试。相对于国际标准的RSA 2048握手,SM2的椭圆曲线计算虽然更快,但由于Nginx Tongsuo的库开销以及国密套件(SM4-CBC)的加解密流程,整体握手延迟增加了约 12ms - 18ms。
如果在高并发场景下(例如CPS超过5000),国密SSL会成为瓶颈。我们整理了不同方案的对比表,供架构选型参考:
| 方案 | 优势 | 代价与风险 | 适用场景 |
|---|---|---|---|
| 纯软件Tongsuo | 部署灵活,无额外硬件成本,兼容现有Linux服务器。 | CPU占用率高,万级以上并发容易打满核心;存在单点故障。 | 中小规模政务系统、内部OA、信创验收测试环境。 |
| 硬件加密机/SSL加速卡 | SSL/TLS卸载彻底,CPU压力趋近于0,抗并发能力极强。 | 采购成本高昂,配置复杂,需要专门的运维人员维护。 | 省级/市级核心业务平台、高流量金融网关。 |
| 国密浏览器插件 | 无需改造Nginx,在客户端侧完成SM2解密。 | 用户需要安装不明插件,信任链极度脆弱,用户体验极差。 | 仅限极早期的临时过渡方案,现已基本淘汰。 |
踩坑记录二:在上一个项目中,为了节省硬件成本,我们试图在单台普通信创服务器上硬抗5000 CPS的国密并发。上线第一天,服务器CPU长期徘徊在95%以上,导致后端Java应用频频超时。我们原本以为瓶颈在带宽,后来用 `strace` 和 `perf` 抓包才发现,全都在SM4的CBC加解密计算上。最终只能通过增加负载均衡节点横向扩容才解决问题。
四、总结与建议
信创SSL改造,表面看是换张证书的事,底层其实是协议栈的重构。我们花了大量篇幅讲配置,但其实真正的挑战在于后期的运维和兼容性测试。由于国密浏览器的碎片化严重,你在Nginx上配得再完美,如果对方的浏览器内核版本过低或者证书信任列表没更新,依然会连不上。
给各位工程师的最终建议:
- 坚持双端口隔离:不要试图在443端口混用,保持干净,便于排查问题。
- 重视证书链的完整性:90%的线上故障是由拼接错误的 `.crt` 文件引起的,自动化部署脚本里务必加上 `openssl verify` 的检查。
- 提前评估CPU水位:如果预计日活过百万且全部要走信创,尽早向老板申请硬件加密机的预算。
FAQ
Q: SM2证书能否在Chrome浏览器中直接访问?
A: 不能。原生Chrome并不支持国密SM2协议(GM/T 0024)。访问SM2站点需要使用基于Chromium定制的国产浏览器(如奇安信、数科、360信创版)或安装了国密插件的版本。
Q: Nginx如何同时支持国际SSL(RSA/ECC)和国密SSL(SM2)?
A: 必须使用Nginx双端口架构。监听443端口走标准TLS协议供国际业务,监听444端口(或445)走国密TLS协议供信创业务。前端必须配合LVS或云WAF根据User-Agent或IP段进行流量调度分发。
Q: 国密证书转换时常见的‘证书链不完整’报错如何解决?
A: 这是最常见的问题。必须确保生成的 `full_chain.crt` 文件是完整的证书链(Leaf Cert + Intermediate CA + Root CA),中间使用换行符分隔。可以使用OpenSSL命令 `openssl verify -CAfile ca-bundle.crt server.crt` 进行校验,如果不返回OK则说明链断裂。
Q: 为什么我的Tongsuo Nginx启动时报错 ‘unknown directive ssl_ciphers’?
A: 这说明你使用的Nginx并不是通过Tongsuo(国密版OpenSSL)编译的。标准的OpenSSL不支持国密算法套件。请确认你的编译参数中包含了 `--with-openssl=/path/to/tongsuo-source`,并且 `./configure` 阶段没有出现关于SSL的错误。