https连接建立以及密钥加密详解

https连接建立以及密钥加密详解

一、TCP三次握手

交换https数据之前,客户端和服务端必须先进行TCP三次握手:

  1. 客户端发送SYN
  2. 服务端回复SYN-ACK
  3. 客户端回复ACK

二、TLS握手(开始传输内容的加密工作)

基于RSA密钥交换算法的TLS握手

  1. ClientHello

    • 客户端支持的TLS协议版本
    • 生成的随机数(用于生成会话密钥的条件之一)
    • 客户端支持的密码套件列表:客户端支持的加密算法,如RSA加密算法
  2. ServerHello

    • 确认TLS版本,浏览器不支持则关闭机密通信
    • 服务器生成随机数,后面用于生产会话密钥
    • 确认密码套件列表,确认使用什么加密算法
    • 服务器的数字证书

    Q:数字证书有什么用?为什么要有数字证书?发明数字证书是为了解决什么问题?

    A:先说一下什么是对称加密和非对称加密:

    • 非对称加密:使用两个密钥,公钥可以任意分发而私钥保密(公钥加密只能用私钥解密,公钥不能解密),可以解决密钥交换问题但速度慢
    • 对称加密:只使用一个密钥,运算速度快,但必须保密,无法做到安全的密钥交换
    • http采用的是混合加密:通信建立前第三步客户端回应采用非对称加密,通信过程中全部使用对称加密的会话密钥加密明文数据

    接下来聊数字证书:前面收到采用非对称加密,这时我们的内容不想被攻击者窃取,所以使用服务器提供的公钥加密,服务器自己用私钥解密,这样攻击者就解密不了,因为只有私钥可以解密,但是我们有个前提必须保障:服务器的公钥怎么到客户端手里,客户端拿到后又怎么保障这个是来自服务器而不是被人偷偷换掉了

    数字证书起的就是一个证明人的作用,服务端的公钥存放在证书中,客户端验证证书的合法性方能拿到公钥。这是数字证书的基本作用,详细后面讲。

  3. 客户端回应

    • 首先通过浏览器或者操作系统中的CA公钥(这个是来验证数字证书的合法性的),确认服务器数字证书的真实性
    • 从数字证书中取出服务器的公钥,然后使用它加密报文,向服务端发送信息:
      • 一个随机数(被公钥加密)
      • 加密通信算法改变通知,随后信息都会使用会话密钥(对称加密)加密
      • 客户端握手结束通知,这一项同时把之前所有内容的发生数据做个摘要(发送整个握手内容中所有消息的哈希值),再用会话密钥加密一下,供服务端校验。如果发现异常,服务端会立即发送一个致命警报(Fatal Alert),并终止握手,双方放弃本次连接。不会尝试修复,直接放弃。

    Q:摘要算法介绍

    A:简单讲就是对传输的内容进行哈希运算计算出哈希值,这个哈希值唯一且不能通过哈希值推导出内容。对方收到后先对内容也计算一个哈希值,进行比较,如果相同说明内容没有被篡改,否则可以判断内容被篡改了。

    上面的第一项的随机数就是整个握手阶段的第三个随机数,服务端和客户端都有了这三个随机数,接着就用双方协商的加密算法,各自生成本次通信的会话密钥。

  4. 服务器的最后回应

    服务器收到客户端的第三个随机数之后,通过协商的加密算法,计算本次通信的会话密钥

    然后向客户端发送最后的消息:

    • 加密通信算法改变通知:表示随后的信息都将用会话密钥加密通信
    • 服务器握手结束后,同时把之前所有的内容的发生的数据做个摘要,用来给客户端校验

至此,整个 TLS 的握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的 HTTP 协议,只不过用会话秘钥加密内容。

缺陷使用RSA算法最大的问题就是不支持前向保密

因为客户端传递随机数给服务端时使用的是公钥加密,一旦服务端的私钥泄漏了,过去被第三方截获的所有TLS密文都会被破解。为了解决这个问题:后面出现了ECDHE密钥协商算法

基于ECDHE密钥交换算法的TLS握手

ECDHE算法具有前向安全,所以被广泛使用

在这之前,先来推导一下算法的由来,我直接不讲数学,用最通俗方法讲解,有兴趣再去看对应的数学是啥

  1. 离散对数

    一个公式:a^i mod p = b

    指数i称为b的以a为底数的模p的离散对数

    特点是根据从左往右计算容易,但从右往左计算就很难,尤其是p为很大的质数

    text 复制代码
    //举个例子
    计算3^1000 mod 97 计算机可以快速计算
    //反过来
    已知3^x mod 97 = 某个数,求x
    //计算机只能暴力尝试,不断带入x计算

    Q:为什么P要是很大的质数?

    A:安全性取决于可能的取值数量的大小:

    • p为质数:可以取到1-p-1的所有值,只能硬试暴力破解;
    • p为合数,结果只能取到p-1的一部分,攻击空间大幅减小
  2. DH算法

    1. 现假设小红和小明约定使用 DH 算法来交换密钥,那么基于离散对数,小红和小明需要先确定模数和底数作为算法的参数,这两个参数是公开的,用 P 和 G 来代称。
    2. 然后小红和小明各自生成一个随机整数作为私钥,双方的私钥要各自严格保管,不能泄漏,小红的私钥用 a 代称,小明的私钥用 b 代称。
    3. 现在小红和小明双方都有了 P 和 G 以及各自的私钥,于是就可以计算出公钥:
    4. 小红的公钥记作 A,A = G ^ a ( mod P );
    5. 小明的公钥记作 B,B = G ^ b ( mod P );
    6. A 和 B 也是公开的,因为根据离散对数的原理,从真数(A 和 B)反向计算对数 a 和 b 是非常困难的,至少在现有计算机的计算能力是无法破解的
    7. 双方交换各自 DH 公钥后,小红手上共有 5 个数:P、G、a、A、B,小明手上也同样共有 5 个数:P、G、b、B、A。
    8. 然后小红执行运算: B ^ a ( mod P ),其结果为 K,因为离散对数的幂运算有交换律,所以小明执行运算: A ^ b ( mod P ),得到的结果也是 K。

    这个K就是对称加密密钥,可以作为会话密钥使用

    整个过程就公开了4个信息:P,G,A,B,由前面的知识可以知道黑客很难破解,因此DH密钥交换是安全的

  3. DHE算法

    DH算法分为static DH 算法和 DHE算法,前者指双方中一般是服务端的私钥一直是一样的,所以服务端的公钥是不变的,攻击者可以截获海量密钥协商过程的数据暴力破解服务器的私钥,所以static DH 不具备前向安全性;DHE则是双方每次密钥交换通信的私钥都是随机生成的,临时的。每个通信过程中的私钥都是没有任何关系的,都是独立的,这样就保证了前向安全。

Q:什么是前向安全?

A:前向安全 是一种通过使用"临时密钥交换"技术,确保长期密钥的泄露不会危及过往会话安全的机制。在监控无处不在、数据存储成本极低的时代,前向安全是确保网络通信"即使未来被攻破,过去依然安全"的核心保障。

  1. ECDHE算法

    DHE算法计算性能不佳,需要做大量乘法,为了提升性能,出现了现在广泛应用于密钥交换的ECDHE算法,本质就是利用ECC椭圆曲线特性,用更少的计算量计算出公钥以及最终的会话密钥。

    • 两人事先确定使用哪种椭圆曲线和曲线上的基点G,这两个参数是公开的
    • 各自随机生成一个随机数作为私钥d,并与基点G相乘得到公钥Q(Q=dG) ×表示点的数乘
    • 双方各自交换,最后小红计算点(x1,y1) = d1Q2,小明计算点(x2,y2) = d2Q1,由于椭圆曲线上是可以满足乘法交换和结合律,所以 d1Q2 = d1d2G = d2d1G = d2Q1 ,因此双方的 x 坐标是一样的,所以它是共享密钥,也就是会话密钥
  2. 接下来我们开始捋一下完整的握手过程:

    1. ClientHello

      客户端使用的TLS版本号

      支持的密码套件列表

      生成的随机数

    2. Server Hello

      确认TLS版本号

      给出一个随机数

      选择一个合适的密码套件:注意!!

      TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

      • 密钥协商算法使用 ECDHE;

      • 签名算法使用 RSA:这里的RSA不用于密钥交换而是用于签名,提供身份认证

      • 握手后的通信使用 AES 对称算法,密钥长度 256 位,分组模式是 GCM;

      • 摘要算法使用 SHA384;


      与上面分开发送Certificate消息,发送证书

      发送完证书后,发送Server Key Exchange消息:

      • 选择椭圆曲线(选好了椭圆曲线相当于椭圆曲线基点G也定好了),公开给客户端
      • 生成随机数作为服务端椭圆曲线的私钥,保留到本地
      • 根据基点G和私钥计算出服务端的椭圆曲线公钥,公开给客户端

      为保证公钥不被第三方篡改,服务端使用RSA签名算法给服务端的公钥做个签名

      注意!!:签名 ≠ 加密

      这里的签名和公钥是两个独立的数据 ,签名并不是对公钥进行加密,而是通过私钥对其哈希值进行签名,用于保证公钥在传输过程中未被篡改,同时证明该公钥确实来自服务器。


      Server Hello Done 打招呼完毕

    3. 客户端回应

      • 证书校验确认服务端身份
      • 生成一个随机数作为客户端椭圆曲线私钥,再根据前面服务端的信息生成客户端的椭圆曲线公钥,然后用Client Key Exchange消息发给服务端

      至此,双方可以计算出(x,y),其中前面讲x是会话密钥,但在实际应用中,最终的会话密钥是用客户端随机数+服务端随机数+x三个材料生成的,因为TLS设计者不信任客户端 或服务器伪随机数的可靠性,为了保证真正的完全随机,把三个不可靠的随机数混合起来,随机的程度就非常高了,足够让黑客计算不出最终的会话密钥。

      算好会话密钥后,客户端会发一个Change Cipher Spec消息,告诉服务端后续改用对称算法加密通信。

      接着,客户端会发Encrypted Handshake Message消息,把之前发送的数据做一个摘要,再用对称密钥加密一下,让服务端做个验证,验证下本次生成的对称密钥是否可以正常使用。

    4. 服务端回应

      最后,服务端也会有一个同样的操作,发Change Cipher Spec和Encrypted Handshake Message消息,如果双方都验证加密和解密没问题,那么握手正式完成。于是,就可以正常收发加密的 HTTP 请求和响应了。

三、扩展与补充

RSA与ECDHE握手过程的区别

  • RSA 密钥协商算法不支持前向保密,ECDHE 密钥协商算支持前向保密
  • 使用了 RSA 密钥协商算法,TLS 完成四次握手后,才能进行应用数据传输,而对于 ECDHE 算法,客户端可以不用等服务端的最后一次 TLS 握手,就可以提前发出加密的 HTTP 数据,节省了一个消息的往返时间(这个是 RFC 文档规定的,具体原因文档没有说明);
  • 使用 ECDHE, 在 TLS 第 2 次握手中,会出现服务器端发出的Server Key Exchange(沟通ECDHE)消息,而 RSA 握手过程没有该消息;

CA证书认证流程

  1. 首先 CA 会把持有者的公钥、用途、颁发者、有效时间等信息打成一个包,然后对这些信息进行 Hash 计算,得到一个 Hash 值;
  2. 然后 CA 会使用自己的私钥将该 Hash 值加密,生成 Certificate Signature,也就是 CA 对证书做了签名;
  3. 最后将 Certificate Signature 添加在文件证书上,形成数字证书;

客户端校验服务端的数字证书的过程:

  1. 首先客户端会使用同样的 Hash 算法获取该证书的 Hash 值 H1;

  2. 通常浏览器和操作系统中集成了 CA 的公钥信息,浏览器收到证书后可以使用 CA 的公钥解密 Certificate Signature 内容,得到一个 Hash 值 H2 ;

  3. 最后比较 H1 和 H2,如果值相同,则为可信赖的证书,否则则认为证书不可信。

证书信任链

操作系统里一般都会内置一些根证书,我们向CA申请的证书一般不是根证书签发的,而是有中间证书签发的,证书之间有一条链式关系连接,可以类比js的一个事件的全过程。举个例子:

  1. 客户端收到 baidu.com 的证书后,发现这个证书的签发者不是根证书,就无法根据本地已有的根证书中的公钥去验证 baidu.com 证书是否可信。
  2. 于是,客户端根据 baidu.com 证书中的签发者,找到该证书的颁发机构是 "GlobalSign Organization Validation CA - SHA256 - G2",然后向 CA 请求该中间证书。
  3. 请求到证书后发现 "GlobalSign Organization Validation CA - SHA256 - G2" 证书是由 "GlobalSign Root CA" 签发的,由于 "GlobalSign Root CA" 没有再上级签发机构,说明它是根证书,也就是自签证书。
  4. 应用软件会检查此证书有否已预载于根证书清单上,如果有,则可以利用根证书中的公钥去验证 "GlobalSign Organization Validation CA - SHA256 - G2" 证书,如果发现验证通过,就认为该中间证书是可信的。 "GlobalSign Organization Validation CA - SHA256 - G2" 证书被信任后,可以使用 "GlobalSign Organization Validation CA - SHA256 - G2" 证书中的公钥去验证 baidu.com 证书的可信性,如果验证通过,就可以信任 baidu.com 证书。

Q:为什么需要证书链这么麻烦的流程?Root CA 为什么不直接颁发证书,而是要搞那么多中间层级呢?

  1. Root CA 私钥是整个信任体系的命脉,频繁用于颁发证书会增加泄露风险
  2. 中间证书出现问题 只需要处理中间证书,如果是直接办法证书出现问题就要直接换它,所有设备都必须更新信任列表,这是巨大的灾难

TLS1.2与TLS1.3比较

TLS1.3比较于TLS1.2,将密钥交换前置到握手初期,并在服务端问候后立即进入加密通信,精简握手消息并强制使用具备前向安全的密钥交换算法。

阶段 TLS1.2 做什么 TLS1.3 做什么 本质区别 / 优化点
客户端问候 支持的协议版本- 加密套件列表- 客户端随机数 支持的协议版本- 精简的加密套件- 客户端随机数 直接带上椭圆曲线公钥 TLS1.3 一开始就发送公钥,为后面提前生成密钥做准备
服务端问候 选择协议版本- 选择加密套件- 服务端随机数 选择协议版本- 选择加密套件- 服务端随机数 返回自己的椭圆曲线公钥 TLS1.3 在这里就能完成密钥交换
密钥交换阶段 还未完成,需要后续步骤 已完成(双方已能算出共享密钥) TLS1.3 密钥生成更早
服务端密钥交换消息 有- 椭圆曲线公钥- 用证书私钥做签名 ------ TLS1.3 减少消息数量,结构更简洁
证书传输 明文发送证书 加密后发送证书 TLS1.3 保护隐私,避免被窃听分析
签名验证阶段 在"服务端密钥交换"中完成 单独通过"证书验证"消息完成 TLS1.3 职责更清晰(认证与密钥交换分离)
服务端结束标志 有(通知客户端服务端发完了) 没有 TLS1.3 删除冗余步骤
客户端密钥交换 客户端再发送自己的公钥 不需要(前面已经发过) TLS1.3 减少一次通信
开始加密通信 很晚(在"切换加密状态"之后) 很早(服务端问候之后就开始) TLS1.3 握手中后半段全部加密
切换加密状态 必须存在 基本废弃(只为兼容) TLS1.3 流程简化
完成握手验证 最后才验证所有握手数据 全程逐步验证(且已加密) TLS1.3 安全性更强
握手往返次数 需要 2 次往返(2 RTT) 只需 1 次往返(1 RTT)甚至支持 0 RTT TLS1.3 明显更快

补充 :TLS 1.3 的 0-RTT 握手是其最重要的性能优化之一。它允许客户端在完全建立加密连接之前(即在第一个数据包中)就向服务器发送应用层数据(如 HTTP 请求)。0-RTT 不能 发生在客户端与服务器的第一次连接中。它必须基于之前已经建立过的连接:

  • PSK(Pre-Shared Key): 在第一次 TLS 1.3 握手(1-RTT)成功后,服务器会发送一个 NewSessionTicket 消息给客户端。
  • 这个 Ticket 包含了一个 PSK(预共享密钥)或者可以推导出 PSK 的信息,以及该 Ticket 的有效期等元数据。
  • 客户端会将这个 PSK 存储在本地,用于后续的快速重连。
  1. 客户端发送(第 1 阶段):
    • 客户端在发送 ClientHello 的同时,附带 early_data 扩展。
    • 客户端利用之前存储的 PSK 导出"早期密钥"(Early Secret)。
    • 关键点: 客户端直接使用这个早期密钥加密 HTTP 请求(例如 GET /index.html),并随 ClientHello 一起发送给服务器。
    • 此时,客户端还没收到服务器的任何回复。
  2. 服务器处理(第 2 阶段):
    • 服务器收到 ClientHello,识别出 PSK。
    • 服务器使用相同的 PSK 导出"早期密钥",解密并处理随附的加密数据(Early Data)。
    • 服务器发送 ServerHello、完成握手,并直接返回应用层响应数据(如 HTML 内容)。
  3. 结果:
    客户端在发出第一个包后,下一个收到的包里可能就包含了业务数据。从应用层角度看,延迟为 0 个往返时延(RTT)。

但是这样存在重放攻击:举个攻击场景:

  • 第一步(截获): 客户端在咖啡厅连 WiFi 发送了一个 0-RTT 请求(比如:GET /buy_ticket)。攻击者通过监听网络,把这个二进制数据包原封不动地录下来。
  • 第二步(重放): 客户端下线后,攻击者把这个数据包再次发给服务器。
  • 第三步(服务器被骗): 服务器收到后,发现 PSK 是对的,解密出来的加密请求也是完整的。服务器并不知道这是攻击者发来的旧包,以为客户端又发起了一次同样的请求。

TLS1.3的风险与性能平衡策略

  1. 服务器端抗重放检测: 服务器记录最近收到的 0-RTT 请求的"指纹"。如果短时间内看到重复的指纹,就拒绝它。但这需要大量内存。
  2. 限制业务场景: 就像之前提到的,只允许**幂等(相同输入都得到相同输出)(GET)**操作。如果攻击者重放了一个"看新闻"的请求,由于看一次和看十次结果一样,重放也就失去了攻击价值。
  3. 过期时间: 强制 0-RTT 的 Ticket(PSK)在很短时间内失效。

TLS记录协议过程(非握手协议过程)

TLS 记录协议负责保护应用程序数据并验证其完整性和来源,所以对 HTTP 数据加密是使用记录协议;

  • 首先,消息被分割成多个较短的片段,然后分别对每个片段进行压缩。
  • 接下来,经过压缩的片段会被加上消息认证码(MAC 值,这个是通过哈希算法生成的),这是为了保证完整性,并进行数据的认证。通过附加消息认证码的 MAC 值,可以识别出篡改。与此同时,为了防止重放攻击,在计算消息认证码时,还加上了片段的编码。
  • 再接下来,经过压缩的片段再加上消息认证码会一起通过对称密钥进行加密。
  • 最后,上述经过加密的数据再加上由数据类型、版本号、压缩后的长度组成的报头就是最终的报文数据。

记录协议完成后,最终的报文数据将传递到传输控制协议 (TCP) 层进行传输。


!! 以上是过程是以前的做法,存在一定的安全风险:

  1. 采用MAC+CBC(一种对称加密的工作模式),会导致Padding Oracle Attack,Lucky13等攻击,具体大家自己了解,但本质就是因为CBC模式需要填充(要求明文长度是块大小的整数倍,块指的是分组密码在进行加密运算时一次性处理的数据单元),解密时先校验填充后校验MAC,攻击者可以利用漏洞不断进行尝试,这里我们以Lucky13进行攻击例子:

    1. 攻击者发送一个精心修改的密文。
    2. 服务器处理时:
      • 如果填充错误,它会立即返回错误,不计算MAC。
      • 如果填充正确,它需要先移除填充,再计算MAC(计算MAC需要遍历整个数据,时间更长)。
    3. 攻击者通过精确测量响应时间:时间短 = 填充错误时间长 = 填充正确
    4. 通过几万次这样的时序试探,攻击者就能像猜密码一样,一字节一字节地解密出整个会话的Cookie、密码等敏感信息。
  2. 解决方法:采用更先进的AEAD机制

    1. 一次性完成认证和加密,减少实现错误

    2. CBC模式需要填充,AEAD不需要填充,根本上移除了填充相关的攻击面

    3. AEAD 是 先验证,后解密 。CBC+MAC 是 先解密,后验证。先验证意味着攻击者连触发解密的机会都没有,也就无法通过操纵解密过程中的中间状态来获取信息。

      • CBC+MAC 模式 :它的验证路径是 明文依赖型

        1. 先解密 密文 -> 得到明文

        2. 检查明文中的填充是否合法 -> 这个检查完全依赖于解密后的明文内容。

          填充字符和明文字符之间确实存在这种可被利用的数学关联,这正是 Padding Oracle Attack 能够成功破解明文的根本原因

        3. 如果填充合法,再对明文计算 MAC。

        4. 攻击者正是利用了"填充是否合法"这个依赖于明文 且容易出错的步骤,通过观察服务器反应(错误信息或时间)来逐步猜解明文。解密过程与明文内容产生了条件分支(例如,if 填充合法 then 做某事)。

      • AEAD 模式 :它的验证路径是 密文+标签依赖型

        1. 同时使用密文、附加数据(AAD)、密钥和随机数(Nonce)来计算一个预期的认证标签
        2. 将这个预期标签与通信中附带的实际标签进行比较。
        3. 只有在标签验证完全通过之后,才会进行解密操作。
        4. 攻击者无法操纵"填充"来创造不同的状态,因为根本没有填充。验证过程只有一个分支:标签对还是错?
相关推荐
TechWayfarer4 小时前
如何搭建企业级IP归属地查询平台?
网络·网络协议·tcp/ip
EmbeddedCore6 小时前
守护网络通信的基石:深入解析SSL/TLS协议
网络·网络协议·ssl
.豆鲨包7 小时前
【计算机网络】数据链路层
网络·网络协议·计算机网络
奋斗tree9 小时前
HTTP Error 503 常见原因及解决方案
网络·网络协议·http
FPGA小迷弟10 小时前
FPGA工程师面试题汇总(二十四)
网络协议·tcp/ip·fpga开发·verilog·fpga
johnny23310 小时前
Python生态HTTP客户端类库:requests、httpx、aiohttp、Niquests、httpcore
python·http
EmbeddedCore10 小时前
在资源受限的M3处理器上实现SSL/TLS通信的完整方案
网络协议·嵌入式·ssl
小小小陆11 小时前
同一台电脑两个WinForm程序TCP通信
网络·网络协议·tcp/ip
醇氧12 小时前
【学习】IP地址分类全解析
网络协议·学习·tcp/ip