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。