服务器端将本机的公钥证书发送给客户端
客户端读取公钥证书,取出服务端公钥
客户端生成一个随机数(秘钥R),用刚才得到的服务器公钥去加密这个随机数行程秘文,发送给服务器
服务器用自己的私钥去解密这个秘文,得到秘钥R
客户端和服务端在后续的通讯过程中就是用这个秘钥R进行通信
客户端发起建立HTTPS连接请求,将SSL协议版本的信息发送给服务端
服务器端将本机的公钥证书发送给客户端
客户端读取公钥证书,取出服务端公钥
客户端将客户端公钥证书发送给服务端
服务器端解密客户端公钥证书,拿到客户端公钥
客户端发送自己支持的加密方案给服务端
服务端根据自己和客户端的能力,选择一个双方都能接受的加密方式,使用客户端的公钥加密后发送给客户端
客户端使用自己的私钥解密加密方案,生成一个随机数R,使用服务器公钥加密之后传给服务端
服务端用自己的私钥去解密这个秘文,得到秘钥R
客户端和服务端在后续的通讯过程中就是用这个秘钥R进行通信
不难发现双向认证会比单项认证更安全,当然性能肯定是不如单向
需要生成的证书文件
服务端公钥证书:server.crt
服务端私钥证书:server-privatekey.pem
客户端公钥证书:client.crt
客户端私钥证书:client-privatekey.pem
客户端集成证书(包括公钥和私钥,用于浏览器访问场景):client.p12
在开始生成这一系列证书之前,需要先生成一个CA根证书,通过这个CA根证书颁发服务器公钥和客户端公钥,假装我们是正规的CA机构(手动狗头)
创建私钥privatekey.pem
openssl genrsa -out privatekey.pem
如果不指定-out参数2048bit的私钥会直接在命令行打印
-out为存储路径
根据私钥生成一个新的证书请求文件
openssl req -key privatekey.pem -new -out ca.csr
-new 生成一个新的证书请求
-out 存储路径
-key 指定读取私钥的文件路径,这里使用了上一步中生成的私钥文件,如果不指定会先初始化一个私钥
执行该命令后根据提示完善一些信息
Country Name:国家,这里限制输入两个字符,中国是CN
State or Province Name:州或者省份
Locality Name:城市
Organization Name:组织,可以采用公司名
Organizational Unit Name:组织单位,有些ca机构没有该内容
Common Name:公用名,这里填域名,没有域名的话用服务器的ip
Email Address:邮箱,这里我回车跳过了
A challenge password:请求文件的密码,可以直接回车跳过
如果不想要在对话框中依次输入信息,可以执行下面的命令
openssl req -key privatekey.pem -new -out ca.csr -subj /C=cn/ST=guangdong/L=guangzhou/O=testcompany/OU=testdepartment/CN=test.com
创建根证书
openssl x509 -req -in ca.csr -out ca.crt -signkey privatekey.pem -CAcreateserial -days 365
x509是一个多功能的证书命令。可以用来展示证书信息、转换证书格式、像mini CA一样签名证书请求或者修改证书信任设置
-in 输入文件的读取路径
-out 输出文件的存储路径
-signkey 私钥文件路径
-CAcreateserial 避免没有CA serial number file(该文件只有一行,包含偶数个十六进制的字符)时候的报错。没有的话这里会自动创建一个。
-days 证书有效天数
生成证书私钥
openssl genrsa -out server-privatekey.pem
使用私钥生成服务器端证书的请求文件
openssl req -key server-privatekey.pem -new -out server.csr -subj /C=cn/ST=guangdong/L=guangzhou/O=testcompany/OU=testdepartment/CN=test.com
这里我直接沿用了CA证书时候的参数,不然开启SSL双向认证的时候无法正常请求
生成服务器端证书
openssl x509 -req -in server.csr -out server.crt -signkey server-privatekey.pem -CA ca.crt -CAkey privatekey.pem -CAcreateserial -days 365
大部分参数在生成CA证书的时候都有使用,这里说明一下两个之前未使用到的参数
-CA 使用的CA证书
-CAkey 使用的CA证书私钥
如果不使用SSL双向认证的话,到这里就可以了,服务端开启ssl有服务端证书server.crt和服务端证书server-privatekey.pem就够了,nginx配置如下
server { #SSL 默认访问端口号为 443 listen 9090 ssl; #请填写绑定证书的域名 #server_name cloud.tencent.com; #请填写证书文件的相对路径或绝对路径 ssl_certificate cert/server.crt; #请填写私钥文件的相对路径或绝对路径 ssl_certificate_key cert/server-privatekey.pem; # ssl_client_certificate cert/client.crt; # ssl_verify_client on; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # ... # ... }
生成客户端证书的过程基本上和生产服务端证书一致
生成客户端证书私钥
openssl genrsa -out client-privatekey.pem
使用证书私钥生成客户端证书请求文件
openssl req -key client-privatekey.pem -new -out client.csr -subj /C=cn/ST=guangdong/L=guangzhou/O=testcompany/OU=testdepartment/CN=test.com
沿用了CA证书时候的参数
生成客户端证书
openssl x509 -req -in client.csr -out client.crt -signkey client-privatekey.pem -CA ca.crt -CAkey privatekey.pem -CAcreateserial -days 365
生成p12格式的证书
openssl pkcs12 -export -clcerts -in client.crt -inkey client-privatekey.pem -out client.p12
pkcs12命令用于生成或者转换p12文件
-export 生成pkcs#12文件
-clcerts 只输出客户端证书
-in 输入文件
-inkey 私钥
-out 输出
server { #SSL 默认访问端口号为 443 listen 443 ssl; #请填写绑定证书的域名 #server_name cloud.tencent.com; #请填写证书文件的相对路径或绝对路径 ssl_certificate cert/server.crt; #请填写私钥文件的相对路径或绝对路径 ssl_certificate_key cert/server-privatekey.pem; #客户端证书 ssl_client_certificate cert/client.crt; #校验客户端证书 ssl_verify_client on; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # ... # ... }
这里开启了校验客户端证书,校验的话可以注释掉ssl_verify_client on;
到这里想要访问服务的话就必须要在客户端导入clien.p12证书,否则客户端请求的时候就会报错