创建用户证书 User Cert
现在,我们终于来到证书链的最下层,用户证书,也叫实体证书(end-entity certificate)。这就是我们平常最常见到的网站的数字证书了,它支撑 HTTPS 协议的基础设施之一。
要创建 User Cert,我们需要与它的签发机构,也就是 Intermediate CA 进行交互。
下面是目录框架示意图:
可以看到,我用两个平行(而不是层级)的目录来管理 Intermediate CA 和 User Certs。 并且,我在 user_certs 目录下为不同的 Web 服务所需的证书创建了单独的目录。
这里我用了一个比较笼统的 user_cert 来命名目录,在具体命名时,我们可以根据自己网站域名来命名。
操作要点
首先,逻辑和步骤与我们之前签发 Intermediate CA 证书的过程是一样的。 同样是三个步骤:
- 创建 Private Key + Password file
- 创建 CSR
- CA 对 CSR 签名,签发最终证书
区别只在于参数配置不一样,比如每个不同的网站的扩展信息不一样(主要是 subjectAltName,也叫 SAN)。
实战案例
现在假设,我们访问 echo 服务,它同时支持 echo1.example.com 和 echo2.example.com 两个域名,甚至泛域名 *.example.com,还支持 IP 地址访问。
进入 user_certs/echo 目录:
cd user_certs/echo
(1) 创建密码文件和私钥
创建密码文件
openssl rand -base64 32 > private/password.txt
创建私钥(RSA 算法)
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out rsa_echo.key
openssl pkcs8 -topk8 -v2 aes256 -iter 100000 -passout file:private/password.txt \
-in rsa_echo.key -out private/rsa_echo_encrypted.key
shred -u rsa_echo.key
检查私钥
openssl asn1parse -in private/rsa_echo_encrypted.key
(2) 创建 CSR
i) 配置信息
req_csr.cnf
[ req ]
default_bits = 4096
default_keyfile = rsa_encrypted.key
distinguished_name = req_distinguished_name
x509_extensions = v3_intermediate_ca
prompt = no
[ req_distinguished_name ]
C = US
ST = TX
O = echo service
CN = echo service
[x509_v3_ext]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
keyUsage = digitalSignature, keyEncipherment, dataEncipherment
extendedKeyUsage = clientAuth,serverAuth
subjectAltName = @alt_names
[alt_names]
IP.1 = 10.10.0.100
DNS.1 = echo1.example.com
DNS.2 = echo2.example.com
DNS.3 = *.example.com
ii) 创建 CSR
openssl req -new \
-passin file:private/password.txt \
-config req_csr.cnf \
-reqexts x509_v3_ext \
-key private/rsa_echo_encrypted.key \
-out rsa_echo.csr
iii) 检查 CSR
openssl req -in rsa_echo.csr -text -noout
现在有了 .csr 文件,int_ca 就可以对其签发证书了。
切换到 int_ca 目录进行操作
(1) 在 int_ca 中创建必要文件和目录
cd ../../int_ca
mkdir -pv newcerts
touch index.txt
echo -ne "00" > serial
echo -ne "00" > crlnumber
(2) 准备配置信息
使用 int_ca 的私钥为 echo 签发证书之前,我们需要再检查一下 int_ca 的各项配置参数是否符合我们的要求:
ica.cnf
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = .
certs = $dir/certs
crl_dir = $dir/crl
database = $dir/index.txt
new_certs_dir = $dir/newcerts
private_key = $dir/CA/private/rsa_encrypted.key
certificate = $dir/CA/rsa_int_ca.crt
serial = $dir/serial
crlnumber = $dir/crlnumber
default_md = sha256
default_days = 3650
default_crl_days = 30
policy = policy_match
copy_extensions = copy
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = optional
organizationalUnitName = optional
commonName = supplied
由于之前在生成 CSR 时,已写入了 v3_intermediate_ca 字段中的信息。因此,我们在使用 int_ca 给其签发证书的时候,可以直接设置 copy_extensions = copy,它表示 int_ca 签署时会直接拷贝 CSR 中的扩展信息,不做任何改变。
不过,如果我们需要为即将要签发的证书定制 v3 extension,我们可以在 ica.cnf 中增加一个段落 [v3_ext_echo],然后在执行命令时用 -extension 选项来指定这个段落。
[v3_ext_echo]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
keyUsage = digitalSignature, keyEncipherment, dataEncipherment
extendedKeyUsage = clientAuth,serverAuth
subjectAltName = @alt_names
[alt_names]
IP.1 = 10.10.0.100
DNS.1 = echo1.example.com
DNS.2 = echo2.example.com
DNS.3 = *.example.com
推荐用 copy 的方式,省事。
(3)签发证书
openssl ca 和 openssl x509 都可以用来签发证书,区别在于前面的 ca 命令有数据库对所签发的证书进行记录(比如 serial, crlnumber 等),而后面的 x509 命令则适用于 ad-hoc 证书的签发,不管理数据库,不记录签发了哪些证书,所以只适合需要一次性证书(比如自签名证书)并且不负责任何后续管理的场景。
由于我们这里专注于证书链系统的构建,所以我们一律使用 openssl ca 命令来构建和管理证书。
注意:签发证书是在 int_ca 目录中操作!
执行命令:
openssl ca -days 365 \
-config ica.cnf \
-cert CA/rsa_int_ca.crt \
-keyfile CA/private/rsa_encrypted.key \
-passin file:CA/private/password.txt \
-in ../user_certs/echo/rsa_echo.csr \
-out ../user_certs/echo/rsa_echo.crt
注:用户证书通常在一年以内,甚至更短。
输出结果:
补充:
如果想由 int_ca 指定 v3 extension 而不是 copy,我们可以这么做:
- 创建一个单独的文件(如
v3_ext_echo.cnf),在里面的段落[ v3_ext_echo ]中填上相应内容。 - 或者直接在
ica.cnf中增加一个段落[ v3_ext_echo ],填上相应内容。
然后执行下面的命令:
openssl ca -days 365 \
-config <(cat ica.cnf v3_ext_echo.cnf) \
-extensions v3_ext_echo \
-cert CA/rsa_int_ca.crt \
-keyfile CA/private/rsa_encrypted.key \
-passin file:CA/private/password.txt \
-in ../user_certs/echo/rsa_echo.csr \
-out ../user_certs/echo/rsa_echo.crt
新证书会生成在 newcerts/ 目录中,默认名字是 serial 编号。比如初始的 serial 是 00,那么签发的第一个证书就是 newcerts/00.pem,serial 文件中会变成 01。
index.txt 中也会增加一条记录,如下:
V 251030162019Z 00 unknown /C=US/ST=TX/O=echo service
进入 user_certs/echo 目录
检查证书
cd user_certs/echo
openssl x509 -text -noout -in newcerts/00.pem
全文完!
下集预告:使用 echo 证书:用 Nginx 搭建 HTTPS 服务器
全文完!
如果你喜欢我的文章,欢迎关注我的微信公众号 deliverit。