2.3. 生成 EC CA 中间证书

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

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

初始化工作目录

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

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

生成 CA 中间证书的 EC 私钥

1MY_CA_L2_KEY_PATH=$MY_CA_L2_DIR/key.pem
2
3openssl ecparam -rand $MY_CA_RAND_FILE -genkey -name secp384r1 -noout -out $MY_CA_L2_KEY_PATH
4openssl ec -aes-256-cfb -in $MY_CA_L2_KEY_PATH -out $MY_CA_L2_KEY_PATH

生成证书签名申请表文件(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 ]
 5default_bits        = 4096
 6distinguished_name  = req_distinguished_name
 7string_mask         = utf8only
 8
 9# SHA-1 is deprecated, so use SHA-2 instead.
10default_md          = sha384
11prompt              = no
12
13[ req_distinguished_name ]
14# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
15countryName                     = CN
160.organizationName              = Demo ORG
17organizationalUnitName          = www.demo.org
18commonName                      = Demo CA EC E1
19EOL

然后使用 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    -md sha384 \
 9    -batch \
10    -in $MY_CA_L2_CSR_PATH \
11    -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

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

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

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

至此,你已经成功生成了一个 EC 二级 CA 证书。

comments powered by Disqus

翻译: