TSL 证书

TSL 证书

CA 证书

CA 证书是什么,证书的本质实际上就是 CA 用 CA 自己的私钥对服务器申请证书的时候提交的服务器的公钥、服务器的域名以及所属单位这些信息的签名进行加密,从而保证信息无法被篡改。
为什么无法被篡改,因为一旦证书内容(比如公钥,比如 IP)被篡改,重新签名之后,就会跟之前加密的签名对不上,客户端就会察觉,那我把签名也更换了不就好了,不行,因为客户端会用 CA 的公钥来对加密的签名进行解密,如果无法解密,说明这个证书不是 CA 签发的,也是无法被信任的。
CA 根据以下流程生成证书:

  1. 生成证书内容。包括:
    • 公钥(想要签发证书的申请证书的时候需要把服务器的公钥发给 CA,详细解析请看 ssh_ca#证书登录的流程
    • 申请者的身份信息(如域名)
    • 证书的有效期
    • 证书序列号等
  2. 签名证书,CA 使用自己的私钥对证书内容进行签名,生成数字签名。
    • 签名过程:使用哈希算法计算证书内容的摘要,并用 CA 的私钥加密摘要。
    • 签名验证:任何人可以使用 CA 的公钥验证签名的有效性,确保证书未被篡改。
      我们在 https#HTTPS 的通信过程 中了解过,服务端将服务器证书发送到客户端之后,客户端需要校验证书的有效性,此时就需要 CA 签发服务器证书的公钥,那客户端从哪儿获取 CA 的公钥呢?答案是客户端操作系统或浏览器中预装了信任的 CA 根证书,其中包含 CA 的公钥。这样客户端用 CA 的公钥验证服务器证书上的数字签名,确保证书是由可信 CA 签发的且未被篡改。

自签名证书

我们有时候会在浏览器地址栏上看到 https 证书不可信,意思其实就是,服务器发给客户端也就是浏览器发的证书不是来自 ca,我们无法保证这个证书不是来自于中间人攻击。
大部分的时候,尤其是在离线环境下,为了避免申请 CA 证书的麻烦,我们都会使用自签名证书。

CA 证书跟自签名证书的区别

ca 证书就是服务器把自己的公钥发到 CA 然后 CA 用自己的私钥来对你发过来的信息(包含公钥)的签名进行加密,详细过程过程请看 ssh_ca#证书登录的流程
而自签名证书就是服务器的公钥不发到 CA 了,直接就在用自己的私钥来对签名进行加密,所以叫自签名。
就是一个用哪个私钥给签名进行加密的区别,除此之外自签名证书的内容和权威 CA 签发的证书基本相同

通过 OpenSSL 进行自签名证书

参考博客 中的脚本在生成私钥的时候加了密码,其实没有必要,我们可以不对私钥进行加密。

local_ip=127.0.0.1
openssl genpkey -algorithm RSA -out private.key
echo -e "CN\nWH\nWC\nHW\nTX\n${local_ip}\n\n\n" | openssl req -new -key private.key -out ssl.csr
# 生成一个有效期为 365 天的证书
openssl x509 -req -days 365 -in ssl.csr -signkey private.key -out public.crt

第一步指定本地 IP,因为证书是跟 IP 地址绑定的
第二步则是生成密钥,这里为了方便我们就不指定密码了,不然后面只要用到了这个私钥都得输入密码,非常不方便。

openssl req 这个命令是一个交互式命令,我们先输入一个信息,点击回车之后再输入第二个信息,输入完所有信息命令就执行结束。我们为了跳过这个交互过程方便我们一键执行,我们就需要把所有的输入都通过 echo+ 管道传递给命令,但是我发现分多次 echo 没有用(即 echo "A" | echo "A" | openssl req),只能把所有的输入和回车一次 echo 给 openssl req,通过文件重定向也能实现类似的效果:openssl req < command.txt
具体跳过交互式命令,请看 用脚本实现交互式命令的输入

第三步则是准备生成证书的请求,将这些请求包装成一个文件,有点类似于填写表单。
第四步就是提交请求,生成证书。
经过上面这几步,证书文件就是 public.crt,私钥就是 private.key
通过 nginx 可以轻松为端口配置 ssl,请看 nginxTips#通过 Nginx 将 HTTP 请求变成 HTTPS,其中 ssl.crt 为 ssl_certificate,ssl.key.unsecure 为 ssl_certificate_key

客户端校验自签名证书的过程

浏览器验证自签名证书时,会依次检查以下内容:

浏览器不信任自签名证书的原因

如何为自签名证书添加信任

由于自签名证书不被浏览器默认信任,用户需要手动将其添加为可信证书,以下是具体步骤:

通过命令行请求 HTTPS

我们可以直接用 curl 的 -k 参数跳过 TSL 证书的验证