linux · 2025-04-30 0

OpenSSL创建生成CA证书、服务器证书

一、SSL认证原理

1.SSL单向认证

对于SSL单向认证:

服务器需要CA证书、server证书、server私钥,客户端需要CA证书。

认证原理:

SSL证书单向认证主要是客户端对服务器身份的验证。当客户端向服务器发起连接请求时,服务器会将自己的数字证书发送给客户端。该数字证书包含了服务器的公钥、证书颁发机构(CA)的签名、证书有效期等信息。客户端会使用预先安装在系统中的CA根证书来验证服务器证书的合法性。如果验证通过,客户端就会认为服务器的身份是可信的,然后双方开始协商加密密钥,建立安全的通信通道。

2.SSL双向认证

对于SSL双向认证:

服务器需要CA证书、server证书、server私钥,客户端需要CA证书,client证书、client私钥。

认证原理:

SSL证书双向认证不仅要求客户端验证服务器的身份,同时也要求服务器验证客户端的身份。在单向认证的基础上,增加了服务器对客户端证书的验证环节。客户端和服务器都需要拥有自己的数字证书,并且都要通过对方的证书验证。

CA证书是证书颁发机构,server证书是颁发对象

二、生成CA证书

1.生成私钥(Private Key)

openssl genrsa -out ca.key 2048

2.生成证书签名请求(CSR)

openssl req -new -key ca.key -out ca.csr -subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=MyCompany/OU=Dev/CN=Ca/emailAddress=admin@test.com"

验证签名请求信息

openssl req -in ca.csr -text -noout

3.生成自签名证书(Self-Signed Certificate)

openssl x509 -req -days 3650 -extensions v3_ca -extfile /etc/ssl/openssl.cnf -signkey ca.key -in ca.csr -out ca.crt

验证证书信息

openssl x509 -in ca.crt -text -noout

三、生成服务器证书

1.生成私钥(Private Key)

openssl genrsa -out server.key 2048

2.生成证书签名请求(CSR)

CSR(Certificate Signing Request)是包含公钥及主体信息的证书请求文件。即便是自签名证书,也推荐通过 CSR 来规范生成证书的过程。

证数各参数含义如下:

C-----国家(Country Name)
ST----省份(State or Province Name)
L----城市(Locality Name)
O----公司(Organization Name)
OU----部门(Organizational Unit Name)
CN----产品名(Common Name)
emailAddress----邮箱(Email Address)

根证书的 Common Name 可以填写 root 或者个人、单位信息
服务器端证书的 Common Name 可以填写域名或者IP或者单位
客户端证书的 Common Name 可以填写个人信息

方式一,生成不带 SAN 的 csr:

openssl req -new -key server.key -out server.csr -subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=MyCompany/OU=Dev/CN=www.test.com/emailAddress=admin@test.com"

如果生成不带 SAN 的 csr,其中 Common Name(CN) 非常重要,一般与访问域名一致。

方式二,生成带 SAN 的 csr:

server.cnf

[ req ]
default_bits = 2048
default_md = sha256
distinguished_name = req_distinguished_name
req_extensions = req_ext
prompt = no

[ req_distinguished_name ]
C = CN
ST = Zhejiang
L = Hangzhou
O = MyCompany
OU = Dev
CN = Server

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = test.com
DNS.2 = www.test.com
DNS.3 = api.test.com
IP.1 = 127.0.0.1
openssl req -new -key server.key -out server.csr -config server.cnf

验证签名请求信息

openssl req -in server.csr -text -noout

3.生成CA证书签署服务器证书

方式一,如果不带 SAN 的 csr,则生成 crt:

openssl x509 -req -days 3650 -extensions v3_req  -extfile /etc/ssl/openssl.cnf -CA  ca.crt -CAkey ca.key -CAserial ca.srl -CAcreateserial -in server.csr -out server.crt

方式二,如果带 SAN 的 csr,则生成 crt:

创建一个扩展配置文件 v3.ext

basicConstraints=CA:FALSE
subjectAltName=@alt_names
keyUsage=digitalSignature, keyEncipherment
extendedKeyUsage=serverAuth

[alt_names]
DNS.1 = test.com
DNS.2 = www.test.com
DNS.3 = api.test.com
IP.1 = 127.0.0.1
openssl x509 -req -days 3650 -extfile v3.ext -CA ca.crt -CAkey ca.key -CAserial ca.srl -CAcreateserial -in server.csr -out server.crt

验证证书信息

openssl x509 -in server.crt -text -noout

当然也可以不用CA证书签署服务器证书,可以生成自签名证书

openssl x509 -req -days 3650 -extensions v3_ca -signkey server.key -in server.csr -out server.crt

四、生成客户端证书

1.生成私钥(Private Key)

openssl genrsa -out client.key 2048

2.生成证书签名请求(CSR)

openssl req -new -key client.key -out client.csr -subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=MyCompany/OU=Dev/CN=Client/emailAddress=admin@test.com"

验证签名请求信息

openssl req -in client.csr -text -noout

3.生成CA证书签署客户端证书

openssl x509 -req -days 3650 -extensions v3_req -extfile /etc/ssl/openssl.cnf  -CA  client.crt -CAkey client.key -CAserial client.srl -CAcreateserial -in client.csr -out client.crt

验证证书信息

openssl x509 -in client.crt -text -noout

五、openssl 参数

1.- -extensions v3_ca -extfile /etc/ssl/openssl.cnf

表示要使用 /etc/ssl/openssl.cnf (ubuntu中的位置) 的 v3_ca 配置,表明是 CA 证书

/etc/ssl/openssl.cnf 的 v3_ca 部分,内容如下:

[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical,CA:true

2.-extensions v3_req -extfile /etc/ssl/openssl.cnf

表示要使用 /etc/ssl/openssl.cnf (ubuntu中的位置) 的 v3_req 配置,表明不是 CA 证书

/etc/ssl/openssl.cnf 的 v3_req 部分,内容如下:

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

3.-CAserial ca.srl -CAcreateserial

-CAserial ca.srl

1) 指定一个文件(这里是 ca.srl),该文件保存了 下一个可用的证书序列号。
2) 每次签发证书后,OpenSSL 会自动将这个序列号加一,并更新该文件。
3) 用于保证每个由 CA 签发的证书都有一个唯一序列号,这是 X.509 标准要求的。
4) 若不使用 -CAserial,默认不会自动生成或维护序列号,可能导致重复的证书序列号。

-CAcreateserial

1) 如果指定的 -CAserial 文件(如 ca.srl)不存在,则创建它并初始化为第一个序列号(通常是 01)。避免因为文件缺失而报错。

六、测试

单向认证命令行:

服务器:

openssl s_server -CAfile ca.crt -cert server.crt -key server.key -accept 22580

客户端:

openssl s_client -CAfile ca.crt -cert client.crt -key client.key -connect 127.0.0.1 -port 443

七、使用

配置单向认证

1.配置 nginx

有了 server.key 和 server.crt 文件后就可以在自己的程序中使用了, 如在 nginx 中使用

server {
    listen       443 ssl;
    server_name  www.test.com;

    charset utf-8;

    # ssl 证书的 crt 文件路径
    ssl_certificate     /etc/nginx/server.crt;
    # ssl 证书的 key 文件路径
    ssl_certificate_key /etc/nginx/server.key;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

2.访问

方式一:

在 curl 命令中,使用 --cacert 参数指定 CA 证书文件

curl --cacert ./ca.crt https://www.test.com

方式二:

ubuntu 客户端导入 CA 根证书

cp ca.crt /usr/local/share/ca-certificates/
update-ca-certificates
curl https://www.test.com

如使用自签名证书出现,且没有把证书导入 /usr/local/share/ca-certificates/,则会出现报错:

zxm@zxm-pc:~$ curl https://www.test.com
curl: (60) SSL certificate problem: self-signed certificate

如使用CA签名的证书出现,,且没有把证书导入 /usr/local/share/ca-certificates/,则会出现报错:

zxm@zxm-pc:~$ curl https://www.test.com
curl: (60) SSL certificate problem: unable to get local issuer certificate

如果 Common Name(CN)与访问的域名不一致的情况下,并且没有配置 SAN 包含指定的域名,例如 CN 配置为 test.com,则会出现报错:

zxm@zxm-pc:~$ curl https://www.test.com
curl: (60) SSL: certificate subject name 'test.com' does not match target host name 'www.test.com'

配置双向认证

有了 server.key,server.crt,ca.crt 文件后就可以在自己的程序中使用了, 如在 nginx 中使用

server {
    listen       443 ssl;
    server_name  www.test.com;

    charset utf-8;

    # 服务端证书配置
    ssl_certificate     /etc/nginx/server.crt;
    ssl_certificate_key /etc/nginx/server.key;

    # 双向认证配置
    ssl_client_certificate /etc/nginx/ca.crt;
    ssl_verify_client on;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

在 curl 命令中,使用 --cacert 参数指定 CA 证书文件,--cert 指定客户端证书,--key 指定客户端密钥

curl --cacert ./ca.crt --cert ./client.crt --key ./client.key https://www.test.com

如果没有指定 --cert 和 --key,则会出现报错:

zxm@zxm-pc:~$ curl --cacert ./ca.crt https://www.test.com
<html>
<head><title>400 No required SSL certificate was sent</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
<hr><center>nginx/1.24.0</center>
</body>
</html>