2.2. 生成 EC CA 根证书

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

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

初始化工作目录

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

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

生成 CA 根证书的 EC 私钥

这里有两类密钥选择,一是 NIST P-* + ECSDA,比如 secp521r1

1MY_CA_ROOT_KEY_PATH=$MY_CA_ROOT_DIR/key.pem
2
3# 生成 CA 根证书的 EC 私钥
4openssl ecparam -rand $MY_CA_RAND_FILE -genkey -name prime256v1 -noout -out $MY_CA_ROOT_KEY_PATH
5
6# 【可选】为该私钥增加 AES 加密保护。
7openssl ec -aes-256-cfb -in $MY_CA_ROOT_KEY_PATH -out $MY_CA_ROOT_KEY_PATH

如果选择 curve25519,则使用如下命令:

 1MY_CA_ROOT_KEY_PATH=$MY_CA_ROOT_DIR/key.pem
 2
 3# 生成 CA 根证书的 EC 私钥
 4openssl genpkey -algorithm ed25519 -out $MY_CA_ROOT_KEY_PATH
 5
 6# 【可选】为该私钥增加 AES 加密保护。
 7cp $MY_CA_ROOT_KEY_PATH $MY_CA_ROOT_KEY_PATH.raw
 8openssl pkcs8 \
 9    -topk8 \
10    -inform PEM \
11    -v2 aes256 \
12    -in $MY_CA_ROOT_KEY_PATH.raw \
13    -out $MY_CA_ROOT_KEY_PATH
14rm -f $MY_CA_ROOT_KEY_PATH.raw

生成证书签名申请表文件

 1EC_CA_ROOT_REQ_PATH=$MY_CA_ROOT_DIR/ca.csr.cnf
 2
 3cat > $EC_CA_ROOT_REQ_PATH << EOL
 4[ req ]
 5
 6default_bits        = 4096
 7distinguished_name  = req_distinguished_name
 8string_mask         = utf8only
 9prompt              = no
10
11# SHA-1 is deprecated, so use SHA-2 instead.
12default_md          = sha384
13
14# Extension to add when the -x509 option is used.
15x509_extensions     = v3_ca
16req_extensions     = v3_ca
17
18[ req_distinguished_name ]
19# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
20countryName                     = CN
210.organizationName              = Demo ORG
22organizationalUnitName          = www.demo.org
23commonName                      = Demo CA EC Root
24
25[ v3_ca ]
26
27subjectKeyIdentifier = hash
28authorityKeyIdentifier = keyid:always,issuer:always
29basicConstraints = critical, CA:true
30keyUsage = critical, digitalSignature, cRLSign, keyCertSign
31EOL

签发自签名 CA 根证书

 1MY_CA_ROOT_CERT_PATH=$MY_CA_ROOT_DIR/ca.pem
 2
 3# 生成一个有效期为 30 年的自签名 CA 根证书
 4openssl req -config $EC_CA_ROOT_REQ_PATH \
 5    -new \
 6    -x509 \
 7    -days 10950 \
 8    -sha256 \
 9    -extensions v3_ca \
10    -key $MY_CA_ROOT_KEY_PATH \
11    -out $MY_CA_ROOT_CERT_PATH

如果使用 Ed25519,则此处的 -sha256 没有任何意义,因为 Ed25519 一定是使用 SHA-512(SHA2) 作为哈希算法的。

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

1openssl x509 -noout -text -in $MY_CA_ROOT_CERT_PATH

通过如下命令验证自签名 CA 证书是否可以自验证。

1openssl verify -CAfile $MY_CA_ROOT_CERT_PATH $MY_CA_ROOT_CERT_PATH

配置 CA

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

  1EC_CA_ROOT_CONF_PATH=$MY_CA_ROOT_DIR/ca.cnf
  2
  3cat > $EC_CA_ROOT_CONF_PATH << EOL
  4[ ca ]
  5default_ca = CA_default
  6
  7[ CA_default ]
  8# Directory and file locations.
  9dir               = $MY_CA_ROOT_DIR
 10certs             = \$dir/certs
 11crl_dir           = \$dir/crl
 12new_certs_dir     = \$dir/issued_certs
 13database          = \$dir/index.txt
 14serial            = \$dir/serial
 15RANDFILE          = \$dir/.rand
 16
 17# The root key and root certificate.
 18private_key       = \$dir/key.pem
 19certificate       = \$dir/ca.pem
 20
 21# For certificate revocation lists.
 22crlnumber         = \$dir/crlnumber
 23crl               = \$dir/crl/ca.crl.pem
 24crl_extensions    = crl_ext
 25default_crl_days  = 30
 26
 27# SHA-1 is deprecated, so use SHA-2 instead.
 28default_md        = sha256
 29
 30name_opt          = ca_default
 31cert_opt          = ca_default
 32default_days      = 375
 33preserve          = no
 34policy            = policy_strict
 35copy_extensions   = copy
 36
 37[ policy_strict ]
 38# The root CA should only sign intermediate certificates that match.
 39countryName             = match
 40stateOrProvinceName     = optional
 41organizationName        = match
 42organizationalUnitName  = optional
 43commonName              = supplied
 44emailAddress            = optional
 45
 46[ policy_loose ]
 47# Allow the intermediate CA to sign a more diverse range of certificates.
 48countryName             = optional
 49stateOrProvinceName     = optional
 50localityName            = optional
 51organizationName        = optional
 52organizationalUnitName  = optional
 53commonName              = supplied
 54emailAddress            = optional
 55
 56[ req ]
 57default_bits        = 4096
 58distinguished_name  = req_distinguished_name
 59string_mask         = utf8only
 60prompt              = no
 61
 62# SHA-1 is deprecated, so use SHA-2 instead.
 63default_md          = sha384
 64
 65# Extension to add when the -x509 option is used.
 66x509_extensions     = v3_ca
 67
 68[ req_distinguished_name ]
 69# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
 70countryName                     = CN
 710.organizationName              = Demo ORG
 72organizationalUnitName          = www.demo.org
 73commonName                      = Demo CA EC Root
 74
 75[ v3_ca ]
 76subjectKeyIdentifier = hash
 77authorityKeyIdentifier = keyid:always,issuer:always
 78basicConstraints = critical, CA:true
 79keyUsage = critical, digitalSignature, cRLSign, keyCertSign
 80
 81[ v3_intermediate_ca ]
 82keyUsage = critical, digitalSignature, cRLSign, keyCertSign
 83extendedKeyUsage = critical, clientAuth, serverAuth
 84basicConstraints = critical, CA:true, pathlen:0
 85subjectKeyIdentifier = hash
 86authorityKeyIdentifier = keyid:always,issuer:always
 87# authorityInfoAccess = caIssuers;URI:http://demo.org/ca.html
 88# crlDistributionPoints = URI:http://demo.org/ca.crl
 89# certificatePolicies = 2.23.140.1.2.1,@policy_issuer_info
 90
 91# [ policy_issuer_info ]
 92# policyIdentifier = 1.3.6.1.4.1.44947.1.2.3.4.5.6.7.8
 93
 94[ crl_ext ]
 95authorityKeyIdentifier=keyid:always
 96
 97[ ocsp ]
 98basicConstraints = CA:FALSE
 99subjectKeyIdentifier = hash
100authorityKeyIdentifier = keyid:always,issuer:always
101keyUsage = critical, digitalSignature
102extendedKeyUsage = critical, OCSPSigning
103EOL

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

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

至此,EC CA 根证书已经生成完毕。

comments powered by Disqus

翻译: