1 骡子的锁匠铺
很久很久之前,骡子开了一家锁匠铺,他说:“我做的锁头很坚固,小偷绝对打不开。”因此动物村里所有的动物都为自己的房子装上了骡子做的锁。
骡子做的锁确实很坚固,但是每把锁头上用的钥匙居然都是同一个形状的。因此小偷只要得到了一栋房子的钥匙,就可以打开所有房子的锁了。
教训:坚固的锁头固然重要,但不可预测的钥匙更加重要。
2 本章概要
- 使用随机数的密码技术
- 随机数的性质
- 伪随机数生成器
- 具体的伪随机数生成器
- 对伪随机数生成器的攻击
3 使用随机数的密码技术
3.1 随机数是干什么的
- 生成秘钥:用于对称密码和消息认证码。
- 生成密钥对:用于公钥密码和数字签名。
- 生成初始化向量(IV):用于分组密码的 CBC、CFC 和 OFB 模式。
- 生成 nonce:用于防御重放攻击以及分组密码的 CTR 模式等。
- 生成盐:用于基于口令的密码(PBE)等。
在这里,请大家记住为了不让攻击者看穿而使用随机数这一观点,因为“无法看穿”,及不可预测性,正是本章的主题。
4 随机数的性质
4.1 对随机数的性质分类
- 随机性:不存在统计学偏差,是完全杂乱的数列。
- 不可预测性:不能从过去的数列推测出下一个出现的数。
- 不可重现性:除非将数列本身保存下来,否则不能重现相同的数列。
为了方便起见,将上述三个性质按顺序分别命名为“弱伪随机数”、“强伪随机数”和“真随机数”。
||随机性|不可预测性|不可重现性||
|:-:|:-:|:-:|:-:|:-:|
|弱伪随机数|✔️|✘|✘|只具备随机性|
|强伪随机数|✔️|✔️|✘|具备不可预测性|
|真随机数|✔️|✔️|✔️|具备不可重现性|
4.2 随机性
杂乱无章并不代表不会被看穿,因此本书中将只具备随机性的伪随机数称为“弱伪随机数”。
4.3 不可预测性
不可预测性(unpredictability),是一种“不可能事先说中”的性质,及不可预测性。即,攻击者在知道过去生成的为随机数列的前提下,依然无法预测出下一个生成出来的伪随机数的性质。
4.4 不可重现性
即,无法重现和某一随机数列完全相同的数列的性质。如果除了将随机数列本身保存下来意外,没有其它方法能够重现该数列,则我们就说该随机数列具备不可重现性。
要生成具备不可重现性的随机数列,需要从不可重现的物理现象中获取信息,比如周围的温度和声音的变化、用户移动的鼠标的位置信息、键盘输入的时间间隔、放射线测量仪的输出值等,根据从这些硬件中获取的信息而生成的数列,一般可以认为是具备不可重现性的随机数列。
5 伪随机数生成器
仅仅靠软件无法生成真随机数,因此要加上一个“伪”。
5.1 伪随机数生成器的结构
伪随机数生成器具有“内部状态”,并根据外部输入的“种子”来生成伪随机数列。
1.伪随机数生成器的内部状态
伪随机数生成器的内部状态,是指伪随机数生成器所管理的内存中的数值。伪随机数生成器会根据内存中的数值进行计算,并将计算的结果作为伪随机数输出。随后,为了响应下一个伪随机数请求。伪随机数生成器会改变自己的内部状态。
2.伪随机数生成器的种子
伪随机数的种子是用来对伪随机数生成器的内部状态进行初始化的。
6 具体的伪随机数生成器
6.1 杂乱的方法
用一个程序员都不懂的算法生成,但是这是错误的,不能用于密码技术。因为,周期太短,使用复杂算法所生成的数列大多数都会具有很短的周期(即短数列的不断重复)。另外则是,无法判断所生成的随机数是否具备不可预测性。
6.2 线性同余法
线性同余法(linear congruential method)是一种使用很广泛的伪随机数生成器算法。然而,它并不能用于密码技术。
A、C、M 都是常量,且 A 和 C 需要小于 M。接下来,根据种子 R0 计算下一个伪随机数 R1:
R1 = (A R0 + C) mod M。
当前得到的伪随机数即是下一个伪随机数的种子:
Rn+1 = (A Rn + C) mod M。
但是这具有周期性,而且可以通过上一个种子得到下一个伪随机数。因此不具备不可预测性,不能将线性同余法用于密码技术。
很多伪随机数生成器的库函数都是采用线性同余法编写的。包括 C 语言的库函数 rand。 以及 java 的 java.util.Random 类等。
6.3 单向散列函数法
攻击者要预测下一个伪随机数,需要知道计数器的当前值,以及,破解单向散列函数的单向性。利用了单向散列函数的单向性。
6.4 密码法
密码的机密性是支撑伪随机数生成器不可预测性的基础。
7 对伪随机数生成器的攻击
7.1 对种子进行攻击
7.2 对随机数池进行攻击
一般不会到了需要的时候才当场生成真随机数,而是会事先在一个名为随机数池(random pool)的文件中积累随机比特序列。当密码软件需要伪随机数的种子时,可以从这个随机数池中取出所需长度的随机比特序列来使用。这是不能被攻击所知道的。
8 本章小结
由于密码技术的伪随机数生成器,需要使用单向散列函数和密码等技术来确保不可预测性。
9 小测验
- 伪随机数的种子需要对攻击者保密。
- 线性同余法可以作为用于密码的伪随机数生成器。
- 具备随机性的伪随机数生成器不一定具备不可预测性。