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协议的基本数据交互流程如下图:
加解密流程详细介绍如下:
客户端:生成一个32byte的random用于计算主密钥、加密密钥和消息的数字签名。在cipher suites中指明自己支持的对称加密、非对称加密和数字签名算法。
服务器端:生成一个32byte的random用于计算主密钥、加密密钥和消息的数字签名。生成一个23byte的SessionID。在client cipher suites中挑选一个加密强度最高的算法组合,作为双方的通讯的算法。
如TLS_RSA_WITH_AES_128_CBC_SHA表示通讯协议时TLS、非对称加密算法为RSA、对称加密算法为AES_128_CBC、数字签名算法为SHA。
服务器端:如果服务端证书是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的证书,然后是直接证书签发者证书,最后是服务器终端证书。
客户端:
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个实际密钥。
客户端:对字符串“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报文类似,是对字符串“server finished”进行计算,用于验证server_write_key和server_write_MAC_secret。
服务器端:首先根据client_write_key解密整个消息体,并对其中的实际数据部分进行HMAC(密钥为client_write_MAC_secret)并和客户端发送过来的MAC进行比较,如果相同则认为数据完整。
客户端:首先根据server_write_key解密整个消息体,并对其中的实际数据部分进行HMAC(密钥为server_write_MAC_secret)并和客户端发送过来的MAC进行比较,如果相同则认为数据完整。
上节是以TLS1.0为基准进行说明,但是SSL/TLS协议簇内的协议之间有一定的差别。
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))
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;
导致在块加密数据解码时有所不同。
默认使用SHA256代替PRF
默认使用SHA256代替PRF