前面两篇文章都阐述清楚了HTTPS如何加密和利用CA证书认证,第一个方法解决了内容加密传输的问题,第二个方案解决了防伪冒的问题,那么就剩下最后一个问题了,如何验证完整性,接下来开始我们的这一章的主要内容:HTTPS的哈希
哈希,键值对数据结构,通过哈希函数把一个空间映射到另一个空间。非常好用的一个工具,而且哪哪儿都有它的影子,比如负载均衡的一致性哈希、密码学中用于信息加密或数据校验的各种哈希(SHA、MD5等)、二维空间定位的GeoHash、对象相似度的SimHash等等。
HTTPS的哈希一共用在2个地方:
1 证书的数字签名
具体做法在上文证书一章节已经说过,不再赘述。在这里使用哈希的目的主要是为了减少非对称加密算法RSA在长文本上的开销。
2 对称加密的Message Digest
在数据通信阶段,SSL/TLS会对原始消息(message)做一次哈希,得到该消息message的摘要,称为消息摘要(Message Digest)。对端接受到消息后,使用协商出来的对称加密密钥解密数据包,得到原始消息message;接着也做一次相同的哈希算法得到摘要,对比发送过来的消息摘要和计算出的消息摘要是否一致,可以判断通信数据是否被篡改。
HTTPS通信流程
到此,HTTPS涉及到的关键问题基本都覆盖了。本章总结整个HTTPS的通信过程:
1. Encrypted Handshake Message
Encrypted Handshake Message作用就是确认协商出来的对称加密密钥SK的正确性,在客户端和服务端协商得到对称加密密钥SK之后,互相给对方发了一条用SK加密的消息,如果这个加密的消息被解密校验成功,那么就说明对称加密密钥SK是正确的。
2. 单向验证和双向验证
本章全部所探讨的案例都是基于单向验证,即客户端向服务端请求证书、验证服务端身份。在一些实际场景中,对安全性的要求更高,有服务端要求验证客户端的身份,即双向验证。双向验证在单向验证基础上,增加“在服务端发送证书之后,向客户端发送‘请求证书’请求,接着验证客户端身份”这个步骤。参考下图(图片出处不查):
问题:HTTPS是否需要做域名劫持?
没必要。
原因如下:https在证书校验这步,客户端除了通过对比数字签名来校验证书的有效性,还会比较证书上的域名是否与自己要访问的域名一致。因此,只要服务器的证书是可信的且客户端不跳过“证书验证”这个步骤,https能够防止域名劫持。
笔者在实际中做过防止域名劫持的工作,具体做法是:首先,客户端向可信赖的域名服务器请求域名对应的IP地址;接着,客户端用IP替换域名进行网络请求。被称为HTTPS的IP直连。但在实际中会遇到了一个问题:域名身份不对。根本解决方案是:1). 书校验时,选择自己定义的hostname进行校验;2). 证书校验前,把URL的IP替换回域名。在很多语言实现中,解决方案更为简单:在请求头部的增加host-name
字段,值填入域名即可。