写点什么

字节面试官:你觉得 HTTPS 能防止重放攻击吗?

  • 2021 年 11 月 11 日
  • 本文字数:1707 字

    阅读完需:约 6 分钟

我们先来回忆一下 HTTPS 的通信流程,HTTPS 协议 = HTTP 协议 + SSL/TLS 协议,摘取一下网上一些八股文的回答(以 RSA 密钥交换的为例)!


  • (1)客户端生成一个随机数 client_random,TLS 版本号,发送到服务端

  • (2)服务端发送自己的随机数 server_random,服务器使用的证书,发送到客户端

  • (3)客户端利用 CA 公钥对证书进行验证,取出服务器公钥

  • (4)客户端生成随机数 pre_master_secret,利用服务器公钥进行加密,传送到服务端

  • (5)服务端利用服务器私钥进行解密取出 pre_master_secret

  • (6)服务端和客户端此时利用随机数 client_random,server_random,pre_master_secret 算出对称密钥(master_secret),利用对称密钥进行对称加密通信


_画外音:_是不是贼熟悉,有背过网络八股文的,一看就懂!


关键问题就在步骤(6),怎么进行加密的?很多文章都没有说明,甚至有的人以为,拿 client_random+server_random+pre_master_secret 直接拼成一个字符串,然后就是对称加密密钥,客户端和服务端拿这个密钥对数据进行加密通信!!


对此,我只能说:"Too young too simple!离谱啊!!"


那正确的过程是怎么样的呢,我们继续往下看!


协议分析


====


我先给本文提到的英文单词,给上我的中文翻译,以防大家混淆:


  • client_random 客户端随机数

  • server_random 服务端随机数

  • pre_master_secret 预备主密钥

  • master_secret 主密钥

  • key_block 密钥块(有的文章把这个东西称为会话密钥)


先大致有个印象,继续往下阅读


现在我们已经有三个参数 client_random,pre_master_secret,server_random,服务端和客户端分别会根据这三个参数,推导出 master_secret,一旦 master_secret 被推导出来,会立刻删除 pre_master_secret。(摘自 rfc2246,section8.1


当 master_secret 计算出以后,立刻计算 key_block(摘自 rfc2246,section6.3),这个密钥块,有的文章里又说他是会话密钥!计算公式如下,


key_block = PRF(master_secret,


"key expansion",


server_random +


client_random)


如公式所示,PRF 是一个 Hash 算法,如 SHA256 这些,具体用哪一个取决于 TLS 协议的版本!我们得到 key_block 后,可以基于到 key_block 继续推导出 6 个密钥值,分别是


  • client_write_MAC_key 客户端消息认证码密钥

  • server_write_MAC_key 服务端消息认证码密钥

  • client_write_key 客户端对称加密密钥

  • server_write_key 服务端对称加密密钥

  • client_write_IV 客户端初始化向量

  • server_write_IV 服务端初始化向量


整个过程用一张图来说明,注意了这六把密钥是根据 key_block 推导而出,也就是意味着这六把密钥是服务端和客户端共同持有的!



大家一定也发现了,你的密钥前都带有 client 或者 server 前缀,这代表密钥是服务端使用还是客户端使用!例如,客户端用 client_write_key 进行数据加密,发送数据,服务端收到消息后利用 client_write_key 进行解密。而后服务端使用 server_write_key 进行数据加密回复信息,客户端收到消息后用 server_write_key 解密服务端发来的信息!


OK,我们继续往下看!


现在我们已经有了 6 把密钥了,已经需要发送的消息 data,那么加密流程具体怎么样的呢?


TLS 一共有三种加密模


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


式,流加密模式、分组模式、 AEAD 模式,我以流加密模式来进行说明,如下图所示



我们现在来看上面的第二步,利用 write_mac_key 对数据加密,加上 MAC 验证码,利用 MAC 码来保证完整性。


那么,这个 MAC 验证码的生成公式又是怎么样的呢?


MAC 验证码


======


在流加密模式下,MAC 验证码公式为(摘自 rfc2246,section6.2.3.1)



看到入参中的 seq_num 了么?**这就是数据的序列号,这个序号就是用来防止重放攻击的!**那这个序列号怎么用的呢?


假设,此时服务端和客户端连接成功后


_(1)_客户端会在内存中记录 client_send 和 client_recv,默认值为 0.客户端每发送一条消息,client_send 会加 1,每接收一条服务端发来的消息,client_recv 会加 1。


_(2)_服务端也会在内存中记录 server_send 和 server_recv,作用和客户端的作用一样。服务端每发送一条消息,server_send 会加 1,每接收一条客户端发来的消息,server_recv 会加 1。


_(3)_客户端发送数据时,以当前 client_send 作为 seq_num,计算 mac 值,发送给服务端,然后 client_send 加 1。

评论

发布
暂无评论
字节面试官:你觉得HTTPS能防止重放攻击吗?