国密SSL/TLS证书申请与部署全流程:从CSR生成到Nginx配置的完整实战

国密算法 · 2026-09-30 · 1 阅读


title: "国密SSL/TLS证书申请与部署全流程:从CSR生成到Nginx配置的完整实战" slug: "gm-ssl-certificate-deployment-full-process" excerpt: "从SM2密钥对生成、CSR证书签名请求制作,到CA签发、Nginx国密双证书部署及双向认证配置,提供可直接复用的完整工程流程与生产环境踩坑记录。" category: gm tags: - SM2 - 国密 - TLS - 证书 - Nginx

前言

国密改造已进入深水区。很多团队卡在证书申请与部署环节——不是不会配Nginx,而是不知道CSR怎么生成、双证书怎么用、双向认证怎么做。本文以真实项目为背景,从零开始走完全流程,重点讲清楚每个环节的技术细节和常见陷阱。

环境准备

工具链清单:

工具用途版本要求
Tongsuo国密OpenSSL实现>= 1.1.1l
gmsslPython国密库>= 3.2.0
OpenSSL CLI证书转换与验证>= 3.0
cryptographyPython密码学库>= 43.0
前置条件:
  • 已申请到有效的SM2服务器证书(含私钥)
  • 已申请到有效的SM2客户端证书(含私钥)
  • 根证书CA链完整

步骤一:生成SM2密钥对与CSR

使用Tongsuo生成SM2密钥对

BASH
# 生成SM2私钥(输出为Tongsuo原生格式)
tongsuo ecparam -genkey -name sm2p256v1 -out server.key

# 查看私钥内容确认生成成功
tongsuo ec -in server.key -text -noout

生成CSR(证书签名请求)

⚠️ 常见陷阱:

  • CSR中的CN必须与服务器域名完全一致,否则浏览器会报证书名称不匹配
  • SAN扩展必须包含所有需要保护的域名,缺少SAN会导致部分客户端拒绝连接
  • 国密CSR不支持通配符域名(如*.example.com),需逐个列出

使用Python验证CSR

PYTHON
from gmssl.sm2 import CryptSM2
from gmssl import func

# 注意:gmssl库的CryptSM2使用硬编码的user_id '1234567812345678'
# 如需自定义user_id,请使用Tongsuo或BabaSSL
print("gmssl库已加载,可进行SM2操作")

## 步骤二:证书申请与获取

### 向CA提交CSR
bash

查看CSR内容确认信息正确

tongsuo req -in server.csr -noout -text

提交到CA(具体流程因CA而异,以下为示例)

通常通过CA提供的Web界面或API提交CSR内容

CODE
### 接收并验证书
bash

从CA获取证书后,验证证书信息

tongsuo x509 -in server.crt -noout -text

验证证书链完整性

tongsuo verify -CAfile ca-chain.crt server.crt
CODE
**证书验证要点:**
1. 检查证书有效期是否在预期范围内
2. 验证Subject字段与CSR中的信息一致
3. 检查Issuer字段是否来自可信CA
4. 确认Key Usage扩展包含digital signature和key encipherment
5. 验证Extended Key Usage包含serverAuth

## 步骤三:Nginx国密TLS配置

### 基础国密TLS配置
nginx server { listen 443 ssl; server_name yourdomain.com; # 国密证书配置(双证书:签名证书 + 加密证书) ssl_certificate /path/to/server_sign.crt; # SM2签名证书 ssl_certificate_key /path/to/server_sign.key; # SM2签名私钥 ssl_certificate /path/to/server_encrypt.crt; # SM2加密证书 ssl_certificate_key /path/to/server_encrypt.key; # SM2加密私钥 # 国密密码套件(Tongsuo支持) ssl_ciphers ECDHE-SM2-SM4-GCM-SM3:ECDHE-SM2-SM4-CBC-SM3:ECDHE-ECDSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; # 国密协议版本 ssl_protocols TLSv1.2 TLSv1.3; location / { root /var/www/html; index index.html; } }
CODE
**⚠️ 关键说明:**
- 国密TLS使用双证书机制:签名证书用于身份认证,加密证书用于密钥交换
- 签名证书对应GM/T 0024-2023中的SM2签名算法
- 加密证书对应GM/T 0024-2023中的SM2加密算法
- Tongsuo会自动根据客户端支持的算法协商选择证书

### 双证书配置详解
nginx

方式一:双证书分开配置(推荐)

ssl_certificate /path/to/sign.crt; ssl_certificate_key /path/to/sign.key; ssl_certificate /path/to/encrypt.crt; ssl_certificate_key /path/to/encrypt.key;

方式二:双证书合并配置

将签名证书和加密证书按顺序合并到一个文件

证书顺序:签名证书在前,加密证书在后

cat sign.crt encrypt.crt > combined.crt

注意:Nginx只支持一个ssl_certificate_key指令,私钥应为签名私钥

ssl_certificate /path/to/combined.crt; ssl_certificate_key /path/to/sign.key;
CODE
**⚠️ 生产环境注意:**
- 双证书私钥文件权限必须设置为600,且属主为nginx运行用户
- 证书文件建议存放在独立的安全目录,避免被其他进程读取

## 步骤四:双向认证(mTLS)配置

### 服务端配置
nginx server { listen 443 ssl; server_name yourdomain.com; # 国密证书 ssl_certificate /path/to/server_sign.crt; ssl_certificate_key /path/to/server_sign.key; ssl_certificate /path/to/server_encrypt.crt; ssl_certificate_key /path/to/server_encrypt.key; # 双向认证:要求客户端提供证书 ssl_verify_client on; # 客户端CA证书链(用于验证客户端证书) ssl_client_certificate /path/to/client-ca.crt; # 验证深度 ssl_verify_depth 2; # 验证失败处理 ssl_crl /path/to/crl.pem; # CRL分发点 location / { # 获取客户端证书信息(用于日志和后续处理) add_header X-Client-DN $ssl_client_s_dn; add_header X-Client-Verify $ssl_client_verify; # 将客户端证书信息传递给后端应用 proxy_set_header X-SSL-Client-Cert $ssl_client_cert; root /var/www/html; index index.html; } }
CODE
### 客户端配置
nginx

客户端也需要配置自己的证书

upstream backend { server backend1:8443; server backend2:8443; }

server { listen 80; server_name client.yourdomain.com; location / { proxy_pass https://backend; # 客户端证书 proxy_ssl_certificate /path/to/client_sign.crt; proxy_ssl_certificate_key /path/to/client_sign.key; proxy_ssl_certificate /path/to/client_encrypt.crt; proxy_ssl_certificate_key /path/to/client_encrypt.key; # 服务端CA证书(用于验证服务端证书) proxy_ssl_trusted_certificate /path/to/server-ca.crt; # 启用双向认证 proxy_ssl_verify on; proxy_ssl_verify_depth 2; } }

CODE
**⚠️ 双向认证常见问题:**
1. **客户端证书未被信任**:检查`ssl_client_certificate`是否正确指向客户端CA证书链
2. **证书链不完整**:确保服务端提供的证书链包含中间CA证书
3. **CRL检查失败**:如果配置了CRL,确保CRL文件有效且未被吊销
4. **证书过期**:检查所有证书(服务端、客户端、CA)的有效期

## 步骤五:验证与测试

### 使用OpenSSL验证连接
bash

测试服务端TLS握手(国密)

tongsuo s_client -connect yourdomain.com:443 -tls1_2

测试双向认证

tongsuo s_client -connect yourdomain.com:443 \ -cert client_sign.crt \ -key client_sign.key \ -cert client_encrypt.crt \ -key client_encrypt.key

查看握手详情

tongsuo s_client -connect yourdomain.com:443 -tls1_2 -msg
CODE
### 使用Python验证
python import ssl import socket

创建国密SSL上下文

ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) ctx.check_hostname = False ctx.verify_mode = ssl.CERT_REQUIRED

加载客户端证书

ctx.load_cert_chain('client_sign.crt', 'client_sign.key') ctx.load_verify_locations('server-ca.crt')

建立连接

with ctx.wrap_socket(socket.socket(), server_hostname='yourdomain.com') as s: cert = s.getpeercert() print(f"服务器证书信息:") print(f" Subject: {cert['subject']}") print(f" Issuer: {cert['issuer']}") print(f" Not Before: {cert['notBefore']}") print(f" Not After: {cert['notAfter']}") # 读取响应 s.sendall(b'GET / HTTP/1.1\r\nHost: yourdomain.com\r\n\r\n') response = s.recv(4096) print(response.decode())
CODE
### 性能基准测试
bash

使用Tongsuo进行性能测试

tongsuo s_client -connect yourdomain.com:443 \ -tls1_2 -num 1000 -quiet

使用wrk进行HTTP压测

wrk -t4 -c100 -d30s --latency \ https://yourdomain.com/ bash

查看Tongsuo支持的国密密码套件

tongsuo ciphers -v | grep -i sm ```

总结

国密SSL/TLS证书申请与部署涉及多个环节,每个环节都有需要注意的细节。本文覆盖了从密钥生成、CSR制作、证书申请到Nginx配置和双向认证验证的完整流程。关键点总结:

  • 双证书机制:国密TLS使用签名证书和加密证书分离的设计,配置时需正确处理
  • SAN扩展:确保证书包含所有需要保护的域名
  • 双向认证:合理配置客户端证书验证,平衡安全与可用性
  • 性能考虑:国密算法性能与硬件加速密切相关,生产环境建议启用硬件加速
在实际项目中,建议建立自动化证书管理系统,确保证书生命周期可追溯、可审计,降低人工操作带来的风险。

相关实践