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
如果你想给密钥加个密码保护,可以加-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年的有效期。嗯,到这里根证书就搞定了。
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的时候,总在openssl.cnf配置上栽跟头,不是路径写错就是策略配错。后来我养成了一个习惯:每改一次配置,就跑一遍openssl ca -gencrl验证一下,没问题再往下走。