TLS 详细解释

前言

什么是tls呢?

tls 全称是transpot layer security,它的前身是ssl,secure sockets layer。

现在已经不用ssl了,但是有些地方也会说是ssl,其实是tls,只是一些老的说法。

那么来看下tls的全称。

正文

首先tls 是需要证书的,这个证书的作用是用来验证,当前的交互单位是真正的服务端,而不是被别人伪造的,

那么是如何证明的呢?

那么自然是通过ca单位进行验证了。

当客户端拿到证书后,那么客户端会去验证这个证书,比如有效期,证书是否吊销等等。

通过一些列验证,证明证书是对的。

那么问题来了,客户端是如何拿到证书的呢?

ClientHello       → 客户端支持的TLS版本、密码套件、随机数
ServerHello      ← 服务器选择的密码套件、随机数
Certificate      ← 服务器证书(含公钥)

嗯,这样就拿到证书了。

也就是说客户端会发起clienthello,协商后面使用的tls版本、密码套件、随机数等。

这里我们就提出了一个问题,既然公钥是公开的,那么好像这一步好像都可以伪造啊。

是的,如果仅仅是这里,那么伪造服务端好像没啥问题啊,因为公钥是公开的。

但是我们的目的不是为了验证证书,而是数据加密,这里是为了客户端拿到的一定是服务端的公钥,而不是伪造的公钥,这里很重要。

好了,现在保证了客户端拿到的公钥一定是服务端的公钥了。

那么如何加密呢?

直接用公钥加密和用公钥解密? 这样不太行,因为公钥是公开的嘛。

一开始有rsa 秘钥交换,这种方式,只是用公钥加密私钥解密来交换后需的加解密方式。

这里就很危险,娓娓道来。

RSA密钥交换的握手流程

  1. Client Hello

客户端向服务器发送支持的TLS版本、密码套件列表(包含TLS_RSA_WITH_*)等。

  1. Server Hello

服务器选择TLS_RSA密钥交换的密码套件(如TLS_RSA_WITH_AES_256_CBC_SHA),并发送服务器证书(包含RSA公钥)。

  1. Premaster Secret生成

客户端生成一个48字节的预备主密钥(Premaster Secret)。

用服务器的RSA公钥加密该密钥,发送给服务器(ClientKeyExchange消息)。

  1. 密钥派生

服务器用RSA私钥解密得到Premaster Secret。

双方根据Premaster Secret、随机数(ClientHello和ServerHello中的)派生会话密钥(加密数据的对称密钥)。

这样看起来好像没啥问题哈,别人好像拿不到Premaster Secret似乎是安全的,因为公钥加密的必须用私钥来解密,然后公钥又是通过验证的。

为什么不安全?

  1. 缺乏前向保密(Forward Secrecy)

若服务器的RSA私钥未来被泄露(如被破解或窃取),攻击者可解密所有历史通信(因会话密钥由RSA加密传输)。

只要是私钥后面被拿到了,前面的会话就可以拿到Premaster Secret,向前保密性是没有的。

前向保密要求每次会话的密钥独立,即使长期私钥泄露也不影响历史通信。RSA密钥交换无法满足这一点。

  1. 依赖单一密钥

RSA密钥交换完全依赖服务器的RSA密钥对。相比之下,DH(Diffie-Hellman)或ECDH密钥交换通过临时密钥对实现每次会话的独立密钥协商。

  1. 密钥管理风险

长期使用的RSA私钥若未妥善保护(如未使用HSM或定期轮换),风险更高

其实总得来说就是缺乏向前保密性,就是私钥被获取,历史的都是问题。

那么如何改善呢? 这个时候就需要临时性,也就是每一次会话都应该会话结束后,就解不开。

既然有临时状态,那么如何才能实现临时性呢?

现在的秘钥生成是 security key = fun(客户端随机数)

依赖客户端随机数,但是这个客户端随机数又是可以通过私钥解开的,这是个传输问题。

如果客户端随机数不仅仅通过私钥解开,之所以能够向前是因为私钥具备稳定性,而不是临时性,而是还存在一个临时的rsa呢?

这个怎么实现呢?

来看一下ECDHE + rsa。

1. ClientHello       → 客户端支持的TLS版本、密码套件、随机数
2. ServerHello      ← 服务器选择的密码套件、随机数
3. Certificate      ← 服务器证书(含公钥)
4. ServerKeyExchange← 服务器的临时ECDH公钥参数(RSA签名)
5. ClientKeyExchange→ 客户端的临时ECDH公钥参数
6. 双方计算共享密钥 → 通过ECDH算法生成会话密钥(无需公钥加密)
7. 切换对称加密     → 后续通信使用AES等对称加密

流程是这样的,还是有点模糊。

因为这里临时ECDH公钥参数 这里是明文,不还是会被捕获吗? 不还是可以解析出来吗?

来看一下细节,细节就是客户端有一个临时私钥。

  1. 客户端的临时私钥是什么?

临时性:仅在单次TLS会话中生成,会话结束后销毁。

作用:用于密钥交换算法(如ECDHE),与服务器的临时公钥共同生成共享密钥(Pre-master Secret)。

数学关系(以ECDHE为例):

客户端生成临时密钥对:

私钥(d_client):保密,仅客户端知晓。

公钥(Q_client = d_client × G):发送给服务器(G为椭圆曲线基点)。

服务器同理生成临时密钥对(d_server, Q_server)。

来看下具体怎么操作的:

  1. ClientHello

客户端发送支持的密码套件和随机数(Client Random),此时尚未生成临时私钥。

  1. ServerHello + ServerKeyExchange:

服务器回复随机数(Server Random)和 临时ECDHE公钥(Q_server)

  • 签名(用长期私钥(如 RSA/ECDSA)签名 Q_server,发送给客户端(ServerKeyExchange))
    【私钥d_server服务端留着】。
  1. ClientKeyExchange

用公钥验证签名. 这里签名是为了证明Q_server 是从服务端发出来的。

客户端生成临时ECDHE密钥对(d_client, Q_client)。

将 Q_client 发送给服务器(明文传输)。

Shared Secret = d_client × Q_server 

服务端得到Shared Secret公式为:

Shared Secret = Q_client × d_server 

因为网络捕获,不知道客户端的d_client也不知道服务的d_server,那么得不到Shared Secret。

  1. 生成秘钥

双方用 Shared Secret、Client Random、Server Random 派生对称密钥(如AES密钥)。

因为ECDHE密钥对是临时的,所以以前的会话也就回复不了。

我们这里每次tls的时候,clienthello阶段,每次都需要发送一个公钥,那么我们缓存的意义何在呢?

其实这个clienthello阶段一定会发生,但是参数的改变可能服务端就不需要发送证书:

会话恢复机制:

Session ID(TLS 1.2)

客户端在ClientHello中携带之前缓存的Session ID。

服务器检查Session ID有效性:

如果有效 → 跳过证书发送,直接复用会话密钥。

如果无效 → 回退到完整握手(发送证书)。

Session Ticket(TLS 1.3)

客户端在ClientHello中携带加密的Session Ticket(由服务器上次握手时签发)。

服务器解密Ticket并验证:

如果有效 → 跳过证书发送,直接恢复会话。

如果无效 → 回退到完整握手(发送证书)。

Client                  Server
------                  ------
ClientHello  ----------->
                       ServerHello
                       Certificate
                       ServerKeyExchange
                       ServerHelloDone
ClientKeyExchange  ----------->
[ChangeCipherSpec]
Finished     ----------->
                       [ChangeCipherSpec]
                       Finished
                       NewSessionTicket  <----------  (Session Ticket 颁发)

简单介绍一下tls。

posted @ 2025-05-07 17:52  敖毛毛  阅读(159)  评论(0)    收藏  举报