找到你要的答案

Q:TLS MAC message verification

Q:TLS消息验证

I'm developing a SSL de-cipher in python but I'm having some problems on HMAC verification:

I've extracted all keyring related material (client IV, MAC, Key and Server IV, MAC, key). When I receive the first Application_Data message (0x17), I am able to decrypt it, but unable to verify message integrity.

On RFC 2246 (https://www.ietf.org/rfc/rfc2246.txt), tells:

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.

Taking this as an example:

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 is extracted from keyring_material
  • message_type is 0x17, because as an Application_data message type, the correct value should be 0x17
  • message version is 0x0303 as it's TLS 1.2
  • message length is 1122, removing preceding IV, offset and MAC verification, message, gets a final length of 1122
  • seq_number is 1 as it's the first message

HMAC_SHA256 calculation, in python, is as follows:

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

My question is, how do I calculate label? As RFC mentions, "+" denotes concatenation, but concatenation of what

  • HEX values converted to string
    • "1" + "17" + "0303" + "462"
  • INT values converted to strings
    • "1" + "23" + "771" + "1122"

And other thing to mention, TLSCompressed.version means:

  • 0x0303
  • 771
  • "1.2"
  • "12"
  • "TLS 1.2"

In this maillist (http://www.ietf.org/mail-archive/web/tls/current/msg14357.html) I found a supposed clarification of MAC values,

   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.

but it makes no sense to me, because it's useless to re-encode decrypted values to check to compute MAC. And from last line "where length is encoded as two bytes in the usual way", does it means that I should use

struct.pack("!H",length)

Then remove "\x" and use this value? or should I encode this value in HEX and then concatenate it?

I'm a bit lost, because RFC are not clear about how values should be used.

I've been trying several combinations (even brute forcing), but none of them worked, I hope you can light my way.

我开发Python的SSL密钥但我对HMAC验证有问题:

I've extracted all keyring related material (client IV, MAC, Key and Server IV, MAC, key). When I receive the first Application_Data message (0x17), I am able to decrypt it, but unable to verify message integrity.

在RFC 2246(http:/ / www.ietf。org / RFC / rfc2246 .txt),告诉:

MAC生成为:

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

其中“+”表示连接。

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 is extracted from keyring_material
  • message_type is 0x17, because as an Application_data message type, the correct value should be 0x17
  • message version is 0x0303 as it's TLS 1.2
  • message length is 1122, removing preceding IV, offset and MAC verification, message, gets a final length of 1122
  • seq_number is 1 as it's the first message

hmac_sha256计算,在Python中,如下:

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

My question is, how do I calculate label? As RFC mentions, "+" denotes concatenation, but concatenation of what

  • HEX values converted to string
    • "1" + "17" + "0303" + "462"
  • INT values converted to strings
    • "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。从最后一行“长度被编码为两个字节通常的方式”,这是否意味着我应该使用

(“包结构!H“,长度)

然后删除“X”并使用这个值?或者我应该将这个值在六然后连接吗?

我有点失落,因为RFC不清楚的值应该被使用。

我一直在尝试几种组合(甚至蛮力),但他们都没有工作,我希望你能照亮我的路。

answer1: 回答1:

Well, after diggin' a bit I've managed to solve the issue.

RFC 5246, in section 6.2.3.1 (http://tools.ietf.org/html/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.

But it does not points the data size, either representation format (hex, string...).

The way every field must be represented is as follows:

  • seq_num:

    • Description: A int counter, starting in 0, which will be incremented every frame received or sended. For a TCP Session, two seq_numbers must be used, one for the server and other for the client, incrementing everytime each of them sends a frame.
    • Representation: This value must be represented as Unsigned Long Long with 8 bytes
    • Representation example: struct.pack("!Q",seq_num)
  • TLSCompressed.type

    • Description: This field is extracted from TLS Record layer (the encrypted payload). For example, if it's an Application Data frame, we must use 0x17.
    • Representation: This value must be represented as Signed Char, with 2 bytes.
    • Representation example: struct.pack("!b",TLSCompressed.type)
  • TLSCompressed.version

    • Description: This field is also extracted from TLS Record layer (the encrypted payload). For example, if the frame is transferred using TLS 1.2, we must use it's hex representation 0x0303.
    • Representation: This value must be represented as Unsigned Short, with 2 bytes.
    • Representation example: struct.pack("!H",TLSCompressed.version)
  • TLSCompressed.length

    • Description: This field represents the actual length of the decrypted payload.
    • Representation: This value must be represented as Unsigned Short, with 2 bytes.
    • Representation example: struct.pack("!H",TLSCompressed.length)
  • TLSCompressed.fragment

    • Description: This field is the actual **decrypted payload.
    • Representation: This value must be represented as a string

As a python example, the HMAC hashing will be as follows for our previous example:

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()

嗯,投入一点之后我设法解决问题。

RFC 5246,第6.2.3.1(http:/ /工具。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:

    • Description: A int counter, starting in 0, which will be incremented every frame received or sended. For a TCP Session, two seq_numbers must be used, one for the server and other for the client, incrementing everytime each of them sends a frame.
    • Representation: This value must be represented as Unsigned Long Long with 8 bytes
    • Representation example: struct.pack("!Q",seq_num)
  • tlscompressed.type

    • Description: This field is extracted from TLS Record layer (the encrypted payload). For example, if it's an Application Data frame, we must use 0x17.
    • Representation: This value must be represented as Signed Char, with 2 bytes.
    • Representation example: struct.pack("!b",tlscompressed.type)
  • tlscompressed.version

    • Description: This field is also extracted from TLS Record layer (the encrypted payload). For example, if the frame is transferred using TLS 1.2, we must use it's hex representation 0x0303.
    • Representation: This value must be represented as Unsigned Short, with 2 bytes.
    • Representation example: struct.pack("!H",tlscompressed.version)
  • tlscompressed.length

    • Description: This field represents the actual length of the decrypted payload.
    • Representation: This value must be represented as Unsigned Short, with 2 bytes.
    • Representation example: struct.pack("!H",tlscompressed.length)
  • tlscompressed.fragment

    • Description: This field is the actual **decrypted payload.
    • Representation: This value must be represented as a string

作为一个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  osx  ssl  hmac  sha256