Skip to content

Latest commit

 

History

History
241 lines (183 loc) · 6.29 KB

2.2.Generate-ECC-CA-Root.md

File metadata and controls

241 lines (183 loc) · 6.29 KB

1.2. 生成 ECC CA 根证书

初始化工作目录

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

export MY_CA_WORKDIR=/data/ca
mkdir -p $MY_CA_WORKDIR

MY_CA_ROOT_DIR=$MY_CA_WORKDIR/ECC/Root

mkdir -p $MY_CA_ROOT_DIR

cd $MY_CA_ROOT_DIR

MY_CA_RAND_FILE=$MY_CA_ROOT_DIR/.rand

mkdir -p newcerts crl
touch index.txt

openssl rand -out $MY_CA_RAND_FILE 65535
md5sum $MY_CA_RAND_FILE | grep -Po '^\w+' > serial

openssl rand -out $MY_CA_RAND_FILE 1048576

生成 CA 根证书的 ECC 私钥

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

MY_CA_ROOT_KEY_PATH=$MY_CA_ROOT_DIR/key.pem

# 生成 CA 根证书的 ECC 私钥
openssl ecparam -rand $MY_CA_RAND_FILE -genkey -name prime256v1 -noout -out $MY_CA_ROOT_KEY_PATH

# 【可选】为该私钥增加 AES 加密保护。
openssl ec -aes-256-cfb -in $MY_CA_ROOT_KEY_PATH -out $MY_CA_ROOT_KEY_PATH

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

MY_CA_ROOT_KEY_PATH=$MY_CA_ROOT_DIR/key.pem

# 生成 CA 根证书的 ECC 私钥
openssl genpkey -algorithm ed25519 -out $MY_CA_ROOT_KEY_PATH

# 【可选】为该私钥增加 AES 加密保护。
cp $MY_CA_ROOT_KEY_PATH $MY_CA_ROOT_KEY_PATH.raw
openssl pkcs8 \
    -topk8 \
    -inform PEM \
    -v2 aes256 \
    -in $MY_CA_ROOT_KEY_PATH.raw \
    -out $MY_CA_ROOT_KEY_PATH
rm -f $MY_CA_ROOT_KEY_PATH.raw

生成证书签名申请表文件

ECC_CA_ROOT_REQ_PATH=$MY_CA_ROOT_DIR/ca.csr.cnf

cat > $ECC_CA_ROOT_REQ_PATH << EOL
[ req ]

default_bits        = 4096
distinguished_name  = req_distinguished_name
string_mask         = utf8only
prompt              = no

# SHA-1 is deprecated, so use SHA-2 instead.
default_md          = sha384

# Extension to add when the -x509 option is used.
x509_extensions     = v3_ca
req_extensions     = v3_ca

[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName                     = CN
0.organizationName              = Demo ORG
organizationalUnitName          = www.demo.org
commonName                      = Demo CA ECC Root

[ v3_ca ]

subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
EOL

签发自签名 CA 根证书

MY_CA_ROOT_CERT_PATH=$MY_CA_ROOT_DIR/ca.pem

# 生成一个有效期为 30 年的自签名 CA 根证书
openssl req -config $ECC_CA_ROOT_REQ_PATH \
    -new \
    -x509 \
    -days 10950 \
    -sha256 \
    -extensions v3_ca \
    -key $MY_CA_ROOT_KEY_PATH \
    -out $MY_CA_ROOT_CERT_PATH

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

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

openssl x509 -noout -text -in $MY_CA_ROOT_CERT_PATH

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

openssl verify -CAfile $MY_CA_ROOT_CERT_PATH $MY_CA_ROOT_CERT_PATH

配置 CA

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

ECC_CA_ROOT_CONF_PATH=$MY_CA_ROOT_DIR/ca.cnf

cat > $ECC_CA_ROOT_CONF_PATH << EOL
[ ca ]
default_ca = CA_default

[ CA_default ]
# Directory and file locations.
dir               = $MY_CA_ROOT_DIR
certs             = \$dir/certs
crl_dir           = \$dir/crl
new_certs_dir     = \$dir/newcerts
database          = \$dir/index.txt
serial            = \$dir/serial
RANDFILE          = \$dir/.rand

# The root key and root certificate.
private_key       = \$dir/key.pem
certificate       = \$dir/ca.pem

# For certificate revocation lists.
crlnumber         = \$dir/crlnumber
crl               = \$dir/crl/ca.crl.pem
crl_extensions    = crl_ext
default_crl_days  = 30

# SHA-1 is deprecated, so use SHA-2 instead.
default_md        = sha256

name_opt          = ca_default
cert_opt          = ca_default
default_days      = 375
preserve          = no
policy            = policy_strict
copy_extensions   = copy

[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
countryName             = match
stateOrProvinceName     = optional
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
default_bits        = 4096
distinguished_name  = req_distinguished_name
string_mask         = utf8only
prompt              = no

# SHA-1 is deprecated, so use SHA-2 instead.
default_md          = sha384

# Extension to add when the -x509 option is used.
x509_extensions     = v3_ca

[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName                     = CN
0.organizationName              = Demo ORG
organizationalUnitName          = www.demo.org
commonName                      = Demo CA ECC Root

[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
extendedKeyUsage = critical, clientAuth, serverAuth
basicConstraints = critical, CA:true, pathlen:0
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
# authorityInfoAccess = caIssuers;URI:http://demo.org/ca.html
# crlDistributionPoints = URI:http://demo.org/ca.crl
# certificatePolicies = 2.23.140.1.2.1,@policy_issuer_info

# [ policy_issuer_info ]
# policyIdentifier = 1.3.6.1.4.1.44947.1.2.3.4.5.6.7.8

[ crl_ext ]
authorityKeyIdentifier=keyid:always

[ ocsp ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
EOL

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

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