使用 OPENSSL 生成CA证书及签名
环境准备
需要安装 openssl。具体安装方法见:https://www.openssl.org/source/
这里用的ubuntu16.04,自带的。
1 2
| ff@xx:~$ openssl version OpenSSL 1.0.2g 1 Mar 2016
|
实践过程
1 2 3 4 5 6 7 8 9 10
| # 生成ca密钥 openssl genrsa -out ca.key 2048 # 生成CA证书 openssl req -x509 -new -nodes -key ca.key -subj "/CN=FENG" -days 365 -out ca.crt # 把ca导出成p12格式, openssl pkcs12 -export -clcerts -in ./ca.crt -inkey ca.key -out ca.p12
# 指定p12密码的方法 # openssl pkcs12 -export -clcerts -in ./ca.crt -inkey ca.key -out ca.p12 -password pass:123123
|
1 2 3 4 5 6 7 8 9 10 11 12
| # 生成站点证书密钥 openssl genrsa -out server.key 2048 # 生成签发申请文件(csr文件) openssl req -new -key server.key -subj "/CN=yy.xx.com" -out server.csr # 用CA对上面生成的证书信息进行签名 openssl x509 -req -days 30 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt # 把服务器的证书导出成p12格式 openssl pkcs12 -export -clcerts -in ./server.crt -inkey server.key -out server.p12
# 指定密码 # openssl pkcs12 -export -clcerts -in ./server.crt -inkey server.key -out server.p12 -password pass:123123
|
这样操作这后文件会生成这8个文件
1 2 3 4 5 6 7 8 9
| ca.crt ca.key ca.p12 ca.srl server.crt server.csr server.key server.p12
|
.key
为私钥文件,以RSA PRIVATE KEY
开始和结束,也可能是.pem
后缀
.csr
为签发申请文件,包含的申请人的一些基本信息,以CERTIFICATE REQUEST
开始和结束
.crt
为证书文件,是通过密钥和基本信息加密生成的,以CERTIFICATE
开始的结束,也可能有别的后缀,如.cer
.p12
为把证书与中间证书及私钥加密放在一个文件中,为二进制文件
- 其中
.csr
文件可以用 CSR文件在线生成工具 来生成
- 关于文件格式的说明详细的可以看 格式说明这篇
实际应用
现在已有站点yy.xx.com
了server.crt
(证书文件),server.key
(私钥文件)。
于是可以在nginx上配置yy.xx.com
的https访问了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name yy.xx.com; ssl_certificate /dir/server.crt; ssl_certificate_key /dir/server.key; ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; ssl_prefer_server_ciphers on;
root /tmp/nginx/;
}
|
crul 验证
配置好之后运行
1
| curl -v https://yy.xx.com
|
发现报错unable to get local issuer certificate
1 2 3 4 5 6
| * SSL certificate problem: unable to get local issuer certificate * Closing connection 0 * TLSv1.2 (OUT), TLS alert, Client hello (1): curl: (60) SSL certificate problem: unable to get local issuer certificate More details here: https://curl.haxx.se/docs/sslcerts.html
|
正常的,因为生成的CA证书明显在不curl默认的根证书列表中的。
所以需要指定根证书,如下
1
| curl -v --cacert ca.crt https:
|
运行结果会握手成功
浏览器验证
用浏览器(以chrome为例)直接访问
会现NET::ERR_CERT_INVALID
这样的错误
也是正常的,也是因为生成根证书并不在计算机中。
现在把根证书导入到计算机中。
把crt文件拷贝到计算机中,打开,安装证书,进入证书导入向导。
第二步中(证书存储)中要选第二项,点浏览,选受信任的根证书颁发机构这一项。
最后会有一个安全警告,选是就可以了。
结果:
IE上,https访问未报错误。
chrome,换一个提示,提示NET::ERR_CERT_COMMON_NAME_INVALID
查了下,参见 主题备用名称缺失
Chrome 58 及以上版本只会使用 subjectAlternativeName 扩展程序(而不是 commonName)来匹配域名和网站证书。主题备用名称可以是域名,也可以是 IP 地址。如果证书没有正确的 subjectAlternativeName 扩展程序,系统就会向用户发送 NET::ERR_CERT_COMMON_NAME_INVALID 错误消息,告知他们连接并非处于私密状态。如果证书缺少 subjectAlternativeName 扩展程序,系统就会在 Chrome DevTools 的“安全”面板中显示警告,告知用户主题备用名称缺失。
简单来说就是签名证书的缺参数。因为这本来也是试验,这部分参书未继续探究。
参考