通俗理解SSL/TLS协议区别与原理

区别(历史)

TLS 1.0又被叫做SSL 3.1
换算关系:

1
2
3
TLS 1.0 = SSL 3.1
TLS 1.1 = SSL 3.2
TLS 1.2 = SSL 3.3

综上,简单说,它们的区别只是版本更迭而已。
展开说的话,历史:

1994年,NetScape公司设计了SSL协议(Secure Sockets Layer)的1.0版,但是未发布。
1995年,NetScape公司发布SSL 2.0版,很快发现有严重漏洞。
1996年,SSL 3.0版问世,得到大规模应用。
1999年,互联网标准化组织ISOC接替NetScape公司,发布了SSL的升级版TLS 1.0版。
2006年和2008年,TLS 1.1版和TLS 1.2版发布。(TLS1.2已经获得主流浏览器支持)
2008年8月,TLS 1.3版发布,性能好。移除了很多东西,速度快了很多,少了一次握手。

TLS1.2: 兼容性高;握手需要2RTT;(重连需要1RTT)
TLS1.3: 安全、性能高;握手需要1RTT;(重连需要0RTT)

综上,可以先用TLS 1.2获得最大的兼容性。

原理

和以前莉姐课上说的PGP协议差不多,都是三板斧:摘要、非对称加密、对称加密。

要解决的问题

1. 窃听。解决方案:加密
2. 篡改。解决方案:摘要 (解决数据完整性)
3. 冒充。解决方案:数字签名 (解决中间人攻击)

架构

ISO七层协议:
TCP : 传输层
TLS : 会话层
表示层略
HTTP: 应用层
TLS+HTTP=>HTTPS

所以是先进行3次握手建立TCP,然后4次握手建立TLS,然后进行HTTP数据传输。

如果在TCP层抓包的话,里头是TLS加密过的数据。(中间人无法知道内容)
如果在HTTP层(应用层)收取数据的话,是已经解密过的明文。(但是中间人不太可能在应用层,除非已经嵌入到业务层代码了。)

这个分层架构的划分其实不太合理,quic重新做了分层,详见:
http://xiaoyue26.github.io/2022/02/17/2022-02/http3-quic%E4%BC%98%E7%BC%BA%E7%82%B9%E5%8F%8A%E5%8E%9F%E5%9B%A0/

简化版加密通信

假设用三个算法做一下加密通信,可以怎么实现呢?
定义如下:
RSA: 一种非对称加密算法
AES: 一种对称加密算法
SHA1: 一种摘要算法

方案1:AES(K,data)

假如客户端是C,服务端是SCS要传输的数据data
直接传明文肯定是不行,可以加密一下。用一个密钥K,加密成AES(K,data)
这里为啥用AES呢,不用RSA呢,因为非对称加密(RSA)太慢了。

  • 问题:
    虽然别人不知道你俩传输了啥,但是可能悄悄得在中间篡改了数据,双方察觉不到。
  • 解决方案:
    加上摘要算法。

方案2:AES(K,data+SHA1(data))

可以在数据后面加上数据的摘要,然后再加密,这样中间人一旦乱改东西马上就会被检测出来,类似于校验位。

  • 问题:
    上述方案都有一个前提,就是通信双方使用同一个K进行加解密。
    那么一开始的时候怎么约定、协商这个密钥K呢?
  • 解决方案:
    先用RSA协商出一个对称密钥K。

协商密钥

最安全的方法当然是线下见面,约定一个密钥K。但是这个通信效率太低了,并发也不高。
为了避免中间人攻击,这个问题的关键点在于确认对方的身份。对于CS架构来说,最关键的是客户端确认服务端的身份。因此一个很自然的思路是让每个服务端有自己的身份证。

计算机领域的话,身份证就是数字证书,颁发身份证的机构就是CA。
具体原理就是非对称加密:
服务端通过数字签名向客户端证明自己的身份,客户端定义一个对称密钥K,然后用服务端的公钥加密一下发给服务端,因为只有服务端能用私钥解开,因此协商密钥的过程是安全的。(即使别人截获到也没关系)

相关原理:

对称加密:

加密时候用密钥K,解密时候也用密钥K,是对称的,因此叫对称加密。

非对称加密:

加密时候用公钥K1,解密时候用私钥K2,不是同一个密钥,不对称,因此叫非对称加密。
msg = RSA(K1,data);
data = RSA(K2,msg)

也就是说,把数据用K1加密一下,可以且仅可以用K2解开;反之用K2加密消息,也可以且仅可以用K1解开,这个特性就很厉害了,正好可以用于身份认证的需求。

回到刚才的需求,需要有一种数字证书的机制。
简单实现就是服务端先去CA申请一对密钥(K1,K2),他选K1作为公钥,另一个K2作为私钥。
当他需要向别人证明自己的身份的时候,他用私钥加密一下消息发给客户端(RSA(K2,data),数字签名)。客户端可以用公钥K1解开消息,确认他的身份。客户端可以用公钥K1加密一份数据发出去,这份数据也就服务端能解开,因为只有服务端有私钥K2。

总结:

数字签名: RSA(私钥K2,data)
加密一份只有指定人能解开的数据: RSA(公钥K1,data)。

这个过程中客户端如何得到公钥K1呢?
可以由服务端发给客户端数字证书,证书由CA签名证明服务端的公钥确实是K1。

客户端是因为信任CA,所以信任CA作保的服务端公钥K1,所以才可以用K1验证服务端的数字签名。(信任传递)
也就是说即使是网络世界,也还是需要签发证书的机构的。类似于一种官方机构。如果没有这种信任的基础,匿名的网络世界是很难建立起互信机制的。

TLS组成部分

握手协议+记录协议

1。握手协议包括:

  • 握手:证书认证、协商算法和密钥;
  • 密码规格变更协议:v1.3删除了;
  • 警告协议: 错误的时候通知对方;
  • 应用数据协议: 传输数据协议;
    2。记录协议:负责使用对称密码对消息进行加密;

TLS运行流程

简单地说就是2个步骤:先协商一个密钥,之后的通信就用这个密钥加密数据。
TLS 1.2:
协商: 4次握手,协商出一个对称加密的密钥K;
通信:双方用K加密数据以后通信。

如上图所示,这4次握手就是想要协商出一个对称加密的密钥KEY,以及摘要算法的密钥。
图中的变量定义:

1
2
3
4
5
6
7
r1: 随机数1;
r2: 随机数2;
r3: 随机数3;
AES(KEY,data): 密钥是KEY,对称加密data;
RSA(K1,data): 密钥是K1, 非对称加密data;
finish: finish信息
HMAC(data): 用HMAC算法对data做摘要(key省略了)。

其中对称加密的KEY是根据3个随机数r1,r2,r3生成出来的。之所以需要这么多随机数,是为了保证这个KEY的随机性。

具体展开来说的话4次握手:
1.客户端=>服务端:

(1)随机数r1;
(2)客户端支持的协议版本、算法版本;

2.服务端=>客户端:

(1)随机数r2;
(2)确定用的协议、算法版本;
(3)CA签名的证书(里面有服务器公钥K1);
(4)服务端数字签名。

3.客户端=>服务端: 先确认服务端的身份、生成r3, 生成对称加密的key,然后发送数据:

(1)用服务器公钥K1非对称加密后的随机数r3;
(2)对称加密过的finish信息以及摘要。
(此时客户端已经有了r1,r2,r3,可以生成对称加密密钥key)

4.服务端=>客户端: 先解开非对称加密的数据,得到r3,然后生成对称加密的key,然后解开finish信息,发现确实能用,也就是客户端进行的对称加密是符合预期的,然后发送:

(1)对称加密过的server finish信息以及摘要。

如果客户端和服务端都能对Finish信息进行正常加解密且消息正确的被验证,则说明握手通道已经建立成功,接下来,双方可以进行对称加密的数据传输了。

几个小细节

  1. 上面的HMAC摘要算法也是有key的,而且也是由r1,r2,r3算出来的;
  2. 大部分时候只需要认证服务端身份(http),有时候也需要认证客户端身份,这个时候就需要客户端也有CA证书。
  3. 实际代码实现中,三个随机数都是有名字的:
    1
    2
    3
    r1: 随机数1; => random_C(random number)
    r2: 随机数2; => random_S(random number)
    r3: 随机数3; => pre-master key(random number)
    r3是关键的加密保护的随机数,r1,r2,r3一起生成key。
    r1,r2的主要用途是为了避免中间人攻击、重放攻击。(用摘要确保r1,r2无篡改,然后又是随机数的话,就不会因为是重复的key被碰撞到相同的r3,从而生成相同的key)
    此外其他术语也略有不同:

DH密钥交换算法(怎么用3个随机数算出密钥)

如上图所示:
客户端计算密钥:

1
2
A= g^a mod p 
K = B^a mod p

服务端计算密钥: b

1
2
B = g^b mod p
K = A^b mod p

同模推导:

1
2
3
4
5
K = A^b mod p 
= (g^a mod p) ^ b mod p
= g^ab mod p
= (g^b mod p ) ^ a mod p
= B^a mod p

三个随机数中,有一个是本地随机生成的,不用网络传输;
(对于服务端来说是a,客户端是b,而网络传输的是A和B,因此中间人进行反向破解难度大)
由于网络上传输的只是p,g和A,B,难以破解出a,b,因此中间人也难以破解出K。

tls1.2实际加密方式

实际上加密算法是需要padding的,最早的padding方法是:
AES(text+MAC(text)+padding)
后来因为这种方式容易遭遇padding攻击,因此tls1.3采用了更安全的padding方法:
E=AES(text+padding)
然后: E+MAC(E)

padding攻击,通过反复修改部分内容、并触发解密过程,从而探测猜测加密算法的密钥;

tls1.3的前向安全性

前向安全: 当前会话的密钥泄露后,不能用来解密以前会话的消息,也就是不影响以前会话的安全性。
例如如果每次会话都用ECDHE协商新的密钥,这次会话的密钥无法用于以前的会话解密,则可以达到前向安全性。

Ephemeral Secret (ES):每个连接新鲜的 ECDHE 协商得出的值。凡是从 ES 得出的值,都是前向安全的(当然,在 PSK only模式下,不是前向安全的)。
Static Secret (SS):从静态,或者半静态key得出的值。例如psk,或者服务器的半静态 ECDH 公钥。

如果用Session ticket或者server config机制来实现0RTT的快速建立连接,本质上是客户端缓存了一部分上次建连的密钥信息;
因此tls1.3虽然提高了性能,但是牺牲了一定时间(配置过期时间内)的前向安全性。

可能的优化

TLS1.2的4次握手可以优化成近似3次握手。
因此协商过程中唯一不会被中间人破译的是客户端第三次握手发送的随机数r3,只要确保这一性质即可。这个r3之所以不会被破译,是因为是用服务端公钥加密的,只有服务端私钥能解开。
因此如果客户端事先知道服务端的公钥,可以在第一次握手的时候,就发送由服务端公钥加密的r3。(对于以前曾经通信过的服务端,这一前提是可行的)

因此整个流程就是:
1.客户端=>服务端:
(1)r1; //防重放
(2)RSA(K1,r3+hash(r3)); //可以把自己支持的所有协议的随机数都算好,加密好。
(3)支持的协议、算法;
2.服务端=>客户端:
(1)RSA(对r1的回应),顺便签名证明自己的身份,也消除了重放攻击;
(2)r2; 明文即可
(3)确定的协议、算法;
(4)AES(Key,finish信息+HMAC(finish信息)); // 客户端知道上述两个信息,就能算出对称加密的key了。

3.客户端=>服务端: AES(Key,finish信息+HMAC(finish信息))

TLS 1.3实际的优化

回顾TLS1.2:
第1个RTT:协商用什么协议,client hello + server hello;
第2个RTT:协商对应协议下,用什么随机数,client key exchange + server key exchange;

TLS1.3的选择:
牺牲兼容性,去掉第一次rtt的密钥协议协商,直接按自己选择的成熟安全的密钥套件生成对应参数,然后发送给服务端;
如果失败,再走HelloRetryRequest。
因此Tls1.3只需要1RTT就可以建连。(第二次建立是甚至0RTT,连协商过程都省了,直接告诉服务器用上次的密钥)

参考链接:
https://www.cnblogs.com/lovesong/p/5186200.html
https://blog.soaer.com/1/3eac1f9d9045410fb249dbc81cff6b22.html
http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html

推荐文章