4、搭建私有CA:生成根密钥、自签名证书与工作目录

好,咱们进入实战环节。搭建私有CA,说白了就是让自己扮演“证书签发官”的角色。你可能会问:为什么不用公共CA?我在项目里遇到过,生产环境设备量一大,每张证书都去公共CA申请,成本高、周期长,而且设备端没法灵活控制。自己搭一个CA,内部用起来方便多了。

嗯,这一节我们一步步来。先准备好CA的根密钥,再生成自签名根证书,最后把CA的工作目录和序列号文件配好。整个过程我建议你在Linux环境下操作,CentOS 7或Ubuntu 20.04都行,OpenSSL版本最好1.1.1以上。

4.1 生成CA根密钥

根密钥是CA的命根子。一旦泄露,你签发的所有证书都不安全了。我个人习惯用RSA 4096位,虽然比2048位慢一点,但安全性高一个档次。

先创建一个目录来存放CA相关文件:

mkdir -p /root/ca
cd /root/ca

然后生成根密钥:

openssl genrsa -out ca.key 4096

这条命令会生成一个4096位的RSA私钥,保存到ca.key文件。注意,这个文件权限一定要收严:

chmod 400 ca.key
⚠️ 重要提醒: 我曾经见过有人把ca.key权限设成644,结果被同事误拷贝走了。虽然没出大事,但吓得我连夜重新生成了一套。记住,ca.key的权限只能是400或600,而且最好备份到离线存储设备。

如果你想给密钥加个密码保护,可以加-aes256参数:

openssl genrsa -aes256 -out ca.key 4096

加了密码后,每次使用ca.key都要输入密码。安全性提高了,但自动化脚本里用起来麻烦。你自己权衡吧。

4.2 自签名根证书

有了密钥,接下来生成根证书。根证书是自签名的——也就是自己给自己发证书。这听起来有点循环论证,但CA的信任链就是这么建立的:你信任根证书,就信任它签发的所有子证书。

先创建一个配置文件ca.cnf,内容如下:

[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_ca
prompt = no

[req_distinguished_name]
C = CN
ST = Beijing
L = Beijing
O = MyCompany
OU = IoT Security
CN = MyCompany Root CA

[v3_ca]
basicConstraints = critical, CA:TRUE
keyUsage = critical, keyCertSign, cRLSign
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer

这里有几个关键点:

  • basicConstraints = CA:TRUE:表明这是一个CA证书,可以签发其他证书
  • keyUsage = keyCertSign, cRLSign:允许用这个证书来签名其他证书和CRL
  • CN:通用名称,我建议用公司名+CA标识,方便识别

然后执行自签名:

openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \
  -out ca.crt -config ca.cnf

解释一下参数:

参数 含义
-x509 直接输出自签名证书,而不是证书签名请求
-new 生成一个新的证书请求
-nodes 不加密私钥(如果ca.key没设密码)
-sha256 使用SHA-256哈希算法,别用SHA-1了,不安全
-days 3650 有效期10年。根证书有效期长一点,省得频繁更新

生成后,验证一下证书内容:

openssl x509 -in ca.crt -text -noout

你会看到CA:TRUE标识,以及10年的有效期。嗯,到这里根证书就搞定了。

💡 小技巧: 我习惯把ca.crt和ca.key分开存放。ca.crt可以公开,设备端需要导入它来验证服务器证书。ca.key必须锁起来,最好放在加密U盘里,用的时候才挂载。

4.3 配置CA工作目录与序列号文件

CA不是光有密钥和证书就完事了。你想想看,每次签发证书都要记录一下:签发给谁、证书序列号是多少、什么时候过期。这些信息需要有个地方存。OpenSSL提供了一套标准的CA目录结构。

创建目录结构:

mkdir -p /root/ca/{certs,crl,newcerts,private,requests}
chmod 700 /root/ca/private

各目录的作用:

目录 用途
certs 存放已签发的证书文件
crl 存放证书吊销列表
newcerts OpenSSL自动存放新签证书的副本
private 存放CA私钥,权限必须700
requests 存放待签名的证书请求文件

接下来创建序列号文件和索引文件:

echo 01 > /root/ca/serial
touch /root/ca/index.txt

serial文件记录下一个要使用的证书序列号。初始值是01,每签发一张证书,OpenSSL会自动加1。index.txt是数据库文件,记录所有已签发的证书信息。格式是这样的:

V	20251231		01	unknown	/C=CN/O=MyCompany/CN=device001

各字段含义:

  • V:证书状态,V=有效,R=吊销,E=过期
  • 20251231:证书到期日期
  • 01:证书序列号
  • unknown:证书请求文件名(OpenSSL自动填充)
  • DN:证书的Distinguished Name

最后,创建OpenSSL主配置文件/root/ca/openssl.cnf:

[ca]
default_ca = CA_default

[CA_default]
dir               = /root/ca
certs             = $dir/certs
crl_dir           = $dir/crl
database          = $dir/index.txt
new_certs_dir     = $dir/newcerts
certificate       = $dir/ca.crt
serial            = $dir/serial
crlnumber         = $dir/crlnumber
crl               = $dir/crl/ca.crl
private_key       = $dir/private/ca.key
RANDFILE          = $dir/private/.rand
default_days      = 365
default_crl_days  = 30
default_md        = sha256
policy            = policy_loose

[policy_loose]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

这里policy_loose表示签发证书时,除了CN必须提供,其他字段都可以省略。这样灵活一些,设备证书不需要填太多信息。

✅ 验证配置: 执行以下命令检查配置是否正确:
openssl ca -config /root/ca/openssl.cnf -gencrl -out /root/ca/crl/ca.crl
如果没有报错,说明CA工作目录和配置文件都准备好了。

4.4 整体流程回顾

来,我们用一张图把这一节的内容串起来:

私有CA搭建流程 1. 生成根密钥 openssl genrsa -out ca.key 4096 2. 自签名根证书 openssl req -x509 ... -out ca.crt 3. 创建目录结构 mkdir -p certs crl newcerts ... 4. 配置序列号文件 echo 01 > serial & touch index.txt 5. 创建OpenSSL配置 openssl.cnf 定义CA策略 6. 验证CA openssl ca -gencrl 关键说明 • 根密钥(ca.key)必须严格保护,权限设为400,建议离线备份 • 根证书(ca.crt)可以公开,设备端需要导入它来建立信任链 • serial和index.txt是CA的“账本”,不要手动修改,让OpenSSL自动管理

你看,整个流程其实不复杂。核心就是三件事:密钥、证书、目录配置。我刚开始搭CA的时候,总在openssl.cnf配置上栽跟头,不是路径写错就是策略配错。后来我养成了一个习惯:每改一次配置,就跑一遍openssl ca -gencrl验证一下,没问题再往下走。