HTTPS (HyperText Transfer Protocol over SecureSocket Layer,基于 SSL 的超文本传输与协议),是以安全为目标的 HTTP 通道,在 HTTP 的基础上通过身份认证传输加密保证了传输过程的安全性。HTTPS 在 HTTP 的基础下加入 SSL/TLS(Transport Layer Security,传输层安全协议),HTTPS 的安全基础是 SSL/TLS,因此加密的详细内容就需要 SSL/TLS。 HTTPS(443 端口) 存在不同于 HTTP(80 端口) 的默认端口及一个传输加密 / 身份认证层(在 HTTP 与 TCP 之间)。这个系统提供了身份验证与加密通讯方法。它被广泛用于万维网上安全敏感的通讯,例如交易支付等方面。

加密算法

作为前置知识,先来了解一下两种常用的加密方式:

  1. 对称加密:加密和解密使用相同的秘钥,加密算法是公开的,秘钥是绝对保密的。

  2. 非对称加密:加密和解密使用不同的秘钥,加密算法是公开的,公钥是也是公开的,私钥是绝对保密的。

HTTPS 在数字证书验证的时候,采用的 RSA(三个发明者的首字母缩写) 密码算法就是一种非对称加密。这种非对称加密算法最大的特点是,通过公钥加密的密文只有对应的私钥才能解密,同样通过私钥加密的密文也只有对应的公钥才能解密,即公钥和私钥互相解密。下面我们将会讲到 HTTPS 是如何通过 RSA 这种密码算法去验证身份的。

数字证书

数字证书(Digital Certificate)是 HTTPS 实现安全传输的基础,它是由权威的 CA(Certificate Authority,证书认证) 机构颁发的,证书的主要内容有:签名算法(Certificate Signature Algorithm)、颁发者(Issuer)、有效期(Validity)、使用者(Subject)、公钥(Public Key)、指纹(Fingerprint)及指纹算法(Fingerprint Algorithm)。

知名的网站都会向权威 CA 机构申请 SSL 数字证书,以增强网站安全性、防止钓鱼网站、提高用户信任度、获得更高的搜索排名。下面以 Edge 浏览器为例,先来看一下数字证书长啥样,之后再解析数字证书是如何进行安全认证的。

  1. 点击网址前面的小锁图标,然后选择连接安全:
    HTTPS 数字证书认证_数字证书

如果小锁是打开的,表示该网站没有启用 HTTPS 访问或者数字证书不被信任。

  1. 点击证书图标,打开证书对话框:
    HTTPS 数字证书认证_证书_02
    如下,显示的是证书概览信息:
    HTTPS 数字证书认证_HTTPS_03

  2. 点击证书路径,双击证书即可查看详情:
    HTTPS 数字证书认证_证书_04
    可以看到证书链:权威 CA 机构的根证书(DigiCert)->中继证书(Encryption Everywhere)->博客园网站证书(*.cnblogs.com)。

  3. 点击详细信息:
    HTTPS 数字证书认证_加密算法_05
    可以看到签名算法、签名哈希算法(指纹算法)、颁发者、有效期、使用者、公钥(RSA 2048 Bits)。还有一个指纹在最下面,就不截图了,它是用来保证数字证书的完整性的,后面会说到。

既然证书都是由权威的 CA 机构颁发的,那么 CA 机构的证书是由谁颁发的呢?聪明的你可能已经想到,是 CA 机构自己给自己颁发的,也就是我们上面说的根证书。

再思考一个问题,每次进行证书校验的时候,都需要向 CA 机构申请它的根证书么?当然不是了,由于 CA 机构的根证书一般都是 20 年以上的有效期,所以将其内置到浏览器中,就不用每次都向 CA 机构获取根证书了。以 Edge 为例,查看浏览器内置的根证书步骤如下:
打开设置,搜索证书:
HTTPS 数字证书认证_加密算法_06
可以看到我们导入的证书,包括内置的根证书:
HTTPS 数字证书认证_数字证书_07

证书的完整性

在上面博客园的证书中可以看到有一个叫指纹的字符串,指纹可以理解为证书身份的唯一代表,是用来保证证书的完整性(Integrity)的,即证书没有被修改过。证书在发布之前,CA 机构对证书的内容用指纹算法(一般是 SHA1 或 SHA256)计算得到一个 hash 值,这个 hash 值就是指纹。为什么用 hash 值作为证书的身份代表呢?

  1. hash 值具有不可逆性,也就是说无法通过 hash 值得出原来的信息内容;
  2. hash 值具有唯一性,即 hash 计算可以保证不同的内容一定得到不同的 hash 值(其实哈希算法存在哈希碰撞的可能性,但是 SHA1 的 hash 值有 160 位,碰撞概率很小,可以忽略不计)。

签名是在信息后面加上的一段数字串,可以证明该信息有没有被修改过。数字证书在发布的时候,CA 机构将证书的指纹和指纹算法通过自己的私钥加密得到的就是证书的签名了

证书的验证

下面基于一个简单的图例,去分析 HTTPS 的数字证书的验证过程(具体的过程请参考文末博客):

  1. 我们访问 HTTPS 网址,浏览器向服务器发送 HTTPS 请求(包含对称加密算法套件)来建立连接,服务器收到 HTTPS 请求后,给浏览器返回选择的对称加密算法和自己的证书

  2. 浏览器接收到证书以后,就要开始进行身份认证工作了。首先从证书中得知证书的颁发机构,然后从浏览器系统中去寻找此颁发机构的根证书:

  • 若能找到根证书,则从根证书中取得那个根公钥,用根公钥去解密此证书的数字签名(根私钥加密的),成功解密的话就得到证书的指纹(记为 h1,代表根证书的原始内容)和指纹算法;然后用指纹算法对当前接收到的证书内容再进行一次 hash 计算得到另一个值 h2,代表当前证书的内容,如果此时 h2 和 h1 是相等的,就代表证书没有被修改过。
  • 若不能找到根证书,则代表此机构不是受信任的,那么就会警告无法确认证书的真假(小锁图标不是闭合的)。
  1. 在证书没有被修篡改的基础上,再检查证书上的使用者的 URL(比如 cnblogs.com)和我们请求的 URL 是否相等,如果相等,那么就可以证明当前浏览器地址栏的网址也是正确的,而不是一些钓鱼网站之类的。
    到这里我们认证了三点信息:

    1. 证书是否为受信任的权威机构颁发的;
    2. 证书是否被第三方篡改过;
    3. 证书是否为服务器发送的。
  2. 对称加密算法相关参数互相传递后,双方都能根据自己和对方的参数生成一个相同的对称加密秘钥,然后就可以进行加密通信了。

总结

数字证书的验证有两个重要的步骤:

  1. 客户端验证服务器发的数字证书有没有被篡改,以及没有被篡改的证书是否为服务器发的证书,而不是任何第三方假冒服务器发的证书;
  2. 客户端将对称加密算法的参数安全地发送给服务器。

这两步都完成以后,整个 HTTPS 的数字证书验证就算是成功了。

一般情况下只需要客户端(浏览器)认证服务器端,即单向认证,相对的还有一个双向认证。双向认证,顾名思义,客户端和服务器端都需要验证对方的身份,在建立 HTTPS 连接的过程中,握手的流程比单向认证多了几步。单向认证的过程,客户端从服务器端下载服务器端公钥证书进行验证,然后建立安全通信通道。双向通信流程,客户端除了需要从服务器端下载服务器的公钥证书进行验证外,还需要把客户端的公钥证书上传到服务器端给服务器端进行验证,等双方都认证通过了,才开始建立安全通信通道进行数据传输。

参考

HTTPS 的数字证书验证原理
HTTPS 协议、TLS 协议、证书认证过程解析