python - TLS MAC 消息验证

标签 python macos ssl hmac sha256

我正在用 python 开发 SSL 解码器,但我在 HMAC 验证方面遇到了一些问题:

我已经提取了所有与 key 环相关的 Material (客户端 IV、MAC、 key 和服务器 IV、MAC、 key )。 当我收到第一条 Application_Data 消息 (0x17) 时,我能够对其进行解密,但无法验证消息的完整性。

在 RFC 2246 ( https://www.ietf.org/rfc/rfc2246.txt ) 上,告诉:

The MAC is generated as:

   HMAC_hash(MAC_write_secret, seq_num + TLSCompressed.type +
                 TLSCompressed.version + TLSCompressed.length +
                 TLSCompressed.fragment));

where "+" denotes concatenation.

seq_num The sequence number for this record.

hash The hashing algorithm specified by SecurityParameters.mac_algorithm.

以此为例:

Chosen cipher_suite is TLS_RSA_WITH_AES_256_CBC_SHA256

client_mac = "some random stuff"
message_type = 0x17
message_version = 0x0303
encrypted_message_length = 1184 (IV|Message|MAC|Offset)
decrypted_message_length = 1122 (removing IV, MAC and offset)
message = "some message of length 1122"
  • client_mac 是从 keyring_material 中提取的
  • message_type是0x17,因为作为Application_data消息类型,正确的值应该是0x17
  • 消息版本为 0x0303,因为它是 TLS 1.2
  • 消息长度为1122,去掉前面的IV,offset和MAC验证,消息,得到最终长度为1122
  • seq_number 为 1,因为它是第一条消息

HMAC_SHA256计算,在python中,如下:

import hashlib
import hmac
hmac.new(<client_mac>,label+message,hashlib.sha256).digest()

我的问题是,如何计算标签? 正如RFC提到的,“+”表示连接,但是连接什么

  • 十六进制值转换为字符串
    • “1”+“17”+“0303”+“462”
  • INT 值转换为字符串
    • “1”+“23”+“771”+“1122”

另外要提的是,TLSCompressed.version 意味着:

  • 0x0303
  • 771
  • “1.2”
  • “12”
  • “TLS 1.2”

在这个邮件列表 ( http://www.ietf.org/mail-archive/web/tls/current/msg14357.html ) 中,我发现了对 MAC 值的假定说明,

   MAC(MAC_write_key, seq_num +
       TLSCipherText.type +
       TLSCipherText.version +
       length of ENC(content + padding + padding_length) +
       IV +
       ENC(content + padding + padding_length));

where the length is encoded as two bytes in the usual way.

但这对我来说毫无意义,因为重新编码解密值以检查计算 MAC 是没有用的。从最后一行 “其中长度以通常方式编码为两个字节”,这是否意味着我应该使用

struct.pack("!H",length)

然后删除“\x”并使用这个值?或者我应该用 HEX 编码这个值然后连接它吗?

我有点迷茫,因为 RFC 并不清楚应该如何使用值。

我一直在尝试几种组合(甚至是暴力破解),但都没有奏效,我希望你能为我指明方向。

最佳答案

好吧,经过一番挖掘,我设法解决了这个问题。

RFC 5246,第 6.2.3.1 节(https://www.rfc-editor.org/rfc/rfc5246#section-6.2.3.1)

The MAC is generated as:

  MAC(MAC_write_key, seq_num +
                        TLSCompressed.type +
                        TLSCompressed.version +
                        TLSCompressed.length +
                        TLSCompressed.fragment);

where "+" denotes concatenation.

但它没有指出数据大小,无论是表示格式(十六进制,字符串...)。

每个字段的表示方式如下:

  • 序号:

    • 描述:一个整数计数器,从 0 开始,每接收或发送一帧都会递增。对于 TCP session ,必须使用两个 seq_numbers,一个用于服务器,另一个用于客户端,每次发送一个帧时递增。
    • 表示:此值必须表示为 Unsigned Long Long 8 个字节
    • 表示示例: struct.pack("!Q",seq_num)
  • TLSCompressed.type

    • 描述:该字段是从 TLS 记录层(加密的负载)中提取的。例如,如果它是一个应用程序数据帧,我们必须使用 0x17。
    • 表示:此值必须表示为 Signed Char,占 2 个字节。
    • 表示示例: struct.pack("!b",TLSCompressed.type)
  • TLSCompressed.version

    • 描述:该字段也是从 TLS 记录层(加密的负载)中提取的。例如,如果使用 TLS 1.2 传输帧,我们必须使用它的十六进制表示形式 0x0303。
    • 表示:此值必须表示为 Unsigned Short,2 个字节。
    • 表示示例: struct.pack("!H",TLSCompressed.version)
  • TLSCompressed.length

    • 说明:该字段表示解密负载的实际长度。
    • 表示:此值必须表示为 Unsigned Short,2 个字节。
    • 表示示例: struct.pack("!H",TLSCompressed.length)
  • TLSCompressed.fragment

    • 说明:此字段**是实际的解密有效负载。
    • 表示:该值必须表示为字符串

作为一个 python 示例,HMAC 散列对于我们之前的示例如下:

hmac_digest = hmac.new(mac_secret,'',digestmod=hashlib.sha256)
hmac_digest.update(struct.pack('!QbHH',seq_num,TLSCompressed.type,TLSCompressed.version, len(decrypted)))
hmac_digest.update(decrypted)
hmac_digest.digest()

关于python - TLS MAC 消息验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31009358/

相关文章:

python - 如何获取列表列表中所有出现的相同值的索引列表?

html - IE 和 MAC 浏览器不支持字体系列

spring - 如何通过 HTTPS 通过 Maven Tomcat7 运行 Spring 应用程序?

python - 加载在 linux 中 pickle 的数据在 mac 中失败

ruby-on-rails - 在 macOS Catalina 上安装 Ruby 2.0.0 的问题

java - 连接到 FTPS 服务器

python - ./manage.py runserver 使用 https

python - 使用 Numpy 在 Python 中进行二次编程?

python - 比较不同列的字符串长度数据框

python - 在 python <= 2.7 中编写 unicode 程序