TLS MAC消息验证

时间:2015-06-23 17:20:09

标签: python macos ssl hmac sha256

我正在开发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,因为它是第一条消息

在python中的HMAC_SHA256计算如下:

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

我的问题是,我该如何计算标签? 正如RFC提到的那样,&#34; +&#34;表示串联,但串联什么

  • HEX值转换为字符串
    • &#34; 1&#34; +&#34; 17&#34; +&#34; 0303&#34; +&#34; 462&#34;
  • 转换为字符串的INT值
    • &#34; 1&#34; +&#34; 23&#34; +&#34; 771&#34; +&#34; 1122&#34;

另外值得一提的是,TLSCompressed.version意味着:

  • 0x0303
  • 771
  • &#34; 1.2&#34;
  • &#34; 12&#34;
  • &#34; TLS 1.2&#34;

在这个maillist(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是没用的。从最后一行&#34;其中长度以通常的方式编码为两个字节&#34; ,这是否意味着我应该使用

  

struct.pack(&#34; 1 H&#34;,长度)

然后删除&#34; \ x&#34;并使用此值?或者我应该在HEX中编码这个值然后连接它?

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

我一直在尝试几种组合(甚至是暴力强迫),但没有一种能够奏效,我希望你能照亮我的方式。

1 个答案:

答案 0 :(得分:2)

好吧,在挖掘之后,我已经设法解决了这个问题。

RFC 5246,第6.2.3.1节(http://tools.ietf.org/html/rfc5246#section-6.2.3.1

  

MAC生成为:

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

其中“+”表示连接。

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

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

  • SEQ_NUM:

    • 描述:一个从0开始的int计数器,它将在每个接收或发送的帧中递增。对于TCP会话,必须使用两个seq_numbers,一个用于服务器,另一个用于客户端,每次每个都发送一个帧时递增。
    • 表示:此值必须表示为无符号长整型,带有8个字节
    • 表示示例: struct.pack("!Q",seq_num)
  • TLSCompressed.type

    • 描述:该字段是从TLS记录层(加密的有效负载)中提取的。例如,如果它是 Application Data 框架,我们必须使用0x17。
    • 表示:此值必须表示为签名字符,包含2个字节。
    • 表示示例: struct.pack("!b",TLSCompressed.type)
  • TLSCompressed.version

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

    • 说明:此字段表示已解密有效内容的实际长度。
    • 表示:此值必须表示为无符号短,带有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()