3.1. 使用二级 CA 签发服务端证书

该文章根据 CC-BY-4.0 协议发表,转载请遵循该协议。
本文地址:https://fenying.net/book/pki-tutorials/3.1.request-server-certificate/

本章节介绍如何利用 OpenSSL 命令行工具,使用二级 CA 证书签发服务端证书。

生成密钥

可以自行选择 RSA 或者 EC 密钥,但是需要注意密钥长度:

  • RSA 2048
  • EC 256

此处使用 RSA 作为示例

 1MY_CA_L2_DIR=$RSA_CA_R1_DIR          # RSA 二级 CA 的根目录
 2
 3NEW_CERT_DOMAIN=www.your-domain.com
 4NEW_SERVER_KEY_PATH=$MY_CA_L2_DIR/private/server-$NEW_CERT_DOMAIN.key.pem
 5
 6openssl genrsa -rand $MY_CA_L2_DIR/.rand -out $NEW_SERVER_KEY_PATH 2048
 7
 8# 或者生成带密码保护的 RSA 密钥
 9# openssl genrsa -rand $MY_CA_L2_DIR/.rand -aes-256-cfb -out $NEW_SERVER_KEY_PATH 2048
10
11# 或者选择 EC 密钥。
12# openssl ecparam -rand $MY_CA_L2_DIR/.rand -genkey -name prime256v1 -noout -out $NEW_SERVER_KEY_PATH
13
14# 如果要对 EC 密钥加密,则须接着执行如下命令
15# openssl ec -aes-256-cfb -in $NEW_SERVER_KEY_PATH -out $NEW_SERVER_KEY_PATH

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

这里分成两步。

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

 1NEW_SERVER_CERT_REQ_PATH=$MY_CA_L2_DIR/csr/server-$NEW_CERT_DOMAIN.csr.cnf
 2
 3cat > $NEW_SERVER_CERT_REQ_PATH << EOL
 4[ req ]
 5distinguished_name  = req_distinguished_name
 6string_mask         = utf8only
 7req_extensions      = req_ext
 8x509_extensions     = v3_req
 9
10# SHA-1 is deprecated, so use SHA-2 instead.
11default_md          = sha256
12prompt              = no
13
14[ req_distinguished_name ]
15# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
16commonName                      = $NEW_CERT_DOMAIN
17
18[req_ext]
19subjectAltName = @alt_names
20
21[v3_req]
22subjectAltName = @alt_names
23
24[alt_names]
25# IP.1 = 127.0.0.1
26DNS.1 = $NEW_CERT_DOMAIN
27EOL

注意服务端证书不能省略 subjectAltName,否则浏览器不识别。

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

1NEW_SERVER_CERT_CSR_PATH=$MY_CA_L2_DIR/csr/server-$NEW_CERT_DOMAIN.csr.pem
2
3openssl req \
4    -config $NEW_SERVER_CERT_REQ_PATH \
5    -new -sha256 \
6    -key $NEW_SERVER_KEY_PATH \
7    -out $NEW_SERVER_CERT_CSR_PATH

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

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

签发证书

到了最关键的一步,这里使用你上面创建的 xxx.csr.pem 文件里的信息,生成一个 x509 证书文件(xxx.cert.pem),并使用 CA 的私钥对该证书进行签名。

 1NEW_SERVER_CERT_PATH=$MY_CA_L2_DIR/issued_certs/server-$NEW_CERT_DOMAIN.cert.pem
 2
 3openssl ca \
 4    -config $MY_CA_L2_DIR/ca.cnf \
 5    -extensions server_cert \
 6    -days 180 \
 7    -notext \
 8    -md sha256 \
 9    -batch \
10    -in $NEW_SERVER_CERT_CSR_PATH \
11    -out $NEW_SERVER_CERT_PATH

命令说明:

  • 选项 -config $MY_CA_L2_DIR/ca.cnf

    该参数用于指定 CA 的配置文件,具体参考前文创建 CA 的说明。

  • 选项 -batch

    表示采用批量自动化模式,从 CA 配置和命令行参数里直接读取信息,而不是命令行手动输入,也不需要手动确认。

  • 选项 -md sha256

    指定证书签名时使用额散列摘要算法,如果省略,则默认使用 CA 配置文件里的 default_md 指定的算法。

  • 选项 -days

    表示证书的有效时长(从签发这一刻的系统时间起算)。如果省略,则默认使用 CA 配置文件里的 default_days 指定的时长。

    如果有需要生成特定时间(如过期的证书,用于某些测试场景),可以将参数 -days 180 替换为 -startdate 220101000000Z -enddate 220301000000Z,其中,

    • -startdate 表示证书有效期开始时间,格式为 YYMMDDhhmmssZ,即年月日时分秒各用2位数表示,尾部的 Z 表示使用 UTC 时区。
    • -enddate 表示证书有效期结束时间,格式同上。

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

1openssl x509 -noout -text -in $NEW_SERVER_CERT_PATH

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

1openssl verify -CAfile $MY_CA_L2_DIR/ca.fullchain.pem $NEW_SERVER_CERT_PATH

生成证书链文件

1NEW_SERVER_FULLCHAIN_PATH=$MY_CA_L2_DIR/issued_certs/server-$NEW_CERT_DOMAIN.fullchain.pem
2
3cat > $NEW_SERVER_FULLCHAIN_PATH << EOL
4$(cat $NEW_SERVER_CERT_PATH)
5
6$(cat $MY_CA_L2_DIR/ca.fullchain.pem)
7EOL

然后用如下命令检查证书链完整性。

1openssl verify -CAfile $MY_CA_L2_DIR/ca.fullchain.pem $NEW_SERVER_FULLCHAIN_PATH

至此,你已经成功生成了一个服务端证书,可以用于配置你的服务端。

comments powered by Disqus

翻译: