PRF = Pseudorandom function

它的作用是: 扩展密钥. 也就是说从一个密钥,生成另外一个密钥.

它的输入是: secret, seed, label.

它的输出是: 任意长度的字节数组

它的定义:

PRF(secret, label, seed) = P_<hash>(secret, label+seed)
P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
                       HMAC_hash(secret, A(2) + seed) + 
                       HMAC_hash(secret, A(3) + seed) + 
                       ...
A() = 
    A(0) = seed
    A(i) = HMAC_hash(secret, A(i-1))

上述表达式中 + 号代表字符数组拼接.

P_hash 定义中, HMAC_hash 可以重复无数次,直到生成的结果长度达到期望。

比如, 当我们使用 P_SHA256 来生成 80 个字节的数组时, HMAC_hash 需要重复三次(直到 A(3)), 生成的结果长度为 96 个字节。 丢弃掉后 16 个字节之后,我们便得到了生成的 80 的字节。

label: 它通常情况下是一个字符串,在不同的上下文中这个字符串不同,但是文档中都会明确说明使用的具体值是什么。


Key Calculation


上面, 我们定义 PRF, 下面我们看看,如何使用 PRF 来生成 TLS 加密所需的密钥。

key_block = PRF(
                master_secret,
                "key expansion",
                server_random + client_random,
            )

其中:

master_secret 作为 secret 输入来生成。 (master_secret 如何获取,我们后边继续讲解)。

"key expansion" 作为 label。

server_random + client_random 作为 seed. (server_random 和 client_random 附在 ClientHello 和 ServerHello 中)

生成的结果需要足够长,然后按照以下规则将它划分为多个密钥:

client_write_MAC_key[mac_key_length]
server_write_MAC_key[mac_key_length]
client_write_key[enc_key_length]
server_write_key[enc_key_length]
client_write_IV[fixed_iv_length]
server_write_IV[fixed_iv_length]

比如, 对于 AES_256_CBC_SHA256 来说,需要生成一个 128 字节的 key_block. mac_key_length 是 32, enc_key_length 是 32, fixed_iv_length 是 0。


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *