TCP 层安全:SSL / TLS
一次性进群,长期免费索取教程,没有付费教程。
教程列表见微信公众号底部菜单
进微信群回复公众号:微信群;QQ群:16004488
微信公众号:计算机与网络安全
ID:Computer-network
一、SSL操作
SSL(Secure Socket Layer)是Netscape公司设计的一个的安全传输协议,可以在TCP之上建立一个加密通道。这种协议在 Web上获得了广泛的应用。随着 SSL的不断流行,IETF介入到其中将SSL进行了标准化,即RFC 2246,并将其称为TLS(Transport Layer Security),事实上,TLS1.0与SSL3.0的差别非常微小。
SSL相当复杂,提供了很多选项和变种。我们将从最简单的例子来研究SSL:建立一个加密通道。然后再考虑更复杂的情形:包括认证对方,将加密和认证分开,重新开始一个以前的会话。通过这些例子来对SSL的大致功能建立一个初步印象。
SSL协议中定义了两种角色,一种是客户,另外一种是服务器,这一区分十分重要,这是因为在SSL中,二者表现十分不同。客户发起连接,而服务器响应连接请求,一般情况下,如WWW浏览中,WWW浏览器是客户而网站是服务器。其他使用SSL的也是如此。对于SSL本身,客户和服务器间最重要的区别是它们在协商安全参数时的不同。由于客户发起连接,它有责任提出一系列选项,而服务器则从这些选项中选择一些作为最后使用的选项。尽管服务器具有最后决定权,但是它只能在客户提出的选项中选择。
SSL依靠客户和服务器之间的报文交换来进行通信。SSL定义了各种层次的报文。表1列出了协议中各层使用的报文,下面将阐述如何使用这些报文进行通信。
表1 SSL报文
1、建立安全通信
SSL客户和服务器所进行的最基本功能就是建立一个加密通道。图1显示了这一操作所需要SSL报文交换,表2总结了图中的各步。
图1 建立安全通信所需要的SSL报文交换
表2 加密通道协商
(1)ClientHello
ClientHello报文是最开始使用的报文,客户端使用这个报文向服务器要求开始协商。表3列出了这一报文中重要的组成部分。
表3 ClientHello组成部分
Version域用来标识客户所支持的最高SSL版本,目前SSL的最高版本是3.0,TLS一般设置为3.1,注意,服务器可能认为客户会支持所有低于此版本的 SSL协议,比如说,如果客户发送的ClientHello中Version为3.0,而服务器只支持2.0的SSL协议,那么将会用2.0的协议报文去回答,这时客户端将选择是继续会话还是终止会话。
RandomNumber域包含了一个随机数,这个随机数和服务器端产生的一个随机数一起,用于进行随后的一些重要密码学运算。在SSL的实现建议中,建议这个随机数中的4个字节由时间和日期组成,时间和日期并不要求精确,因为它们并不用于计时,只是为了避免产生两个相同的随机数,从而被第三方进行重放攻击。这个值中剩下的28字节,要求是在密码学中安全的随机数。安全性并不总是产生的随机数的要求,但在SSL中随机数的安全性十分重要。在很多计算机系统中,随机数是用一种叫做“伪随机数”的算法产生的,这种算法虽然能够产生看似随机的数值,但有很大的安全问题,如果攻击者知道所用的算法和一些随机值,那么他可以准确地预测出之后的所有随机数,这样可能会导致系统被攻击。因此SSL中建议使用安全的方法来产生随机数。
SessionID用来标识这一安全会话。
客户使用CipherSuite域来列出自己所支持的各个密码参数,包括算法类型和密钥长度。服务器可以从这个列表中选择用在本会话中的参数。
CompresseionMethod域用来表示数据压缩的格式,目前SSL中还没有这方面的参数说明,因此,这个域的使用有限。
(2)ServerHello
在服务器接到ClientHello报文之后,回应以ServerHello报文,如表4所示,ServerHello报文的格式与ClientHello格式类似,ServerHello用来决定最后所用的密码学参数。
表4 ServerHello组成部分
服务器用版本域来标识最后会话所用的SSL版本,这与客户端的Version域不同。对于客户端,Version域说明了客户端所支持的最高SSL版本,而ServerHello中的Version域则说明了服务器最后决定用于本次会话的SSL版本,服务器所决定的版本不应当高于客户端所标识的最高支持的版本号。客户端收到ServerHello报文后,如果不支持服务器的选择,则可以断开这次会话。
RandomNumber域包含了一个随机数,它与ClientHello中的组成相同,其中的4个字节由时间和日期组成,另外28个字节是服务器产生的安全的随机数。
SessionID用来标识这一安全会话。
CipherSuite域用来定义本次会话中所使用的算法和密钥长度。
CompresseionMethod域用来表示数据压缩的格式,目前SSL中还没有这方面的参数说明。
(3)ServerKeyExchange
ServerKeyExchange报文包含服务器本身的公钥,具体的格式因公钥体制的不同而不同,这一信息的明文传输使得不能够将会话密钥放在这一报文中。
(4)ServerHelloDone
这一报文告诉客户端服务器已经完成了开始的协商过程,这一报文主要的意义在于,客户端在收到这一报文之后,就可以开始着手建立安全连接了。
(5)ClientKeyExchange
协商结束后,客户端使用这个消息告诉服务器自己的会话密钥。在这一消息中,会话密钥用服务器的公钥进行加密,一方面,避免了会话密钥被监听,另外一方面也可以验证服务器是否拥有相应的私钥。这样,就避免了攻击者冒充服务器,然后将攻击者的公钥发送给客户端这种可能。
(6)ChangeCipherSpec
在客户发出 ClientKeyExchange 报文后,双方就开始使用这些参数进行会话了。SSL 定义了ChangeCipherSpec报文用来明确地指定自己所使用的参数。
定义这个报文,首先是由于建立安全通道的转变点十分关键,所以双方必须明确自己所用的参数。这些参数包括所用的算法、密钥长度、所用的密钥等信息。另外,由于SSL中允许客户和服务器所用的会话密钥不同,也就是说,服务器发往客户端的数据与客户端发往服务器的数据加密密钥不同,因此,需要用这个报文来进行复核。
SSL定义了两种参数,一种是读参数,一种是写参数,写参数定义了自己发送的报文的加密方式和密钥,读参数定义了自己读报文的加密方式和密钥。无论客户端和服务器端,在发送 ChangeCipherSpec 报文时,写参数开始作用,而当收到对方发送的 ChangeCipherSpec时,读参数开始作用。
建立安全通信过程中,客户端状态转移如表5所示。
表5 客户端状态处理
类似的,服务器端的状态转移如表6所示。
表6 服务器端状态处理
从以上两个表可以看出,客户端和服务器所采取的措施是相对应的。
(7)Finished
在发送完ChangeCipherSpec报文后,每个系统将发送Finished报文,Finished报文使得双方可以核对加密通道已经被安全可靠地建立了。Finished 报文有两个目的,首先,由于Finished 报文本身也是在加密通道中传输的,因此如果对方不能够解密并验证这一报文,就说明在协商过程中出现了一些偏差。其次,在Finished报文中,包含一些协商中重要内容的摘要信息。如表7所示,注意其中包含有所有协商过程中的报文(不包含ChangeCipherSpec报文,因为从严格意义上讲,这一报文并不属于协商过程),这样,即使攻击者设法在其中插入了一些报文或者是删除了一些报文,那么也会造成客户端和服务器端之间的摘要值不匹配的情况出现。
Finished报文中所验证的信息包括:
密钥信息;
所有双方所交换的报文的内容(不包括ChangeCipherSpec);
一个标识是客户还是服务器的特殊值。
2、结束安全通信
SSL定义了一种用来安全结束通信的过程,用来防止遭到截断攻击。所谓截断攻击,就是攻击者通过过早地终止通信来实现对安全的破坏。例如,如果双方通信的内容是“明天删除所有文件,除非得到其他消息”,如果攻击者设法在两句之间终止通信,那么就可能造成双方的误解。SSL 定义了一个特殊消息,ClosureAlert来报告信息已经完全发送,可以结束连接了。这样如果收到了一些信息,但是没有收到 ClosureAlert 报文,那么就可以知道信息还没有发送完全,结束安全通信的过程,如图2所示。
图2 结束安全通信的过程
事实上,在Web服务中,这一消息并不是总是能收到,Web服务器和客户端采取了另外一些措施来防止截断攻击。
3、验证服务器的身份
以上所阐述的安全通信连接的建立,虽然对于提高安全性有很大的意义,但是并不能够保证通信双方身份的真实性。加密只是保护了数据的保密性,但是如果一方已经被冒充,那么也会产生安全风险。为此,SSL采取了一些措施用以判断对方身份的真实性,以避免身份的冒充。
不过,在 SSL 中,源认证并不总是必要的,例如对于 Web 上的电子商务,客户端需要辨别服务器的身份,这是必须的,但是服务器一般不必要通过SSL来认证客户端身份的真实,因为可以通过其他手段,如付费方式等来判断客户的真假。因此,SSL允许只对服务器进行源认证。
表7总结了为了认证服务器所需要采取的措施,除了加黑的地方,这些步骤和简单的加密并没有什么大的不同。
表7 认证服务器的身份
(1)Certificate
为了鉴别服务器的身份,服务器发送 Certificate 报文来发送自己的证书。该报文中包括一个从服务器的证书到证书权威(CA)的根证书的证书链。客户端需要验证这一证书的真实可信,为此它需要验证证书签名、有效时间、是否被取消等。此外,这也需要这一CA是被客户端所信任。这是通过其他方式来实现的,例如,客户端事先通过其他安全渠道知道该可信CA的根证书,例如,IE预装一些可信的CA的根证书。
在验证过程中,一个容易被忽略的细节就是,客户端不仅应当验证该证书的真实可信,还需要验证这一证书确实应当是该服务器的。例如,某个恶意的公司得到一个公司的证书之后,然后把这一证书作为自己的证书来使用,以进行冒充。在一些情况中,它可能会导致一些问题。解决这个问题,需要依赖客户足够聪明,许多证书中,都有该证书所属的域名,因此,一般来说只需要客户端验证一下即可。
(2)ClientKeyExchange
ClientKeyExchange报文与服务器的略有所不同,如果只进行加密,客户端将用服务器在ServerKeyExchange中给出的公钥来加密本报文中的信息,这样就能够验证服务器的身份了。在这种情况下,服务器需要先通过Certificate报文发送自己的证书。
4、将加密和认证分离
上一部分中,服务器通过发送 Certificate 报文,客户端使用其中的公钥来加密,从而认证服务器。但是这一步骤,在某些情况中,是不大可能实现的。例如,对于DSA算法,只能用来签名,不能用来加密。因此,这时客户端就无法使用上述的步骤验证服务器身份了。
即使对于那些能够用来加密的算法来说,将签名和加密分开也有一定的道理,首先,这样做有时是基于法律因素,一些国家对于加密技术有一定的出口限制,但对数字签名的限制则要相对弱一些,例如美国。因此,在一些实现中,对于签名使用较长的密钥,但是加密密钥则相对短很多。
SSL提供了用于将加密和认证分开的方式,表8总结了这些步骤。这一过程中,最重要的三个报文是Certificate、ServerKeyExchange和ClientKeyExchange报文。
表8 加密和认证功能分开的方式
(1)Certificate
与以前所讨论的大致相同,只是这一证书中的公钥只用来进行身份鉴别。
(2)ServerKeyExchange
这与以前没有认证时所讨论的相同,惟一的不同在于,这个公钥需要利用 Certificate 报文中的公钥进行签名。
(3)ClientKeyExchange
客户使用这一报文来完成协商过程。这一报文中包含有双方所选择的对称加密算法和密钥信息,并利用在ServerKeyExchange中的公钥进行加密。
5、认证客户端的身份
SSL也支持认证客户端的身份。如表9所示。它们与对服务器的认证比较相似。这一过程中比较不同的报文主要是 CertificateRequest 报文、客户端的 Certificate 报文以及CertificateVerify报文。
表9 认证客户端的身份
(1)CertificateRequest
在SSL协议中,由服务器决定是否需要客户端提供证书,如果服务器需要客户端提供证书,则发出CertificateRequest报文即可。CertificateRequest报文也可以在ServerKeyExchange报文之后。SSL中规定,在服务器验证自己之前,不能够要求客户的证书。
CertificateRequest 报文包含有两个域,一个证书类型的列表和一系列识别名,如表10所示。
表10 CertificateRequest组成
(2)Certificate
这一报文格式和以前所讨论的相同,如果客户端有服务器所希望要的证书,则回应这一报文,如果客户端没有证书或者是证书不符合服务器的要求,则回应NoCertificateAlert报文。服务器可以决定是继续或终止这一会话。
注意在SSL中,客户的公钥只用作签名,而不用来进行加密,这与服务器的公钥有所不同。因此,事实上客户端没有和ServerKeyExchange相对应的报文,ClientKeyExchange报文用来传输会话密钥信息,而不是公钥信息。
(3)CertificateVerify
只发送 Certificate 报文本身,还不能完成客户身份认证这一目的。客户端必须证明自己拥有私钥。因此,客户端需要发送CertificateVerify报文。这一报文中含有那些客户和服务器端都有的信息的密码学摘要,这样服务器就可以利用客户的公钥来验证这一签名的正确性。这些信息包括密钥信息和双方以前所交换的SSL报文。
值得注意的是,CertificateVerify并不是紧随着Certificate报文,而是在ClientKeyExchange报文之后才发出。之所以这样,是因为这个报文的内容依赖于 ClientKeyExchange 报文的内容。只有当服务器接收到ClientKeyExchange之后,才能够进行验证。
6、重新开始以前的会话
进行SSL会话需要很复杂的协商过程。为了减轻会话协商的开销,SSL允许重新使用以前已经建立的会话的参数。如图3和表11所示。
图3 重新开始以前的会话的步骤
表11 重新开始以前的会话
如图3所示,服务器发送ServerHello报文之后,马上发送ChangeCipherSpec和Finished报文,同样,客户端在收到ServerHello之后,马上发送ChangeCipherSpec和Finished报文。二者同时激活上一次会话所使用的参数。
在这一协商过程中,关键在于 ClientHello 报文,报文中含有客户端所希望使用会话的SessionID,如果服务器同意客户的请求,就在ServerHello报文中表示同意,否则二者开始正常的协商。
尽管这一方式节省了很多协商带来的开销,但是不可避免地也降低了系统的安全程度,因此在使用前应当仔细权衡。
二、报文格式
SSL协议报文来自于这样几个部分,ChangeCipherSpec协议、Alert协议、HandShake协议,以及应用层如HTTP,Record层协议接收这些报文,然后根据一定的格式要求将它们送到传输层发送。
1、传输层需求
SSL协议本身需要底层协议来完成报文的实际传输,SSL要求传输层准确、有序地传递各个SSL报文,因此,一般来说SSL构建于TCP之上,如图4所示。
图4 SSL的体系结构
就如所有在TCP层之上的协议一样,SSL需要识别出协议中报文的开始和结束,为此,SSL对每个会话报文都在头部标明了这一报文的长度,这样也方便在一个TCP数据包中传输多个SSL报文。
2、Record层
SSL使用Record层来包装所有的SSL报文,它为Alert、ChangeCipherSpec、HandShake以及应用层协议报文提供一个统一的格式。
Record层在每个上面产生的报文加上5个字节的头,如果报文需要进行完整性验证,还需要在尾部加上报文摘要值,如果需要还要进行报文加密。图5显示了Record层的报文格式,表12是除了加密和报文验证码之外的图中各个域的描述,图中具有多个字节的域的字节顺序为网络顺序,也就是高位字节在前的顺序。
图5 Record数据包结构
表12 SSL Record层的各个域
SSL中有4种高层协议,表13中列出了对应于这些协议的相应值。
表13 Record层协议类型
3、ChangeCipherSpec协议
ChangeCipherSpec 协议相当简单,它只有一个报文,这一报文就是前面所介绍的ChangeCipherSpec报文,那么,为什么不把这一报文归到其他协议如HandShake协议中呢?这是因为,ChangeCipherSpec协议必须是一个单独的协议,否则SSL就无法正常工作了。我们知道,在Record层封装时,SSL协议总是将加密或报文验证码等服务加到整个报文上,不过ChangeCipherSpec则不然,这一报文的产生意味着一些密码学服务参数的改变或生效,只有部分内容进行加密,这样,它与其他协议都显得不大一致,因此,最好的解决方法就是把它单独做成一个协议。ChangeCipherSpec协议相当简单,参考图6,它的内容只有一个字节,值为1。
图6 ChangeCipherSpec协议数据包
4、Alert协议
Alert协议用来指示错误或者是警告信息,如图4所示,Alert协议也使用Record的格式来封装,图7画出了最后形成的报文格式,Alert 协议定义了两个域,即严重程度和具体描述。
图7 Alert协议数据包
(1)严重程度
这一域表明所产生的错误的严重程度,它或者是警告(值为1),或者是致命错误(值为2),致命错误表示在会话中遇到了严重的问题,双方必须立即终止会话。警告信息则没有那么严重,双方可以选择继续会话。
(2)具体描述
Alert中的第二字节描述了所产生的错误,这一字节的值及其所表示的含义如表14所示。
表14 具体描述的值及其所表示的含义
5、HandShake协议
HandShake协议主要用来进行会话中参数的协商过程。如图4所示,HandShake协议也使用Record层来封装自己的报文,多个HandShake消息可以封装在一个Record报文中。图8描述了它的大致格式。
图8 HandShake协议数据包结构
每个HandShake 消息都用一个字节来描述消息的特定类型,表15中列出了SSL所定义的类型。类型后的三个字节指出HandShake消息内容的长度,这一长度以字节为单位且不包含类型和长度域。下面将详细介绍这些报文。
表15 HandShake协议报文
(1)HelloRequest
HelloRequest报文用于服务器向客户端要求重新开始SSL协商过程。这一报文通常很少使用,但是给服务器一个机会来改变现在所使用的参数。例如,如果某个特定连接已经持续了相当长时间,以至于有可能已不再足够安全,这时服务器就可以发送HelloRequest报文让客户端重新进行一次协商,来选择出新的参数。HelloRequest的格式相当简单,如图9所示,它的类型为0,长度也是0。
图9 HelloRequest数据包结构
(2)ClientHello
ClientHello消息通常用于开始SSL协商会话,图10画出了ClientHello消息的组成,它类型为 1,长度用两个字节来表示,长度后面的两个字节标识了所用的版本号,目前,这里的版本号总是和Record层的版本号相同,但是这使得HandShake协议和Record层协议可以分别发展,协议之后的32字节是随机数,如前所述,32字节中的前4字节是当前时间。
图10 ClientHello数据包格式
随机数之后的一个字节指出SessionID所占用的字节数,然后就是SessionID。如果客户端希望重新使用以前某次会话中得到的密码学参数,则将 SessionID 设置为那次会话的SessionID,否则为 0。在 SSL 中,规定 SessionID 最长不超过 32 字节。SSL 中没有规定SessionID的产生方法,但是,由于ClientHello是以明文形式传输,因此SessionID中不应当含有任何降低系统安全性的数据。
之后就是客户所建议的密码学参数集,首先的一个字节指出随后的参数集的长度,以字节为单位。然后就是密码学参数集,每2字节描述一个参数,因此,参数集的长度总是偶数。目前SSL所支持的密码学参数如表16所示。
表16 SSL3.0所支持的密码学参数集
ClientHello的最后一个域用来指定压缩方式,首先是一个压缩方式集的长度,然后是压缩方式集,每个字节用来描述一种压缩方式。由于目前SSL还没有定义压缩方式,因此一般在实现中,长度字节为1,而紧跟着1字节为0,表示不进行压缩。
(3)ServerHello
如图11所示,ServerHello和ClientHello的格式相似,区别主要有两点,首先它的类型为 2,其次就是它只指定一种密码学参数和一种压缩方式,这一种必须来自于客户端所提出的集合中。
图11 ServerHello消息格式
服务器可以指定 SessionID 也可以不指定。如果指定,说明允许客户端以后重新使用这次会话所产生的密码学参数,如果不指定,则应当设置SessionID长度为0,不允许客户重用此次会话所使用的参数。
(4)Certificate
Certificate报文的格式如图12所示,它的类型为11,类型之后示3个字节的内容长度,然后是证书链部分的长度,由此可知,这一长度比内容长度少3个字节。每个证书首先由长度域指出证书部分的长度,随后即是证书。报文中的一个证书是发送方的证书,然后是签发这一证书的CA的证书,再其后是给上一个 CA签发证书的CA的证书,以此类推,直到根CA的证书为止。
图12 Certificate消息格式
(5)ServerKeyExchange
服务器用 ServerKeyExchange 消息来和客户端交换有关密钥生成方面的一些信息,它的格式依所使用的密钥交换算法而定。图13、图14和图15画出了当交换算法是Diffie-Hellman、RSA及Fortezza时的不同情况。注意在消息中没有明确的标识指出所用的具体算法,因此,客户端必须依赖以前所得到的信息才能知道应当是哪一种算法(密钥交换的算法来自于ServerHello报文,而签名算法可以来自于Certificate报文)。ServerKeyExchange的类型为12。
图13显示了在Diffie-Hellman密码交换算法中所使用的格式。Diffie-Hellman所使用的三个常数(p、q、Ys)形成了报文中长度之后的6个域,每个常数用一个长度域和一个值域来标识。
图13 ServerKeyExchange(Diffie-Hellman)消息格式
图14显示了RSA交换算法中使用的格式。密钥信息中包含了RSA所使用的模和公开指数,每个常数用一个长度域和一个值域来标识。
图14 ServerKeyExchange(RSA)消息格式
图15显示了Fortezza/DMS算法中使用的格式。密钥信息包含了Fortezza中的rs值,由于rs总是128个字节长,因此使用报文长度一个域就足够了。
图15 ServerKeyExchange(Fortezza)消息格式
除了Fortezza/DMS之外,ServerKeyExchange 也可以包含签名数据,具体的格式因签名算法的不同而异。如果SSL会话中不进行服务器验证,那么就没有签名这一项。否则,如果服务器已经用 Certificate 消息发送了服务器的证书,则格式依赖于证书中所指定的签名算法而定。如果服务器的证书是用于RSA签名的,则对MD5摘要和SHA摘要连接在一起形成的数据进行签名,注意对两个摘要值只形成了一个签名,而不是对两个摘要值分别形成签名。如果证书用于DSA签名,则只对SHA摘要值进行签名,无论是哪种,摘要函数的输入都由以下几个部分组成:ClientHello中的随机数,ServerHello中的随机数,以及密钥交换中的参数值。
(6)CertificateRequest
为了验证客户端身份的真实性,服务器需要向客户端发送CertificateRequest报文来要求得到客户端的证书,同时也标明服务器所接收证书的要求。图16画出了这一报文的格式。它的类型值为13,类型和长度之后,是一系列的服务器接收的证书类型,以长度开始,然后每一字节表示一种类型。表17列出了目前定义的证书类型值和代表的意义。
图16 CertificateRequest消息格式
表17 证书类型
除此之外,报文中还包括服务器所认可的CA的识别名,以2字节的长度开始,然后跟着所认可的识别名列表,每个识别名也有自己的长度域。
(7)ServerHelloDone
这一报文标志着协商过程服务器端的结束,它的格式如图17所示,报文类型为14,不含有任何内容。
图17 ServerHelloDone消息格式
(8)ClientKeyExchange
客户端用 ClientKeyExchange 消息来告诉服务器用来保证会话安全的密钥信息,它的格式依所使用的密钥交换算法而定。图18、图19和图20画出了当交换算法是 RSA、Diffie-Hellman及Fortezza时的不同情况。注意在消息中没有明确的标识指出所用的具体算法,因此,必须依赖以前所得到的信息才能知道应当是哪一种算法所对应的格式。ClientKeyExchange的类型为16。
图18显示了在RSA密码交换算法中所使用的格式,在类型和长度之后,只包含加过密的初始主密值,初始主密值用服务器的公钥进行加密,这一公钥来源于ServerKeyExchange或Certificate报文。
图18 ClientKeyExchange(RSA)消息格式
初始主密值是得到会话的主密钥的初始值。对于RSA密钥交换算法而言,初始主密值是两个字节的版本号(对于 3.0来说这两个字节是3和0),然后是 46字节安全生成的随机数。
对于Diffie-Hellman密钥交换算法而言,需要区分两种情况。如果Diffie-Hellman密钥交换是临时的,那么格式如图19,在报文内容中包含有客户端的Yc(图中的DH Y)的长度及其值,如果是固定的,则 Yc的值已经在客户端的证书中传输,ClientKeyExchange报文为空。
图19 ClientKeyExchange(Diffie-Hellman)消息格式
对于Fortezza/DMS 密钥交换算法,图20中还需要一系列参数,这些常数如表 18所示。
图20 ClientKeyExchange(Fortezza)消息格式
表18 Fortezza/DMS ClientKeyExchange的参数
(9)CertificateVerify
客户端通过CertificateVerify报文来证明自己确实拥有所发出证书的私钥。如图21所示,在CertificateVerify报文中含有一些信息摘要的客户端签名。信息的格式依赖于证书中所指定的签名算法。如果服务器的证书是用于 RSA签名的,则对MD5摘要和SHA摘要连接在一起形成的数据进行签名,注意对两个摘要值只形成了一个签名,而不是对两个摘要值分别形成签名。如果证书用于DSA签名,则只对SHA摘要值进行签名。
图21 CertificateVerify消息格式
无论对于哪种签名,摘要函数的输入是相同的,客户端通过3个步骤来建立这些信息。首先它们计算出一个特殊值即主密值,其过程如表19所示。
表19 主密值的计算
Master secret=MD5 (premaster secret+SHA (‘A’+premaster secret+ClientHello.random
+ServerHello.random))
+
MD5(premaster secret+SHA (‘BB’+premaster secret+ClientHello.random
+ServerHello.random))
+
MD5(premaster secret+SHA (‘CCC’+premaster secret+ClientHello.random
+ServerHello.random))
在产生主密值之后,客户端开始构建CertificiateVerify报文,首先客户产生所有先前SSL协商所交换报文全部内容的摘要值,然后是主密钥,然后是48(对于MD5算法)或40(对于SHA算法)字节的0x36,这些经过MD5或SHA后,得到的摘要值,进入到下一轮,在下一轮中,主密钥,然后是48(对于MD5算法)或40(对于SHA算法)字节的0x5c,然后是上一轮所得到的摘要值,一起再经过一次摘要运算,就得到了最后的摘要值。
(10)Finished
最后的报文是Finished报文,类型为20,这一报文表示SSL协商过程已经结束,所协商出的参数已经生效。Finished报文本身将使用所协商出的参数进行加密,图22就是这一报文的格式。
图22 Finished消息格式
Finished报文中含有两个摘要值,一个使用MD5算法一个使用SHA算法。两个摘要函数的输入都是相同的。首先发送方产生所有先前SSL协商所交换报文全部内容的摘要值,然后是标明发送方身份的一个整数(客户端是 0x434c4e54,服务器是0x53525652),然后是主密钥,然后是 48(对于MD5算法)或 40(对于SHA 算法)字节的0x36,这些经过MD5或SHA后,得到的摘要值,进入到下一轮,在下一轮中,主密钥,然后是48(对于MD5算法)或40(对于SHA算法)字节的0x5c,以及上一轮所得到的摘要值,一起再经过一次摘要运算,就得到了最后的摘要值。
这个过程和CertificateVerify中的过程有两点不同,首先,在这一过程中还有标明发送方身份的一个整数,而对于CertificateVerify,由于只有客户端才发送这一报文,因此没有这一身份标识。其次,这一过程中使用了两种签名算法。
另外一个需要注意的是,无论是CertificateVerify还是Finished报文,在计算所有协商过程中的报文的摘要值时,都不包含ChangeCipherSpec报文,这是因为ChangeCipherSpec报文不属于HandShake协议中。
6、安全报文
Finished是第一个使用SSL协商所得的安全服务的报文,它之后的所有报文,包括之后如果重新协商时可能的协商报文,也都将使用这些安全服务。这些报文中,最重要的就是应用层报文了,应用层的需求是建立SSL会话的主要原因,应用层数据交换是双方所真正需要的。SSL主要提供两种安全服务,即加密和报文完整性验证,这将在以下详述。
(1)报文验证码(MAC)
SSL支持两种报文验证码,它们分别是MD5和SHA,使用哪种依赖于协商而定。MD5和SHA所产生的MAC值长度有所不同,MD5产生的长度为16字节,而SHA所产生的为20字节。它们所产生的MAC码被附加到消息之后,由SSL将消息内容和MAC码一起加密传输。
MAC码的产生与HandShake协议中的比较相似,首先是一个被称为是MAC写密值的特殊值,然后是48(对于MD5算法)或40(对于SHA算法)字节的0x36,然后是64比特的序列号、16比特的数据长度,再加上数据内容,这些经过MD5或SHA后,得到的摘要值,进入到下一轮,在下一轮中,MAC写密钥,然后是48(对于MD5算法)或40(对于SHA算法)字节的0x5c,以及上一轮所得到的摘要值,一起再经过一次摘要运算,就得到了最后的摘要值,如图23所示。
图23 摘要值的产生过程
这里涉及两个特殊值,即MAC写密值和序列号。序列号是一个对发出去的报文进行计数的一个量,每次ChangeCipherSpec都置为0,Record层每发一个报文都加1。
(2)加密
SSL协议支持流加密算法和块加密算法,以前所介绍的例子中使用的都是流加密算法,在流加密中,被加密的数据只是消息内容和MAC值。
对于块加密算法则有所不同,由于块加密算法一般要求数据长度是块的整数倍,因此,需要进行填充。为了能够便于让接收方识别哪些是正文,填充的最后一个字节指出了填充字节的长度,这样解密后,只需要从末尾开始倒推即可。
(3)产生密码学参数
SSL的加密和报文验证码算法依赖于一系列只有通信双方才知道的密值,生成这些密值是 SSL 协商的三个目的之一(另外两个是验证对方和协商密码学参数)。这些值中最重要的是主密值的生成。
产生主密值之后,将基于主密值产生通信中所需要的其他密值。首先需要决定需要哪些密值,这取决于双方协商的结果,通常是表20中的一些值。双方从中选择自己所需要生成的密值,然后根据所需要的长度产生相应的值。
表20 共享的密值
为了产生这些值,双方需要进行类似于主密钥生成的密钥生成步骤:首先将字符“A”和主密钥、服务器的随机值、客户端的随机值相连,计算它们的SHA摘要,然后将主密钥和上一步所产生的摘要值相连,计算它们的MD5摘要,如果所得的16字节摘要值不符合要求,就重新进行上述计算,只不过将字符“A”换成字符“BB”,如果仍然不能满足要求,则将“BB”换成“CCC”重复,以此类推直到产生满足要求的值为止。
大多数情况下,这样产生的密钥值就可以直接进行使用。但是对于那些可出口的密码算法,还需要将进行进一步的处理,以满足出口限制。通常可出口的密码算法使用的密钥长度较短。
7、密码学参数集
3.0版的SSL协议定义了31种不同的密码学参数集,为参数协商提供了丰富的选择。其中使用了14种密钥交换算法,表21列出了这些密钥交换算法。对于那些可出口的密码学参数集,表中也指定了出口政策中的长度限制。
表21 密码学参数集
SSL协议所支持的加密算法如表22所示,其中标注“*”的算法满足出口限制。
表22 加密算法
表23列出了SSL所支持的摘要算法。
表23 摘要算法
三、传输层安全协议(TLS)
在SSL协议提出之后,由于它在互联网中的应用越来越重要,IETF负责了SSL的进一步的发展。为了更清晰地和IPSEC相区别,IETF将它改名为传输层安全协议TLS。
TLS没有对SSL进行大规模的改动,相对来说,TLS比SSL 3.0的改动还不如SSL 3.0对SSL 2.0的改动多。表24列出了这些改动。
表24 TLS和SSL协议的不同
1、TLS协议版本
为了保持和SSL的兼容,TLS1.0的版本是3.1。
2、Alert协议类型信息
TLS对SSL的改进之一就是增加了更多的安全警告信息类型。如表25所示,TLS的安全警告信息类型数目几乎是SSL的两倍。表25中,TLS所增加的警告信息类型前加点表示,此外,TLS删除了警告类型41(NoCertificate),这是因为这个警告比较难于实现,实现它必须保证Alert和协商协议的严格同步,在TLS中,如果客户端没有合适的证书,就直接返回一个空白的Certificate报文。
表25 TLS Alert描述
3、报文认证
另外一个TLS的改进点是用来进行报文验证的算法,SSL报文认证中混合了密钥信息和应用层数据,因此显得很杂乱。TLS 则使用了标准的报文认证方式 H-MAC(报文验证摘要码),H-MAC算法是一个已经确立的标准,并已经进行过严格的分析。注意H-MAC并不指定特定的摘要算法,它可以使用任何合适的摘要算法。
TLS报文认证中直接使用了H-MAC产生报文验证码MAC,所用的算法和密码由协商得出。所防护的信息包括序列号、TLS协议报文类型、TLS版本、报文长度和报文内容。
4、密钥生成
在H-MAC协议的基础上,TLS定义了一种产生伪随机数的方法。通过一个种子值和密值,它可以产生无限多的伪随机数。如图24和表26所示,这种方法不限定特定的摘要算法,任何摘要算法都可以。
图24 密钥生成步骤
表26 产生伪随机数的方法
为了更进一步地优化这一算法,TLS协议定义了伪随机数产生函数PRF,PRF中同时使用了两种摘要算法即 MS5和SHA,这样即使其中一个摘要算法出现了安全问题,另一个算法也能够保证数据的安全。如表27所示,函数的输入是一个初始值、一个密值和一个标志(Label),密值被分成两个部分,一部分用来作为MD5的输入,而另外一部分则作为SHA的输入,标志和初始值被组合在一起成为一个值。注意MD5和SHA所产生的摘要长度不同,分别为16字节和20字节,因此对于表中的步骤2和步骤3需要不同的轮数。
表27 TLS的伪随机数产生函数PRF
TLS密钥的产生过程和SSL主要原理是相同的,首先利用初始主密钥(premaster key)产生主密钥,然后将主密钥作为密值,字符串“key expansion”作为标志,服务器方的随机数和客户端的随机数合在一起作为种子值,利用PRF产生出密钥。
48 字节的主密钥本身也是通过 PRF 函数所产生的。利用初始主密钥,字符串“master secret”作为标志,服务器方的随机数和客户端的随机数合在一起作为种子值,从而产生了主密钥。它们的产生过程如图25所示。
图25 主密钥的产生过程
5、CertificateVerify
CertificateVerify报文也与SSL中略有所不同,在SSL中,CertificateVerify所签名的信息包括一个复杂的对协商报文的两层摘要、主密钥以及填充值。但对于TLS,则只包括本次会话中已经交换的协商信息。
6、Finished
TLS也略微简化了Finished报文,在TLS中,Finished报文只包含12字节的值,这一值是由主密钥、标志“client finished”(对于客户端)或者是“server finished”(对于服务器)、以及所有协商报文的MD5摘要和SHA摘要连在一起,经过PRF所产生的,图26描述了这一过程。
图26 Finished消息的产生过程
7、基本密码学参数集
TLS支持SSL中除了Fortezza/DMS之外的所有密码学参数集,由于IETF有一套成熟的体制来评价新提出的密码学参数集,因此在 TLS 添加新的算法要相对容易得多。表28列出了TLS所支持的基本密码学参数集以及它们在Hello报文中的值。其中出口限制一栏中如果有“*”则说明可以出口。
表28 TLS1.0所支持的基本密码学参数集
微信公众号:计算机与网络安全
ID:Computer-network