预主密钥在 TLS 握手中被加密和交换。此值用于派生主密钥。主密钥用于通过将其传递给伪随机函数 (PRF) 并组合来自握手的其他数据片段来派生所有其他密钥材料。
导出 PSK 的 Pre-Master Secret
来自RFC427:第 2 节
预主密钥的形成如下:如果 PSK 的长度为 N 个八位字节,则将 auint16
与 N 值、N 个零八位字节、auint16
与 N 值以及 PSK 本身连接起来。
如果使用带 PSK 的 Diffie Hellman,第 3 节:
预主密钥形成如下。首先,以与 [TLS] 中其他基于 Diffie-Hellman 的密码套件相同的方式执行 Diffie-Hellman 计算。令 Z 为该计算产生的值(与其他基于 Diffie-Hellman 的密码套件一样,前导零字节被剥离)。连接uint16
包含 Z 长度(以八位字节为单位)的 a、Z 本身、uint16
包含 PSK 长度(以八位字节为单位)的 a 以及 PSK 本身。
如果使用带 PSK 的 RSA,第 4 节
从客户端发送到服务器的 EncryptedPreMasterSecret 字段包含一个 2 字节的版本号和一个 46 字节的随机值,使用服务器的 RSA 公钥加密,如 [TLS] 的第 7.4.7.1 节所述。实际的 premaster secret 由双方形成如下:将 uint16 与值 48、2 字节版本号和 46 字节随机值、包含 PSK 长度(以八位字节为单位)和 PSK 的 uint16 连接起来本身。(因此,预主密钥比 PSK 长 52 个八位字节。)
派生主密钥
以下所有内容不仅适用于 TLS PSK;它适用于所有密钥交换类型。来自 RFC 2246:第 8.1 节
对于所有密钥交换方法,使用相同的算法将 pre_master_secret 转换为 master_secret。计算完 master_secret 后,应该从内存中删除 pre_master_secret。主密钥的长度始终为 48 字节。premaster secret 的长度将根据密钥交换方法而有所不同。
master_secret = PRF(pre_master_secret, "master secret",
ClientHello.random + ServerHello.random)
[0..47];
PRF 被定义为结合两个不同的散列函数。 RFC 2246 的第 5 节:
首先,我们定义一个数据扩展函数 P_hash(secret, data),它使用单个哈希函数将密钥和种子扩展为任意数量的输出:
P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
HMAC_hash(secret, A(2) + seed) +
HMAC_hash(secret, A(3) + seed) + ...
Where + indicates concatenation.
A() is defined as:
A(0) = seed
A(i) = HMAC_hash(secret, A(i-1))
上面描述的函数真的是P_MD5
or P_SHA1
。TLS PRF 描述如下:
TLS 的 PRF 是通过将秘密分成两半并使用一半以 P_MD5 生成数据,另一半以 P_SHA-1 生成数据,然后将这两个扩展函数的输出进行异或 (XOR) 来创建的。
因此,让我们声明以下内容:
L_S = length in bytes of secret;
L_S1 = L_S2 = ceil(L_S / 2);
那么PRF是:
PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
P_SHA-1(S2, label + seed);
派生加密密钥
密钥派生在 RFC 2246:第 6.3 节中描述
整个keyblock派生如下:
key_block = PRF(SecurityParameters.master_secret,
"key expansion",
SecurityParameters.server_random +
SecurityParameters.client_random);
一旦生成了足够的材料并将其存储在 中key_block
,key_block
就会将其拆分为加密/解密密钥。加密或解密取决于方向。因为它们都被称为写键。key_block
依次拆分为数组:
client_write_MAC_secret[SecurityParameters.hash_size]
server_write_MAC_secret[SecurityParameters.hash_size]
client_write_key[SecurityParameters.key_material_length]
server_write_key[SecurityParameters.key_material_length]
client_write_IV[SecurityParameters.IV_size]
server_write_IV[SecurityParameters.IV_size]
对可导出的分组密码执行了一些额外的计算。您也可以在 RFC2246 的第 6.3 节中阅读这些详细信息。 第 6.3.1 节给出了这些计算的示例,没有额外的描述。