Ubuntu 18.04下基于OpenSSL 1.1.1构建完整国密SM2证书链实战指南

发布时间:2026/7/24 18:05:43
Ubuntu 18.04下基于OpenSSL 1.1.1构建完整国密SM2证书链实战指南 1. 项目概述与背景最近在搞一个对数据安全要求比较高的内部项目客户明确要求通信链路必须支持国密算法。国密SM2作为非对称加密算法的核心其证书的生成和管理就成了必须跨过去的一道坎。网上资料虽然不少但要么是蜻蜓点水要么环境交代不清对于想在稳定生产环境比如我们用的Ubuntu 18.04 LTS里从零开始构建一套完整SM2证书体系的人来说总感觉缺了那么点“一步到位”的踏实感。这次我就把整个在Ubuntu 18.04上基于OpenSSL 1.1.1编译、配置并最终亲手签发包含根证书、中间证书和服务端证书的完整SM2证书链的过程掰开揉碎了讲清楚。你会发现只要工具版本和配置参数搞对了这事儿并没有想象中那么玄乎完全可以在自己的开发机或测试服务器上复现。2. 环境准备与核心工具选型2.1 为什么是Ubuntu 18.04和OpenSSL 1.1.1选择Ubuntu 18.04 LTS主要是看中其长期支持带来的稳定性。很多企业的生产环境仍在使用它在这个系统上验证通过意味着方案有较好的向后兼容性和参考价值。而OpenSSL 1.1.1系列则是关键中的关键。国密算法在OpenSSL中的原生支持是从1.1.1版本才开始引入的之前的版本需要打补丁或者使用GmSSL等分支。直接使用官方原生的OpenSSL 1.1.1不仅能获得最新的安全补丁也避免了因使用第三方分支可能带来的兼容性和维护风险。虽然Ubuntu 18.04默认仓库里的OpenSSL版本可能略旧但我们可以通过编译指定版本来获得我们需要的功能。2.2 系统基础环境检查与配置首先登录你的Ubuntu 18.04系统建议使用一个具有sudo权限的普通用户而不是直接使用root这更符合安全操作规范。我们先更新系统并安装一些编译所需的依赖包sudo apt update sudo apt upgrade -y sudo apt install build-essential checkinstall zlib1g-dev -ybuild-essential提供了GCC编译器、make等基础编译工具checkinstall能帮助我们将编译好的软件打包成deb包方便管理zlib1g-dev是OpenSSL编译可能需要的压缩库开发文件。完成这一步我们就为编译工作准备好了“工地”。2.3 编译安装OpenSSL 1.1.1我们不使用系统自带的版本而是下载、编译并安装一个纯净的OpenSSL 1.1.1。这里我选择1.1.1w版本这是一个经过长期考验的稳定终版。下载源代码找一个合适的目录例如/usr/local/src。cd /usr/local/src sudo wget https://www.openssl.org/source/openssl-1.1.1w.tar.gz sudo tar -xzf openssl-1.1.1w.tar.gz cd openssl-1.1.1w配置编译选项这里有几个关键参数。sudo ./config --prefix/usr/local/openssl --openssldir/usr/local/openssl shared zlib--prefix/usr/local/openssl指定安装目录。将其安装到/usr/local下与系统自带的OpenSSL隔离避免冲突。--openssldir/usr/local/openssl指定OpenSSL的配置文件、证书存储等目录。shared生成动态链接库.so文件方便其他程序调用。zlib启用zlib压缩支持。编译与安装sudo make sudo make test # 强烈建议运行测试套件确保编译正确 sudo make install编译过程可能需要几分钟。make test能帮你发现潜在的环境问题如果所有测试通过心里会踏实很多。配置系统环境变量为了让系统优先使用我们新安装的OpenSSL需要更新动态链接库缓存和PATH。echo /usr/local/openssl/lib | sudo tee /etc/ld.so.conf.d/openssl-1.1.1w.conf sudo ldconfig然后将OpenSSL的可执行文件路径添加到当前用户的PATH中可以写入~/.bashrc或~/.profileecho export PATH/usr/local/openssl/bin:$PATH ~/.bashrc source ~/.bashrc验证安装openssl version如果输出显示OpenSSL 1.1.1w ...并且路径是/usr/local/openssl/bin/openssl那么恭喜你环境准备就绪。注意编译安装OpenSSL是整个过程的基础也是最容易出错的环节。如果make test失败请仔细检查错误信息通常是缺少某个依赖库。另外确保系统没有残留的老版本OpenSSL头文件或库文件干扰。3. 国密SM2证书链原理与规划在动手敲命令之前我们得先搞清楚要创建什么。一个完整的PKI公钥基础设施证书体系通常是树状结构对于我们要搭建的测试或内部环境一个典型的三层结构就足够了根证书Root CA、中间证书Intermediate CA、最终实体证书End-Entity Certificate比如服务器证书。根证书Root CA这是整个证书链信任的锚点。它通常自签名并且其私钥需要被极其安全地离线保管。在内部系统中我们需要将根证书的公钥部分即根证书文件导入到操作系统或应用程序的“受信任的根证书颁发机构”存储区。中间证书Intermediate CA由根证书签发。它的作用是作为根CA的代理用于签发最终的服务器或客户端证书。这样做的好处是即使中间证书的私钥泄露我们可以用根证书吊销它而无需动摇根证书本身的权威也无需重新分发根证书。根证书的私钥因此可以保持离线更加安全。服务器证书Server Certificate由中间证书签发直接安装在Web服务器如Nginx、Apache上用于HTTPS服务。证书中包含服务器的域名或IP地址以及对应的SM2公钥。我们的操作流程将是1) 创建根CA并自签根证书2) 创建中间CA并由根CA为其签发证书3) 创建服务器证书请求CSR并由中间CA签发服务器证书。4. 创建国密SM2根证书Root CA根证书是信任的起点我们将为其创建独立的目录结构以保持清晰。4.1 建立根CA工作目录与配置文件mkdir -p ~/sm2_ca/root cd ~/sm2_ca/root mkdir certs crl newcerts private chmod 700 private touch index.txt echo 1000 serialcerts存放已签发的证书。crl存放证书吊销列表本次不涉及。newcerts存放新签发证书的副本。private存放CA的私钥权限设置为700确保只有所有者可读。index.txtOpenSSL CA数据库记录所有已签发证书。serial证书序列号文件初始值设为1000。接下来创建根CA的配置文件root_openssl.cnf。这个文件定义了CA的默认设置、策略和扩展项对于正确生成符合规范的证书至关重要。# ~/sm2_ca/root/root_openssl.cnf [ ca ] default_ca CA_default [ CA_default ] dir /home/你的用户名/sm2_ca/root certs $dir/certs crl_dir $dir/crl database $dir/index.txt new_certs_dir $dir/newcerts certificate $dir/certs/root_ca.crt serial $dir/serial crlnumber $dir/crlnumber private_key $dir/private/root_ca.key RANDFILE $dir/private/.rand default_days 3650 default_crl_days 30 default_md sm3 preserve no policy policy_strict name_opt ca_default cert_opt ca_default [ policy_strict ] countryName match stateOrProvinceName match organizationName match organizationalUnitName optional commonName supplied emailAddress optional [ req ] default_bits 256 default_md sm3 default_keyfile privkey.pem distinguished_name req_distinguished_name x509_extensions v3_ca string_mask utf8only prompt no [ req_distinguished_name ] countryName CN stateOrProvinceName Beijing localityName Beijing organizationName MyRoot CA Org organizationalUnitName IT Department commonName MyRoot SM2 CA [ v3_ca ] subjectKeyIdentifier hash authorityKeyIdentifier keyid:always,issuer basicConstraints critical, CA:true keyUsage critical, digitalSignature, cRLSign, keyCertSign关键点解析default_md sm3这是国密的核心。指定默认的摘要算法为SM3国密标准中的杂凑算法。default_bits 256对于SM2算法密钥长度固定为256位即32字节。[ v3_ca ]扩展段CA:true表明这是一个CA证书keyCertSign表示该证书可用于签发其他证书。prompt no和[ req_distinguished_name ]中预设了值是为了在非交互式模式下运行方便自动化。你可以根据实际情况修改国家、组织等信息。4.2 生成根CA私钥与自签名证书现在使用配置文件来生成根CA的私钥和证书。cd ~/sm2_ca/root # 生成SM2私钥 openssl ecparam -genkey -name sm2 -out private/root_ca.key # 使用配置文件生成证书请求CSR并自签为证书 openssl req -config root_openssl.cnf -new -x509 -key private/root_ca.key -out certs/root_ca.crt -days 3650openssl ecparam -genkey -name sm2 -out private/root_ca.keyecparam是椭圆曲线参数命令-name sm2指定使用国密SM2曲线-genkey表示生成密钥对。这条命令生成了根CA的SM2私钥。openssl req ... -x509 ...req命令处理证书请求。-x509选项直接输出一个自签名的证书而不是一个证书请求CSR。-config指定了我们的配置文件它提供了除Common Name外的所有DN可识别名称信息。-days 3650设定了证书有效期为10年。执行后你会在private/目录下得到受密码保护的私钥root_ca.key如果配置了-passout参数在certs/目录下得到根证书root_ca.crt。实操心得根CA的私钥是安全的核心。在生产环境中这个私钥应该在生成后立即被转移到离线、安全的介质如加密的硬件安全模块HSM或离线U盘中保存并从生成它的服务器上彻底删除。我们这里为了演示暂时保留在本地。5. 创建国密SM2中间证书Intermediate CA中间CA的创建过程与根CA类似但它的证书是由根CA签发的。5.1 建立中间CA工作目录与配置文件mkdir -p ~/sm2_ca/intermediate cd ~/sm2_ca/intermediate mkdir certs crl newcerts private csr chmod 700 private touch index.txt echo 1000 serial echo 1000 crlnumber创建中间CA的配置文件intermediate_openssl.cnf内容与根CA的类似但有一些关键区别。# ~/sm2_ca/intermediate/intermediate_openssl.cnf [ ca ] default_ca CA_default [ CA_default ] dir /home/你的用户名/sm2_ca/intermediate certs $dir/certs crl_dir $dir/crl database $dir/index.txt new_certs_dir $dir/newcerts certificate $dir/certs/intermediate_ca.crt serial $dir/serial crlnumber $dir/crlnumber private_key $dir/private/intermediate_ca.key RANDFILE $dir/private/.rand default_days 1825 default_crl_days 30 default_md sm3 preserve no policy policy_loose name_opt ca_default cert_opt ca_default [ policy_loose ] countryName optional stateOrProvinceName optional localityName optional organizationName optional organizationalUnitName optional commonName supplied emailAddress optional [ req ] default_bits 256 default_md sm3 default_keyfile privkey.pem distinguished_name req_distinguished_name x509_extensions v3_intermediate_ca string_mask utf8only prompt no [ req_distinguished_name ] countryName CN stateOrProvinceName Beijing localityName Beijing organizationName MyIntermediate CA Org organizationalUnitName Secure Services Dept commonName MyIntermediate SM2 CA [ v3_intermediate_ca ] subjectKeyIdentifier hash authorityKeyIdentifier keyid:always,issuer basicConstraints critical, CA:true, pathlen:0 keyUsage critical, digitalSignature, cRLSign, keyCertSign关键点解析policy policy_loose中间CA在签发服务器证书时对申请者信息的匹配要求可以放宽optional这样在签发不同域名或用途的服务器证书时更灵活。pathlen:0这个扩展项表示该中间CA不能再签发下级CA证书它只能签发最终实体证书。这符合我们三层结构的设计增强了安全性。default_days 1825中间证书有效期设为5年通常比根证书短比服务器证书长。5.2 生成中间CA私钥与证书签发请求CSRcd ~/sm2_ca/intermediate # 生成中间CA的SM2私钥 openssl ecparam -genkey -name sm2 -out private/intermediate_ca.key # 生成证书签发请求 openssl req -config intermediate_openssl.cnf -new -key private/intermediate_ca.key -out csr/intermediate_ca.csr5.3 使用根CA为中间CA签发证书这一步需要用到根CA的私钥和证书。我们回到根CA的目录进行操作。cd ~/sm2_ca/root # 使用根CA的配置和私钥为中间CA的CSR签发证书 openssl ca -config root_openssl.cnf -extensions v3_intermediate_ca -days 1825 -notext -md sm3 -in ../intermediate/csr/intermediate_ca.csr -out ../intermediate/certs/intermediate_ca.crtopenssl ca这是OpenSSL的CA命令用于签发和吊销证书。-config root_openssl.cnf指定使用根CA的配置。-extensions v3_intermediate_ca指定使用配置文件中的v3_intermediate_ca扩展段这确保了生成的证书具有正确的CA属性。-in和-out指定输入的CSR文件和输出的证书文件路径。执行命令后OpenSSL会提示你确认签发。查看根CA目录下的index.txt你会看到一条新记录。中间CA的证书intermediate_ca.crt现在位于~/sm2_ca/intermediate/certs/目录下。5.4 验证中间证书并创建证书链文件我们可以验证中间证书是否由根证书正确签发openssl verify -CAfile certs/root_ca.crt ../intermediate/certs/intermediate_ca.crt如果输出../intermediate/certs/intermediate_ca.crt: OK说明验证通过。为了方便服务器配置我们创建一个从服务器证书到根证书的完整证书链文件。这个文件在配置Nginx等服务器时非常有用。cd ~/sm2_ca cat intermediate/certs/intermediate_ca.crt root/certs/root_ca.crt intermediate/certs/ca-chain.crt现在ca-chain.crt文件包含了中间证书和根证书顺序是从下级到上级。6. 签发国密SM2服务器证书服务器证书是最终安装在Web服务器上的证书。我们将为域名myserver.example.com请替换为你的实际域名或IP签发证书。6.1 生成服务器私钥与CSR首先为服务器生成SM2私钥和证书请求。我们可以在一个单独的目录操作但这里为了简便在中间CA目录下进行。cd ~/sm2_ca/intermediate # 生成服务器SM2私钥 openssl ecparam -genkey -name sm2 -out private/myserver.key # 生成服务器证书请求 openssl req -config intermediate_openssl.cnf -new -key private/myserver.key -out csr/myserver.csr在生成CSR时命令行会交互式地询问DN信息。最关键的是Common Name必须输入你服务器要使用的域名或IP地址例如myserver.example.com。其他信息如组织名等可以根据需要填写也可以留空因为我们在配置文件中设置了policy_loose。6.2 创建服务器证书扩展配置文件服务器证书需要一些特定的扩展属性比如subjectAltNameSAN主题备用名称现代浏览器都要求HTTPS证书包含SAN扩展。我们创建一个文件server_ext.cnf来定义这些扩展。# ~/sm2_ca/intermediate/server_ext.cnf [ req ] default_bits 256 default_md sm3 distinguished_name req_distinguished_name req_extensions v3_req prompt no [ req_distinguished_name ] countryName CN stateOrProvinceName Beijing localityName Beijing organizationName MyServer Inc commonName myserver.example.com [ v3_req ] basicConstraints CA:FALSE keyUsage nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage serverAuth subjectAltName alt_names [ alt_names ] DNS.1 myserver.example.com DNS.2 www.myserver.example.com IP.1 192.168.1.100 # 可选如果你的服务器通过IP访问关键点解析commonName这里预设为myserver.example.com你也可以在命令行交互时输入。[ v3_req ]扩展段CA:FALSE明确这不是一个CA证书。keyUsage定义了密钥用途数字签名和密钥加密。extendedKeyUsage serverAuth表明此证书用于服务器身份验证。subjectAltName这是必须的列出了证书有效的所有域名和IP。DNS.1是主域名DNS.2可以是其他子域名。6.3 使用中间CA签发服务器证书现在使用中间CA的私钥和证书结合扩展配置文件来签发服务器证书。cd ~/sm2_ca/intermediate openssl ca -config intermediate_openssl.cnf -extensions v3_req -days 375 -notext -md sm3 -in csr/myserver.csr -out certs/myserver.crt -extfile server_ext.cnf-extensions v3_req指定使用CSR中或-extfile指定的v3_req扩展段。-extfile server_ext.cnf提供包含SAN等扩展的配置文件。-days 375服务器证书有效期通常较短这里设为约1年符合最佳实践。签发成功后服务器证书myserver.crt位于~/sm2_ca/intermediate/certs/目录对应的私钥myserver.key在private/目录。6.4 验证服务器证书链最后我们验证一下整个证书链是否完整有效。cd ~/sm2_ca openssl verify -CAfile intermediate/certs/ca-chain.crt intermediate/certs/myserver.crt如果输出intermediate/certs/myserver.crt: OK说明从服务器证书到根证书的信任链是完整的。7. 在Nginx中配置国密SM2证书证书生成好了最终要投入使用。以Nginx为例展示如何配置。你需要将前面生成的三个文件准备好服务器私钥~/sm2_ca/intermediate/private/myserver.key服务器证书~/sm2_ca/intermediate/certs/myserver.crt证书链文件~/sm2_ca/intermediate/certs/ca-chain.crt将它们复制到Nginx服务器的一个安全目录例如/etc/nginx/ssl/。修改Nginx的站点配置文件如/etc/nginx/sites-available/default或你的自定义配置文件server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name myserver.example.com www.myserver.example.com; # 国密SM2证书和密钥 ssl_certificate /etc/nginx/ssl/myserver.crt; ssl_certificate_key /etc/nginx/ssl/myserver.key; # 证书链文件确保客户端能构建完整的信任链 ssl_trusted_certificate /etc/nginx/ssl/ca-chain.crt; # 其他SSL优化配置... ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; # 你的应用配置... root /var/www/html; index index.html index.htm; }配置完成后检查配置并重载Nginxsudo nginx -t sudo systemctl reload nginx现在你的网站就应该可以通过HTTPS使用国密SM2证书访问了。由于根证书是我们自签的浏览器会提示“不安全”你需要将根证书root_ca.crt导入到操作系统或浏览器的“受信任的根证书颁发机构”中警告才会消失。对于内部系统测试这一步是常规操作。8. 常见问题、排查技巧与安全实践8.1 常见错误与解决方案openssl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file问题系统找不到我们编译的OpenSSL库。解决确保执行了sudo ldconfig并且环境变量LD_LIBRARY_PATH如果需要或/etc/ld.so.conf.d/下的配置正确。最可靠的方法是按照前面步骤将库路径添加到/etc/ld.so.conf.d/并运行ldconfig。签发证书时提示“The stateOrProvinceName field needed to be the same in the CA certificate...”问题证书请求中的主题信息如国家、省份与CA证书的签发策略policy不匹配。解决检查CA配置文件如root_openssl.cnf或intermediate_openssl.cnf中的policy段。根CA的policy_strict要求国家、省份、组织名必须匹配而中间CA的policy_loose则宽松很多。确保在生成CSR时输入的信息符合CA的策略要求或者修改策略配置。浏览器访问HTTPS站点提示“证书不受信任”或“NET::ERR_CERT_AUTHORITY_INVALID”问题客户端浏览器不信任签发服务器证书的根CA。解决这是预期行为因为根CA是我们自建的。对于内部系统你需要将root_ca.crt文件导入到客户端操作系统或浏览器的受信任根证书存储区。切勿将内部根证书公开放到互联网或导入到不信任的设备上。Nginx启动失败SSL相关错误问题Nginx可能不支持SM2算法或证书格式问题。解决首先确认Nginx是否支持国密。标准版Nginx需要集成支持国密的密码库如tongsuo。检查Nginx错误日志/var/log/nginx/error.log获取具体信息。另外确保证书和密钥文件路径正确且Nginx进程用户如www-data有读取权限。8.2 安全实践与私钥管理私钥保护CA的私钥尤其是根CA是安全命脉。在生产环境中根CA私钥应在生成后立即离线保存如加密的HSM或离线存储介质并从线上服务器删除。中间CA的私钥也应受到严格保护例如使用强密码加密存储。证书有效期遵循“根长中间中服务器短”的原则。根证书10-20年中间证书5-10年服务器证书1-2年。短期有效的服务器证书有助于在私钥泄露时减少损失。密钥算法与长度国密SM2的密钥长度是固定的256位其安全性相当于RSA 2048-3072位。确保整个证书链根、中间、服务器都使用SM2算法避免混合算法可能带来的兼容性问题。证书吊销本教程未涉及证书吊销列表CRL或在线证书状态协议OCSP。在生产环境中如果中间CA或服务器证书的私钥泄露你需要建立吊销机制。这涉及到在CA配置中启用CRL生成和分发点CRL Distribution Point扩展。8.3 关于OpenSSL历史漏洞的思考在搜索资料时你可能会看到类似“OpenSSL 缓冲区溢出拒绝服务漏洞(CVE-2016-2177)”这样的信息。这个漏洞主要危害是攻击者可以构造恶意数据触发OpenSSL库中的缓冲区边界计算错误导致服务进程崩溃从而造成拒绝服务DoS影响应用程序的正常运行。这提醒我们几个关键点第一始终使用官方维护的最新稳定版本如我们选择的1.1.1w并及时关注安全公告打补丁第二在编译时可以考虑启用更严格的安全编译选项第三将OpenSSL服务部署在防火墙后最小化其暴露面。对于我们当前生成国密证书的场景使用已经修复了历史漏洞的最新稳定分支并保持环境更新是基本的安全前提。