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
- 20 个字节用于客户端 MAC 密钥 (SHA1)
- 20 个字节用于服务器 MAC 密钥 (SHA1)
- 32 个字节用于客户端加密密钥 (AES256)
- 服务器加密密钥 (AES256) 的 32 个字节
- 客户端 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
有人能帮忙吗?
加密完成数据第一行为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 数据并在日志文件中为您提供大量详细信息。
我正在尝试了解最终加密握手消息的工作原理
为此,我试图确保我的算法给出与这个有效示例相同的结果:
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
- 20 个字节用于客户端 MAC 密钥 (SHA1)
- 20 个字节用于服务器 MAC 密钥 (SHA1)
- 32 个字节用于客户端加密密钥 (AES256)
- 服务器加密密钥 (AES256) 的 32 个字节
- 客户端 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
有人能帮忙吗?
加密完成数据第一行为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 数据并在日志文件中为您提供大量详细信息。