SSL/TLS协议簇加解密流程

一、概述
      SSL协议是最早Netscape公司开发的安全通信协议,用于浏览器安全通信。到SSL Version3,提交作为IFTF草案,已经广泛的应用Intetnet通信。之后IETF对SSLv3稍作改动并更名为TLS1.0,对应RFC2246,之后的TLS1.1、TLS1.2先后被接受为RFC4346,RFC5246,另外由于TLS是基于TCP协议设计,导致其不能处理独立纪录,不允许SSL时有数据丢失,在RFC4347中提出了一种“Datagram TLS”---DTLS,可以理解为TLS1.1的分支。

      SSL/TLS协议的设计目标是保证数据的机密性和完整性。因此在SSL/TLS协议中包含了3类算法:对称加密算法(保证机密性),数据签名算法(保证完整性)和公钥算法(用于交换密钥)。下面以TLS1.0为基准介绍SSL/TLS协议簇加解密流程。

二、加解密流程
      SSL/TLS协议的基本数据交互流程如下图:

      加解密流程详细介绍如下:

 

      Client Hello :表示客户端向服务器发起SSL握手请求。
      客户端:生成一个32byte的random用于计算主密钥、加密密钥和消息的数字签名。在cipher suites中指明自己支持的对称加密、非对称加密和数字签名算法。

     
      Server Hello:表示服务器相应客户端的SSL握手请求。
      服务器端:生成一个32byte的random用于计算主密钥、加密密钥和消息的数字签名。生成一个23byte的SessionID。在client cipher suites中挑选一个加密强度最高的算法组合,作为双方的通讯的算法。

      如TLS_RSA_WITH_AES_128_CBC_SHA表示通讯协议时TLS、非对称加密算法为RSA、对称加密算法为AES_128_CBC、数字签名算法为SHA。

     
      Certificate:服务端证书。
      服务器端:如果服务端证书是Base64编码,首先把证书进行Base64解码,得到的是使用ASN.1格式编码的X.509证书。

      证书中的信息包括:

     客户端:根据收到的证书,判断其合法性,并计算得到服务器的公钥(对于RSA算法,是解析得到n和e,对于DH算法解析得到a和q)。

     证书合法性的判断方法:

     ~颁布者的合法性(hash值)

     ~有效期

     ~签名值是否合法:首先对证书中除签名值部分的内容按照证书中的签名

     算法进行签名,把得到的签名按照asn.1编码方式进行编码:OBJECT格式的签名算法+ ASN_OCTET_STRING格式的签名值A;把证书中的签名值按照证书中的主体公钥算法进行解密得到B;当A和B完全相同时认为证书有效(证书制作过程中的签名值计算方法:计算得到A,和客户端计算方法相同,用服务器私钥对A进行加密,得到证书中的签名值)

      一般情况下客户端收到的是一个证书链,第一个是服务器的证书,之后是服务器证书签发者。。。最后是自签名的根证书。如下图。在实际解析中先要验证根CA的证书,然后是直接证书签发者证书,最后是服务器终端证书。

     Certificate Request:当服务器需要验证客户端证书时使用。
    
     Server Key Exchange:用于交换对车密钥,只有在使用RSA扩展选项或者DH算法时才会使用。
 
     Server Hello Done:表示握手消息结束。
 
     Client Key Exchange:交换预主密钥。
     客户端:

           RSA算法:

                 随机生成48byte的预主密钥,把48byte的第一个字节设置成主版本号,第二个字节设置成次版本号。用步骤2中协商得到的非对称加密算法进行加密。传递给服务器端。

           DH算法:

                得到随机数Xc,计算得到Yc,把Yc通过Client Key Exchange消息明文传递为服务器端;根据a,q,Xc,Ys计算得到预主密钥。

     客户端和服务器端都需要根据预主密钥计算得到主密钥、加密密钥和签名密钥,方法如下:

          RSA算法:     

                接到客户端加密的预主密钥,按照非对称密钥进行解密,得到预主密钥。然后按照PRF算法计算得到主密钥。(生成主密钥的算法SSL和TLS略有不同。)

          DH算法:

                根据a,q,Xs,Yc计算得到预主密钥。

          根据预主密钥计算得到主密钥的算法(PRF算法):就是带密钥的MD5签名算法和带密钥SHA签名算法得到的结果异或得到的。

         MD5:

              密钥:预主密钥的前24byte,签名文本:字符串“master secret”+服务器端32byte的random + 客户端32byte的random,生成48byte的MD5Hash值

         SHA:

             密钥:预主密钥的后24byte,签名文本:字符串“master secret”+服务器端32byte的random + 客户端32byte的random,生成48byte的SHAHash值

         得到主密钥:MD5Hash XOR SHAHash

         最后根据主密钥计算的到6个实际使用的密钥:client_write_MAC_secret;server_write_MAC_secret;client_write_key;server_write_key;client_write_IV;server_write_IV;

         计算方法和计算主密钥的方法类似,都使用PRF算法。不同的是提供给MD5和SHA的密钥是主密钥,最后生成的Hash长度为148。然后把148byte的Hash依次赋值给上述6个实际密钥。

     Change Cipher Spec:表示之后的消息传输都将采用对称加密方式进行。
     Encryted HandShake Message:加密的Finish报文,用于验证双方协商的对称加密算法、客户端密钥。
 
    ~客户端给服务器发送的Finished报文:
          客户端:对字符串“client finished”应用PRF算法:MD5和SHA的密钥是主密钥,加密的密文是SSL握手以来所有消息的串联,生成的Hash值为12Byte;对生成的12byte应用HMAC算法,算法的密钥是client_write_MAC_secret,把计算得到的MAC值添加到Hash后面;如果是对称加密算法是块加密算法,那么还需要填充pad。最后用第2步中协商的对称加密算法对上述数据进行整体加密,加密密钥是前面中计算得到的client_write_key。

         服务器端:首先用密钥为的client_write_key对称加密算法对数据进行解密,计算字符串“client finished”的MAC值和客户端发送过来的12byte进行比较,相同则认为client_write_key的对称加密正确,再用client_write_MAC_secret计算MAC值,和客户端的数据进行比较,如果相同则认为client_write_MAC_secret正确。

    ~服务器给客户端发送的Finished报文:
    和客户端给服务器发送的Finished报文类似,是对字符串“server finished”进行计算,用于验证server_write_key和server_write_MAC_secret。

  
    APP Data:加密数据。
    服务器端:首先根据client_write_key解密整个消息体,并对其中的实际数据部分进行HMAC(密钥为client_write_MAC_secret)并和客户端发送过来的MAC进行比较,如果相同则认为数据完整。

    客户端:首先根据server_write_key解密整个消息体,并对其中的实际数据部分进行HMAC(密钥为server_write_MAC_secret)并和客户端发送过来的MAC进行比较,如果相同则认为数据完整。

 
三、协议簇
    上节是以TLS1.0为基准进行说明,但是SSL/TLS协议簇内的协议之间有一定的差别。

3.1 SSL3.0
 
     生成主密钥
     TLS1.0使用了PRF算法,其核心是分别用MD5和SHA分别计算的到Hash,并把MD5Hash和SHAHash相异或得到主密钥;

     SSL的计算方法:把SHA计算得到的Hash作为MD5的输入,计算得到16byte的Hash值,重复计算3次,把3次计算得到的3个16byte的Hash拼接成主密钥。

     生成计算密钥
     区别同上

     数字签名算法
     对于加密数据的数字签名算法。

     TLS1.0使用了RFC2104定义的HMAC算法:HMAC:MAC = H(Key^oPad,H(Key^iPad , context))

     SSLv3使用的MAC算法和HMAC算法类似:MAC = H(Key+oPad, H(Key+iPad , context))

3.2 TLS1.1
     加密数据格式
     TLS1.0中块加密数据的格式为

     block-ciphered struct {

         opaque content[TLSCompressed.length];

         opaque MAC[CipherSpec.hash_size];

         uint8 padding[GenericBlockCipher.padding_length];

         uint8 padding_length;

     } GenericBlockCipher;

     TLS1.1块加密数据的格式为

     block-ciphered struct {

          opaque IV[CipherSpec.block_length];

          opaque content[TLSCompressed.length];

          opaque MAC[CipherSpec.hash_size];

          uint8 padding[GenericBlockCipher.padding_length];

          uint8 padding_length;

      } GenericBlockCipher;

      导致在块加密数据解码时有所不同。

3.3 TLS1.2
     生成主密钥
          默认使用SHA256代替PRF

     生成计算密钥
          默认使用SHA256代替PRF


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/sealyao/archive/2010/09/23/5901510.aspx

posted @ 2011-04-08 17:33  p2liu  阅读(332)  评论(0编辑  收藏  举报