共计 4082 个字符,预计需要花费 11 分钟才能阅读完成。
最近开始做 Https 网络方面的工作,花时间学习了下 Https,SSL/TLS 相关的内容。把我对于 Https,SSL/TLS 的理解跟大家分享下,顺便埋个伏笔,时机成熟之后还要跟大家分享下《加解密基础知识》,因为 SSL/TLS 有很多加解密方面的知识。在技术方面,我对于我自己的要求是所到之处,必须深入理解。对于理解不透彻或者有误的地方,欢迎大家参与讨论。
概述
Https(Hyper Text Transfer Protocol over Secure Socket Layer),是一种基于 SSL/TLS 的 Http,所有的 http 数据都是在 SSL/TLS 协议封装之上传输的。Https 协议在 Http 协议的基础上,添加了 SSL/TLS 握手以及数据加密传输,也属于应用层协议。所以,研究 Https 协议原理,最终其实是研究 SSL/TLS 协议。
SSL 协议,是一种安全传输协议,最初是由 Netscape 在 1996 年发布,由于一些安全的原因 SSL v1.0 和 SSL v2.0 都没有公开,直到 1996 年的 SSL v3.0。TLS 是 SSL v3.0 的升级版,目前市面上所有的 Https 都是用的是 TLS,而不是 SSL。本文主要分析和讲解 TLS。
TLS 握手
TLS 的握手阶段是发生在 TCP 握手之后。握手实际上是一种协商的过程,对协议所必需的一些参数进行协商。TLS 握手过程分为四步,过程如下:(备注:图中加方括号的均为可选消息)
Client Hello
由于客户端 (如浏览器) 对一些加解密算法的支持程度不一样,但是在 TLS 协议传输过程中必须使用同一套加解密算法才能保证数据能够正常的加解密。在 TLS 握手阶段,客户端首先要告知服务端,自己支持哪些加密算法,所以客户端需要将本地支持的加密套件 (Cipher Suite) 的列表传送给服务端。除此之外,客户端还要产生一个随机数,这个随机数一方面需要在客户端保存,另一方面需要传送给服务端,客户端的随机数需要跟服务端产生的随机数结合起来产生后面要讲到的 Master Secret。
Server Hello
上图中,从 Server Hello 到 Server Done,有些服务端的实现是每条单独发送,有服务端实现是合并到一起发送。Sever Hello 和 Server Done 都是只有头没有内容的数据。
服务端在接收到客户端的 Client Hello 之后,服务端需要将自己的证书发送给客户端。这个证书是对于服务端的一种认证。例如,客户端收到了一个来自于称自己是 www.alipay.com 的数据,但是如何证明对方是合法的 alipay 支付宝呢?这就是证书的作用,支付宝的证书可以证明它是 alipay,而不是财付通。证书是需要申请,并由专门的数字证书认证机构 (CA) 通过非常严格的审核之后颁发的电子证书。颁发证书的同时会产生一个私钥和公钥。私钥由服务端自己保存,不可泄漏。公钥则是附带在证书的信息中,可以公开的。证书本身也附带一个证书电子签名,这个签名用来验证证书的完整性和真实性,可以防止证书被串改。另外,证书还有个有效期。
在服务端向客户端发送的证书中没有提供足够的信息的时候,还可以向客户端发送一个 Server Key Exchange。
此外,对于非常重要的保密数据,服务端还需要对客户端进行验证,以保证数据传送给了安全的合法的客户端。服务端可以向客户端发出 Cerficate Request 消息,要求客户端发送证书对客户端的合法性进行验证。
跟客户端一样,服务端也需要产生一个随机数发送给客户端。客户端和服务端都需要使用这两个随机数来产生 Master Secret。
最后服务端会发送一个 Server Hello Done 消息给客户端,表示 Server Hello 消息结束了。
Client Key Exchange
如果服务端需要对客户端进行验证,在客户端收到服务端的 Server Hello 消息之后,首先需要向服务端发送客户端的证书,让服务端来验证客户端的合法性。
在此之前的所有 TLS 握手信息都是明文传送的。在收到服务端的证书等信息之后,客户端会使用一些加密算法 (例如:RSA, Diffie-Hellman) 产生一个 48 个字节的 Key,这个 Key 叫 PreMaster Secret,很多材料上也被称作 PreMaster Key, 最终通过 Master secret 生成 session secret,session secret 就是用来对应用数据进行加解密的。PreMaster secret 属于一个保密的 Key,只要截获 PreMaster secret,就可以通过之前明文传送的随机数,最终计算出 session secret,所以 PreMaster secret 使用 RSA 非对称加密的方式,使用服务端传过来的公钥进行加密,然后传给服务端。
接着,客户端需要对服务端的证书进行检查,检查证书的完整性以及证书跟服务端域名是否吻合。
ChangeCipherSpec 是一个独立的协议,体现在数据包中就是一个字节的数据,用于告知服务端,客户端已经切换到之前协商好的加密套件的状态,准备使用之前协商好的加密套件加密数据并传输了。
在 ChangecipherSpec 传输完毕之后,客户端会使用之前协商好的加密套件和 session secret 加密一段 Finish 的数据传送给服务端,此数据是为了在正式传输应用数据之前对刚刚握手建立起来的加解密通道进行验证。
Server Finish
服务端在接收到客户端传过来的 PreMaster 加密数据之后,使用私钥对这段加密数据进行解密,并对数据进行验证,也会使用跟客户端同样的方式生成 session secret,一切准备好之后,会给客户端发送一个 ChangeCipherSpec,告知客户端已经切换到协商过的加密套件状态,准备使用加密套件和 session secret 加密数据了。之后,服务端也会使用 session secret 加密后一段 Finish 消息发送给客户端,以验证之前通过握手建立起来的加解密通道是否成功。
根据之前的握手信息,如果客户端和服务端都能对 Finish 信息进行正常加解密且消息正确的被验证,则说明握手通道已经建立成功,接下来,双方可以使用上面产生的 session secret 对数据进行加密传输了。
Secret Keys
上面的分析和讲解主要是为了突出握手的过程,所以 PreMaster secret,Master secret,session secret 都是一代而过,但是对于 Https,SSL/TLS 深入的理解和掌握,这些 Secret Keys 是非常重要的部分。所以,准备把这些 Secret Keys 抽出来单独分析和讲解。
我们先来看看这些 Secret Keys 的的生成过程以及作用流程图:
PreMaster secret
PreMaster secret 是在客户端使用 RSA 或者 Diffie-Hellman 等加密算法生成的。它将用来跟服务端和客户端在 Hello 阶段产生的随机数结合在一起生成 Master secret。在客户端使用服务单的公钥对 PreMaster secret 进行加密之后传送给服务端,服务端将使用私钥进行解密得到 PreMaster secret。也就是说服务端和客户端都有一份相同的 PreMaster secret 和随机数。
PreMaster secret 前两个字节是 TLS 的版本号,这是一个比较重要的用来核对握手数据的版本号,因为在 Client Hello 阶段,客户端会发送一份加密套件列表和当前支持的 SSL/TLS 的版本号给服务端,而且是使用明文传送的,如果握手的数据包被破解之后,攻击者很有可能串改数据包,选择一个安全性较低的加密套件和版本给服务端,从而对数据进行破解。所以,服务端需要对密文中解密出来对的 PreMaster 版本号跟之前 Client Hello 阶段的版本号进行对比,如果版本号变低,则说明被串改,则立即停止发送任何消息。
关于 PreMaster Secret(Key)的计算请参考《Htttps SSL/TLS PreMaster/Master Secret(Key)计算》。
Master secret
上面已经提到,由于服务端和客户端都有一份相同的 PreMaster secret 和随机数,这个随机数将作为后面产生 Master secret 的种子,结合 PreMaster secret,客户端和服务端将计算出同样的 Master secret。
Master secret 是有系列的 hash 值组成的,它将作为数据加解密相关的 secret 的 Key Material。Master secret 最终解析出来的数据如下:
其中,write MAC key,就是 session secret 或者说是 session key。Client write MAC key 是客户端发数据的 session secret,Server write MAC secret 是服务端发送数据的 session key。MAC(Message Authentication Code),是一个数字签名,用来验证数据的完整性,可以检测到数据是否被串改。关于 MAC 的工作原理详见 MAC。
关于 Session Secret(Key)的计算请参考《Htttps SSL/TLS Session Secret(Key)计算》。
应用数据传输
在所有的握手阶段都完成之后,就可以开始传送应用数据了。应用数据在传输之前,首先要附加上 MAC secret,然后再对这个数据包使用 write encryption key 进行加密。在服务端收到密文之后,使用 Client write encryption key 进行解密,客户端收到服务端的数据之后使用 Server write encryption key 进行解密,然后使用各自的 write MAC key 对数据的完整性包括是否被串改进行验证。
总结
讲到这里,Https 的原理,实际上是 SSL/TLS 的原理都讲解完毕,我只能说 TLS 不仅是一个安全传输协议,而且是一个艺术品。
本文永久更新链接地址:http://www.linuxidc.com/Linux/2015-07/120229.htm