TLS 1.0 RFC http://www.ietf.org/rfc/rfc2246.txt
TLS 1.1 RFC http://www.ietf.org/rfc/rfc4346.txt
TLS 1.2 RFC http://www.ietf.org/rfc/rfc5246.txt
TLS 1.3 见:https://blog.csdn.net/mrpre/article/details/81532469
我的TLS实现,大家可以参考:https://github.com/mrpre/atls/
这里根据TLS的实现,进行总结。至于各个版本号之间丢弃了哪些算法、新增了哪些算法,直接看RFC即可,这里并不关心。
这里只关心TLS报文内在处理逻辑存在哪些变化,即站在代码的角度剖析。各位看官如果对TLS协议不熟悉,那么不建议看此文章。要读懂此文章需要对TLS实现由较深的理解,想了解TLS基础知识,建议从本系列开头看起。
区别1:对finished报文(Encrypted handshake message)影响
TLS 1.0 TLS 1.1 在计算finish时,进行的是MD5+ SHA1组合方式运算,而在TLS 1.2下,摘要算法变成了单次SHA256。
伪代码如下
If(version >= TLS1_2)
{
If (cipher.mac == SHA384)
{
restult = SHA384(handshake_in );
}
Else
{
restult = SHA256(handshake_in);
}
}
Else
{
restult = md5(handshake_in) + sha1(handshake_in);
}
其中 handshake_in是 字符串常量+所有握手信息(类型为Handshake的message)。
例如
作为client端handshake_in =“client finidhed” + all_handshake
作为Server 端handshake_in = “server finidhed” + all_handshake
注:对于加密套件存在SHA384及其以上的高级摘要算法,无论TLS哪个版本,都用 加密套件指定的 握手摘要算法计算 摘要,如上伪代码所示(RFC上说对于每一种新的算法, 都需要指定default还是SHAXXX,但是在实现上,都是根据MAC是什么,SHAXXX就是什么)。
其实加密套件中指定的摘要算法是用来在加密时进行HMAC的,并不影响握手流程中的运算,但是如果两端协商的加密套件支持SHAXXX,那么必然表示两端支持SHAXXX算法,那么在SHAXXX安全性高于SHA256的情况下,握手阶段需要摘要算法就没必要那么‘死’只用SHA256。当然目前也没有比SHA384更高的了。
区别2:对PRF算法的影响
先用伪代码梳理逻辑:
If(version >= TLS1_2)
{
If (cipher.mac == SHA384)
{
TLS1_2_PRF(SHA384, in, srcret);
}
Else
{
TLS1_2_PRF(SHA256, in, srcret);
}
}
Else
{
TLS1_PRF(MD5,SHA1, in, srcret);
}
1:对于SHA384的判断,上面已经说过,这里不再赘述。
2:可以看到TLS1.2和TLS 1.0 TLS 1.1的PRF实现也不同,参数不同。
TLS 1.2 的PRF
单次P_HASH,P_HASH使用的是SHA256
TLS 1.1 的PRF
两次P_HASH,第一次P_HASH使用的是MD5,以及secret的前半部分;第二次P_HASH使用的SHA1,以及secret的后半部分。两次P_HASH的结果进行亦或(xor),得到最后结果。
注意secret如果是偶数,则正好各一半,如果是奇数:
例如secret是1234567,则前一半 指的是1234,后一半指的是4567,中间一个字节公用。
区别3:对Certificate verify的影响
Certificate vertify是客户端在发送证书后,为了表明自己是证书的拥有者,用自己的私钥对之前收到、发送的握手信息进行签名。(和finished类似)。
同样签名前,需要对握手信息进行HASH运算。
TLS1.0 TLS1.1:
使用MD5+SHA1的形式对握手信息进行摘要运算,这个流程和计算finished一样,只是不加字符串常量’XXX finished’。
注:有一个例外,对于ECDSA签名算法(客户端证书是ECC证书),只做单次SHA1计算。
TLS 1.2:
TLS 1.2 下, certificate verify报文格式和之前的不同,多出2个字节(Signature Hash Algorithm),表示hash_alg以及sign_alg。具体握手摘要根据hash_alg进行单次计算。
同样,如果加密套件存在SHA384,则使用SHA384
TLS 1.2下 Certificate verify的格式
伪代码如下:
If(version >= TLS1_2)
{
result = SHAXXX(all_handshake);
ADD_MD_INFO_TO_PACKET();//报文中增加两个字节表明自己签名算法
}
Else
{
If(ECDSA_SIGN)
{
result = SHA1(all_handshake);
}
Else
{
result = MD5(all_handshake) + SHA1(all_handshake)
}
}
总结来说:
1:TLS 1.2需要增加2个字节表明签名算法类型(非对称+摘要)。而TLS1.2之前的协议默认就用md5+sha1的形式计算摘要,非对称算法肯定使用私钥类型对应的算法,这个无需显示表明。
2:ECDSA签名需要特殊对待。
区别4:对server key exchange的影响
TLS1.2下和 certificate verify类似,报文格式较之前版本有不同。多了2个字节表示HASH算法和签名算法。
签名时的摘要逻辑和certificate verify一样。
区别5:对加密的影响
这个变化是TLS1.1开始变化的,不是TLS1.2。
为了对抗beast攻击,SSL在加密数据前,需要填充一个BLOCK_SIZE(IV_SIZE)长度的随机数,这个随机值也被作为数据的一部分进行加密,在解密时,同样进行解密,然后丢弃。
CBC下,对于上述这个场景我们其实可以进行优化,这个BLOCK_SIZE的数据对于发送端来说可以不进行加密,然后下一个数据块的Write_IV改成这个随机数,这样CBC模式就可以完整的工作。对于解密方来说,这个BLOCK_SIZE的数据可以不解密,然后解密下一个块时的Read_IV变成这个随机数,CBC模式也能正常工作。减少了一个BLOCK_SIZE的解密、加密数据。详细优化方案见我的博客 http://blog.csdn.net/mrpre/article/details/78093370
如果觉得有用,请打赏N元:http://39.98.242.44