企业内网双CA证书体系搭建:RSA与国密SM2混合架构实战指南

📅 2026/7/1 10:05:25
企业内网双CA证书体系搭建:RSA与国密SM2混合架构实战指南
1. 项目概述为什么企业内网需要双CA证书体系在数字化办公成为常态的今天企业内网早已不是简单的几台电脑连个交换机那么简单。OA系统、ERP、CRM、代码仓库、文件服务器、内部监控平台……这些承载着企业核心数据和业务流程的系统都跑在内网里。很多运维兄弟可能会觉得内网嘛关起门来的自家地盘用个HTTP、用个弱密码好像也无伤大雅。但现实是内网安全事件一旦发生往往比外网攻击更具破坏性。内部人员无意的误操作、被攻陷的跳板机横向移动、甚至是恶意内部人员的窃取都让内网成了“最危险的地方”。这时候为内网服务强制启用HTTPS实现通信加密和身份认证就成了构筑安全防线的基石。而HTTPS的核心就是一套可靠的公钥基础设施PKI其心脏则是证书颁发机构CA。只用RSA算法行不行当然可以它是国际通用、久经考验的标准。但在一些对自主可控有要求或者需要遵循特定行业规范如金融、政务的场景下国密算法SM2就成了必选项。所以搭建一套同时支持RSA和国密SM2的双CA证书体系就相当于给内网安全上了“双保险”既兼容现有广泛的国际生态又满足了国密合规与自主可控的战略需求。这个项目就是带你从零开始用最核心的工具OpenSSL以及其国密分支GmSSL手把手构建一个完整的企业级双根CA架构。我会把每一步的命令、背后的原理、以及我踩过的坑都掰开揉碎了讲清楚。无论你是刚开始接触PKI的运维新人还是想完善现有体系的安全工程师这篇近万字的实操指南都能让你获得一套立即可用的方案。2. 核心架构设计与思路拆解在动手敲命令之前我们必须先把架构想明白。一个设计良好的CA体系是后续一切稳定运行的前提。2.1 双CA体系的核心逻辑我们不是要搭建两个完全独立、互不关联的CA那样管理成本会翻倍。我们的目标是构建一个“双根并行、中间CA签发”的混合架构。这是什么意思呢两个根CA我们首先创建两个最高级别的根证书一个使用RSA算法例如4096位另一个使用国密SM2算法。根CA是信任的源头它们的私钥必须被极其严格地保护通常离线存储放在物理安全的保险柜里几乎不直接用于签发最终的用户证书。两个中间CA分别为RSA根CA和国密根CA创建对应的中间CA证书。中间CA的私钥可以部署在线上服务器用于日常签发和吊销服务器证书或用户证书。这样做的好处是安全分层即使中间CA的私钥不慎泄露我们只需吊销该中间CA证书而无需动摇整个根CA的信任体系影响范围可控。统一的签发流程业务系统根据需要向对应的中间CA申请证书。例如一个需要兼容老旧浏览器或国际软件的服务申请RSA证书一个面向特定国产化环境或要求国密合规的服务则申请SM2证书。它们遵循相同的证书申请、审核、签发流程只是背后的密码算法不同。这种架构的优势在于灵活性高、安全性好、便于管理。你可以根据业务需求灵活选择证书类型同时通过中间CA隔离了风险。2.2 工具选型OpenSSL 与 GmSSLOpenSSL这是PKI领域的“瑞士军刀”功能无比强大全球通用。我们将用它来处理所有RSA相关的操作以及大部分证书格式转换、查看等通用功能。GmSSL这是OpenSSL的一个重要分支由北京大学维护完整支持了国密SM2、SM3、SM4算法。要生成和操作国密证书GmSSL是目前最成熟、最方便的选择。注意在同一个系统上OpenSSL和GmSSL可以共存但要注意环境变量避免命令冲突。通常我们会用openssl命令调用原生OpenSSL用gmssl命令调用国密版本。实操心得建议在Linux服务器如CentOS 7/8或Ubuntu 20.04/22.04上部署。生产环境推荐使用稳定的发行版。在开始前请确保通过openssl version和gmssl version如果已安装确认工具版本。OpenSSL建议1.1.1以上GmSSL建议3.0以上版本。2.3 目录结构规划清晰的目录结构是良好管理的开始。我建议在服务器上建立如下目录/pki/ ├── root-ca/ # 根CA总目录 │ ├── rsa/ # RSA根CA工作目录 │ │ ├── private/ # 存放绝密的RSA根CA私钥 (权限700) │ │ ├── certs/ # 存放RSA根CA证书、已签发证书副本 │ │ ├── crl/ # 存放RSA证书吊销列表(CRL) │ │ ├── newcerts/ # 存放所有RSA签发证书的序列号存档 │ │ ├── index.txt # RSA证书数据库文件 │ │ └── serial # RSA当前证书序列号文件 │ └── gm/ # 国密根CA工作目录子目录结构与rsa/相同 ├── intermediate-ca/ # 中间CA总目录 │ ├── rsa/ # RSA中间CA工作目录子目录同root-ca/rsa/ │ └── gm/ # 国密中间CA工作目录子目录同root-ca/gm/ └── server-certs/ # 存放最终生成的服务器证书和私钥创建目录并设置权限的命令如下sudo mkdir -p /pki/{root-ca,intermediate-ca,server-certs}/{rsa,gm}/{private,certs,crl,newcerts} sudo chmod 700 /pki/*/rsa/private /pki/*/gm/private # 私钥目录严格权限 sudo touch /pki/root-ca/rsa/index.txt /pki/root-ca/gm/index.txt sudo touch /pki/intermediate-ca/rsa/index.txt /pki/intermediate-ca/gm/index.txt sudo echo 1000 /pki/root-ca/rsa/serial sudo echo 1000 /pki/root-ca/gm/serial sudo echo 1000 /pki/intermediate-ca/rsa/serial sudo echo 1000 /pki/intermediate-ca/gm/serial3. 核心细节解析与实操要点搭建CA本质上是在和密钥、证书配置文件打交道。理解其中的关键细节能帮你避开99%的坑。3.1 配置文件CA行为的“宪法”OpenSSL/GmSSL的行为主要由一个openssl.cnf配置文件控制。我们需要为根CA和中间CA准备不同的配置以区分它们的角色。这里以RSA根CA的配置为例国密CA的配置类似主要区别在于default_md默认摘要算法等参数。RSA根CA配置文件 (/pki/root-ca/rsa/openssl.cnf) 核心节选[ ca ] default_ca CA_default [ CA_default ] dir /pki/root-ca/rsa # 工作目录 database $dir/index.txt # 证书数据库 new_certs_dir $dir/newcerts # 新证书存放目录 certificate $dir/certs/root-ca.crt # CA自己的证书 serial $dir/serial # 序列号文件 private_key $dir/private/root-ca.key # CA的私钥 RANDFILE $dir/private/.rand default_days 3650 # 根证书默认有效期10年 default_crl_days 30 # CRL默认有效期30天 default_md sha256 # 默认使用SHA256摘要 preserve no policy policy_strict # 使用严格策略 [ policy_strict ] countryName match # 必须匹配 stateOrProvinceName match organizationName match organizationalUnitName optional commonName supplied emailAddress optional [ req ] default_bits 4096 # RSA密钥长度4096位 distinguished_name req_distinguished_name req_extensions v3_req [ req_distinguished_name ] countryName Country Name (2 letter code) countryName_default CN stateOrProvinceName State or Province Name (full name) stateOrProvinceName_default Beijing localityName Locality Name (eg, city) localityName_default Beijing organizationName Organization Name (eg, company) organizationName_default MyCompany Inc. organizationalUnitName Organizational Unit Name (eg, section) organizationalUnitName_default IT Security Department commonName Common Name (e.g. server FQDN or YOUR name) commonName_max 64 [ v3_req ] basicConstraints CA:FALSE keyUsage nonRepudiation, digitalSignature, keyEncipherment [ v3_ca ] # 用于CA证书的扩展项 subjectKeyIdentifier hash authorityKeyIdentifier keyid:always,issuer basicConstraints critical, CA:true keyUsage critical, digitalSignature, cRLSign, keyCertSign关键点解析policy_strict定义了证书申请中哪些字段必须与CA证书匹配match哪些可以不同optional哪些必须由申请者提供supplied。根CA通常使用严格策略。default_md摘要算法。RSA体系常用sha256国密体系应使用sm3。basicConstraints CA:true这是区分一个证书是否为CA证书的关键标识。中间CA的证书也有这个标识而最终服务器证书是CA:FALSE。keyUsage指明了证书的用途。CA证书需要有keyCertSign证书签名和cRLSignCRL签名权限而服务器证书通常只需要digitalSignature和keyEncipherment。注意事项为国密CA准备配置文件时除了将default_md改为sm3default_bits参数对SM2算法无效SM2的曲线是固定的。SM2的密钥对生成命令参数与RSA不同下文会具体说明。3.2 密钥与证书的生命周期管理密钥生成与保护私钥是安全的根本。生成后应立即设置权限为600仅属主可读可写并备份到安全的离线介质。任何情况下都不应通过网络明文传输私钥。证书签名请求无论是CA证书还是最终用户证书申请流程都是生成私钥 - 用私钥生成证书签名请求 - 由上级CA对请求进行签名生成证书。序列号与数据库index.txt文件记录了所有签发证书的详细信息状态、过期时间、主体等。serial文件是下一个证书的序列号。每次签发序列号递增并在数据库中留下记录。这是实现证书吊销的基础。证书吊销列表当某个证书的私钥泄露或人员离职时需要吊销该证书。CA会生成一个证书吊销列表文件其中包含了所有被吊销证书的序列号。客户端如浏览器可以定期获取并校验CRL。4. 实操过程与核心环节实现现在我们进入最核心的实操环节。请跟着步骤一步步操作。4.1 第一步生成离线根CA证书根CA必须离线操作确保绝对安全。生成RSA根CAcd /pki/root-ca/rsa # 1. 生成4096位的RSA私钥 openssl genrsa -aes256 -out private/root-ca.key 4096 # 系统会提示你输入一个密码来加密私钥文件请务必使用高强度密码并牢记。 # 2. 使用私钥生成自签名的根证书有效期10年 openssl req -config openssl.cnf \ -key private/root-ca.key \ -new -x509 -days 3650 -sha256 -extensions v3_ca \ -out certs/root-ca.crt # 执行命令后会交互式地让你输入国家、省份、组织等信息。这些信息将成为你根CA的身份标识。 # Common Name (CN) 可以设为类似 “MyCompany Root RSA CA” 的名字。生成国密SM2根CA这里我们需要使用gmssl命令。cd /pki/root-ca/gm # 1. 生成SM2私钥。SM2基于椭圆曲线无需指定长度。 gmssl ecparam -genkey -name sm2p256v1 -out private/root-ca.key # 2. 为了安全同样建议用密码加密私钥文件可选但推荐 gmssl pkey -in private/root-ca.key -aes256 -out private/root-ca-encrypted.key # 输入密码后可以将原未加密的私钥删除保留加密后的版本。 mv private/root-ca-encrypted.key private/root-ca.key # 3. 生成自签名根证书。注意国密证书的签名算法是sm2-with-sm3。 gmssl req -config openssl.cnf \ # 这里用的是国密CA专用的配置文件其中default_mdsm3 -key private/root-ca.key \ -new -x509 -days 3650 -sm3 -extensions v3_ca \ -out certs/root-ca.crt # 同样交互式输入信息CN可以设为 “MyCompany Root GM CA”。操作后检查# 查看RSA根证书信息 openssl x509 -in /pki/root-ca/rsa/certs/root-ca.crt -text -noout # 查看国密根证书信息 (gmssl同样支持x509子命令) gmssl x509 -in /pki/root-ca/gm/certs/root-ca.crt -text -noout重点检查Issuer和Subject是否一致自签名、CA:TRUE、有效期、公钥算法RSA 4096 / SM2、签名算法sha256WithRSAEncryption / sm2sign-with-sm3。4.2 第二步生成并签发中间CA证书中间CA将在线上服务器运行负责日常签发。为RSA中间CA生成密钥和证书请求cd /pki/intermediate-ca/rsa # 1. 生成中间CA的私钥 openssl genrsa -aes256 -out private/intermediate-ca.key 4096 # 2. 生成证书签名请求 openssl req -config openssl.cnf -new -sha256 \ -key private/intermediate-ca.key \ -out csr/intermediate-ca.csr # CN可以设为 “MyCompany Intermediate RSA CA”。用RSA根CA签发中间CA证书cd /pki/root-ca/rsa # 使用根CA的配置和私钥对中间CA的请求进行签名 openssl ca -config openssl.cnf -extensions v3_intermediate_ca \ -days 1825 -notext -md sha256 \ -in /pki/intermediate-ca/rsa/csr/intermediate-ca.csr \ -out /pki/intermediate-ca/rsa/certs/intermediate-ca.crt # 系统会提示输入根CA私钥的密码。签名后会在index.txt和newcerts/下留下记录。注意需要在根CA的配置文件中定义v3_intermediate_ca段落其basicConstraints为CA:true, pathlen:0pathlen:0表示该中间CA不能再向下签发子CA增强了安全性。为国密中间CA执行类似操作cd /pki/intermediate-ca/gm # 生成SM2私钥和CSR gmssl ecparam -genkey -name sm2p256v1 -out private/intermediate-ca.key gmssl pkey -in private/intermediate-ca.key -aes256 -out private/intermediate-ca.key gmssl req -config openssl.cnf -new -sm3 \ -key private/intermediate-ca.key \ -out csr/intermediate-ca.csr cd /pki/root-ca/gm # 用国密根CA签发 gmssl ca -config openssl.cnf -extensions v3_intermediate_ca \ -days 1825 -notext -md sm3 \ -in /pki/intermediate-ca/gm/csr/intermediate-ca.csr \ -out /pki/intermediate-ca/gm/certs/intermediate-ca.crt4.3 第三步创建证书链文件客户端如浏览器需要信任根CA但通常只直接安装了根证书。为了验证由中间CA签发的服务器证书需要提供完整的证书链。# RSA证书链 cat /pki/intermediate-ca/rsa/certs/intermediate-ca.crt \ /pki/root-ca/rsa/certs/root-ca.crt /pki/intermediate-ca/rsa/certs/ca-chain.crt # 国密证书链 cat /pki/intermediate-ca/gm/certs/intermediate-ca.crt \ /pki/root-ca/gm/certs/root-ca.crt /pki/intermediate-ca/gm/certs/ca-chain.crt这个ca-chain.crt文件有时也叫fullchain.pem就是需要和服务器证书一起部署的文件。4.4 第四步签发服务器证书以Nginx为例现在我们可以为内网服务器如internal-app.mycompany.com签发证书了。申请RSA服务器证书# 1. 在服务器上或一个临时目录生成服务器私钥和CSR openssl genrsa -out server.key 2048 # 服务器证书2048位足够 openssl req -new -key server.key -sha256 -out server.csr # 在提示输入Common Name时必须填写服务器的精确域名或IP如 internal-app.mycompany.com。 # 还可以通过配置文件添加subjectAltName扩展包含多个域名或IP。 # 2. 将server.csr提交给RSA中间CA进行签发 cd /pki/intermediate-ca/rsa openssl ca -config openssl.cnf -extensions server_cert \ -days 375 -notext -md sha256 \ -in /path/to/server.csr \ -out certs/internal-app.mycompany.com.crt # 生成的证书在 certs/ 目录下。 # 3. 将证书、私钥和链文件部署到Nginx # server.crt: 上一步签发的证书 # server.key: 第一步生成的私钥 # ca-chain.crt: 第三步生成的证书链Nginx配置示例server { listen 443 ssl; server_name internal-app.mycompany.com; ssl_certificate /etc/nginx/ssl/internal-app.mycompany.com.crt; ssl_certificate_key /etc/nginx/ssl/server.key; ssl_trusted_certificate /etc/nginx/ssl/ca-chain.crt; # 用于OCSP装订等 # ... 其他SSL配置 }申请国密服务器证书流程完全类似只是命令换成gmssl算法参数换成-sm3并且注意国密双证书体系签名证书和加密证书。在简化实践中我们通常先实现SM2的单证书签名加密一体方案。# 生成SM2服务器密钥和CSR gmssl ecparam -genkey -name sm2p256v1 -out server-gm.key gmssl req -new -key server-gm.key -sm3 -out server-gm.csr # 使用国密中间CA签发 cd /pki/intermediate-ca/gm gmssl ca -config openssl.cnf -extensions server_cert \ -days 375 -notext -md sm3 \ -in /path/to/server-gm.csr \ -out certs/internal-app-gm.mycompany.com.crt国密证书通常需要支持国密的Web服务器如Nginx的国密分支Tengine或nginx-gm才能使用。4.5 第五步部署根证书到客户端信任库要让内网用户无警告地访问HTTPS服务必须将两个根证书root-ca.crt导入到所有客户端的信任根证书存储区。Windows双击.crt文件选择“安装证书”存储位置选择“受信任的根证书颁发机构”。Linux将根证书文件复制到/usr/local/share/ca-certificates/然后执行sudo update-ca-certificates。浏览器对于Chrome/Firefox等也可以在浏览器设置中手动导入并信任根证书。Java应用需要将根证书导入到JVM的信任库cacerts中keytool -import -trustcacerts -alias my-rsa-root -file root-ca.crt -keystore $JAVA_HOME/jre/lib/security/cacerts。重要提示这是内网自建CA最关键也最容易出错的一步。务必确保所有需要访问服务的客户端机器都正确安装了根证书。否则浏览器会显示“不安全的连接”警告。5. 常见问题与排查技巧实录在实际搭建和运维中你会遇到各种各样的问题。这里记录了几个最典型的坑和解决办法。5.1 证书链不完整导致浏览器不信任问题现象浏览器访问HTTPS网站提示“此证书无效”或“无法验证此证书的颁发者”。排查在浏览器中点击锁图标 - “证书” - “证书路径”。如果只显示服务器证书和中间CA证书没有显示根证书或者根证书显示为“不可信”就是证书链问题。解决确保服务器配置正确Nginx的ssl_certificate指令应该指向一个包含服务器证书中间CA证书的文件按顺序拼接或者分别配置ssl_certificate服务器证书和ssl_certificate_chain中间CA证书。最佳实践是拼接成一个文件。cat internal-app.mycompany.com.crt intermediate-ca.crt fullchain.crt # 然后Nginx配置 ssl_certificate fullchain.crt;确保客户端安装了根证书这是内网CA的前提。检查客户端信任库。5.2 “subjectAltName”缺失导致证书错误问题现象用域名访问正常但用IP地址访问或者用其他未声明的域名访问浏览器报证书与站点名称不匹配。原因现代浏览器遵循ACME标准更看重subjectAltName扩展而不是Common Name。证书中必须包含该扩展。解决在生成CSR时使用一个配置文件来指定subjectAltName。# 文件 server-req.cnf [req] distinguished_name req_distinguished_name req_extensions v3_req [req_distinguished_name] # ... 国家、组织等信息 ... [v3_req] basicConstraints CA:FALSE keyUsage nonRepudiation, digitalSignature, keyEncipherment subjectAltName alt_names # 关键 [alt_names] DNS.1 internal-app.mycompany.com DNS.2 app.mycompany.local IP.1 192.168.1.100生成CSR时引用此配置openssl req -new -key server.key -sha256 -out server.csr -config server-req.cnf。在CA签发时也需要在CA的配置中启用copy_extensions选项需谨慎有安全风险或手动在签发命令中指定扩展。5.3 国密证书在非国密环境中无法识别问题现象在标准的Nginx或Apache上配置国密SM2证书服务无法启动或客户端无法握手。原因标准的OpenSSL和Web服务器不支持国密算法。国密证书需要国密算法库和国密协议栈的支持。解决使用支持国密的Web服务器如Tengine阿里基于Nginx的国密分支或nginx-gm。编译这些软件时需要链接GmSSL或TongSuo原BabaSSL等国密密码库。客户端也需要支持国密。对于浏览器可能需要安装国密浏览器扩展或使用支持国密的浏览器如部分国产浏览器。对于内部系统间的API调用需要使用支持国密的客户端库如gmssl的Python/Go绑定。5.4 证书过期或即将过期问题现象服务突然中断日志显示SSL握手失败检查证书发现已过期。预防与解决监控建立证书过期监控。可以使用脚本定期检查证书的notAfter字段在到期前30天、15天、7天发出告警。Zabbix、Prometheus都有相关插件。自动化续期对于内部服务可以编写自动化脚本在证书到期前自动用CA的流程生成新证书并滚动重启相关服务。切记私钥可以复用但最好定期更换。吊销流程如果私钥泄露必须立即吊销证书。在中间CA目录下执行openssl ca -config openssl.cnf -revoke newcerts/01.pem # 01.pem是证书序列号对应的文件 openssl ca -config openssl.cnf -gencrl -out crl/ca.crl.pem然后发布CRL文件到可访问的URL并在CA证书的CRL分发点扩展中配置该URL。5.5 OpenSSL命令执行报错“Unable to load CA private key”问题现象在执行openssl ca签发命令时提示无法加载CA私钥。排查密码错误最可能的原因。确保你输入的密码是保护CA私钥文件的密码。文件路径错误检查配置文件openssl.cnf中private_key项指向的路径是否正确文件是否存在。文件格式错误确认私钥文件是有效的PEM格式。可以用openssl rsa -in private/ca.key -check对于RSA或gmssl pkey -in private/ca.key -check对于SM2来验证。权限问题确保运行OpenSSL命令的用户对私钥文件有读取权限。搭建和维护一套完整的双CA体系是个细致活前期规划越清晰后期运维越轻松。这套体系不仅能用于HTTPS还可以用于代码签名、客户端认证、VPN证书等场景是企业内网身份认证和加密通信的统一基石。最关键的是通过亲手搭建一遍你对PKI的理解会从概念层面深入到每一个配置文件和命令行参数以后再遇到任何证书相关的问题你都能从容应对。