首发于TLS与OpenSSL

PRF

PRF(Pseudo-random Function)是从协商参数到对称加密信道参数转换的核心装置,对称加密信道所需要的参数都是通过协商得到的内容进行PRF运算得到的。

TLS1.1的时候PRF通过指定集中哈希操作的组合来约定算法,TLS1.2的时候通过加密套件的方法指定。如果说TLS和SSL最大的区别的话,恐怕就是PRF算法了。即使是PRF算法本身也经历了变化。TLS1.2的PRF是当前最常用的,理解这一个算法可以有承上启下的作用。

TLS1.2的PRF算法的目的是生成对称加密的信道参数,对称加密信道的最重要的密码学参数是对称加密的密钥,哈希的密钥(HMAC),IV(初始向量),PRF算法最后就是用来生成这6个参数的(每个两份,发送和接收不同)。并不是所有的对称加密信道都可以用这6个值来代表,但是现代比较常用的GCM算法 ( Galois/Counter Mode) 是可以的,早期的AEAD算法,通过在外部组合哈希算法和加密算法的做法是不能完全用PRF所生成的6个参数描述的,还需要其他的信息。现代的GCM算法使用的IV都是固定长度的,而以前老版本的并不一定是。

PRF生成信道参数的思想是通过双方握手交换的随机数进行一个随机展开,最终生成一串数字序列。实际上这个数字序列在PRF算法中可以是无限长度的,只是TLS只是使用了足够表达这6个参数的长度就好了。

TLS的完整性使用HMAC来保证,这个HMAC是属于数据层的协议,并不是TLS握手的协议。也就是说可以完全独立于业务逻辑来看待这个HMAC,但是HMAC所使用的密钥又是通过TLS握手协商出来的。HMAC是指一个带密钥的哈希算法,这个密钥被设计插入到哈希算法的计算过程中,同一个哈希算法使用不同的密钥得到的结果是完全不一样的。HMAC使用的哈希算法理论上可以是任意种类的哈希,但是TLS1.2规定了这个哈希算法是SHA-256。PRF的定义基于这个HMAC算法。

因为PRF算法可以展开成一个无限长度的序列,所以PRF就一定拥有某种形式的递归定义,可以将有限长度的输入递归运算变成无限长度的输出,这个递归函数就是PRF的核心函数。

P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +

HMAC_hash(secret, A(2) + seed) +

HMAC_hash(secret, A(3) + seed) + ...

A(0) = seed

A(i) = HMAC_hash(secret, A(i-1))

这个函数里有两个输入,一个是密钥secret,一个是种子,通过这个递归函数,这两个输入数据就可以得到无限长度的输出数据串。这个函数的名字叫做P_hash。这个函数里面的主要计算就是一个HMAC函数,最终的输出数据串是由无限个HMAC计算结果拼接得到的。HMAC函数的第一参数永远是私钥,这也符合HMAC函数的定义,第二个参数就是递归的关键变量了。通过一个A(i)的递归定义,一个HMAC的依赖计算的链条被构建出来用来作为HMAC函数的种子,不断产生的新的种子就能不断的产生新的不同的输出数据串。

在TLS中,我们需要6个数据的结果,我们需要提前知道这个结果总共需要的数据的长度,例如需要80个(RFC中的例子),SHA-256定义的HMAC就需要计算到A(3),一共96的串长度。这样这个A(3)的递归定义就与数学里面常见的阶数概念关联起来了。用不到的数据就会被直接丢弃。

一个完整的TLS中的PRF算法的定义是 :

PRF(secret, label, seed) = P_hash(secret, label + seed)

这个与PRF模型最大的区别是多了一个label。这个label是一个ASCII字符串。由于PRF算法生成最终的信道参数是服务器单边决定的,所以这个label具体是什么不重要,是一个服务器可以任意设置的量。对于客户端来说,对称加密的信道参数都是服务器发送来的,所以他根本不关心服务器是怎么生成的。

编辑于 2018-06-13

文章被以下专栏收录