不开头就直接说技术背景了。
国密证书这几年在政企、金融、能源这些对合规要求严格的行业里越来越常见,几乎成了等保测评和国密改造的标配。但真要上手用GmSSL搭一套私有CA,网上的资料往往东一榔头西一棒子,要么只讲单张自签名证书,要么直接扔一个命令让人照抄,完全没解释清楚证书链是怎么一层层串起来的。这篇就是我踩过不少坑之后的完整记录:从CentOS 7上编译GmSSL开始,到生成SM2根证书、签发中间CA、再签服务器和客户端证书,最后把整条证书链串起来验证通,每一步都写了“为什么这么干”。
适用人群很明确:正在做国密改造的运维、要搭内部测试环境的开发,以及被等保要求逼着上国密证书但不知道从哪下手的同行。看完这篇,你至少能在自己的机器上复现一套能用的国密私有证书体系,而不是拿到一堆命令却不知道哪步会挂。
1. 项目理解与整体设计
1.1 国密证书和传统RSA证书的本质区别
国密证书核心是SM2非对称算法,它基于椭圆曲线,但曲线参数是中国自主定义的,和传统的RSA、甚至国际通用的ECDSA(比如secp256r1曲线)都不一样。这意味着你用OpenSSL默认生成的私钥、证书,在国密环境下根本验不过去。就像你家锁换了新款钥匙,旧钥匙插得进去但拧不动。
国密证书体系还有一个特殊之处:整套体系不仅包含SM2算法,还涉及SM3哈希、SM4对称加密,以及基于这些算法实现的TLCP(Transport Layer Cryptography Protocol,传输层密码协议)。网上很多文章只讲了“怎么生成SM2证书”,却没提国密SSL握手和TLS握手在协议细节上的差异,这就导致证书明明签出来了,但部署到Nginx或者Java应用里死活不认。
1.2 为什么私有CA比自签名证书更靠谱
单一的自签名证书只能解决“这一个服务有证书”的问题,但没法解决“多个服务互信”的问题。如果公司有10台内网服务器要做国密双向认证,你用10张自签名证书,那每台机器都得维护其他9台的信任列表,增删节点时全是坑。私有CA的好处是:只要所有节点都信任这一个根CA,根CA签发的所有子证书天然被信任。新增节点时只需在CA端签一张新证书,各节点不需要做任何变动。
私有CA的另一个价值是链式审计。根证书只用来签中间CA,中间CA签服务器和客户端证书,每一层职责清晰。万一某台服务器私钥泄露,你可以只吊销它那一张证书,不影响整个CA体系。这在等保测评里是很加分的点,审计人员看到成体系的CA结构,明显比一张裸的自签名证书要正规得多。
1.3 目录结构与证书链规划
开始动手前,先把目录结构规划好。我见过不少人在/root下乱建目录,最后证书私钥散落各处,自己都找不到。以下是我常用的结构:
mkdir -p /opt/gmca/{private,ca,newcerts,server,client,crl,conf} touch /opt/gmca/index.txt echo '01' > /opt/gmca/serial echo '1000' > /opt/gmca/crlnumber目录规划的核心原则是“私钥和证书分离”,private目录权限必须锁死,只允许root访问,服务器和客户端证书目录则用来放最终签发好的成品。index.txt记录证书签发历史,serial文件管理证书序列号,这两个文件在OpenSSL/GmSSL的CA操作中会被自动更新,线程安全性由文件锁保证,不需要手动干预。
链条规划方面,我建议至少做两层:根CA(自签名)→ 中间CA → 服务端证书/客户端证书。两层结构的好处是根私钥可以离线存放(比如拷贝到U盘锁起来),日常签发只用中间CA,极大降低根私钥泄露风险。
2. 环境准备与GmSSL编译
2.1 系统环境和依赖检查
本次实操使用CentOS 7系列,内核版本3.10,这也是国内很多政企客户依然在用的主力系统。开始前先检查基础编译工具链:
yum install -y gcc gcc-c++ make perl coreutilsGmSSL编译依赖的组件不多,基本就是标准的C编译环境和Perl。有一点要注意:GmSSL虽然提供OpenSSL兼容接口,但它和系统自带OpenSSL在头文件、库文件上可能存在命名冲突,安装时绝不能覆盖系统的/usr/lib64/libssl.so等库文件,否则系统里SSH、Yum这些依赖OpenSSL的程序会全部崩掉。
2.2 离线环境的依赖处理思路
很多内网环境是隔离的,没有外网Yum源。这问题我踩过不止一次,现在处理思路有三种,按优先级排列:
第一种,尽量用Docker镜像解决。在内网提前导出一个带编译环境的CentOS 7镜像,传到目标机器,然后通过Docker容器进行离线编译。这样系统依赖几乎不需要额外安装,只要Docker能跑就行。“离线安装Docker”本身也是个经典问题,通常是准备好离线rpm包或者内网Yum源,再通过systemctl enable docker设置开机自启。Docker方案的优势是环境隔离,编译GmSSL不会污染宿主机,出问题了直接删容器重来。
第二种,在一台有外网的机器上用yumdownloader下载全部rpm依赖包,再拷贝到内网用rpm -Uvh *.rpm安装。这个方式你需要先找一个和部署环境完全一致的系统做依赖收集,否则容易出现glibc版本不匹配的问题。
第三种,如果网络条件实在太受限,只有纯内网环境,那就确认一下机器上是否已有基础编译工具链。很多政企服务器虽然没外网,但装机时都会带上gcc和make,如果没有,只能找运维要安装盘或者内网源。
2.3 GmSSL源码编译实战
GmSSL项目的主线版本目前维护在GitHub上,国内也有一些镜像仓库。下载源码压缩包后,解压并进入源码目录,执行以下编译流程:
tar zxf GmSSL-master.tar.gz cd GmSSL-master ./config --prefix=/opt/gmssl no-shared make -j$(nproc) make install这里的关键参数是--prefix和no-shared。--prefix指定安装目录,我建议装在独立目录,避免和系统OpenSSL冲突。no-shared则生成静态库,生成的gmssl命令是静态链接的可执行文件,往其他机器拷贝时不用再带一堆.so库。如果你需要给其他程序做动态链接调用,可以去掉no-shared,但要做好库文件路径配置。
编译完成后,验证版本:
/opt/gmssl/bin/gmssl version如果能看到GmSSL版本号和Supported algorithms列表里出现SM2、SM3、SM4,说明编译安装成功。务必使用全路径调用gmssl命令,不要直接输gmssl,除非你把/opt/gmssl/bin加入PATH,否则很容易误用系统的openssl命令,两者命令参数虽然相似,但算法支持完全不同。
3. 构建根证书与根CA
3.1 生成SM2根密钥
国密证书的第一步是生成SM2私钥。命令如下:
/opt/gmssl/bin/gmssl ecparam -genkey -name sm2p256v1 -out /opt/gmca/private/rootca.key chmod 600 /opt/gmca/private/rootca.key这条命令和OpenSSL生成ECDSA密钥非常相似,但曲线名必须是sm2p256v1。这是国密标准定义的曲线,在GmSSL中简称为sm2p256v1。如果你误用别的曲线,比如prime256v1,生成的私钥虽然也能签名,但不符合国密标准,验签时用其他国密设备会直接失败。
私钥生成后,我建议顺手做一次密钥格式检查:
/opt/gmssl/bin/gmssl ec -in /opt/gmca/private/rootca.key -text -noout | head -20检查输出里的ASN1 OID是否为sm2p256v1,确认无误再进入下一步。私钥文件的权限务必要设置成600,后续所有私钥都按这个标准执行。等保测评里私钥保护是硬指标,权限裸奔会直接扣分。
3.2 创建自签名根证书
根证书是整个CA体系的信任锚点,有效期我建议设10年。这一层是自签名,即证书的签发者和使用者都是自己。
/opt/gmssl/bin/gmssl req -new -x509 -key /opt/gmca/private/rootca.key \ -out /opt/gmca/ca/rootca.crt -days 3650 \ -subj "/C=CN/O=ExampleOrg/CN=Example Root CA" \ -sm3 -sigopt sm2_id:1234567812345678这里要解释几个关键参数:
-sm3指定摘要算法为国密SM3。国密证书签名必须使用SM3作为哈希函数,如果用SHA256,验签时部分国密设备会拒绝。这就是为什么不能用OpenSSL直接签国密证书的原因之一,OpenSSL里没有SM3算法的实现。
-sigopt sm2_id:1234567812345678指定SM2签名时使用的ID。SM2签名算法和国际ECDSA不同,它在签名和验签时都需要一个ID标识,而且双方必须一致。这个ID是国密标准里规定的默认值,但如果你的应用自定义了ID,后续所有签名验签操作都要传同样的ID。这是很多人在部署时最容易忽略的坑,签名时用的是默认ID,应用接管时用的是自定义ID,结果验签永远失败。
-subj里国家字段必须用CN,名称尽量让人一眼看出这是哪家的根CA。示例里我用了ExampleOrg,你实际使用时替换成真实组织名。
3.3 根证书自检
根证书生成后,用以下命令验证:
/opt/gmssl/bin/gmssl x509 -in /opt/gmca/ca/rootca.crt -text -noout重点关注三个维度:签名算法显示为sm2-with-sm3,公钥算法显示为id-ecPublicKey且曲线为sm2p256v1,证书的Issuer和Subject完全一致。这三个条件同时满足,根证书才算合格。
4. 签发完整证书链
4.1 生成中间CA密钥与证书请求
中间CA是整套体系中的二层节点,它不直接面向终端用户,而是负责签发服务器和客户端证书。这样设计的好处前面讲过:根私钥可以离线冷存,日常运维操作全部在中间CA层面完成。
/opt/gmssl/bin/gmssl ecparam -genkey -name sm2p256v1 -out /opt/gmca/private/interca.key chmod 600 /opt/gmca/private/interca.key /opt/gmssl/bin/gmssl req -new -key /opt/gmca/private/interca.key \ -out /opt/gmca/ca/interca.csr \ -subj "/C=CN/O=ExampleOrg/OU=PKI Service/CN=Example Intermediate CA"这里的CSR(证书签名请求)是中间CA向根CA提交的“申请书”,里面包含了中间CA的公钥和身份信息,但不含签名。
4.2 用根CA签发中间CA证书
签发的核心命令是用根证书对CSR进行签名,同时要加上一系列扩展项来控制中间CA的权限。这里需要先准备一个扩展配置文件,因为GmSSL命令行直接传扩展项没有OpenSSL那么灵活,用配置文件更可靠。
创建/opt/gmca/conf/interca.ext:
basicConstraints=critical,CA:TRUE,pathlen:0 keyUsage=critical,keyCertSign,cRLSign subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer三个扩展项的含义分别是:
basicConstraints标记这个证书是CA证书,pathlen:0表示它下面不能再签发CA证书,只能签终端实体证书。这个限制非常重要,能防止中间CA被攻破后攻击者再签发新的CA证书,扩散攻击范围。
keyUsage限制密钥的用途,keyCertSign表示可以用这个密钥签发证书,cRLSign表示可以签署证书吊销列表。中间CA不能用来做TLS服务器身份认证,所以不能加digitalSignature和keyEncipherment。
subjectKeyIdentifier和authorityKeyIdentifier是证书链验证时的辅助信息,帮助验证者快速定位签发证书的父证书。
执行签发:
/opt/gmssl/bin/gmssl x509 -req -in /opt/gmca/ca/interca.csr \ -CA /opt/gmca/ca/rootca.crt -CAkey /opt/gmca/private/rootca.key \ -CAserial /opt/gmca/serial \ -out /opt/gmca/ca/interca.crt -days 3650 \ -extfile /opt/gmca/conf/interca.ext注意-CAserial参数指定serial文件路径,签发成功后GmSSL会自动递增序列号。之前创建目录时我们初始化的serial文件是'01',所以这张中间CA证书的序列号就是01。
4.3 签发服务端证书
服务端证书用于网站、API、Nginx等场景。生成密钥和CSR的步骤和中间CA类似,但扩展项完全不同:
/opt/gmssl/bin/gmssl ecparam -genkey -name sm2p256v1 -out /opt/gmca/server/server.key chmod 600 /opt/gmca/server/server.key /opt/gmssl/bin/gmssl req -new -key /opt/gmca/server/server.key \ -out /opt/gmca/server/server.csr \ -subj "/C=CN/O=ExampleOrg/OU=IT Dept/CN=api.example.org"CN字段务必填服务的实际域名或IP地址。国密证书在客户端校验时,会严格比对证书CN(或SAN扩展)与访问的域名,不一致会直接提示不安全。
创建/opt/gmca/conf/server.ext:
basicConstraints=critical,CA:FALSE keyUsage=critical,digitalSignature,keyEncipherment extendedKeyUsage=serverAuth subjectAltName=DNS:api.example.org,IP:192.168.1.10subjectAltName(SAN)之前是可选,但现在的浏览器和应用基本都强制要求SAN字段。如果你只填了CN没填SAN,Chrome等浏览器会报“NET::ERR_CERT_COMMON_NAME_INVALID”。SAN里列出所有需要用这个证书访问的域名和IP。
执行签发:
/opt/gmssl/bin/gmssl x509 -req -in /opt/gmca/server/server.csr \ -CA /opt/gmca/ca/interca.crt -CAkey /opt/gmca/private/interca.key \ -CAserial /opt/gmca/serial \ -out /opt/gmca/server/server.crt -days 825 \ -extfile /opt/gmca/conf/server.ext这里是关键:服务端证书是中间CA签发的,不是根CA直接签的。这样整条信任链是“根证书 → 中间CA证书 → 服务器证书”三层结构,验证时客户端从服务器证书开始,向上找到中间CA证书,再继续向上验证到根证书。
4.4 签发客户端证书
国密双向认证场景中常见的做法是客户端也需要一张证书,服务器端反过来验证客户端身份。签发客户端证书的步骤几乎一样,只是扩展项里extendedKeyUsage变成clientAuth。
/opt/gmssl/bin/gmssl ecparam -genkey -name sm2p256v1 -out /opt/gmca/client/client.key chmod 600 /opt/gmca/client/client.key /opt/gmssl/bin/gmssl req -new -key /opt/gmca/client/client.key \ -out /opt/gmca/client/client.csr \ -subj "/C=CN/O=ExampleOrg/OU=IT Dept/CN=alice"创建/opt/gmca/conf/client.ext:
basicConstraints=critical,CA:FALSE keyUsage=critical,digitalSignature extendedKeyUsage=clientAuth subjectAltName=email:alice@example.org执行签发:
/opt/gmssl/bin/gmssl x509 -req -in /opt/gmca/client/client.csr \ -CA /opt/gmca/ca/interca.crt -CAkey /opt/gmca/private/interca.key \ -CAserial /opt/gmca/serial \ -out /opt/gmca/client/client.crt -days 825 \ -extfile /opt/gmca/conf/client.ext4.5 生成证书链文件
证书链文件是把中间CA证书和服务器证书按顺序拼接在一起的文件,部署到Nginx等服务器时使用。顺序不能错,最上面必须是服务器证书本身,然后是中间CA证书:
cat /opt/gmca/server/server.crt /opt/gmca/ca/interca.crt > /opt/gmca/server/server_chain.crtNginx里ssl_certificate配置项填这个链文件,Nginx发送证书给客户端时会把链文件里的所有证书一次性发给客户端,客户端就能从服务器证书逐级往上验证到根证书。
同理,客户端如果也要验证服务器,可以在客户端配置里使用包含根证书的信任库。需要说明的是,如果你不打算把服务器证书和中间CA拼接,也可以直接配置中间CA后让客户端自己去找上级证书,但很多客户端没有这个自动寻找能力,所以拼好链文件是最稳妥的做法。
5. 证书链验证与部署实操
5.1 验证证书链完整性
证书签完之后,验证是最重要的一步。很多人签完证书觉得“反正生成了就是对的”,结果部署时各种问题,回头一查是证书链不完整。用GmSSL验证证书链完整性的命令如下:
/opt/gmssl/bin/gmssl verify -CAfile /opt/gmca/ca/rootca.crt \ -untrusted /opt/gmca/ca/interca.crt /opt/gmca/server/server_chain.crt-CAfile参数指定根证书(信任锚点),-untrusted参数指定中间证书列表。验证器会用根证书验证中间CA,再用中间CA验证服务器证书。看到“OK”输出,说明整条链验证通过。
如果是验证客户端证书,命令类似:
/opt/gmssl/bin/gmssl verify -CAfile /opt/gmca/ca/rootca.crt \ -untrusted /opt/gmca/ca/interca.crt /opt/gmca/client/client.crt这里有一个非常重要的细节:验证时如果报“unable to get local issuer certificate”,说明证书链不完整或者根证书不是信任锚点;如果报“self-signed certificate”,说明根证书在验证链里被重复传递了。这两种报错是排错时最常遇到的。
5.2 证书链内部结构检查
用以下命令查看证书链文件中包含了几张证书:
/opt/gmssl/bin/gmssl crl2pkcs7 -nocrl -certfile /opt/gmca/server/server_chain.crt | \ /opt/gmssl/bin/gmssl pkcs7 -print_certs -text -noout | grep "subject="正常输出应该有两行subject信息,一行是服务器证书的Subject,一行是中间CA证书的Subject。如果只有一行,说明链拼接少了中间证书。这个检查方法在排Nginx证书链问题时特别好用。
5.3 部署到Nginx的实操记录
Nginx要支持国密证书,需要编译进国密模块。目前最常见的方案是使用Tengine(淘宝开源的Nginx分支),它自带国密SSL支持。如果你的环境是纯Nginx,需要打上国密补丁重新编译。这个操作有一定工作量,但网上补丁包比较成熟,基本是:
./configure --with-openssl=/opt/gmssl --add-module=/path/to/nginx-gmssl-module make && make install编译完成后,Nginx配置里的SSL证书部分和普通证书没有太大区别:
server { listen 443 ssl; server_name api.example.org; ssl_certificate /opt/gmca/server/server_chain.crt; ssl_certificate_key /opt/gmca/server/server.key; ssl_protocols TLSv1.2 TLSv1.3; # 国密双证书模式下,还需要配置签名证书和加密证书 # ssl_sign_certificate /opt/gmca/server/sign.crt; # ssl_sign_certificate_key /opt/gmca/server/sign.key; # ssl_enc_certificate /opt/gmca/server/enc.crt; # ssl_enc_certificate_key /opt/gmca/server/enc.key; }传统TLS是单证书机制,一张证书既承担签名也承担加密责任。但国密TLCP协议是双证书机制,签名证书和加密证书分开。上面示例里注释掉的配置就是双证书模式对应的字段,如果你采购了国密SSL网关或者使用支持双证书的服务端软件,需要按这个逻辑准备两套证书。不过在我们纯GmSSL手工签发的体系里,一张证书可以同时承担两个角色,应用方如果不强制要求双证书,单证书就能正常跑国密握手。
5.4 在Java环境中使用国密证书
JVM默认的加密Provider不认识SM2和SM3,需要引入Bouncy Castle或者其他国密Provider。以Bouncy Castle为例:
Security.addProvider(new BouncyCastleProvider()); KeyStore ks = KeyStore.getInstance("PKCS12", "BC");同时,把根证书导入到JVM的cacerts信任库中,Java应用才能信任私有CA签发的证书:
keytool -import -trustcacerts -alias gmroot \ -file /opt/gmca/ca/rootca.crt \ -keystore $JAVA_HOME/jre/lib/security/cacerts这里记住:导入的是根证书,不是中间CA证书,也不是服务器证书。Java运行时信任根,就能通过证书链自动信任根签发的所有下级证书。
6. 常见问题与排查技巧实录
6.1 证书链验证报错速查表
| 报错信息 | 可能原因 | 解决方案 |
|---|---|---|
| unable to get local issuer certificate | 根证书不是验证时的信任锚点 | 检查-CAfile参数指向的根证书是否正确 |
| self-signed certificate | 验证时把根证书放进了untrusted列表 | 把根证书从-untrusted参数中移除 |
| certificate signature failure | 中间CA证书和签发它的私钥不匹配 | 重新用根CA签发中间CA证书 |
| certificate is not authorized to issue | 中间CA的basicConstraints缺少CA:TRUE | 重新用根CA签发中间CA,补上CA扩展 |
| SM2 ID mismatch | 签名时用的sm2_id和验签时不一致 | 统一签名验签的-sigopt sm2_id参数值 |
6.2 私钥和证书长度不同的坑
手摸排查时,很容易忽略长度对比检查。私钥和证书里的公钥是配套的,如果错搭了,部署时握手会失败。每次签发完成,我习惯用以下命令检查密钥对匹配:
# 查看CSR里的公钥 /opt/gmssl/bin/gmssl req -in server.csr -text -noout | grep "pub:" -A 2 # 查看证书里的公钥 /opt/gmssl/bin/gmssl x509 -in server.crt -text -noout | grep "pub:" -A 2 # 查看私钥对应的公钥 /opt/gmssl/bin/gmssl ec -in server.key -text -noout | grep "pub:" -A 2三处输出的公钥十六进制字符串必须完全一致,有一处不同就是搭错对。
6.3 一个容易让人崩溃的问题:CA证书也被当成服务器证书使用
有用户把CA里生成的中间CA证书直接拿来当服务器证书部署,请求客户端一直报不信任。原因很简单:中间CA证书的有效用途是签发下级证书,不是服务端身份认证。部署时必须要用服务器证书(basicConstraints的CA标志为FALSE),而不是CA证书。你可以用以下命令快速区分:
/opt/gmssl/bin/gmssl x509 -in cert.pem -noout -text | grep "CA:"服务器证书输出CA:FALSE,CA证书输出CA:TRUE,一眼就能看出来。
6.4 离线部署时的常见操作错误
离线环境最容易犯的错误是照抄有网环境命令而不做适配。比如yum装依赖装不上,你却还死磕在线源。实际做法是把所有依赖包提前下载好,以GmSSL编译本身为例,gcc、make、perl这几个rpm包提前准备好,离线安装时用rpm -Uvh --nodeps强装。如果内网机器已经装了Docker,可以直接用docker pull提前在有网环境拉取镜像,save成tar包,到离线环境load。这个思路在处理CentOS 7的离线编译场景时非常通用,不只是GmSSL,任何需要编译的中间件都适用。
6.5 序列号混乱导致的问题
如果serial文件被误删或重复,签发的证书序列号可能冲突。证书序列号冲突会导致部分客户端缓存了旧证书,新证书加载时因为序列号相同而拒绝信任。解决方法是每次签发前备份serial文件。我的习惯是先复制一份到bak目录再去发证书,确保序列号池始终可回溯。
6.6 GmSSL版本差异带来的兼容性警告
GmSSL项目迭代速度比较快,不同版本的命令参数有过调整。比如早期版本里SM2签名参数是-sm2-id,后来改成了-sigopt sm2_id。如果你拿网上老文章里的命令直接跑,很可能报参数错误。遇到这种问题时,先看当前版本的手册:
/opt/gmssl/bin/gmssl req -help | grep -i "sig"以源码中实际支持的参数为准,不要硬套网上命令。同一套证书体系内的所有签发操作,建议使用同一个GmSSL版本完成,避免跨版本签名导致兼容性问题。
7. 扩展思考:证书生命周期管理
7.1 证书续期与吊销
CA体系搭建完成只是开始,更关键的是生命周期管理。证书到期前要提前续期,续期流程和首次签发几乎一样,只是CSR可以直接复用原来的私钥生成,不一定需要重新生成密钥。如果出于安全考虑,建议续期时顺便轮换密钥,私钥使用时间越长泄露风险越大。
吊销场景完全绕不开。人员离职、服务器下线、私钥泄露,都需要吊销对应证书。GmSSL支持生成CRL(证书吊销列表),操作命令如下:
/opt/gmssl/bin/gmssl ca -gencrl -crldays 30 \ -keyfile /opt/gmca/private/interca.key \ -cert /opt/gmca/ca/interca.crt \ -out /opt/gmca/crl/interca.crl \ -config /opt/gmca/conf/ca.conf客户端在验证证书链时,会同时检查CRL确认证书未被吊销。如果客户端没有配置CRL分发地址,吊销功能形同虚设。所以,在生产环境中要确保每个节点的证书配置文件里都配置了CRL Distribution Point。
7.2 引入在线状态查询机制
CRL是离线列表,更新频率有限,实时性不够。更严格的场景里,建议启用OCSP(在线证书状态协议)服务。GmSSL没有内置完整的OCSP服务端,但可以借助开源的OCSP响应器,把中间CA的密钥接入,实时响应客户端对证书状态的查询。这块需要单独部署,但带来的收益是实时的吊销反馈。对于金融场景,这基本是准入要求。
7.3 私钥备份与密钥管理方案
说一句掏心窝的话,私钥备份是整个CA体系里最容易被忽视、但后果最严重的环节。根私钥丢了,整套体系作废,所有下级证书要全部重签。所以建议对根私钥做物理隔离+加密备份,密钥文件本身用SM4加密后再存放。
/opt/gmssl/bin/gmssl sms4 -e -in rootca.key -out rootca.key.enc -pass pass:your-passphrase加密后的私钥文件可以放到保险柜或者其他安全的离线介质。日常签发操作只接触中间CA私钥,根私钥只在极少数时间(比如签发中间CA、更新根证书)才临时解密启用。这套做法可以极大降低私钥泄露风险。
8. 心得体会与后续建议
整套流程跑下来,我最大的感受是:国密证书的技术门槛其实不在算法本身,GmSSL已经把SM2、SM3这些底层实现了,真正难的是整个PKI体系的理解,以及部署环节里各单位对国密支持程度的参差不齐。如果你只是需要一张能过检的国密证书,那直接用在线CA或硬件加密机就可以,不一定要自己搭私有CA;但如果你需要一个可审计、可控制、可持续的证书管理体系,那按照上面这套流程搭建是相当可靠的。
最后再分享一个小技巧:签发前准备一个checklist,逐项打勾,能减少绝大多数低级错误。我的清单包括:私钥权限是否为600、serial是否备份、CSR里的CN是否和SAN一致、扩展文件是否填写正确、签发完有没有做verify、证书链文件拼接顺序是否无误。每一步都花不了几秒钟,但省下的排错时间可能是几小时。国密改造这条路,细心比什么都重要。