DTLS AES 256 CBC with SHA,我如何计算最终加密的握手消息

DTLS AES 256 CBC with SHA, how do I calculate the final encrypted handshake message

我正在尝试了解最终加密握手消息的工作原理

为此,我试图确保我的算法给出与这个有效示例相同的结果:

https://www.cloudshark.org/captures/56acf0481a79

由于 0xFEFF header.

,我很确定 DTLS 1.0 遵循 RFC 4347

已知的有

Preshared Key: 123456789012345678901234567890aa
Server Random: d87eeeb79b8c5bb29a6e01236ca75a00d515ac18a060e7b4dd4aa85d66130b41
Client Random: df14cead6b8a82a7f0fa710ed4437fa747f5f20e160b6865a3486ca3abc1c427
Cipher Suite: TLS_PSK_WITH_AES_256_CBC_SHA

我正在执行以下步骤:

预掌握秘密

The premaster secret is formed as follows: if the PSK is N octets long, concatenate a uint16 with the value N, N zero octets, a second uint16 with the value N, and the PSK itself. (RFC 4279 Section 2)

  001000000000000000000000000000000000
  0010123456789012345678901234567890aa

master_secret = PRF(pre_master_secret, "master secret", ClientHello.random + ServerHello.random) [0..47];

The PRF is defined as combining two different hashing functions. Section 5 of RFC 2246:

197c358a9de99d7c50120aea40af2095
c7c340719385f23f5355004c07d9f896
681942c494eb0d77992c3acf1bc92e4f 

根据RFC4346 key_block = PRF(SecurityParameters.master_secret, "key expansion", ServerHello.random + ClientHello.Random) Section 6.3

在这种情况下我们需要生成136字节

4921654a071c95e2ddb8e3a8162258fa
acffdd8def0a0b7ce49f492a6f088af9
e539aae851232337c90564d6d4b01fb1
0b34466fe379e34b10b5738203453253
3fe0823297ca5c111b3d23dfb6145447
a638a84376f21a845de503b324f2beab
e145274f680519cc2ecc088e0bf6fb37
69b31c82df3ce706f6ac2cb45226234a
dbd564a2b43c79ee

如果以上是正确的那么

Client Write Key: c90564d6d4b01fb10b34466fe379e34b
                  10b57382034532533fe0823297ca5c11
Client Write IV: 2ecc088e0bf6fb3769b31c82df3ce706

因此,如果我用上面的密钥和IV解密客户端握手加密记录,我得到

7fd6314cf559a60c14a44a2fd4ac5494
1400000c000200000000000ce93fd3d8
557a3eb9574d25943e01f797b982a5ed
35ce268520ef7475144441ea03030303

如何获取上面的值?

我知道这需要进行哈希处理(Client Hello + Sever Hello + Sever Hello Done + Client Key Exchange 的串联)

010000390000000000000039feffdf14
cead6b8a82a7f0fa710ed4437fa747f5
f20e160b6865a3486ca3abc1c4270000
0006008d008c00ff0100000900230000
000f0001010200003600000000000000
36feffd87eeeb79b8c5bb29a6e01236c
a75a00d515ac18a060e7b4dd4aa85d66
130b4100008d00000eff010001000023
0000000f0001010e0000000001000000
00000010000011000100000000001100
0f436c69656e745f6964656e74697479

有人能帮忙吗?

加密完成数据第一行为IV。因此,在您的解密输出中,您需要删除前 16 个字节,这给我们:

14 00 00 0C 00 02 00 00 00 00 00 0C E9 3F D3 D8
55 7A 3E B9 57 4D 25 94 3E 01 F7 97 B9 82 A5 ED
35 CE 26 85 20 EF 74 75 14 44 41 EA 03 03 03 03

从最后开始我们有以下部分:

填充(4 字节)

最后四个字节 (03 03 03 03) 正在填充,因此我们可以跳过它们。

MAC(20 字节)

接下来的 20 个字节 (3e 01 f7 97 b9 82 a5 ed 35 ce 26 85 20 ef 74 75 14 44 41 ea) 是 HMAC-SHA1 以一种特殊的方式计算出来的:你需要先附加纪元 + 消息序列号(在我们的例子中 00 01 00 00 00 00 00 00 ),然后添加 TLS 记录头(没有纪元和序列号),内容大小设置为实际内容大小(在我们的例子中为 0x18):

00 01 00 00 00 00 00 00 16 FE FF 00 18 14 00 00
0C 00 02 00 00 00 00 00 0C E9 3F D3 D8 55 7A 3E
B9 57 4D 25 94

让我们将其保存到名为 handshake-client-finished-without-mac.bin 的文件中并调用 openssl:

$ openssl dgst -sha1 -hmac $(cat client-mac-key.bin) handshake-client-finished-without-mac.bin
HMAC-SHA1(handshake-client-finished-without-mac.bin)= 3e01f797b982a5ed35ce268520ef7475144441ea

客户端 MAC 密钥(来自您已经生成的密钥块)是:

49 21 65 4A 07 1C 95 E2 DD B8 E3 A8 16 22 58 FA
AC FF DD 8D

我们刚刚验证了 MAC 是正确的。让我们继续处理消息字节。

验证数据(12 字节)

接下来的 12 个字节 (E9 3F D3 D8 55 7A 3E B9 57 4D 25 94) 是验证数据。您正确地从之前的所有消息中提取了字节。我们现在需要计算这些字节的 MD5 和 SHA1 哈希:

$ openssl dgst -md5 to_hash.bin
MD5(to_hash.bin)= fcc3d19566dc07777834ebddf9dd5dc4

$ openssl dgst -sha1 to_hash.bin
SHA1(to_hash.bin)= 2b069b971ceb63e2f0e6d2687479a10b0aee6abd

然后将它们合并(md5+sha1)并保存到client-data-for-prf.bin。最后,我们使用 PRF 函数计算 12 个字节(我使用了 github 中的 PRF 实现):

.\PRF.exe -l "client finished" -s .\master-secret.bin -d .\client-data-for-prf.bin -o
 client-prf-result.bin -n 12

client-prf-result.bin 将包含与加密消息中的验证数据相等的字节。

握手报头(12 字节)

Offset Field
00     Handshake Type: Finished (20)
01     Length: 12
04     Message Sequence: 2
06    Fragment Offset: 0
09    Fragment Length: 12

旁注

如果您在使用 TLS 时再次遇到问题,您可以查看 Wireshark 调试日志,它揭示了很多关于线路上发生的事情。右键单击任何 DTLS 帧并打开协议首选项:

然后设置您已有的预共享密钥并选择一个您要保存日志的文件:

单击“确定”,Wireshark 将解密您的 TLS 数据并在日志文件中为您提供大量详细信息。