深入TLS/SSL协议

https://juejin.im/post/5eb21f06e51d454d8e56abf3
TLS/SSL协议是为了解决网络通讯中的信息安全问题而诞生的。
它的设计目的主要有三个:



身份验证——搞清楚与我通讯的人是不是我所想的那个。
保密性——就算第三方拿到了通讯内容,也搞不清楚其中所表达的意思。
完整性——保证通讯内容的完整性。



TLS/SSL协议主要包含两部分:
1、Record记录协议



使用对称加密算法来解决通讯消息加密的部分。



2、Handshake握手协议



为了完成对称加密,需要通过握手协议来传递密钥。

对称加密
对称加密算法是指在加密和解密过程中使用相同的密钥。
举例:
张三在与李四通讯时为了防止第三方窃听,使用莫斯密码将通讯内容加密。李四接收到通讯内容后,使用相同的莫斯密码将内容解密。
因为使用了相同的莫斯密码,所以这属于对称加密。
网络通讯中的对称加密之所以能够使用相同的密钥对内容进行加/解密,是因为使用了异或运算。
异或运算
在数学领域中异或运算:当两两数值相同为否,而数值不同时为真。
在计算机领域中的异或运算:



举例:
现有一把密钥:1010,与明文:0110。
1、使用密钥对明文进行加密,得出密文为:1100



1 XOR 0 = 1
0 XOR 1 = 1
1 XOR 1 = 0
0 XOR 0 = 0



2、使用相同的密钥对密文进行解密,得出明文:0110



1 XOR 1 = 0
0 XOR 1 = 1
1 XOR 0 = 1
0 XOR 0 = 0



可见XOR异或运算是对称加密的关键!
优点:



异或运算执行速度非常快,只需遍历一遍就可以了。



缺点:



要求进行异或运算的密钥与明文长度要一致的。明文有大有小,大到可以是几百兆甚至是几个G,要求密钥是同样的大小是不可能的。



填充
异或运算要求双方长度一致的这个缺点要怎么解决呢?聪明的同学或许已经想到解决方法了:就是将明文划分为多个等长的块。
比如密钥为16字节的,那就将明文划分为多个16字节的块,分别用密钥对这些明文块进行加解密。
Block cipher分组加密原理就是这样:将明文划分为多个等长的Block块,对每一个Block块分别加解密。
但并不是所有的明文都能恰好的划分为16字节的块。这时就需要填充!
填充的目的:



当最后一个明文Block块的长度不足时,就需要填充。



填充主要有两种方法:



位填充:以比特位为单位进行填充。
字节填充:以字节为单位进行填充。



其中字节填充有4种填充方式:



补零–最后不足的字节全部填上0。
比如以16字节划分,最后一个Block块只有12个字节,那么就填入00 00 00 00。
ANSI X9.23–也是补零,只是在最后一个字节填写说明需要填充多少个字节。
比如以16字节划分,最后一个Block块只有12个字节,那么就填入00 00 00 04。
ISO 10126–填随机数,在最后一个字节填写说明需要填充多少个字节。
比如以16字节划分,最后一个Block块只有12个字节,那么就填入45 A3 D2 04。
PKCS7–需要填充多少个字节,就填写多少。
比如以16字节划分,最后一个Block块只有12个字节,那么就填入04 04 04 04。



工作模式
对明文进行分组、填充后,还要按照一定的规律或方法进行加/解密。这些规律或者方法就是工作模式。
分组工作模式:block cipher mode of operation



允许使用用一个分组密码密钥对多于一块的数据进行加密,并保证其安全性。



1、 电子密码本ECB模式–Electronic codebook
就是直接将明文分解为多个块,对每个块进行加密。



这种工作方法非常简单、快速。但是缺点在于同样的明文块会被加密成相同的密文块;因此,它不能很好的隐藏数据模式。
举例:
对图片进行ECB之后,是无法隐藏到图像的轮廓特性的。如下图所示:



2、密码分组链接CBC模式–Cipher-block chaining
每个明文块先与前一个密文块进行异或后,再进行加密。在这种方法中,每个密文块都依赖于它前面的所有明文块。同时,为了保证每条消息的唯一性,在第一个块中需要使用初始化向量。



它的主要缺点在于加密过程是串行的,无法被并行化。
3、计数器模式CTR模式–Counter
CTR将块密码变为流密码。它通过递增一个加密计数器以产生连续的密钥流,其中,计数器可以是任意保证长时间不产生重复输出的函数。



这样加密和解密过程均可以进行并行处理而且加密效果也非常理想。
CTR模式同样存在问题:无法提供密文的完整性校验。当密文在传输过程中存在丢失的情况下,是无法保证密文的完整性的。
完整性校验
MAC算法–Message Authentication Code。
MAC算法能够实现消息的完整性校验。工作原理是基于hash函数的。
hash函数是一种从任何一种数据中创建小的数字“指纹”的方法。hash函数把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定下来。
简而言之就是:无论输入多长的字符串,通过hash函数,都能得到定长较短的字符串。



MAC工作流程如图所示:



发送方使用密文与密钥通过MAC算法生成一个MAC序列。然后将密文与MAC序列值一起打包发送。
接收方拿到之后,将密文与密钥使用相同的MAC算法也生成一个MAC序列。然后比对这两个MAC序列是否相同。



CTR分组工作模式加上MAC算法就诞生了GCM分组工作模式。
AES对称加密算法
高级加密标准AES算法–Advanced Encryption Standard



常用的填充方法:PKCS7
常用的分组工作模式:GCM



AES的分组Block块长度固定为128比特,也就是16字节。
密钥长度则可以是128,192或256比特。
AES加密过程是在一个4×4的字节矩阵上运作。



所以从上图中看出,分组长度128比特分为4个32比特。而不同长度的密钥则分为4、6、8组32位比特的矩阵。
AES加密流程:如图所示



10轮加密可分为初始轮、普通轮和最终轮。
1、初始轮



AddRoundKey轮密钥加



2、普通轮



AddRoundKey轮密钥加
SubBytes字节替代
ShiftRows行移位
MixColumns列混合



3、最终轮



SubBytes字节替代
ShiftRows行移位
AddRoundKey轮密钥加



addRoundKey轮密钥加



矩阵中的每一个字节都与该次回合密钥(round key)做XOR运算;每个子密钥由密钥生成方案产生。



SubBytes字节替代



透过一个非线性的替换函数,用查找表的方式把每个字节替换成对应的字节。



ShiftRows行移位



将矩阵中的每个横列进行循环式移位。



MixColumns列混合



为了充分混合矩阵中各个直行的操作。这个步骤使用线性转换来混合每内联的四个字节。最后一个加密循环中省略MixColumns步骤,而以另一个AddRoundKey取代。



非对称密码
对称加密的最大的问题是怎么把密钥传递给对方。非对称密码可以实现密钥的安全传递。
每一个参与方都有一对密钥:



公钥–对对方公开
私钥–仅自己拥有



非对称加解密过程:



使用对方的公钥加密
使用自己的私钥解密



举例:
张三要和李四通讯
第一步:张三用李四的公钥进行加密,将密文发送给李四。
第二步:李四用自己的私钥进行解密。
密文是无法通过公钥解密的,只有私钥才能解密。
张三怎么拿到李四的公钥?有两种办法:



第一种:通过PKI公钥基础设施拿到的。
第二种:建立链接过程中通过握手过程由李四传给张三的。



RSA算法
RSA是基于公开密钥密码体制的。
公开密钥密码体制是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。
RSA算法中公私钥的产生:



随机选择两个不想等的质数p和q。
计算p和q的乘积n(明文小于n)。
计算n的欧拉函数v, v=(p-1)*(q-1)。
随机选择一个整数e,且1<e<v,k与v是互质。
计算e对于v的膜反元素d,(d * e)%v = (e * d)%v = 1。
公钥:(e, n)。
私钥:(d, n)。



RSA的安全性依赖于大数因数分解非常非常困难,也就是通过一个大数n是非常难的分解出p和q。
RSA算法的加解密流程:如下图所示



加密
m是明文,c是密文
解密



由于进行大量的大数乘法运算,RSA的速度是对应同样安全级别的对称密码算法的1/1000左右。
PKI公钥基础设施
PKI是非对称密码学的一个非常重要的应用。
基于私钥加密,只能使用公钥解密的原理实现身份验证的作用。
签名与验签的流程



首先网站站长通过RSA算法生成一对公私钥,然后将公钥与站长的个人身份发送给Certificate Authority数字证书认证机构
由CA机构核实完个人信息后就对这些信息使用CA机构的私钥进行加密生成一个公钥数字证书
然后将这个公钥数字证书颁发给站长。公钥数字证书的组成:CA信息、公钥用户信息、公钥、权威机构的签名和有效期。



具体的流程:如图所示



签名:



将站长的个人信息通过hash函数生成一个hash值。
然后用CA机构的私钥对hash值进行加密。
将加密后的内容与站长的个人信息还有网站的公钥一起打包成一个公钥数字证书。



验签:



当浏览器拿到这个公钥数字证书之后,就把该证书内容分解出两部分:站长个人信息与加密的hash值。
浏览器将站长的个人信息通过证书说明的hash函数生成一个hash值。
然后用CA机构的公钥解密证书中的加密的hash值。
对比两个hash值是否相等。



证书类型:



域名验证证书domain validated:DV证书
DV证书通常是免费的
组织验证证书organization validated:OV证书
OV证书验证更为严格,通常是收费的
扩展验证证书extended validate:EV证书
EV证书最为严格,所以也是最贵的。



从加密安全性上看,三类证书的保密性都是一样的,只有在站长的个人信息验证上有所不同。
DH密钥交换协议
上面说到张三有两种办法可以拿到李四的公钥:



第一种:通过PKI公钥基础设施拿到的。
第二种:建立链接过程中通过握手过程由李四传给张三的。



RSA算法一般是第一种方法中用于CA机构的身份验证上的。事实上RSA算法用于第二种方法也是可行的。
举例:
张三与李四建立链接。李四用RSA算法生成一对公私钥,在握手中李四将公钥传递给张三。然后张三将对称加密的密钥用公钥进行加密后传递给李四,李四用私钥解密得到密钥。
就算第三方拿到公钥,没有私钥是无法解密密文的。
但这种方式有一个缺点:没有前向保密性。
也就是说当第三方将通讯的报文全部保存下来后,在破解出私钥之后,就能知道所有密文内容。
而DH密钥交换协议就解决了这个问题。它可以双方在完全没有对方任何预先信息的条件下通过不安全信道创建起一个密钥。所以每一次通讯中密钥都是实时生成的
具体流程:



首先在握手过程中,李四生成一对公私钥,将公钥发送给张三。
张三收到李四的公钥后,自己也生成一对公私钥,将自己的公钥发送给李四。
然后张三和李四用DH协议将对方的公钥和自己的私钥生成一个密钥。这两个密钥是完全相同的。



DH密钥交互协议的原理:



李四指定两个随机公开数g和p,然后指定自己私钥a,根据g、p和私钥a生成公钥A。
李四将公开数g和p与自己公钥A发送给张三。
张三自己指定一个私钥b,然后基于公开数g、p和私钥b生成公钥B。
张三将自己公钥B发送给李四。
张三和李四根据对方的公钥和自己的私钥,生成对称加密用的密钥K。



如图所示



DH交换协议的问题:容易遭到中间人伪造攻击。
简单来说:第三方假装自己是张三向李四进行一次DH密钥交换,然后又假装李四向张三进行一个DH密钥交换。就可以知道密钥K。
解决这个方法很简单,就是使用PKI公钥基础体系中的身份验证。第三方就无法假装李四这个站长了。
从图中看出DH协议也涉及到大量的大数乘法运算,速度也是非常慢的。而目前使用的DH密钥交换协议是基于ECC椭圆曲线加持过的,速度非常的快。称为ECDHE密钥交换算法。具体细节可以自己去搜索查询。
总结
TLS1.2中经常使用的一个安全套件是:
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
具体说明一下:



ECDHE:密钥交换算法
RSA:身份验证算法
AES:对称加密的算法
128:对称加密的密钥长度
GCM:对称加密的工作模式
SHA256:hash算法


Category golang