【问题标题】:TLS MAC message verificationTLS MAC 消息验证
【发布时间】:2015-06-23 17:20:09
【问题描述】:

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

我提取了所有与密钥环相关的材料(客户端 IV、MAC、密钥和服务器 IV、MAC、密钥)。 当我收到第一条 Application_Data 消息 (0x17) 时,我可以解密它,但无法验证消息的完整性。

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

MAC 生成为:

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

其中“+”表示连接。

seq_num 此记录的序列号。

散列 由指定的哈希算法 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,偏移量和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));

长度以通常的方式编码为两个字节。

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

struct.pack("!H",length)

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

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

我一直在尝试几种组合(甚至是暴力破解),但都没有奏效,希望你能照亮我的道路。

【问题讨论】:

    标签: python macos ssl hmac sha256


    【解决方案1】:

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

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

    MAC 生成为:

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

    其中“+”表示连接。

    但它不分数据大小,无论是表示格式(十六进制、字符串...)。

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

    • seq_num:

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

      • 描述:该字段是从 TLS 记录层(加密的有效负载)中提取的。例如,如果是 Application Data 帧,我们必须使用 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()
    

    【讨论】:

      猜你喜欢
      • 2012-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-19
      • 2014-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多