在很多使用到证书的场景, 比如 HTTPS, 可以选择去申请一个免费的证书, 也可以尝试自签名证书, 申请免费证书请看:使用certbot自动申请ssl证书 或者 使用acme.sh来自动更新https证书, 本文介绍自签名证书.

SSL 协议加密方式

SSL 协议即用到了对称加密也用到了非对称加密 (公钥加密),在建立传输链路时,SSL 首先对对称加密的密钥使用公钥进行非对称加密,链路建立好之后,SSL 对传输内容使用对称加密。

  • 对称加密
    速度高,可加密内容较大,用来加密会话过程中的消息。

  • 公钥加密
    加密速度较慢,但能提供更好的身份认证技术,用来加密对称加密的密钥。

CA 证书

生成 CA 私钥

1
openssl genrsa -out ca.key 4096

生成一个 ca.key 文件

生成 CA 证书

1
openssl req -utf8 -new -x509 -days 3650 -key ca.key -out ca.crt -subj '/C=CN/ST=Shanghai/L=Pudong/O=iuxt/OU=张理坤/CN=www.i.com/emailAddress=iuxt@qq.com'
1
openssl req -utf8 -new -x509 -days 3650 -key ca.key -out ca.crt

需要交互式输入:

提示 含义 输入内容
Country Name 国家 CN
State or Province Name Shanghai
Locality Name 留空
Organization Name 组织名,公司名 iuxt
Organizational Unit Name 团体名 留空
Common Name 你的名字或域名 zhanglikun
Email Address 电子邮箱 iuxt@qq.com

就可以生成 ca.crt 文件, 这个文件需要加入到客户端的 受信任的根证书颁发机构

Server 证书

生成 server 端的私钥

1
openssl genrsa -out server.key 4096

生成 server 端数字证书请求

1
openssl req -utf8 -new -key server.key -out server.csr -subj '/C=CN/ST=Shanghai/L=Pudong/O=iuxt/OU=张理坤/CN=*.i.com/emailAddress=iuxt@qq.com'
1
openssl req -utf8 -new -key server.key -out server.csr

需要交互式输入:

提示 含义 输入内容
Country Name 国家 CN
State or Province Name Shanghai
Locality Name 留空
Organization Name 组织名,公司名 iuxt
Organizational Unit Name 团体名 留空
Common Name 你的名字或域名 这里必须写域名或者 ip
Email Address 电子邮箱 iuxt@qq.com

用 CA 私钥签发 server 的数字证书

解决 chrome 不受信任的问题

vim server.ext

1
2
3
4
5
6
7
8
9
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName=@SubjectAlternativeName

[ SubjectAlternativeName ]
DNS.1=i.com
DNS.2=*.i.com
IP.1=192.168.1.1
IP.2=192.168.1.2

在里面填写证书绑定的 IP 和域名, 支持通配符

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

生成 server.crt 证书文件

将 server 证书配置到 nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server {
listen 80;
listen [::]:80;
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate ssl/i.com.crt; # server 证书
ssl_certificate_key ssl/i.com.key; # server 私钥
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
server_name i.com;

client_max_body_size 1024m;

location / {
default_type text/plain;
return 200 "hello";
}
}

配置客户端信任 CA 证书

使用自签名的证书的域名,客户端是不信任的, 除非客户端信任对应的自签名 CA 证书。

右键 cacert.crt 选择安装证书, 放进受信任的根证书颁发机构。

windows安装CA证书

1
2
sudo cp cacert.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

然后使用 curl 等工具就受信任了。

1
2
3
sudo cp cacert.crt /etc/pki/ca-trust/source/anchors/
sudo ln -s /etc/pki/ca-trust/source/anchors/cacert.crt /etc/ssl/certs/cacert.crt
sudo update-ca-trust

然后使用 curl 等工具就受信任了。

如果只是需要 https 证书,到这里就可以了,下面的步骤是双向认证以及吊销证书需要的。


吊销证书

我是在 Ubuntu 24.04 系统下操作。不同系统可能会有差别。

生成证书吊销列表

准备一份 openssl.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
35
36
37
38
[ ca ]
default_ca = CA_default

[ CA_default ]
# 根目录设置为自定义路径
dir = ./ca

# 默认算法
default_md = sha256

# CA 的数据库文件
database = $dir/index.txt
# 证书的序列号文件
serial = $dir/serial
# 新证书的默认有效期
default_days = 365
# 吊销证书的理由
crl_reason = unspecified
# 默认的证书颁发策略
policy = policy_anything

# CRL 选项
crlnumber = $dir/crlnumber
default_crl_days = 30
crl_extensions = crl_ext

[ policy_anything ]
# 配置任何策略
countryName = optional
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ crl_ext ]
# CRL 的扩展配置
authorityKeyIdentifier = keyid:always

吊销指定证书

其他的证书都是 ca 签发的, 不管是 nginx 用的 server 证书,还是双向认证用到的 client 证书, 吊销证书后需要重新生成 crl 文件

1
2
3
4
5
6
7
8
9
10
touch ca/index.txt

# crlnumber初始化,第一次给个初始值即可,后面不需要修改,每次重新生成crl的时候会自增。
[ ! -f ca/crlnumber ] && echo "01" > ca/crlnumber

# 吊销指定证书
openssl ca -config openssl.cnf -cert ca/ca.crt -keyfile ca/ca.key -revoke ssl/i.com.crt

# 吊销完成后,重新生成吊销列表,建议定期重新生成 CRL 文件,并在 Nginx 上 reload 配置
openssl ca -config openssl.cnf -cert ca/ca.crt -keyfile ca/ca.key -gencrl -out ca/crl.pem

服务端 nginx 配置

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
server {
listen 80;
listen [::]:80;
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate ssl/i.com.crt;
ssl_certificate_key ssl/i.com.key;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
server_name i.com;

ssl_client_certificate ssl/ca.crt; # 配置 CA 证书,用于验证客户端证书的签发者
ssl_verify_client on; # 启用客户端证书验证
ssl_crl ssl/crl.pem; # 配置 CRL 文件路径,用于检查吊销的证书

client_max_body_size 1024m;

location / {
default_type text/plain;
return 200 "hello";
}
}

配置客户端 client 证书

证书生成方式和上面一样,p12 格式包含私钥和证书,所以生成完成后需要转换成 P12 格式(Windows 系统),然后导入到 Windows 系统中。

1
openssl pkcs12 -export -in zhangsan.crt -inkey zhangsan.key -out zhangsan.p12

双击导入,存储位置选择个人
image.png

访问对应网站的时候浏览器会提示让选择证书
image.png|845

这是证书被吊销的样子:
image.png|843

其他

查看证书有效期

1
openssl x509 -in cacert.crt -noout -dates