OpenSSL生成自签名证书

要写个支持TLS的客户端、服务端socket程序,那么先看如何用OpenSSL生成证书。

环境

OS:Ubuntu 1804
OpenSSL 1.1.1 11 Sep 2018

生成证书

SSL(Secure Sockets Layer,安全套接字协议)是为网络通信提供安全及数据完整性的一种安全协议,支持单向认证和双向认证。

  • 单向认证: client校验server合法性。client需要ca.crt,server需要server.crt、server.key
  • 双向认证: client与server相互校验。client需要client.key、client.crt、ca.crt,server需要server.key、server.crt、ca.crt

生成CA证书

1、创建CA证书私钥

1
2
3
$ mkdir key
$ cd key
$ openssl genrsa -out ca.key 2048

2、用CA证书私钥生成X509证书

1
2
3
4
5
6
7
8
9
$ openssl req -new -x509 -days 3650 -key ca.key -out ca.crt
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:BJ
Locality Name (eg, city) []:BJ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:SELF
Organizational Unit Name (eg, section) []:SELF
Common Name (e.g. server FQDN or YOUR name) []:CA
Email Address []:

3、先创建好CA目录,并准备好CA的序列号、索引文件

1
2
3
4
$ mkdir -p demoCA/newcerts
$ cd demoCA
$ touch index.txt index.txt.attr
$ echo 00 > serial

4、用openssl生成随机数种子,当前用户的根目录下执行

1
2
3
4
5
$ openssl rand -writerand .rnd
$ pwd
/home/top
$ ls -rlt .rnd
-rw------- 1 top top 1024 12月 4 11:40 .rnd

生成服务端证书

1、生成2048 bit的服务端私钥

1
$ openssl genrsa -out server.key 2048

2、用服务端私钥生成证书签名请求CSR

1
2
3
4
5
6
7
8
9
$ openssl req -new -key server.key -out server.csr
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:BJ
Locality Name (eg, city) []:BJ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:SELF
Organizational Unit Name (eg, section) []:SELF
Common Name (e.g. server FQDN or YOUR name) []:SERVER
Email Address []:

3、通过CA生成服务端自签名证书
Ubuntu 1804的openssl.cnf位置在/etc/ssl/openssl.cnf,其他操作系统可以通过find命令来查找位置,如果需要自定义证书和证书申请中的一些属性和扩展可以将该文件拷贝到自定义文件夹后进行修改。

1
$ openssl ca -in server.csr -out ./demoCA/server.crt -cert ca.crt -keyfile ca.key -config /etc/ssl/openssl.cnf -days 3650

注意生成签名请求时信息需要填写,否则会提示:

1
2
3
4
Using configuration from /etc/ssl/openssl.cnf
Check that the request matches the signature
Signature ok
The commonName field needed to be supplied and was missing

另外生成签名请求时除了Common Name字段,其他字段必须与CA保持一致,当然Common Name字段可相同,否则:

1
2
3
4
5
Using configuration from /etc/ssl/openssl.cnf
Check that the request matches the signature
Signature ok
The countryName field is different between
CA certificate (VN) and the request (CN)

那么正确执行时信息如下:

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
Using configuration from /etc/ssl/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Dec 4 15:32:09 2021 GMT
Not After : Dec 4 15:32:09 2022 GMT
Subject:
countryName = CN
stateOrProvinceName = BJ
organizationName = SELF
organizationalUnitName = SELF
commonName = SERVER
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
A4:64:1F:61:A6:9F:0C:5A:4D:9C:63:9B:07:C3:E5:D2:BA:B9:70:D0
X509v3 Authority Key Identifier:
keyid:C8:AD:BE:A0:BD:FF:CE:7D:06:2F:25:3E:0D:9C:46:B5:67:C1:47:CC

Certificate is to be certified until Dec 4 15:32:09 2022 GMT (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

4、验证有效性

1
2
$ openssl verify -CAfile ca.crt demoCA/server.crt
demoCA/server.crt: OK

5、文件结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ tree
.
├── ca.crt
├── ca.key
├── demoCA
│   ├── index.txt
│   ├── index.txt.attr
│   ├── index.txt.attr.old
│   ├── index.txt.old
│   ├── newcerts
│   │   └── 00.pem
│   ├── serial
│   ├── serial.old
│   └── server.crt
├── server.csr
└── server.key

2 directories, 12 files

到这里,能用于单向认证的证书就生成好了,将server.keyserver.crtca.crt分别应用到服务端、客户端的程序即可。

生成客户端证书

与服务端1-3步类似,生成客户端所需的证书。其中第二步:

1
2
3
4
5
6
7
8
9
$ openssl req -new -key client.key -out client.csr
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:BJ
Locality Name (eg, city) []:BJ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:SELF
Organizational Unit Name (eg, section) []:SELF
Common Name (e.g. server FQDN or YOUR name) []:CLIENT
Email Address []:

可以注意到,CA、服务端、客户端的信息大部分一致,只有Common Name不同。生成后在demoCA里可以找到client.crt文件。

现在就能用于双向认证了。

参考

1、https://www.openssl.org/docs/man1.1.1/man3/RAND_write_file.html
2、https://docs.azure.cn/zh-cn/articles/azure-operations-guide/application-gateway/aog-application-gateway-howto-create-self-signed-cert-via-openssl
3、https://cloud.tencent.com/document/product/214/54254

0%