1.3. 生成 RSA CA 中间证书

该文章根据 CC-BY-4.0 协议发表,转载请遵循该协议。
本文地址:https://fenying.net/book/pki-tutorials/1.3.generate-rsa-ca-intermediate/

本章节介绍如何使用 OpenSSL 生成 RSA 二级 CA 证书。

初始化工作目录

假定 RSA CA 的工作目录在 /data/ca/RSA/R1,那么执行如下脚本:

 1export MY_CA_WORKDIR=/data/ca
 2
 3MY_CA_L2_DIR=$MY_CA_WORKDIR/RSA/R1
 4
 5mkdir -p $MY_CA_L2_DIR
 6
 7cd $MY_CA_L2_DIR
 8
 9mkdir -p certs crl csr issued_certs private
10touch index.txt
11
12MY_CA_RAND_FILE=$MY_CA_L2_DIR/.rand
13
14openssl rand -out $MY_CA_RAND_FILE 65535
15sha1sum $MY_CA_RAND_FILE | grep -Po '^\w+' > serial
16
17openssl rand -out $MY_CA_RAND_FILE 65535
18sha1sum $MY_CA_RAND_FILE | grep -Po '^\w+' > crlnumber
19
20openssl rand -out $MY_CA_RAND_FILE 1048576

生成 CA 中间证书的 RSA 私钥

1MY_CA_L2_KEY_PATH=$MY_CA_L2_DIR/key.pem
2
3# 生成一个 3072 位的 RSA 私钥
4openssl genrsa -rand $MY_CA_RAND_FILE -aes-256-cfb -out $MY_CA_L2_KEY_PATH 3072

生成证书签名申请表文件(xxx.csr.pem)

首先,创建一个申请表草稿(xxx.csr.cnf),这是一个用于描述要申请的证书的详细信息的文本文件

 1MY_CA_L2_REQ_PATH=$MY_CA_L2_DIR/ca.csr.cnf
 2
 3cat > $MY_CA_L2_REQ_PATH << EOL
 4[ req ]
 5distinguished_name  = req_distinguished_name
 6string_mask         = utf8only
 7
 8# SHA-1 is deprecated, so use SHA-2 instead.
 9default_md          = sha384
10prompt              = no
11
12[ req_distinguished_name ]
13# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
14countryName                     = CN
150.organizationName              = Demo ORG
16organizationalUnitName          = www.demo.org
17commonName                      = Demo CA RSA R1
18EOL

然后使用 openssl req 命令,在该申请表里添加你的二级 CA 公钥,并使用你二级 CA 私钥,对该申请表进行签名,从而得到一个新的文件 xxx.csr.pem,这是一个 BASE64 编码的 DER 文件。

1MY_CA_L2_CSR_PATH=$MY_CA_L2_DIR/ca.csr.pem
2
3openssl req \
4    -config $MY_CA_L2_REQ_PATH \
5    -new \
6    -key $MY_CA_L2_KEY_PATH \
7    -out $MY_CA_L2_CSR_PATH

可以通过如下命令查看该文件的详细信息。

1openssl req \
2    -in $MY_CA_L2_CSR_PATH \
3    -noout \
4    -text

签发 CA 中间证书

限制开始使用根 CA 签发二级 CA 证书。这里使用你上面创建的 xxx.csr.pem 文件里的信息,生成一个 x509 证书文件(ca.pem),并使用 CA 的私钥对该证书进行签名。

这里签发的是一个 10 年有效期的二级 CA。

 1MY_CA_L2_CERT_PATH=$MY_CA_L2_DIR/ca.pem
 2
 3openssl ca \
 4    -config $MY_CA_ROOT_DIR/ca.cnf \
 5    -extensions v3_intermediate_ca \
 6    -days 3650 \
 7    -notext \
 8    -batch \
 9    -in $MY_CA_L2_CSR_PATH \
10    -out $MY_CA_L2_CERT_PATH

然后可以通过如下命令查看生成证书的详细信息。

1openssl x509 -noout -text -in $MY_CA_L2_CERT_PATH

通过如下命令验证二级 CA 证书是否可以用根 CA 证书验证。

1openssl verify -CAfile $MY_CA_ROOT_CERT_PATH $MY_CA_L2_CERT_PATH

生成证书链文件

1MY_CA_L2_CERT_CHAIN_PATH=$MY_CA_L2_DIR/ca.fullchain.pem
2
3cat > $MY_CA_L2_CERT_CHAIN_PATH << EOL
4$(cat $MY_CA_L2_CERT_PATH)
5
6$(cat $MY_CA_ROOT_CERT_PATH)
7EOL

配置 CA

最后对 CA 进行配置,以用于签发其他证书。

 1MY_CA_L2_CONF_PATH=$MY_CA_L2_DIR/ca.cnf
 2
 3cat > $MY_CA_L2_CONF_PATH << EOL
 4# OpenSSL intermediate CA configuration file.
 5# Copy to /root/ca/intermediate/openssl.cnf.
 6
 7[ ca ]
 8# man ca
 9default_ca = CA_default
10
11[ CA_default ]
12# Directory and file locations.
13dir               = $MY_CA_L2_DIR
14certs             = \$dir/certs
15crl_dir           = \$dir/crl
16new_certs_dir     = \$dir/issued_certs
17database          = \$dir/index.txt
18serial            = \$dir/serial
19RANDFILE          = \$dir/.rand
20
21# The root key and root certificate.
22private_key       = \$dir/key.pem
23certificate       = \$dir/ca.pem
24
25# For certificate revocation lists.
26crlnumber         = \$dir/crlnumber
27crl               = \$dir/crl/intermediate.crl.pem
28crl_extensions    = crl_ext
29default_crl_days  = 30
30
31# SHA-1 is deprecated, so use SHA-2 instead.
32default_md        = sha256
33
34name_opt          = ca_default
35cert_opt          = ca_default
36default_days      = 375
37preserve          = no
38policy            = policy_loose
39copy_extensions   = copy
40
41[ policy_loose ]
42# Allow the intermediate CA to sign a more diverse range of certificates.
43# See the POLICY FORMAT section of the ca man page.
44countryName             = optional
45stateOrProvinceName     = optional
46localityName            = optional
47organizationName        = optional
48organizationalUnitName  = optional
49commonName              = supplied
50emailAddress            = optional
51
52[ client_cert ]
53# Extensions for client certificates (man x509v3_config).
54basicConstraints = CA:FALSE
55subjectKeyIdentifier = hash
56authorityKeyIdentifier = keyid:always,issuer:always
57keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
58extendedKeyUsage = clientAuth
59# authorityInfoAccess = caIssuers;URI:http://demo.org/ca.html
60# certificatePolicies = 2.23.140.1.2.1,@policy_issuer_info
61# authorityInfoAccess = OCSP;URI:http://ocsp.demo.org/
62
63[ server_cert ]
64# Extensions for server certificates (man x509v3_config).
65keyUsage = critical, digitalSignature, keyEncipherment
66extendedKeyUsage = serverAuth, clientAuth
67basicConstraints = CA:FALSE
68subjectKeyIdentifier = hash
69authorityKeyIdentifier = keyid:always,issuer:always
70# authorityInfoAccess = caIssuers;URI:http://demo.org/ca.html
71# certificatePolicies = 2.23.140.1.2.1,@policy_issuer_info
72# authorityInfoAccess = OCSP;URI:http://ocsp.demo.org/
73
74# [ policy_issuer_info ]
75# policyIdentifier = 1.3.6.1.4.1.44947.1.2.3.4.5.6.7.8
76# CPS.1 = "http://cps.demo.org/"
77# userNotice.1 = @policy_issuer_notice
78
79# [ policy_issuer_notice ]
80
81# explicitText="This is a demo certificate"
82# organization="Demo ORG"
83
84EOL

注意,此时的 CA 不允许重复对同一个 commonName 签发证书,需要改成可以对同一个主体重复颁发证书:

1echo 'unique_subject = no' > $MY_CA_L2_DIR/index.txt.attr

至此,你已经成功生成了 RSA CA 中间证书。

comments powered by Disqus

翻译: