前言

在本站之前一篇文章 如何成为 CA,并签发自己的证书 中,我们介绍了如何做一个“正规”的自签名证书。

但是,这个方法对于现代的浏览器不太管用了,因为 Chrome、Firefox 等浏览器已经不再判定证书的 CN (Common Name) 字段与域名是否一致了,而是改用判定 SAN (Subject Alternative Name) 字段。具体为什么这么做以及 SAN 的含义,网上有很多解释,很重要但是这里不谈,只谈如何在自签名证书中正确配置 SAN 字段。

网上的教程有很多,但很多没有说清楚,或者缺少一些关键步骤和参数,导致实际情况下出各种问题,这里我尽量整理了一个完善的版本。

准备步骤

首先,CA 的证书与文首提到的文章一致,如果之前配置过,那就不需要再生成了。

然后,生成待签发证书的私钥,这一步也与上述文章相同:

1
openssl genrsa -out example.key 4096

关键在于 CSR 的创建

之前创建 CSR 的时候会手动输各个字段,但其中不包含 SAN 字段,所以我们需要一个配置文件来配置 SAN 字段(当然直接包含在命令行里面也行,但很麻烦)。

建议新建一个目录叫 certreq,然后在里面新建一个文件叫 req.conf,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[req]
distinguished_name = req_distinguished_name
req_extensions = req_ext
prompt = no

[req_distinguished_name]
C = <修改为实际值>
ST = <修改为实际值>
L = <修改为实际值>
O = <修改为实际值>
OU = <修改为实际值>
CN = <修改为实际值>

[req_ext]
subjectAltName = @alt_names

[alt_names]
# 这里就是 SAN 字段,以下修改为实际值
DNS.1 = vvzero.com
DNS.2 = *.vvzero.com
IP.1 = 1.1.1.1
IP.2 = 1.1.1.2
IP.3 = 1.1.1.3

然后生成 CSR 文件:

1
openssl req -new -key example.key -out example.csr -config req.conf

检查 CSR 文件中是否存在 SAN 字段

1
openssl req -noout -text -in example.csr | grep -A 1 "Subject Alternative Name"

如果打印出了你的配置,则代表创建成功。如果没有输出,请检查有没有操作错误。

用 CA 的私钥签发证书

1
openssl x509 -req -days 365 -in example.csr -CA /path/to/CAPrivate.pem -CAkey /path/to/CAPrivate.key -CAcreateserial -out example.crt -extensions req_ext -extfile req.conf

注意其中的 -extensions req_ext -extfile req.conf 是关键,很多教程没有加这个参数,导致生成的证书丢了 SAN 字段。

验证证书的 SAN 字段

1
openssl x509 -text -noout -in example.crt | grep -A 1 "Subject Alternative Name"

同上,需要打印出正确的 SAN 配置,才算成功。