三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

TLS通信加密 对称加密 公钥加密

TLS通信加密 对称加密 公钥加密

TLS通信加密

在了解TLS之前,我们先来了解一下公钥加密对称加密两种加密方式

对称加密

对称加密(Symmetric Encryption)是一种加密方式,它使用同一个密钥(Key)进行加密和解密

明文(原始信息) | | 使用密钥加密 ↓ 密文(看不懂的数据) | | 使用同一个密钥解密 ↓ 明文(恢复原信息)

以下是常见的对称加密算法

算法特点
AES (Advanced Encryption Standard)目前最常用,安全性高,广泛用于文件、通信、数据库加密
DES (Data Encryption Standard)较老,密钥长度短,已不安全
3DES (Triple DES)DES 的增强版,但速度慢,逐渐淘汰
ChaCha20高性能,常用于移动设备和网络通信

优点

  • 速度快,加密和解密效率高——适合加密大量数据

  • 资源消耗低,对CPU和内存的要求较小

问题

  1. 密钥如何安全的传递?

    假设A使用密钥K加密了文件,此时B需要通过这个密钥K解密文件,问题是如何将A手中的密钥K传给B?如果在传输的过程中被攻击者截取K,那么加密就失效了——这个问题叫做密钥分发问题

  2. 密钥管理困难

    每两个人之间可能就需要一个密钥,当用户量很大的时候就需要很多密钥,数量会快速增长

公钥加密

公钥加密(Public Key Encryption,也叫非对称加密,Asymmetric Encryption)是一种使用一对密钥的加密方式:

  • 公钥(Public Key):可以公开给任何人

  • 私钥(Private Key):必须自己保管,不能泄露

发送方 接收方 ​ 拿到你的公钥 | | 加密消息 ↓ 密文 -----------------------> 私钥解密 | ↓ 原文

也就是说使用公钥进行加密,但是解密只有接受方的私钥可以解密

  • 解决了密钥交换问题,黑客只有公钥而获取不到私钥进行解密

数字签名

私钥签名 → 公钥验证

这种用法通常用在数字签名或者是身份验证的情况,而且准确来说,此时公钥解密的不是会话内容,而是服务端发来的证书是CA机构签名的,CA用服务端持有的私钥给证书签名,而客户端使用CA提供的公钥去解签,用来证明身份

私钥 ↓ 生成签名 ↓ 消息 + 签名

接受方如果可以使用公钥也就证明了这个人的身份,在生活中可以确认

  • 是不是官方

  • 文件有没有被修改

缺点——速度慢

TLS

TLS(Transport Layer Security,传输层安全协议)是现代互联网安全通信的核心协议。你每天使用的 HTTPS、网银、邮箱、API 调用,背后基本都依赖 TLS。

前面我们讲了:

  • 对称加密:速度快,适合大量数据,但密钥分发困难

  • 公钥加密:解决密钥交换和身份认证问题,但速度慢

TLS 的目标就是:

利用非对称密码技术建立信任和交换密钥,再利用对称加密高速保护通信数据。

在客户端和服务器进行通信中,有几个要求

  1. 保密性(Confidentiality):别人不能看懂数据

  2. 完整性(Integrity):数据不能被修改

  3. 身份验证(Authentication):接收方身份正确


TLS通信完整流程(TLS 1.3

一次HTTP连接

客户端 服务器 ​ ClientHello -------------> ​ <------------- ServerHello ​ <------------- Certificate ​ <------------- Finished ​ Client Finished ----------> ​ =========================== 开始加密通信 ===========================

这里我们讲的是验证服务器身份,而不验证客户端身份

第一步:Client Hello

  • 客户端向服务端发送“TLS版本,支持的密码算法,随机数,临时公钥”

这个随机数是哪里来的?

  • 在 TCP 连通的瞬间,客户端调用操作系统的安全随机接口(RAND_bytes),用系统采集的物理噪声作为原料,在内存里现打出一个32 字节(256 bit)的随机值,直接塞进第一个网络包里发出去了

第二步:Server Hello

  • 服务端向客户端发送“选择的TLS版本,选择加密算法,临时公钥,证书链,随机数

  • 此时双方都有一对临时密钥对——这个密钥对是用来计算预主密钥的,请继续向下看

  • 客户端私钥 客户端公钥 ​ 服务器私钥 服务器公钥
  • 说明:客户端和服务端分别在自己的内存中,随机产生一个只有自身知道的——临时私钥,两个私钥完全不同,绝对不通过网络传输,然后在客户端和服务端分别将自己生成的数字通过OPENSSL库,产生两个新的数字,也就是两个临时公钥,之后把公钥发给对方

  • 此时我们需要注意:临时密钥对:每一次握手都会生成,会互相发送,只在内存中存活,用完即焚; 长期密钥对(证书):只有服务端有。服务端会把长期公钥发送给客户端用来进行身份验证,对应的长期私钥锁在服务器的硬盘中,客户端没有长期私钥

    TLS │ ┌────────┴────────┐ │ │ 身份认证(长期 密钥交换(临时 │ │ 证书/签名 ECDHE │ │ “你是谁?” “共同秘密是什么?”

第三步:Certificate

为了防止攻击者伪装成服务器,在服务端发送临时公钥或者发送的同时我们需要进行身份验证

服务端向客户端发送数字证书(Certificate),里面有服务端长期公钥,然后发送一个关键消息——CertificateVerify。该消息包含一个数字签名,是服务器用其长期私钥对整个“握手记录”(到目前为止所有握手消息)的签名。

客户端收到后,用证书中的长期公钥验证签名,就可以证明:对方确实有这个证书对应的私钥,确认服务器的身份

第四步:ECDHE密钥交换

目标是:双方在不传输自己的秘密的前提下,计算出同一个密钥

F代表OPENSSL之类的加密

  1. 客户端先(F(客户端临时私钥)),然后把再把接收到的服务端的公钥加进去

    (F(服务端公钥+F(客户端临时私钥)))

  2. 服务端执行和客户端一样的操作,就会发现这样算出来的两个结果是一样的,这个结果就叫预主密钥

    客户端: 自己的私钥 + 对方的公钥 ↓ 共享秘密 服务器: 自己的私钥 + 对方的公钥 ↓ 共享秘密
  3. 在这个过程中,虽然客户端和服务端的临时公钥是公开的,但是攻击者仍然得不到临时私钥所以肯定得不到最后的预主密钥

第五步:真正的数据加密密钥

ECDHE ↓ 预主密钥 ↓ HKDF 密钥派生 ↓ 各种 TLS Traffic Secret ↓ 具体加密密钥AES KEY

之前我们分别生成了统一的预主密钥,我们接着对这个密钥进行加密——HKDF(密钥派生函数)

一次TLS会话需要多个不同的密钥,而我们将会话密钥当作原材料,进行HKDF之后就可以派生多个相互独立的密钥,这些密钥会用来加密传输

过程并没有说的这么简单,简单理解称

ECDHE共享秘密 ↓ HKDF ↓ Handshake Secret ↓ HKDF ↓ Handshake Traffic Secret ↓ HKDF ↓ 具体加密密钥

还会生成:

Client Handshake Traffic Secret Server Handshake Traffic Secret Client Application Traffic Secret Server Application Traffic Secret

HKDF是如何工作的?

HKDF(基于HMAC的密钥派生函数)是一个标准化的密钥派生函数,它由两个核心步骤组成:

  1. 提取(Extract):输入原始密钥材料(IKM)和一个“盐值(Salt)”,输出一个固定长度的伪随机密钥(PRK)。这一步是为了“提纯”原始材料。

  2. 展开(Expand):将上一步的PRK,结合不同的“上下文信息(Info)”,通过多次计算,输出任意长度的最终密钥。

第六步:握手完成

双方确认彼此派生出相同的密钥,

  • 客户端和服务器各自发送一条Finished消息。这条消息的内容是所有握手消息的哈希值,并用握手流量密钥加密。

  • 对方收到后,用自己计算出的密钥解密并验证哈希值。如果一致,则证明双方密钥派生完全正确,且握手过程未被篡改

第七步:应用数据加密

总结一张图

服务器 │ ┌────────┴────────┐ │ │ 长期密钥对 临时密钥对 │ │ 私钥 + 公钥 私钥 + 公钥 │ │ ↓ ↓ 身份认证 ECDHE │ │ │ ↓ │ Shared Secret(预主密钥 │ │ │ ↓ │ HKDF │ │ │ ↓ │ Traffic Secret(还有HKDF的操作,最终生成使用的AES KEY │ │ │ ↓ │ AEAD(用密钥加密实际数据 │ │ └────────────→ 加密通信
← 返回列表