首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

TLS协议中PRF和TLS1.3中的HKDF

  • 24-03-03 17:01
  • 4058
  • 11165
blog.csdn.net

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) = seed
      A(i) = HMAC_hash(secret, A(i-1))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

所谓的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
  • 1
  • 2
  • 3

TLS 1.2中

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

可见,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
                 |
                 v
   PSK ->  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_secret
                 v
           Derive-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_secret
                 v
           Derive-Secret(., "derived", "")
                 |
                 v
      0 -> 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

说实话,这张图让我第一次对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)
  • 1
  • 2
  • 3

而

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

所以

Derive-Secret(Secret, Label, Messages) 
= HKDF-Expand(Secret, HkdfLabel, Hash.length)
  • 1
  • 2
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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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

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

图解1 - 从上往下看

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

图2

                 0
                 |
                 v
   PSK ->  HKDF-Extract = Early Secret
                 |
                 |
                 |
                 |
                 v
           Derive-Secret(., "derived", "")
                 |
                 v
(EC)DHE -> HKDF-Extract = Handshake Secret
                 |
                 |
                 |
                 |
                 |
                 v
           Derive-Secret(., "derived", "")
                 |
                 v
      0 -> HKDF-Extract = Master Secret
                 |
                 |
                 |
                 |
                 |
                 |
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

这个图正是 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", "")
                 |
                 v
      in secret -> HKDF-Extract = xxx
                 |
                 |
                 |
       
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

多次反复调用,就形成了图2。
psk和0生成 early secret
early secret和pms生成handshake secret
handshake secret和0生成master secret

图解2 - 从左往右看

计算出来的 early secret、handshake secret、master 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)
  • 1
  • 2

其中 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

注:本文转载自blog.csdn.net的Mrpre的文章"https://blog.csdn.net/mrpre/article/details/80056618"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top