一、背景
现在大多数的网站都升级为https协议了,包括百度、知乎等,当然还包括对安全性要求高的支付业务和银行业务都是用https。https相对于http的劣势是,https建立连接需要多次握手,而且还要进行RSA加密解密,这是个耗时的过程,那么为什么对安全性要求不高的网站也升级为https。那是因为http是用明文传输,在传输过程中,我们的信息可能会被篡改,或者会被第三方截取插入一些别的信息,比如说广告植入,这严重影响了用户体验。
既然要升级为https协议,那就很有必要知道https的原理是什么,https是怎么保证信息只有通信双方能解析而不被第三方截获导致信息被窃取、篡改。
二、https验证原理
2.1 原理图
下面是一张https建立连接的原理图,下面会对每一步进行说明。
2.2 https建立连接过程
2.2.1 客户端访问https连接
这一步,就是相当于我们在浏览器上输入url回车的过程。这个时候浏览器或者客户端(接下来统一为客户端)会把我们客户端支持的加密算法Cipher Suite(密钥算法套件)带给服务端。
2.2.2 - 2.2.3 服务端发送证书(公钥)给客户端
服务端接收Cipher后,和自己支持的加密算法进行比对,如果不符合,则断开连接。否则,服务端会把符合的算法和证书发给客户端,包括证书时间、证书日期、证书颁发的机构。
2.2.4- 2.2.5 客户端验证服务端的证书
1、客户端验证证书,包括颁发证书的机构是否合法与是否过期,证书中包含的网站地址是否与正在访问的地址一致等
2、验证通过后(或者用户接受了不信任的证书),客户端会生成一个随机字符串,然后用服务端的公钥进行加密。这里就保证了只有服务端才能看到这串随机字符串(因为服务端拥有公钥对应的私钥,RSA解密,可以知道客户端的随机字符串)。
3、生成握手信息 用约定好的HASH算法,对握手信息进行取HASH,然后用随机字符串加密握手信息和握手信息的签名HASH值,把结果发给服务端。这里之所以要带上握手信息的HASH是因为,防止信息被篡改。如果信息被篡改,那么服务端接收到信息进行HASH时,就会发现HASH值和客户端传回来的不一样。这里就保证了信息不会被篡改。
2.2.6 - 2.2.7 服务端接收加密信息,解密得到客户端提供的随机字符串
服务端接收到加密信息后,首先用私钥解密得到随机字符串。然后用随机字符串解密握手信息,获得握手信息和握手信息的HASH值,服务端对握手信息进行HASH,比对客户端传回来的HASH。如果相同,则说明信息没有被篡改。
服务端验证完客户端的信息以后,同样使用随机字符串加密握手信息和握手信息的HASH值发给客户端。
2.2.8 客户端验证服务端返回的握手信息,完成握手
客户端接收到服务端发回来的握手信息后,用一开始生成的随机字符串对密文进行解密,得到握手信息和握手信息的HASH值,像一步服务端验证一样对握手信息进行校验,校验通过后,握手完毕。从这里开始,客户端和服务端的通信就使用那串随机字符串进行AES对称加密通信。
2.3 验证总结
使用RSA非对称算法,服务端向客户端发送公钥,公钥包含了域名、颁发机构、过期日期。保证了公钥的合法性和服务端的身份正确性(而不会被黑客冒充)
客户端向第三方验证公钥的合法性,验证通过后向服务端约定对称加密的随机字符号。保证了随机字符串只有通信双方知道。
接下来的通信就使用这个随机字符号进行加密通信。因为随机字符串只有双方知道,所以信息不会被截获。
三、客户端验证证书的合法性
为了验证证书的合法性,首先客户端要知道一些合法的证书机构,这就是我们所说的根证书。而根证书会保存在用户的浏览器或者其它客户端,像jdk的根证书列表。
当然证书不可能只有几个机构进行颁发的,所以证书的颁发是一级一级的。客户端在验证证书也是一级一级往下验证。下面是阿里的证书:
最顶级的VeriSign Class 3 Public Primary Certification Authori... 就是根证书了, 这个证书一般会保存在客户端,在客户端安装时就有一组根证书了,如果服务端根证书在客户端的信任列表中,那么就会向根证书验证二级证书的合法性,然后再向二级证书机构验证三级证书的合法性,以此类推。