使用 openssl 验证证书

证书可以具有层次结构,认证机构的公钥可以由其它认证机构施加数字签名,生成认证机构的公钥证书,一个认证机构的公钥来验证另一个认证机构的公钥,会最终形成一个认证链,认证链的终点称为根CA (Root CA). 根CA机构为自己的公钥进行数字签名,称为自签名(self-signature)

使用 openssl 生成两层结构的 CA

1
2
3
4
5
6

Root CA -----> Sub CA -------> Server Certificate

Root CA 自签名为自己颁发证书
Root CA 为 Sub CA 颁发证书(Root CA 私钥对 Sub CA 公钥进行数字签名)
Sub CA 为 Server 颁发证书 (Sub CA 私钥对 Server 的公钥进行数字签名)

具体命令

  1. 生成 Root CA 自签名
1
2
3
4
5
6
7
8
9
10
# req 表示 csr 证书签名请求
# -nodes 表示对密钥不加密
# -newkey 生成新的密钥,使用的公钥密码的类型和参数
# -keyout 密钥输出文件
# -x509 输出一个x509证书,而不是一个 csr 文件
# -days 证书有效期
$ openssl req -nodes -newkey rsa:2048 -keyout root_ca_key.pem -out root_ca.crt -x509 -days 365

root_ca_key.pem # Root CA 密钥文件
root_ca.crt # Root CA 证书文件
  1. 生成 Sub CA 的密钥,CSR 文件,以及通过 Root CA 为其颁发证书
1
2
3
4
5
6
7
8
9
10
11
# 生成 Sub CA 的密钥,CSR 文件
$ openssl req -nodes -newkey rsa:2048 -keyout sub_ca_key.pem -out sub_ca.csr

sub_ca.csr # sub CA CSR 证书签名请求文件
sub_ca_key.pem # sub CA 密钥文件

# 通过 Root CA 为其颁发证书
$ openssl x509 -req -in sub_ca.csr -days 365 -CA root_ca.crt -CAkey root_ca_key.pem -CAcreateserial -out sub_ca.crt -extfile ext.cnf

$ cat ext.cnf
basicConstraints=critical,CA:TRUE

上述的 -extfile 指定了 x509 扩展文件(extentisons) ,其中指明了颁发的证书作为 CA. 可以通过查看证书的内容看到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ openssl x509 -in sub_ca.crt -noout -text -purpose -ext basicConstraints

Certificate:
Data:
Version: 3 (0x2)
Serial Number:
33:7a:a8:42:c1:0a:39:59:55:fe:21:ab:88:a0:15:7d:d2:19:ac:32
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = CN, ST = Sichuan, L = Chengdu, O = CdTech, OU = IT, CN = www.CdTech.com, emailAddress = CdTech@CdTech.com
Validity
Not Before: Jan 31 11:53:54 2021 GMT
Not After : Jan 31 11:53:54 2022 GMT
Subject: C = CN, ST = Sichuan, L = Luzhou, O = LuzhouTech, OU = IT, CN = www.LuzhouTech.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:ad:a7:b4:4e:57:7e:a8:2b:95:49:79:06:bc:9e:
60:04:a4:2c:4f:45:dd:47:69:7c:bd:1f:88:14:3a:
b3:48:6a:80:bb:ed:97:99:eb:ab:b9:bf:c9:51:c3:
......
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
6b:b8:19:ea:77:7e:75:bd:22:3f:85:d0:17:84:b2:3e:cc:7a:
b1:80:b3:26:25:26:27:1b:42:b6:1d:90:db:40:41:1f:17:90:
e1:36:2e:b4:70:89:23:52:d8:af:86:98:2a:54:ba:09:8a:03:
......

最早进行测试的时候,没有指定该扩展,通过 sub CA 的私钥对 Server 进行签发证书后,使用 openssl verify 会验证失败,所以这里猜想,应该是没有指定 CA:TRUE 的扩展,所以验证的时候,不会将 sub CA 作为一个 CA 对待。可以通过 openssl x509v3_config 查看更详细的内容。serverfault 中的该问题 openssl invalid CA certificate 应该和这里是一样的问题

  1. 生成 Server 的密钥,CSR 文件,并通过 sub CA 私钥为其颁发证书
1
2
3
4
5
6
7
8
$ openssl req -nodes -newkey rsa:2048 -keyout server_key.pem -out server_ca.csr

server.csr
server_key.pem

$ openssl x509 -req -in server_ca.csr -days 365 -CA sub_caa.crt -CAkey sub_ca_key.pem -CAcreateserial -out server.crt

server.crt # server 的公钥证书,由 sub CA 进行数字签名

证书验证

1
2
3
# 根证书验证(自签名)
$ openssl verify -CAfile root_ca.crt root_ca.crt
root_ca.crt: OK
1
2
3
# sub CA 证书验证
$ openssl verify -CAfile root_ca.crt sub_ca.crt
sub_ca.crt: OK
1
2
3
4
5
# server 证书验证
cat sub_ca.crt root_ca.crt > chain.crt

openssl verify -CAfile chain.crt server.crt
server.crt: OK

安装证书

Linux: Installed CA certificate as trusted certificate

1
2
3
4
5
6
7
sudo mkdir /usr/share/ca-certificates/extra

sudo cp root_ca.crt /usr/share/ca-certificates/extra/root_ca.crt

sudo dpkg-reconfigure ca-certificates

sudo update-ca-certificates

*使用空格选中要安装的证书 root_ca.crt,回车,就可以安装,安装完后,再对 root_ca.crt sub_ca.crt 进行验证,就不要再指定 -CAfile了,因为已经将根证书安装在系统中称为信任的证书

image-20210131213446735

参考文献

[1] openSSL certificate-verification on Linux

[2] openssl invalid CA certificate

[3] openssl man x509

[4] openssl man x509v3 config

[5] verify-a-certificate-chain-using-openssl-verify

[6] Ubuntun 的证书配置

[7] 如何制作 CSR 文件

[8] 验证证书链

[9] openssl 证书操作

[10] 深入剖析 RSA 密钥原理及实践