0

我试图了解最终的加密握手消息是如何工作的

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

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

由于 0xFEFF 标头,我很确定 DTLS 1.0 遵循 RFC 4347。

已知的是

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

我正在执行以下步骤:

预大师秘密

premaster secret 的形成如下:如果 PSK 的长度为 N 个八位字节,则连接一个值为 N 的 uint16、N 个零八位字节、一个值为 N 的第二个 uint16 以及 PSK 本身。(RFC 4279 第 2 节

  001000000000000000000000000000000000
  0010123456789012345678901234567890aa

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

PRF 被定义为结合两个不同的散列函数。RFC 2246 的第 5 节:

197c358a9de99d7c50120aea40af2095
c7c340719385f23f5355004c07d9f896
681942c494eb0d77992c3acf1bc92e4f 

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

  • 客户端 MAC 密钥 (SHA1) 20 个字节
  • 服务器 MAC 密钥 (SHA1) 20 个字节
  • 32 字节的客户端加密密钥 (AES256)
  • 32 字节的服务器加密密钥 (AES256)
  • 客户端 IV 16 字节(AES 使用 128 位块)
  • 服务器 IV 16 字节(AES 使用 128 位块)

在这种情况下,我们需要生成 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

任何人都可以帮忙吗?

4

1 回答 1

0

加密完成数据的第一行是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 以一种特殊的方式计算的:您需要先附加 epoch + 消息序列号(在我们的例子中00 01 00 00 00 00 00 00),然后添加 TLS 记录头(没有 epoch 和序列号)和内容大小设置到实际内容大小(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 帧并打开协议首选项:

DTLS 首选项

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

按键设置

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

于 2018-11-07T10:37:15.173 回答