ssl证书,以 Nginx 为例
文章目录
- 1 证书概述
- 1.1 常见证书格式
- 1.2 证书的几种扩展名
- 1.3 关于 PKCS#12 格式
- 2 Nginx 下证书配置
- 2.1 证书的工作原理
- 2.1.1 单向认证
- 2.1.2 双向认证
- 2.2 CA 机构签发
- 2.2.1 免费 SSL 证书申请
- 2.2.2 双向认证
- 2.3 自签证书
- 2.3.1 单向认证
- 2.3.2 双向认证
- 附录 1:Windows 凭据
- 1.1 查看 Windows 凭据
- 1.2 cmdkey 使用
- 参考文章
1 证书概述
1.1 常见证书格式
-
1)SSL 数字证书:
- 在 HTTPS(HTTP over SSL)请求的 SSL 握手阶段,服务端以数字证书的方式将 RSA 公钥传给客户端,以保证公钥在传输过程中不被篡改。随后在通信过程中,该公钥将用于加密一个密钥,这个密钥则会对通信数据进行对称加密。
- SSL 数字证书的主要目的是用于传递服务端公钥,以及验证服务器信息。
-
2)X.509 数字证书标准,定义证书文件的结构和内容,详情参考 RFC5280。X.509 标准的证书文件具有不同的编码格式,一般有 PEM 和 DER 两种格式
-
3)PEM:Privacy Enhanced Mail,以 “-----BEGIN XXX-----” 开头,“-----END XXX-----” 结尾,内容为 Base64 编码的数据。
- (1)查看 PEM 编码的证书内容:
openssl x509 -in xxx.pem -text -noout
- (2)可以用来编码存储公钥(RSA PUBLIC KEY)、私钥(RSA PRIVATE KEY)、证书签名请求(CERTIFICATE REQUEST)等数据
- (3)Apache 和 Nginx 多使用这种编码格式
-
4)DER:Distinguished Encoding Rules,文件内为二进制编码。
- (1)查看 DER 编码的证书内容:
openssl x509 -in xxx.der -inform der -text -noout
- (2)Java 和 Windows 服务器应用偏向于使用这种编码格式
-
5)PEM 和 DER 之间的互转:
# PEM 转 DER openssl x509 -in xxx.pem -outform der -out xxx.der # DER 转 PEM openssl x509 -in xxx.der -inform der -outform pem -out xxx.pem # 要转换 KEY 文件也类似,只不过把 x509 换成 rsa ,要转 CSR 的话,把 x509 换成 req
1.2 证书的几种扩展名
-
1)常见的证书编码格式虽然有 PEM 和 DER 格式,但文件扩展名除了 .pem 和 .der 这两种外,还有 .crt、.cer、.key、.csr、.p12 等。
-
2).crt:常用于 UNIX 系统证书的后缀,可能采用 PEM 或 DER 编码,多数为 PEM 编码。
-
3).cer:常用于 Windows 系统证书的后缀,可能采用 PEM 或 DER 编码,多数为 DER 编码。
-
4).key:通常用来存放公钥或私钥,可能是 PEM 或 DER 编码。
-
5).csr:证书签名请求文件,用于服务器向证书分发机构申请证书。核心内容是公钥,生成该申请文件时,同步也会生成私钥,要自己保管好。
-
6).pfx/.p12:Predecessor of PKCS#12。UNIX 下,一般 CRT 和 KEY 分开存放到不同文件中。Windows 下则将它们存放在一个 PFX 文件(包含证书及私钥)中,且通常附带一个 “提取密码”。
# 将 PFX(DER 编码) 转换为 PEM 编码 openssl pkcs12 -in for-iis.pfx -out for-iis.pem -nodes
-
7).crl:证书吊销列表文件,用于记录已被吊销的证书。
-
8).jks:Java Key Store,使用 keytool 可以生成,也可以将 PFX 转换为 JKS。
1.3 关于 PKCS#12 格式
-
1)证书一般和密钥对一起保存,PKCS#12 格式可以将证书和密钥对打包成一个文件,并对文件进行加密保存。
-
2)PKCS#12 是公开密钥加密学的一种格式,是微软发布的一种格式,后缀一般是 .pkcs12、.pfx、.p12。
-
3)可以通过 OpenSSL pkcs12 子命令将密钥对(privkey.pem)、服务器实体证书(cert.pem)、中间证书(chain.pem) 转换成一个文件(会使用口令保护):
# 中间证书如果不存在可以不指定 openssl pkcs12 \ -export -out cert.pfx \ -inkey privkey.pem -in cert.pem -certfile chain.pem
-
4)需要使用证书时,可以从 cert.pfx 导出密钥对和证书(需要输入口令):
# 导出密钥对 openssl pkcs12 -in cert.pfx -nodes -nocerts -out new_privkey.pem # 导出服务器实体证书 openssl pkcs12 -in cert.pfx -nodes -clcerts -out new_cert.pem # 导出中间证书 openssl pkcs12 -in cert.pfx -nodes -cacerts -out new_chain.pem
2 Nginx 下证书配置
2.1 证书的工作原理
2.1.1 单向认证
-
1)单向认证(图源自网络):
-
2)服务器和 CA 机构各有一套公私钥(实际应用还有中间证书),通信前:
- (1)服务器将自己的公钥以及国家、省、市、公司、域名、邮箱 等信息发给 CA 机构请求签名。
- (2)CA 机构使用自己的私钥对服务器的这些信息进行签名,并生成证书返回给服务器。
-
3)所谓验证证书合法性,即客户端使用内置在 PC 或浏览器的 CA 机构公钥,对证书的签名进行验证(私钥加密,公钥解密),签名一致则表示服务器证书可信,进而表明证书内的服务器公钥可信。
2.1.2 双向认证
-
1)双向认证(图源自网络):
-
2)可以发现,服务端需要使用根证书的公钥解密客户端证书,从而拿到客户端公钥。即 CA 机构的根证书需要分别对服务端、客户端的证书加密。
2.2 CA 机构签发
2.2.1 免费 SSL 证书申请
-
1)由于免费的 CA 机构不会对 IP 地址签发证书,所以我们要整个域名,直接去微信搜索 “1元域名”(1 年)。
- (1)在腾讯云买到了 luyao.email 域名(可能需要一个模板去审核,耗时 1 小时)
- (2)在腾讯云的 ssl 免费证书申请页面,没有找到根据 csr(证书签名请求文件,用于服务器向证书分发机构申请证书) 申请证书的地方,所以选择阿里云来申请免费证书
-
2)生成服务器私钥与证书签名请求文件 csr:
# 生成服务器私钥 openssl genrsa -out server_private.key 2048 # 生成服务器的证书签名请求文件 server.csr,用于服务器向证书分发机构申请证书。 MSYS_NO_PATHCONV=1 \ openssl req -new -key server_private.key -out server.csr \ -subj "/C=CN/ST=Henan/L=Henan/O=luyao/OU=luyao/CN=luyao.email/emailAddress=luyaocode@outlook.com"
- 这里的 “MSYS_NO_PATHCONV=1” 用来解决使用 git bash 中 openssl 执行上述命令时,出现的 “/ 默认被认作为 git 的安装目录” 问题
-
3)把上述生成的 server.csr 文件通过 “CSR管理” 上传到阿里云(同时上传的还有 server_private.key 私钥)
-
4)在 “免费证书” 中申请证书,“选择已有的 CSR” 为我们上传的 csr 文件:
-
5)在证书申请记录的 “验证” 中按照要求配置域名的 DNS 解析记录(申请成功删除即可),等待 CA 机构审核即可(大概几分钟可接收到签发成功短信)。
-
6)下载 nginx 服务器证书,其中包括 luyao.email.key 和 luyao.email.pem。配置到 nginx:
server { listen 443 ssl; server_name luyao.email; ssl_certificate ../sslKey/luyao.email.pem; ssl_certificate_key ../sslKey/luyao.email.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; location / { root html; index index.html index.htm; } } # 自动切换 HTTP 到 HTTPS server { listen 80; server_name luyao.email; #charset koi8-r; #access_log logs/host.access.log main; # redirect HTTP to HTTPS by rewrite rewrite ^(.*)$ https://$host$1; location / { root html; index index.html index.htm; }
2.2.2 双向认证
- 1)没有找到免费可用的证书。
2.3 自签证书
2.3.1 单向认证
-
1)CA 机构:
# 生成 CA 机构私钥 openssl genrsa -out ca_private.key 2048 # 使用 CA 机构的私钥生成证书,用来签发服务器证书(“/ ”默认被认作为 git 的安装目录,MSYS_NO_PATHCONV 用来解决该问题) MSYS_NO_PATHCONV=1 \ openssl req -new -x509 -key ca_private.key -out ca.crt -days 365 \ -subj "/C=CN/ST=Henan/L=Henan/O=ca/OU=ca/CN=www.ca.com/emailAddress=ca@ca.com"
- 这里的 ca_private.key 是我们自身作为 CA 机构为所有的服务器签发证书所用的私钥。而生成的 ca.crt 则用于给服务器请求证书签名,即根证书 root.crt 。
-
2)服务器:
# 生成服务器私钥 openssl genrsa -out server_private.key 2048 # 生成服务器的证书签名请求文件 server.csr,用于服务器向证书分发机构申请证书。 MSYS_NO_PATHCONV=1 \ openssl req -new -key server_private.key -out server.csr \ -subj "/C=CN/ST=Henan/L=Henan/O=server/OU=server/CN=server.com/emailAddress=server@server.com"
-
3)将服务器的证书签名请求文件 server.csr 发送给 CA 机构,由其对该证书进行签名:
# 被 CA 机构签名后的证书文件 server.crt openssl x509 -req -days 365 -CA ca.crt -CAkey ca_private.key -CAcreateserial \ -in server.csr -out server.crt
-
4)配置到 Nginx:
server { listen 443 ssl; server_name localhost; ssl_certificate ../sslKey/server.crt; ssl_certificate_key ../sslKey/server_private.key; ...... }
2.3.2 双向认证
- 1)双向认证
# (1)CA 机构
# CA 私钥
openssl genrsa -out ca_private.key 2048
# CA 根证书
MSYS_NO_PATHCONV=1 \
openssl req -new -x509 \
-key ca_private.key \
-out ca_root.crt \
-days 365 \
-subj /C=CN/ST=Henan/L=Henan/O=ca/OU=ca/CN=ca.com/emailAddress=ca@ca.com
# (2)服务器
# 服务器私钥
openssl genrsa -out server_private.key 2048
# 服务器请求证书
MSYS_NO_PATHCONV=1 \
openssl req -new \
-key server_private.key \
-out server.csr \
-subj /C=CN/ST=Henan/L=Henan/O=server/OU=server/CN=luyao.email/emailAddress=server@server.com
# CA 机构根据服务器请求证书生成服务器证书
openssl x509 -req \
-days 365 \
-CA ca_root.crt \
-CAkey ca_private.key \
-CAcreateserial \
-in server.csr \
-out server.crt
# (3)客户端
# 客户端 1 私钥
openssl genrsa -out client1_private.key 2048
# 客户端 1 请求证书
MSYS_NO_PATHCONV=1 \
openssl req -new \
-key client1_private.key \
-out client1.csr \
-subj /C=CN/ST=Henan/L=Henan/O=client/OU=client/CN=luyao.email/emailAddress=client@client.com
# CA 机构根据客户端请求证书生成客户端证书
openssl x509 -req \
-days 365 \
-CA ca_root.crt \
-CAkey ca_private.key \
-CAcreateserial \
-in client1.csr \
-out client1.crt
# 客户端 2 私钥
openssl genrsa -out client2_private.key 2048
# 客户端 2 请求证书
MSYS_NO_PATHCONV=1 \
openssl req -new \
-key client2_private.key \
-out client2.csr \
-subj /C=CN/ST=Henan/L=Henan/O=client/OU=client/CN=luyao.email/emailAddress=client@client.com
# CA 机构根据客户端请求证书生成客户端证书
openssl x509 -req \
-days 365 \
-CA ca_root.crt \
-CAkey ca_private.key \
-CAcreateserial \
-in client2.csr \
-out client2.crt
- 4)配置到 Nginx:
server {
listen 10443 ssl;
server_name localhost;
ssl_certificate ../sslKey/server.crt;
ssl_certificate_key ../sslKey/server_private.key;
ssl_client_certificate ../sslKey/ca_root.crt;
ssl_verify_client on;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
- 5)测试:
curl --cert client.crt --key client_private.key --cacert server.crt https://luyao.email:10443
附录 1:Windows 凭据
1.1 查看 Windows 凭据
-
(1) 图形化界面查看:
- “Win + R” 后输入 “control” 回车,“用户账户” -> “凭据处理器” -> “管理 Windows 凭据”
- “Win + R” 后输入 “control” 回车,“用户账户” -> “凭据处理器” -> “管理 Windows 凭据”
-
(2) 命令查看:
cmdkey /list
1.2 cmdkey 使用
-
(1) 先看一下使用说明
PS C:\Windows\system32> cmdkey 创建,显示和删除保存的用户名和密码。 此命令的语法为: CMDKEY [{/add | /generic}:targetname {/smartcard | /user:username {/pass{:password}}} | /delete{:targetname | /ras} | /list{:targetname}] 示例: 要列出可用的凭据: cmdkey /list cmdkey /list:targetname 要创建域凭据: cmdkey /add:targetname /user:username /pass:password cmdkey /add:targetname /user:username /pass cmdkey /add:targetname /user:username cmdkey /add:targetname /smartcard 要创建普通凭据: /add 开关可以由 /generic 替代,来创建普通凭据 要删除现有凭据: cmdkey /delete:targetname 要删除 RAS 凭据: cmdkey /delete /ras
-
(2) 整理:
# 查看 cmdkey /list cmdkey /list:targetname # 这里的 targetname 支持正则,如 git* 可以列出所有目标以 git 开头的凭据 # 删除 cmdkey /delete:git:http://xxx.com # 添加 cmdkey /generic:git:http://xxx.com /user:licong /pass:Passw0rd
参考文章
- https://www.cnblogs.com/guogangj/p/4118605.html
- https://blog.csdn.net/u011001084/article/details/54708258
- https://blog.csdn.net/as3luyuan123/article/details/13709923
- https://help.aliyun.com/zh/api-gateway/user-guide/mutual-tls-authentication