前言
在 HTTPS 协议的握手过程中,客户端除了要获取到来自服务端的公钥,还要获取到一个数字证书。公钥是用于加密加密客户端生成的会话密钥返还给服务端,是保证过程的内容隐秘性;而证书则是用于判断当前的内容确实是来自于可信的服务端,即前证明发送方的身份。
如果数字证书是可信的,那么客户端就会进行之后的握手操作(生成会话密钥返回给服务端……);若不可信,一般的浏览器都会提示你当前网站存在危险,然后让你选择是否继续访问。
之前仅仅是知道数字证书是用来验证发送方可靠的,今天就来进一步看看这到底是怎么验证的。
服务端配置证书
数字证书是由一种权威机构 Certificate Authority (CA) 所颁发的证书,就好比车管所给我发驾驶证证明我可以开车上路,公安局给我发身份证证明我就是我。网站的开发者向这类机构申请证书然后保存在网站的服务器,这样就可以在 HTTPS 的握手阶段传给客户端了。
首先,网站公司将含有自己身份信息的表单提交给 CA 机构,这些身份信息包括公钥、公司的信息、站点信息等。CA 对这类信息进行审核,若一切顺利,则 CA 对这些明文资料进行 HASH 得到信息摘要,接着用 CA 自己的私钥对摘要进行加密,得到数字签名。接着将数字签名附加在表单上,就变成了数字证书,返回给网站公司。
客户端验证证书
客户端浏览器在收到证书后,主要关注证书有效期、证书是否被吊销、证书是否是 CA 颁发的、CA 本身是否合法。
对于证书的有效期,浏览器直接用当前的时间比对证书上时间即可判断。对于证书是否被吊销,有两种方式进行验证:一是下载证书的吊销列表,通过查表判断;二是在线验证。
对于验证证书是否是 CA 颁发的,类似重复了一遍 CA 颁发证书的流程:
- 浏览器对证书中的公钥和信息部分进行 HASH 得到信息摘要。
- 浏览器使用 CA 的公钥,将数字签名解密,得到另一份信息摘要。
- 比对这两份信息摘要,对,检查内容是否被篡改比对的是内容的哈希值!
所以,实际上服务端要有两个证书,一个是当前网站的证书,一个是 CA 的证书,这两者要一同发给客户端浏览器。
CA 的合法性
虽然证书是由 CA 颁发,但是 CA 本身可能是恶意的非法机构,所以还需要保证 CA 的合法性。首先 CA 数目众多,所以全部存储起来进行查表验证不切实际,所以 CA 采用树状的结构进行组织,分为根 CA 和中间 CA。根 CA 是经过了严格的验证的,操作系统会内置这些合法的根 CA。
所以,总体的验证过程就是,从当前的 CA 沿着数字证书链,一直查找到根 CA,然后比对操作系统维护的根 CA 集合判断合法性。
数字证书 & 数字签名
这两个概念我个人容易混淆,再进行区分一下:
- 证书,包含了签名,用于提供发送方的基本信息,如公钥、网站资料
- 签名,用于验证发送方是否通过 CA 验证;由于签名使用的是非对称加密获得,所以数字签名的另一个作用就是用于判断数字证书是否被篡改。
总结一下
- 数字证书 = 网站身份信息 + 数字签名
- 数字签名 = 加密(HASH(网站信息)),也就是对摘要进行加密
- 客户端如何验证证书?
- 证书可靠性:服务端传来 CA证书、网站证书,使用 CA 公钥解密数字签名得到网站信息的 HASH;主动将网站信息进行 HASH;两者进行比对
- CA 的合法性:沿着数字证书链找到根 CA,与操作系统保存的根 CA 集合进行比对