国密 HTTPS 改造的核心是把 TLS 握手从国际算法体系切到以 SM2、SM3、SM4 为底座的国密体系,同时保留 RSA 证书对外提供兼容访问。国密 HTTPS 改造并不需要改动后端业务代码,只要在 Web 服务或网关层完成双证书加载与 NTLS 协议启用即可。本文给出基于 Tengine + Tongsuo(铜锁)的国密 HTTPS 改造完整配置流程,包含 SM2 双证书生成、签名结构与加密结构分离、配置验证与兼容性处理。
适用场景
- 政务、金融、能源、医疗等行业的系统需要满足国密算法改造与信创验收要求。
- 站点需要在保留主流浏览器访问能力的同时,为支持国密协议的客户端提供自主可控的加密通道。
- 内网系统、专用终端、政务专网客户端已支持 SM2/SM4,需要服务端同步开启。
- 产品交付时被要求提供「国密算法支持能力」的配置说明与验证报告。
前置条件
- 服务器已开放 443 端口,域名解析正常,且已完成基础的 HTTPS 可用性验证。
- Tengine 2.4 及以上,编译时接入 Tongsuo 密码库并加载
ngx_tongsuo_ntls模块。 - 国密证书两套:签名证书(用于身份认证与签名)与加密证书(用于密钥交换),两者必须是独立密钥对。
- 正式环境建议使用具备国密资质的 CA 签发证书;测试环境可用 Tongsuo 自签 CA 生成。
- 已确认业务侧不需要支持 TLS 1.0/1.1,国密改造通常与协议版本收紧同时执行。
原理说明
国密 TLS(NTLS)与国际 TLS 的差异集中在三处:
- 算法替换:非对称加密与签名使用 SM2(基于椭圆曲线),摘要使用 SM3,对称加密使用 SM4。
- 双证书体系:国际 TLS 中一张证书同时承担签名与加密职责,国密体系要求签名证书与加密证书分离,各自独立密钥,私钥分离存放可降低单点泄露的影响范围。
- 协议标识:Tengine 通过
enable_ntls开关启用 NTLS 握手,国密握手与国际握手在同一 443 端口上按客户端 ClientHello 自动分流。
兼容策略上推荐 双栈共存:国密客户端走 SM2 签名+SM4 加密套件,普通浏览器走 RSA 证书与国际套件,两者互不干扰,不需要为国密单独开端口或子域名。
操作步骤
1. 编译安装 Tengine 与 Tongsuo
cd /usr/local/src
tar -xzf Tongsuo-8.2.1.tar.gz
tar -xzf tengine-2.4.1.tar.gz
cd tengine-2.4.1
./configure --prefix=/usr/local/tengine \
--add-module=modules/ngx_tongsuo_ntls \
--with-openssl=../Tongsuo-8.2.1 \
--with-openssl-opt="enable-ntls" \
--with-http_ssl_module \
--with-http_v2_module \
--with-stream --with-stream_ssl_module
make -j$(nproc) && make install
关键点是 –with-openssl-opt=”enable-ntls”,它让底层密码库开放 NTLS 能力;缺少该参数时 enable_ntls 指令会报未知指令。编译完成后用 /usr/local/tengine/sbin/nginx -V 确认模块与编译参数已包含上述内容。
2. 生成 SM2 双证书(测试环境自签)
cd /usr/local/tengine/conf && mkdir -p cert && cd cert
OSSL=/usr/local/tongsuo/bin/openssl
# 生成 SM2 根 CA
$OSSL ecparam -genkey -name SM2 -out ca.key
$OSSL req -new -x509 -key ca.key -out ca.crt -days 3650 -sm3 \
-subj "/C=CN/O=Example Security/CN=Example SM2 Root CA"
# 生成签名密钥与 CSRs
$OSSL ecparam -genkey -name SM2 -out sign.key
$OSSL req -new -key sign.key -out sign.csr -sm3 \
-subj "/C=CN/O=Example Security/CN=www.example.com"
# 生成加密密钥与 CSR
$OSSL ecparam -genkey -name SM2 -out enc.key
$OSSL req -new -key enc.key -out enc.csr -sm3 \
-subj "/C=CN/O=Example Security/CN=www.example.com"
# 用 CA 分别签发签名证书与加密证书
$OSSL x509 -req -in sign.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out sign.crt -days 3650 -sm3
$OSSL x509 -req -in enc.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out enc.crt -days 3650 -sm3
# 合并证书链
cat sign.crt ca.crt > server_sign.pem
cat enc.crt ca.crt > server_enc.pem
chmod 600 sign.key enc.key ca.key
两套密钥必须分开生成,严禁复用同一密钥对。生产环境把 CA 私钥离线保存,服务器上只放服务端证书与私钥,私钥文件权限设为 600 并由专用账户持有。
3. 配置双证书与 NTLS
server {
listen 443 ssl;
server_name www.example.com;
# 启用国密 NTLS 协议
enable_ntls on;
# 国密签名证书
ssl_sign_certificate cert/server_sign.pem;
ssl_sign_certificate_key cert/sign.key;
# 国密加密证书
ssl_enc_certificate cert/server_enc.pem;
ssl_enc_certificate_key cert/enc.key;
# 国际 RSA 证书,用于兼容普通浏览器
ssl_certificate cert/server_rsa.pem;
ssl_certificate_key cert/server_rsa.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECC-SM2-WITH-SM4-GCM-SM3:ECDHE-SM2-WITH-SM4-GCM-SM3:HIGH:!aNULL:!MD5;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
root /var/www/html;
index index.html;
}
四条国密指令中,ssl_sign_certificate 与 ssl_enc_certificate 分别对应签名与加密结构,不可混用文件。若不需要兼容国际客户端,可省略 RSA 两行,但多数面向公网的站点都建议保留双栈。实际可用的国密套件名称以本机编译结果为准,先用 /usr/local/tongsuo/bin/openssl ciphers -ntls -v | grep SM2 列出支持的套件再回填。
4. 平滑生效
/usr/local/tengine/sbin/nginx -t
/usr/local/tengine/sbin/nginx -s reload
nginx -t 必须通过后再 reload。若报 unknown directive "enable_ntls",说明模块未编译进去,需回到第 1 步检查 --add-module 与 enable-ntls 参数。
配置验证
- 国密握手验证:用支持 NTLS 的客户端测试,命令为
/usr/local/tongsuo/bin/openssl s_client -connect www.example.com:443 -ntls -cipher ECC-SM2-WITH-SM4-GCM-SM3,握手成功后会输出国密套件与Peer signature type: SM2字样。 - 国际协议兼容验证:用普通 openssl 执行
openssl s_client -connect www.example.com:443 -tls1_2,确认 RSA 链路仍可用,双栈没有互相挤占。 - 证书结构验证:
openssl x509 -in server_sign.pem -noout -text查看公钥算法是否为id-ecPublicKey且曲线为SM2,签名算法为SM3withSM2。 - 浏览器可用性验证:主流浏览器访问应正常展示锁标识;若报证书错误,通常是证书链合并顺序有误或缺少中间证书。
- 协议收紧验证:
openssl s_client -connect www.example.com:443 -tls1_1应当握手失败,确认弱协议已按预期禁用。
常见问题
FAQ 1:配置完成后浏览器仍提示证书无效,如何排查?
按三步定位。第一,确认访问路径走的是 RSA 还是国密:普通浏览器不支持 NTLS,必然走 RSA 链路,若只配置了国密证书而没配置 RSA 证书,浏览器就会握手失败。第二,检查证书链是否完整,server_rsa.pem 必须是「站点证书 + 中间证书」的完整链,顺序不能颠倒。第三,核对域名与证书 CN/SAN 是否一致,国密证书与国际证书的 SAN 需覆盖全部对外域名。三步都正常但仍报错时,用 openssl s_client -connect 域名:443 -servername 域名 观察服务端实际下发的证书序列号,确认与预期文件一致。
FAQ 2:国密改造后性能下降明显,如何优化?
国密握手的计算开销高于部分国际套件,优先从四方面优化。一是开启会话复用,配置 ssl_session_cache shared:SSL:10m 并适当延长 ssl_session_timeout,把重复握手的比例压下来。二是优先使用 GCM 模式套件,其吞吐优于 CBC 模式。三是在网关层终结国密流量,后端内网继续使用明文或国际协议,避免每层都做国密运算。四是国密证书的私钥运算在 CPU 上完成,若单机承载连接数很高,可开启多 worker 进程并把加密任务分散到更多核心,必要时引入国密硬件加密卡。压测时用 ab 或 wrk 分别测试国密与国际链路的 QPS,对比后再决定是否需要扩容。
总结
国密 HTTPS 改造的落地要点只有四个:编译时打开 enable-ntls、配置四个国密证书指令、保留 RSA 证书做兼容、用 s_client 验证握手套件。签名证书与加密证书必须分离生成并分离存放,这是国密体系与国际体系最大的结构差异,也是合规检查的重点项。改造完成后建议把验证命令固化成巡检脚本,在证书到期、配置变更与系统升级后自动跑一遍,避免出现「配置看起来对、实际走的是国际套件」的假合规。