1.SSL整体框图
SSL协议是应用层次(http协议)和TCP层级的一个可选的位置,可以从下面的图中非常清楚看到该层次:
绿色的框图就是这个SSL./TLS的位置,最右面的SSL/TLS图可以进一步的抽象为下面的图:
SSL Record Protocol: 记录协议,给上层的各种协议提供一些方法支撑。
SSL Handshake Protocol: 握手协议,在普通的socket的TCP/IP的三次握手的前提之上,又加了SSL的四次握手的过程。
SSL Change Cipher Spec Protocol:密码套件规范交换协议,在SSL握手的最后一步,使用这个协议。
SSL Alert Protocol:警告协议,当SSL握手或者传输过程中,出现错误的时候,使用这个协议。
上述的四个协议,梯次配合,共同给TCP/IP上了一把安全锁。
2.握手协议概述
SSL的握手协议在以前的文章中重点分析过,一共分为四个过程:
第一阶段:双方互相hello,展示出双方支持的密钥支持等一些限制信息。
第二阶段:服务器端推动证书,服务器端根据策略选择的加密策略,证书请求(如果是双向认证的话),serverHelloDone消息;
第三阶段:客户端接收证书,基于策略确实服务器的加密策略,证书校验(一些耗时的delegate操作,如CRL),证书发送*(如果双向认证);
第四阶段:客户端和服务器端,进行密钥规范交换协议,并将加密解密等算法套件设置到通道中(实际上这一步后SSLSession就生成了);
四个阶段完成后,整个SSL通道成功建立,到这一步为止,双方就可以利用SSL通道的机制,进行传输数据了,再传输的数据的过程中,会用到记录协议,这个后面会详细的讲解。
因为前面的文章已经重点分析过,这里只针对握手协议中比较重要的几个点进行再次强调一下:
a.密码套件的支持
我们在tomcat调试的源码的过程中,发现其SSL提供的密码套件有一个固定的格式,如下面的格式:
Tomcat默认支持了160多种格式,这些字段是通过_来进行分割的:
b.重用一个SSL会话
其次,上面已经提到了SSLSession,在SUN的JSSE的包中,已经抽象了这个SSLSession,它的实现内容就在SUN的包中。
与其对应的是SSLConnection,这个在JSSE包中对应的就是HttpsConnection。
多个HttpsConnection可以共享一个SSLSession,而这个重用的过程就是共享一个会话。
我们来看看基于这种重用,究竟会省略掉握手协议的哪一个部分:
通过上图,可以发现,握手协议中比较重要,并且比较耗时的密码协商,发送的证书,甚至客户端最耗时的delegate(CRL校验)等全部没有了,双发直接来回一个hello。、
在hello信息中,其中的一位就是SessionID的信息:
以上述的C语言的实现为例,当这个id为空的时候,说明肯定是一个新会话,如果这个id已经有值了,那么就会走上述的这样的一个流程。
3.密码交换协议
密码交换协议主要用于握手协议的最后一步中,其实这个协议的数据包就是一个字节:
主要的作用就是告知服务器端和客户端,双方密码套件已经设置到通道中了(实际上这个时候SSLSession就已经建立了,可以通过SSLSession拿到密码套件了)。
这个相当于一个标识为,告知下一步双方可以发送数据了,这条消息会改变双方的读写模式,为正式进入下一个SSL传输的阶段打好前哨。
4.警告协议
警告协议也很好理解,当SSL交互的过程中出现问题的时候,会调用这个协议,对双方进行通知,SSLSession,SSLConnection的断开等等操作,这个规范就是警告协议。
可以看到的是,警告协议也就是2个标识位,多了一个。
第一个标识位是level,和咱们在业务中定义的log4j的日志非常的像;
第二个是alert消息,这个alert消息按理来说,应该是任意多的byte的,但是由于字节的限制,仅仅就是1个byte就搞定了,那么这里面需要预定义一些消息:
当SSL出现问题的时候,双方交互的告警消息就是按照这个格式来做的,这也就构成了告警协议。
5.记录协议
从前面的框图来看,其实记录协议是一个底层的协议。
记录协议的触发是在客户机和服务器握手成功后使用,即客户机和服务器鉴别对方和确定安全信息交换使用的算法后,开始进行传入阶段,即进入记录协议。
记录协议向连接提供两个服务:
(1)保密性:使用握手协议定义的秘密密钥实现
(2)完整性:握手协议定义了MAC,用于保证消息完整性、
我们分解一下在SSL信道建立后,传输一个数据包,内容为abcdefghi,它并不会在信道中直接传abcdefghi,而是会进行下面的好几道的工序的组装:
第一步、fragmentation(分段)
记录层将上层数据分为小于214字节大小的块,或者更小。由于记录层是多层结构,因此不同的TLS记录层内容类型的数据可能会交错。
第二步、compression(压缩){可选}
当前连接会话中如果定义了压缩算法,则需要对片段进行压缩。压缩必须为无损压缩,不能将内容长度增加超过1024字节。
第三步、计算消息认证码(MAC)
根据RFC2104定义的HMAC算法(TLS1.2改为HMAC-SHA256),计算出MAC值。并将其添加在(压缩后)分段的片段后。
第四步、encryption(加密)
采用CBC模式,然后根据握手阶段cipher spec指定的算法对分段块进行加密。
什么是CBC模式?
密码分组链接(CBC,Cipher-block
chaining)模式。在CBC模式中,每个明文块先与前一个密文块进行异或后,再进行加密。在这种方法中,每个密文块都依赖于它前面的所有明文块。同时,为了保证每条消息的唯一性,在第一个块中需要使用初始化向量。
CBC是最为常用的工作模式。它的主要缺点在于加密过程是串行的,无法被并行化,而且消息必须被填充到块大小的整数倍。解决后一个问题的一种方法是利用密文窃取。
注意在加密时,明文中的微小改变会导致其后的全部密文块发生改变,而在解密时,从两个邻接的密文块中即可得到一个明文块。因此,解密过程可以被并行化,而解密时,密文中一位的改变只会导致其对应的明文块完全改变和下一个明文块中对应位发生改变,不会影响到其它平文的内容。
第五步、添加SSL记录头
消息头包括上层协议类型、主次版本以及加密后密文以及MAC的长度。也就是SSL的服务器和客户端两端交互消息的格式,其实都是用这个记录协议进行封装的。
从记录协议可以看出,SSL信道的传输的数据也是极难被破解的。
6.TLS协议改进
a.TLS与SSL的差异
- 版本号:TLS记录格式与SSL记录格式相同,但版本号的值不同,TLS的版本1.0使用的版本号为SSLv3.1。
- 报文鉴别码:SSLv3.0和TLS的MAC算法及MAC计算的范围不同。TLS使用了RFC-2104定义的HMAC算法。SSLv3.0使用了相似的算法,两者差别在于SSLv3.0中,填充字节与密钥之间采用的是连接运算,而HMAC算法采用的是异或运算。但是两者的安全程度是相同的。
- 伪随机函数:TLS使用了称为PRF的伪随机函数来将密钥扩展成数据块,是更安全的方式。
- 报警代码:TLS支持几乎所有的SSLv3.0报警代码,而且TLS还补充定义了很多报警代码,如解密失败(decryption_failed)、记录溢出(record_overflow)、未知CA(unknown_ca)、拒绝访问(access_denied)等。
- 密文族和客户证书:SSLv3.0和TLS存在少量差别,即TLS不支持Fortezza密钥交换、加密算法和客户证书。
- certificate_verify和finished消息:SSLv3.0和TLS在用certificate_verify和finished消息计算MD5和SHA-1散列码时,计算的输入有少许差别,但安全性相当。
- 加密计算:TLS与SSLv3.0在计算主密值(master secret)时采用的方式不同。
- 填充:用户数据加密之前需要增加的填充字节。在SSL中,填充后的数据长度要达到密文块长度的最小整数倍。而在TLS中,填充后的数据长度可以是密文块长度的任意整数倍(但填充的最大长度为255字节),这种方式可以防止基于对报文长度进行分析的攻击。
b.TLS的主要增强内容
TLS的主要目标是使SSL更安全,并使协议的规范更精确和完善。TLS 在SSL v3.0 的基础上,提供了以下增强内容:
- 更安全的MAC算法
- 更严密的警报
- “灰色区域”规范的更明确的定义
c.TLS对于安全性的改进
- 对于消息认证使用密钥散列法:TLS 使用“消息认证代码的密钥散列法”(HMAC),当记录在开放的网络(如因特网)上传送时,该代码确保记录不会被变更。SSLv3.0还提供键控消息认证,但HMAC比SSLv3.0使用的(消息认证代码)MAC 功能更安全。
- 增强的伪随机功能(PRF):PRF生成密钥数据。在TLS中,HMAC定义PRF。PRF使用两种散列算法保证其安全性。如果任一算法暴露了,只要第二种算法未暴露,则数据仍然是安全的。
- 改进的已完成消息验证:TLS和SSLv3.0都对两个端点提供已完成的消息,该消息认证交换的消息没有被变更。然而,TLS将此已完成消息基于PRF和HMAC值之上,这也比SSLv3.0更安全。
- 一致证书处理:与SSLv3.0不同,TLS试图指定必须在TLS之间实现交换的证书类型。
- 特定警报消息:TLS提供更多的特定和附加警报,以指示任一会话端点检测到的问题。TLS还对何时应该发送某些警报进行记录。