从零到一:在Nginx中部署SM2国密证书实战指南

张开发
2026/4/16 18:48:15 15 分钟阅读

分享文章

从零到一:在Nginx中部署SM2国密证书实战指南
1. 为什么你需要SM2国密证书最近两年越来越多的企业开始收到合规部门的邮件要求将现有的RSA证书替换为国密SM2证书。我第一次接到这个任务时也是一头雾水花了两周时间才把整套流程跑通。现在回想起来其实整个过程并不复杂只是当时缺少一份真正从零开始的完整指南。SM2算法是我国自主设计的椭圆曲线公钥密码算法相比传统的RSA算法有几个明显优势首先是安全性更高256位的SM2密钥强度相当于3072位的RSA其次是运算速度更快特别是在移动设备上能显著降低功耗最重要的是它符合国内密码管理政策要求。我去年给某金融机构做迁移时他们的测试数据显示SM2的握手速度比RSA快了近40%。2. 环境准备搭建支持SM2的OpenSSL2.1 检查现有环境在开始之前先用这个命令检查你的OpenSSL是否支持SM2openssl ecparam -list_curves | grep sm2如果没有任何输出说明需要重新编译OpenSSL。我去年在CentOS 7上就遇到过这个问题系统自带的OpenSSL 1.0.2根本不支持SM2。2.2 编译安装支持SM2的OpenSSL这里我推荐使用OpenSSL 1.1.1以上版本编译时记得加上enable-sm2参数wget https://www.openssl.org/source/openssl-1.1.1w.tar.gz tar -zxvf openssl-1.1.1w.tar.gz cd openssl-1.1.1w ./config --prefix/usr/local/openssl --openssldir/usr/local/openssl enable-sm2 make -j4 sudo make install编译完成后记得更新系统路径echo export PATH/usr/local/openssl/bin:$PATH ~/.bashrc source ~/.bashrc3. 生成SM2证书全流程3.1 创建SM2私钥生成私钥时要注意密钥长度SM2固定使用256位openssl ecparam -genkey -name sm2p256v1 -out sm2.key这里有个坑要注意有些老版本的OpenSSL可能会报unknown curve错误这时候需要确认编译时确实启用了SM2支持。3.2 生成证书签名请求(CSR)创建CSR文件时建议加上-sm3参数指定签名算法openssl req -new -key sm2.key -out sm2.csr -sm3 -subj /CCN/STBeijing/LBeijing/OYourCompany/CNyourdomain.com我遇到过CSR被CA拒绝的情况后来发现是因为没加-sm3参数。国内CA机构通常要求使用SM3作为哈希算法。3.3 获取签名证书把CSR提交给CA机构后你会得到一个.crt文件。这里有个重要提示国内主流CA如CFCA、上海CA的SM2证书价格比RSA证书贵30%左右但有些云服务商(比如阿里云)现在提供免费的SM2试用证书。4. Nginx配置详解4.1 基础证书配置把证书和私钥放到/etc/nginx/ssl/目录下后nginx配置应该这样写server { listen 443 ssl; server_name yourdomain.com; ssl_certificate /etc/nginx/ssl/sm2.crt; ssl_certificate_key /etc/nginx/ssl/sm2.key; # 必须配置的加密套件 ssl_ciphers EECDHSM2AESGCM:EECDHSM2AES; ssl_prefer_server_ciphers on; }这里最容易出错的是ssl_ciphers配置我第一次配的时候漏掉了EECDHSM2结果Chrome直接报错ERR_SSL_VERSION_OR_CIPHER_MISMATCH。4.2 性能优化配置SM2证书在Nginx上需要特别优化才能发挥最佳性能ssl_protocols TLSv1.2 TLSv1.3; ssl_ecdh_curve sm2p256v1; ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_session_tickets off;重点是这个ssl_ecdh_curve配置它指定了密钥交换使用的椭圆曲线。实测加上这个配置后TLS握手时间能缩短20%。5. 验证与排错5.1 基础验证方法配置完成后先用这个命令检查nginx配置是否正确nginx -t然后使用openssl验证证书链openssl verify -CAfile chain.crt sm2.crt我建议再用这个命令测试实际握手情况openssl s_client -connect yourdomain.com:443 -cipher ECDHE-SM2 -tls1_25.2 常见问题解决问题1浏览器提示不安全连接 解决方案检查证书链是否完整可能需要配置ssl_trusted_certificatessl_trusted_certificate /etc/nginx/ssl/chain.crt;问题2Nginx启动报错SSL_CTX_use_certificate:key values mismatch 解决方案这通常是证书和私钥不匹配导致的用这个命令检查openssl x509 -noout -modulus -in sm2.crt | openssl md5 openssl ec -in sm2.key -noout -text | grep -A 3 pub:6. 进阶配置技巧6.1 双证书部署方案为了兼容老旧客户端可以采用RSASM2双证书方案server { listen 443 ssl; ssl_certificate /etc/nginx/ssl/rsa.crt; ssl_certificate_key /etc/nginx/ssl/rsa.key; ssl_certificate /etc/nginx/ssl/sm2.crt; ssl_certificate_key /etc/nginx/ssl/sm2.key; ssl_configuration_method dual; }这个配置下支持SM2的客户端会自动选择SM2证书其他客户端会使用RSA证书。6.2 OCSP Stapling配置SM2证书也可以启用OCSP装订提升性能ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 valid300s; resolver_timeout 5s;配置后可以用这个命令验证openssl s_client -connect yourdomain.com:443 -status -tls1_2 /dev/null 21 | grep -i OCSP response7. 生产环境注意事项在实际部署中我发现有几点特别重要首先是证书续期问题SM2证书的有效期通常比RSA证书短建议设置自动监控其次是兼容性问题Windows 7的IE11需要特别处理最后是性能监控建议在Nginx日志中添加$ssl_cipher和$ssl_protocol字段方便分析SM2使用情况。配置完成后别忘了测试不同场景下的表现特别是移动端设备。我在华为手机上就遇到过TLS握手失败的情况后来发现是没正确配置中间证书。现在每次部署新证书我都会用这个在线工具全面测试https://www.ssllabs.com/ssltest/

更多文章