Thrift&SSL编程#06#客户端与服务端通信数字证书生成篇

关于Thrift和OpenSSL的安全通信,上篇我们描述了zlib的编译方法,本文编译libevent库。

  • 01#编译OpenSSL库;
  • 02#编译Boost库;
  • 03#编译zlib库;
  • 04#编译libevent库;
  • 05#编译Thrift库;
  • 06#生成客户端和服务端通信所用的数字证书
  • 07#编写基于Linux系统的测试代码(单向验证:客户端验证服务端);
  • 08#编写基于Windows系统的测试代码(单向验证:客户端验证服务端);
  • 09#编写基于Linux系统的测试代码(双向验证:客户端验证服务端+服务端验证客户端);
  • 10#编写基于Windows系统的测试代码(双向验证:客户端验证服务端+服务端验证客户端);
  • 11#自定义数字证书的验证策略;

我们知道x509数字证书有V1和V3版本,对于我们来说采用V1版本即可,考虑到证书生成的便捷性,推荐使用如下的第二种方法生成我们需要的证书。

证书生成方法1:交互模式生成证书-V1版本

第一步,将下述内容保存为文件,名称可以为openssl.cnf,后续在使用openssl命令时将使用到。

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

[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = AU
countryName_min = 2
countryName_max = 2

stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Some-State

localityName = Locality Name (eg, city)

0.organizationName = Organization Name (eg, company)
0.organizationName_default = Internet Widgits Pty Ltd

organizationalUnitName = Organizational Unit Name (eg, section)

commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_max = 64

emailAddress = Email Address
emailAddress_max = 64

第二步,使用如下命令创建根证书的私钥和公钥证书文件:

1
2
3
4
5
openssl genrsa -out ca.key 2048

openssl req -new -config openssl.cnf -key ca.key -out ca.csr

openssl x509 -req -days 3650 -sha256 -signkey ca.key -in ca.csr -out ca.crt

上述命令执行过程如下图所示:

第三步,使用如下命令创建服务端证书的私钥和公钥证书文件:

1
2
3
4
5
openssl genrsa -out server.key 2048

openssl req -new -config openssl.cnf -key server.key -out server.csr

openssl x509 -req -days 3650 -sha256 -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt

上述命令执行过程如下图所示:

第四步,使用如下命令创建客户端证书的私钥和公钥证书文件:

1
2
3
4
5
openssl genrsa -out client.key 2048

openssl req -new -config openssl.cnf -key client.key -out client.csr

openssl x509 -req -days 3650 -sha256 -CA ca.crt -CAkey ca.key -CAcreateserial -in client.csr -out client.crt

上述命令执行过程如下图所示:

上述命令执行完毕,我们可以在当前目录看到如下文件:

证书生成方法2:非交互模式生成证书-V1版本(该方法是本系列推荐的方法,比较简单实用)

第一步,将下述内容保存为文件,名称可以为min.cnf,后续在使用openssl命令时将使用到。

1
2
3
4
[req]
distinguished_name = req_distinguished_name

[req_distinguished_name]

第二步,使用如下命令创建根证书的私钥和公钥证书文件:

1
2
3
4
5
6
##R1) 根证书的生成命令
openssl genrsa -out ca.key 2048

openssl req -new -config min.cnf -key ca.key -out ca.csr -subj "/C=CN/ST=ShanDong/L=JiNan/O=RootCA/OU=RootSign/CN=RootSignEV/emailAddress=ca@root.com"

openssl x509 -req -days 3650 -sha256 -signkey ca.key -in ca.csr -out ca.crt

第三步,使用如下命令创建服务端证书的私钥和公钥证书文件:

1
2
3
4
5
6
7
8
9
10
##S1) 服务端证书生成命令:
openssl genrsa -out server.key 2048

openssl req -new -config min.cnf -key server.key -out server.csr -subj "/C=CN/ST=GuangDong/L=ShenZhen/O=Mancode/OU=MIG/CN=127.0.0.1/emailAddress=server@mancode.net"

##S2) 根证书对服务端证书进行签名,命令:
openssl x509 -req -days 3650 -sha256 -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt

##S3) 服务端证书的验证,命令:
openssl verify -CAfile ca.crt server.crt

第四步,使用如下命令创建客户端证书的私钥和公钥证书文件:

1
2
3
4
5
6
7
8
9
10
##C1) 客户端证书生成命令:
openssl genrsa -out client.key 2048

openssl req -new -config min.cnf -key client.key -out client.csr -subj "/C=CN/ST=HuBei/L=WuHan/O=SanXian/OU=RD/CN=127.0.0.1/emailAddress=client@sanxian.site"

##C2) 根证书对客户端证书进行签名,命令:
openssl x509 -req -days 3650 -sha256 -CA ca.crt -CAkey ca.key -CAcreateserial -in client.csr -out client.crt

##C3) 客户端证书的验证,命令:
openssl verify -CAfile ca.crt client.crt

依次使用上述命令,执行过程如下图所示:

上述命令执行完毕,我们可以在当前目录看到如下文件:

双击各数字证书文件,我们查看下证书的使用者信息:

根公钥证书服务端公钥证书客户端证书

这里简单介绍一下,使用者信息中的各种简写参数的含义:

证书中的参数简写openssl命令参数含义备注
CCCountry Name (2 letter code)国家代码(2位)
SSTState or Province Name (full name)省份/州
LLLocality Name (eg, city)城市名称
OOOrganization Name (eg, company)公司/组织名称
OUOUOrganizational Unit Name (eg, section)部门名称
CNCNCommon Name (e.g. server FQDN or YOUR name)通用名称,通常是域名/个人姓名/IP地址
EemailAddressEmail Address邮箱地址

至此,使用当前方法已生成了客户端和服务端通信用的数字证书,各证书的具体的使用方法,我们将在后文介绍。

证书生成方法3:非交互模式生成证书-V3版本

第一步,将下述内容保存为文件,名称可以为openssl.cnf,后续在使用openssl命令时将使用到。

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
[req]
prompt = no
default_bits = 2048
distinguished_name = req_distinguished_name
x509_extensions = v3_ca
req_extensions = v3_req

[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alternate_names

[alternate_names]
IP.1=127.0.0.1
IP.2=::1
IP.3=::ffff:127.0.0.1
DNS.1=localhost

[v3_ca]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:TRUE, pathlen:0
keyUsage = critical, cRLSign, keyCertSign, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alternate_names

[req_distinguished_name]

第二步,使用如下命令,依次生成根证书、服务端证书、客户端证书:

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
##R1) 根证书的生成命令
openssl genrsa -out ca.key 2048

openssl req -new -config openssl.cnf -key ca.key -out ca.csr -subj "/C=CN/ST=ShanDong/L=JiNan/O=RootCA/OU=RootSign/CN=RootSignEV/emailAddress=ca@root.com"

openssl x509 -req -extfile openssl.cnf -days 3650 -sha256 -signkey ca.key -in ca.csr -out ca.crt -extensions v3_req -extensions v3_ca

##S1) 服务端证书生成命令:
openssl genrsa -out server.key 2048

openssl req -new -config openssl.cnf -key server.key -out server.csr -subj "/C=CN/ST=GuangDong/L=ShenZhen/O=Mancode/OU=MIG/CN=127.0.0.1/emailAddress=server@mancode.net"

##S2) 根证书对服务端证书进行签名,命令:
openssl x509 -req -extfile openssl.cnf -days 3650 -sha256 -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt -extensions v3_req -extensions v3_ca

##S3) 服务端证书的验证,命令:
openssl verify -CAfile ca.crt server.crt

##C1) 客户端证书生成命令:
openssl genrsa -out client.key 2048

openssl req -new -config openssl.cnf -key client.key -out client.csr -subj "/C=CN/ST=HuBei/L=WuHan/O=SanXian/OU=RD/CN=127.0.0.1/emailAddress=client@sanxian.site"

##C2) 根证书对客户端证书进行签名,命令:
openssl x509 -req -extfile openssl.cnf -days 3650 -sha256 -CA ca.crt -CAkey ca.key -CAcreateserial -in client.csr -out client.crt -extensions v3_req -extensions v3_ca

##C3) 客户端证书的验证,命令:
openssl verify -CAfile ca.crt client.crt

依次使用上述命令,执行过程如下图所示:

上述命令执行完毕,我们可以在当前目录看到如下文件:

证书生成方法4:非交互模式生成证书-基于配置文件-V3版本

第一步,将下述内容保存为:rootca.cnf

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
31
32
33
34
[req]
prompt = no
default_bits = 2048
distinguished_name = req_distinguished_name
x509_extensions = v3_ca
req_extensions = v3_req

[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alternate_names

[alternate_names]
IP.1=127.0.0.1
IP.2=::1
IP.3=::ffff:127.0.0.1
DNS.1=localhost

[v3_ca]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:TRUE, pathlen:0
keyUsage = critical, cRLSign, keyCertSign, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alternate_names

[req_distinguished_name]
C = CN
ST = ShanDong
L = JiNing
O = RootCA
OU = RootSign
CN = RootSignEV
emailAddress = ca@rootca.com

第二步,将下述内容保存为:server.cnf

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
31
32
33
34
[req]
prompt = no
default_bits = 2048
distinguished_name = req_distinguished_name
x509_extensions = v3_ca
req_extensions = v3_req

[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alternate_names

[alternate_names]
IP.1=127.0.0.1
IP.2=::1
IP.3=::ffff:127.0.0.1
DNS.1=localhost

[v3_ca]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:TRUE, pathlen:0
keyUsage = critical, cRLSign, keyCertSign, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alternate_names

[req_distinguished_name]
C = CN
ST = GuangDong
L = ShenZhen
O = Mancode
OU = MIG
CN = 127.0.0.1
emailAddress = server@mancode.net

第三步,将下述内容保存为:client.cnf

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
31
32
33
34
[req]
prompt = no
default_bits = 2048
distinguished_name = req_distinguished_name
x509_extensions = v3_ca
req_extensions = v3_req

[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alternate_names

[alternate_names]
IP.1=127.0.0.1
IP.2=::1
IP.3=::ffff:127.0.0.1
DNS.1=localhost

[v3_ca]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:TRUE, pathlen:0
keyUsage = critical, cRLSign, keyCertSign, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alternate_names

[req_distinguished_name]
C = CN
ST = HuBei
L = WuHan
O = SanXian
OU = RD
CN = 127.0.0.1
emailAddress = client@sanxian.site

第四步,使用如下命令,依次生成根证书、服务端证书、客户端证书:

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
##R1) 根证书的生成命令:
openssl genrsa -out ca.key 2048

openssl req -new -config rootca.cnf -key ca.key -out ca.csr

openssl x509 -req -extfile rootca.cnf -days 3650 -sha256 -signkey ca.key -in ca.csr -out ca.crt -extensions v3_req -extensions v3_ca

##S1) 服务端证书生成命令:
openssl genrsa -out server.key 2048

openssl req -new -config server.cnf -key server.key -out server.csr

##S2) 根证书对服务端证书进行签名,命令:
openssl x509 -req -extfile server.cnf -days 3650 -sha256 -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt -extensions v3_req -extensions v3_ca

##S3) 服务端证书的验证,命令:
openssl verify -CAfile ca.crt server.crt

##C1) 客户端证书生成命令:
openssl genrsa -out client.key 2048

openssl req -new -config client.cnf -key client.key -out client.csr

##C2) 根证书对客户端证书进行签名,命令:
openssl x509 -req -extfile client.cnf -days 3650 -sha256 -CA ca.crt -CAkey ca.key -CAcreateserial -in client.csr -out client.crt -extensions v3_req -extensions v3_ca

##C3) 客户端证书的验证,命令:
openssl verify -CAfile ca.crt client.crt

依次使用上述命令,执行过程如下图所示:

上述命令执行完毕,我们可以在当前目录看到如下文件:

双击各数字证书文件,我们查看下证书的使用者信息:

根公钥证书服务端公钥证书客户端证书