TLS 协议中 PRF 和 TLS 1.3 中的 HKDF

我的TLS实现,大家可以参考:https://github.com/mrpre/atls/
TLS 1.3协议详解:https://blog.csdn.net/mrpre/article/details/81532469
TLS 1.0/1.1/1.2协议中,使用了PRF算法进行 key derive。
TLS 1.3中使用了标准的HKDF来进行key derive。

这里大概先回顾一下 <= TLS 1.2 时密钥导出流程和PRF算法使用场景。
然后再说一下 TLS 1.3 中的HKDF 算法 流程。

PRF算法:

PRF算法可以生成指定长度的数据

PRF调用了P_HASH算法
所以 先说P_HASH

(1) P_HASH

RFC定义:

P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +HMAC_hash(secret, A(2) + seed) +HMAC_hash(secret, A(3) + seed) + ...
其中
A() 如下定义:A(0) = seedA(i) = HMAC_hash(secret, A(i-1))

所谓的P_HASH,其实具体点就是 P_SHA256、P_SHA1…等,所以P_HASH中HMAC具体使用的HASH算法依据的就是P_HASH的具体HASH算法。P_hash中计算HMAC_hash的次数,取决于想要的输出的长度。
P_HASH迭代调用HMAC,其实 实现并不复杂,一个大循环判断是当前结果否已经满足输出长度,在循环里,先算法A(x),然后再算HMAC_hash(secret, A(x) + seed)
所以PRF算法很简单。

(2)PRF

P_HASH说完,该说一下PRF了,上面说过PRF实际调用了 P_HASH,所以现在描述下PRF

TLS 1.0/1.1 中

r1 = P_MD5(...);
r2 = P_SHA1(...);
r  = r1 xor r2

TLS 1.2中

P_SHA256(...)或者P_SHA384(...)(具体使用哪个依据握手协商的加密套件)

可见,TLS1.2中,PRF算法其实就是直接调用了P_HASH算法,而TLS 1.0/1.1调用了两次P_HASH,一次是MD5一次是SHA1,两次的结果进行亦或才是最后的结果。

PRF算法在TLS协议中的运用

TLS 协议中:
(1)
当计算主密钥(master secret)时
sec 是 “master secret” + client_random + server_random
seed 是 pre_master_secret
输出是 master secret,48字节

(2)
当计算对称密钥(key material)时
sec 是 “key expansion” + server_random + client_random
seed 是 master secret
输出是key block,输出字节长度根据加密算法而定。
key block中的各个部分,就是实际加解密使用的key。

(3)
当计算finished时
sec 是 “client/server finished”
seed 是握手的hash值
输出是12字节的值。

HKDF

HKDF本身不复杂,但是 在 TLS1.3 中的应用就比较复杂了。
HKDF详细的Paper见该文:https://eprint.iacr.org/2010/264.pdf 但是我觉得没必要看,因为看不懂。

建议看下面2篇文章:
我的HKDF RFC翻译 https://blog.csdn.net/mrpre/article/details/79879392
我的HKDF 示例代码 https://blog.csdn.net/mrpre/article/details/79881184

HKDF 在 TLS1.3中的应用,先上 RFC 的 key derive 的图:

图1

                 0|vPSK ->  HKDF-Extract = Early Secret|+-----> Derive-Secret(.,|                     "ext binder" ||                     "res binder",|                     "")|                     = binder_key|+-----> Derive-Secret(., "c e traffic",|                     ClientHello)|                     = client_early_traffic_secret|+-----> Derive-Secret(., "e exp master",|                     ClientHello)|                     = early_exporter_master_secretvDerive-Secret(., "derived", "")|v
(EC)DHE -> HKDF-Extract = Handshake Secret|+-----> Derive-Secret(., "c hs traffic",|                     ClientHello...ServerHello)|                     = client_handshake_traffic_secret|+-----> Derive-Secret(., "s hs traffic",|                     ClientHello...ServerHello)|                     = server_handshake_traffic_secretvDerive-Secret(., "derived", "")|v0 -> HKDF-Extract = Master Secret|+-----> Derive-Secret(., "c ap traffic",|                     ClientHello...server Finished)|                     = client_application_traffic_secret_0|+-----> Derive-Secret(., "s ap traffic",|                     ClientHello...server Finished)|                     = server_application_traffic_secret_0|+-----> Derive-Secret(., "exp master",|                     ClientHello...server Finished)|                     = exporter_master_secret|+-----> Derive-Secret(., "res master",ClientHello...client Finished)= resumption_master_secret

说实话,这张图让我第一次对TLS协议产生了反感。

用到的函数

看似很复杂,但是捋一下其实不复杂。

上面出现2个函数
1:HKDF-Extract,这个函数就是HKDF的extract,它的实现见我上面给的链接。
2:Derive-Secret,这个要着重说一下

根据RFC的定义

Derive-Secret(Secret, Label, Messages)
= HKDF-Expand-Label(Secret, Label,Transcript-Hash(Messages), Hash.length)

HKDF-Expand-Label(Secret, Label, Context, Length)
= HKDF-Expand(Secret, HkdfLabel, Length)

所以

Derive-Secret(Secret, Label, Messages)
= HKDF-Expand(Secret, HkdfLabel, Hash.length)
struct {uint16 length = Length;opaque label<7..255> = "tls13 " + Label;opaque context<0..255> = Context;
} HkdfLabel;
其中
HkdfLabel = Hash.length(2 字节) + label_length(1字节) + "tls13 " + Label + Hash.length(1字节) + HASH(Messages)

也就是说Derive-Secret就是HKDF的expand操作。
Derive-Secret在OpenSSL中的实现是 tls13_hkdf_expand 函数。

至此我们可以总结出,上面这个流程图中,无非2个操作,HKDF的extract和HKDF的expand操作。

图解1 - 从上往下看

不考虑图1右侧的 Derive-Secret, 那么流程图就变成了如下图2形式:

图2

                 0|vPSK ->  HKDF-Extract = Early Secret||||vDerive-Secret(., "derived", "")|v
(EC)DHE -> HKDF-Extract = Handshake Secret|||||vDerive-Secret(., "derived", "")|v0 -> HKDF-Extract = Master Secret||||||

这个图正是 tls13_generate_secret 函数所干的事情,而这个函数被如下函数调用,
tls_psk_do_binder/ssl_derive 计算 early secret
tls13_generate_handshake_secret 计算 handshake secret
tls13_generate_master_secret 计算 master secret
正好印证了tls13_generate_secret的作用。

注意:tls13_generate_secret 实际函数执行的是如图三这个流程
图三

           Derive-Secret(., "derived", "")|vin secret -> HKDF-Extract = xxx|||

多次反复调用,就形成了图2。
psk0生成 early secret
early secretpms生成handshake secret
handshake secret0生成master secret

图解2 - 从左往右看

计算出来的 early secrethandshake secretmaster secret并不会直接用来加密数据,完全可以理解为是为了计算秘钥key而产生的临时变量。这些临时变量需要按照 图1 中右侧的流程计算,生成的XXX_traffic_secret ( XXX_traffic_secret被称之为basekey ),
然而XXX_traffic_secret也不会用来加密。。。还需要按照RFC 7.3 节中描述的步骤:

[sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length)
[sender]_write_iv  = HKDF-Expand-Label(Secret, "iv" , "", iv_length)

其中 Secret 就是 XXX_traffic_secret 。而输出[sender]_write_key[sender]_write_iv就是加密时实际使用的参数了 。
这个流程在 tls13_derive_key 以及 tls13_derive_iv中实现 。

Finish key

HKDF导出的流程中,还会导出一个finished_key
finished 计算
HMAC( MD(all_handshake), finished_key)


finished_key = HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)
BaseKey就是 handshake_traffic_secret

TLS协议中PRF和TLS1.3中的HKDF相关推荐

  1. TLS协议中的握手协议

    TLS 握手协议(handshake protocol) 握手是TLS协议中最精密复杂的部分.在这个过程中,通信双方协商连接参数(沟通双方各有什么加密算法,选择一个最合适的算法),并且完成身份验证.根 ...

  2. tshark 解析pcap中带TLS协议的数据包

    tshark的简单用法参考:tshark解析本地pcap数据包提取五元组{src_ip,src_port,proto,dst_ip,dst_port}与时间戳,包长 详细用法:官方DOC 比如提取一个 ...

  3. SSL/TLS协议详解(中)——证书颁发机构

    SSL/TLS协议详解(中)--证书颁发机构 本文翻译自:https://www.wst.space/ssl-part-3-certificate-authority/ 上一篇中,我们讨论了关于Dif ...

  4. SSL / TLS协议中数字签名与hash算法的联系

    今天要为大家介绍的是哈希算法,在介绍SHA之前,只有了解什么是SHA,我们才清楚SSL证书如何使用哈希来形成数字签名.那么什么是哈希呢? HASH算法将任意长度的二进制值映射为较短的固定长度的二进制值 ...

  5. 9. PKI - 三种密钥交换算法详解(RSA DHE ECDHE)及他们在SSL/TLS协议中的应用

    9. PKI - 三种密钥交换算法详解(RSA& DHE& ECDHE)及他们在SSL/TLS协议中的应用 RSA密钥交换算法 DHE密钥交换算法 ECDHE密钥交换算法 参考 密钥交 ...

  6. 蚂蚁区块链第9课 SSL/TLS工作原理及在蚂蚁BAAS中的应用

    1,摘要 辉哥在学习蚂蚁BAAS系统时,发现了一堆证书或者公私钥名称,包括trustCa,ca.crt,client.crt,client.key,pub.txt,MyPKCS12.p12等等文件,不 ...

  7. SSL协议安全系列:PKI体系中的证书吊销

    GoSSIP_SJTU · 2016/03/03 10:06 0x00 前言 在前面的章节我们讨论了部分SSL/TLS握手协议.记录协议中存在的安全问题,针对它们的攻击以及相应的加固方案.在SSL/T ...

  8. android设置tls版本,Android O移除HttpsURLConnection中不安全的TLS版本回退

    原标题:Android O移除HttpsURLConnection中不安全的TLS版本回退 为提高安全性,在 Android O 中,已从 HttpsURLConnection 中移除不安全的 TLS ...

  9. vue-router 路由嵌套显示不出来_网络协议|OSI模型第三层网络层中的路由

    的IP协议 OSI第二层中用以太网协议定义了信息传输单元,简称为帧,它长这个样子. 同样的在OSI第三层中,会用 IP 协议去定义信息传输单元,简称为数据包,它长这个样子. 实际上,最终在网络上传输的 ...

最新文章

  1. 【面试】如何进行自我介绍
  2. 2013年1月31号
  3. html怎么引入sass样式,[样式设置] 使用sass格式的方式
  4. 十四、汇编指令(存储、加法、减法、乘法、除法、跳转、子程序、if判断、中断)
  5. 数据告诉你,哪个省才是高考地狱模式?
  6. apache http server 停止工作_Tomcat9配置HTTP/2
  7. linux 解压 7z 乱码,7z-linux下解决中文名乱码的终极办法
  8. 龙芯 Linux usb,使用debirf制作龙芯2F的LiveUSB
  9. python 音乐相册_‎App Store 上的“魔力相册-音乐相册、视频电子相册制作工具”...
  10. 【数据库取证篇】阿里云RDS数据库简介
  11. java 迭代_java迭代是什么意思
  12. Win8.1 安装nltk及nltk_data数据
  13. Netty解决TCP粘包/拆包导致的半包读写问题
  14. wdcp v2.5.15 php版本,wdcp_v2.5.15(20150826) 如何开启 多 SSL 站点!
  15. 【IP代理】吐槽某大爷IP
  16. 3.后端学习JavaScript
  17. 计算机网络安全漏洞及防范措施论文,浅谈计算机网络安全漏洞及防范措施论文.doc...
  18. 联想rd服务器系统安装,联想RD430服务器安装Windows2008R2系统
  19. 2021年科技园区规划设计方案
  20. 章丘谋定大葱功能性-农业大健康·万祥军:不当村官当会长

热门文章

  1. 【图像增广库imgaug】官方文档翻译(二):在多个 CPU 内核上进行扩充
  2. 直流分流器 shunt 电阻
  3. 揭秘开心网:创始人无专属办公室月薪9000
  4. 手写一个线程池,带你学习ThreadPoolExecutor线程池实现原理
  5. 基于Flink+Alink构建全端亿级实时用户画像系统
  6. 【博主推荐】html好看的拼图小游戏(附源码)
  7. 请简述cat和tail -f 的区别?
  8. 浪潮NF5270M3 刷uefi_创18项世界纪录,浪潮打造AI应用最强服务器
  9. 仿苹果手机通讯录按字母定位
  10. HTML学习笔记——文字与段落标记