深入浅出 HTTPS:从原理到实战
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.2 随机数

首先介绍密码学中看似很简单,但是很难正确使用的算法,这就是随机数生成算法。在密码学中随机数的用途非常大,其他密码学算法内部都会用到随机数。

对于随机数,读者都有一些印象,网络上有很多随机数生成小工具。从开发者直观的角度看,随机数就是一串杂乱无序的字母、数字、符号组合,但这不是真正的随机数,更不能用在密码学中,为了理解随机数的本质,先介绍随机数的类型。

2.2.1 随机数的类型

通过表2-1可以看出,不同类型的随机数具备不同的特性,理解这些特性非常重要。

表2-1 随机数类型

1)效率

在软件或者密码学应用中需要大量的随机数,必须在很短的时间内生成随机数,否则就不是一个好的随机数生成器。

2)随机性

生成的随机数只要不存在统计学偏差,那么这个随机数就具备随机性(randomness),比如随机数生成器从0到9几个数字中随机选出四个数字,在生成的随机数中,0到9数字出现的次数是平均的,代表该随机数生成器具备随机性。

3)不可预测性

有些随机数看上去很随机,但是这些随机数之间可能存在一定的关联,比如通过以前的随机数可以推断出后续的随机数,这种随机数就具备不可预测性(unpredictable)。密码学中的随机数必须具备不可预测性,否则就会存在安全问题,当然非密码学应用使用具备随机性的随机数就足够了。

4)不可重现性

所谓不可重现性(unrepeat)就是不管经过多长时间,不会产生完全相同的随机数。在软件层面不可能生成完全不一样的随机数,在一定周期内,密码学随机数算法最终会生成两个完全相同的随机数,只是周期长短的问题。

在密码学中应该尽量使用周期相对长的随机数,为了实现真正不可重现性的随机数,必须基于物理设备或者物理现象。

2.2.2 随机数的工作原理

不管是真正的随机数生成器TRNG(True Random Number Generator),伪随机数生成器PRNG(Preudo Random Number Generator),还是密码学伪随机数生成器CPRNG(Cryptography secure Preudo Random Number Generator),内部工作原理是一样的,CPRNG是PRNG随机数生成器中的一种。

随机数生成器内部会维护一个状态(internal state),对于TRNG来说,内部状态的数值来自外部设备,称为熵(entrory),比如动态的时间、变化的温度、声音的变化、鼠标位置。

而对于PRNG来说,内部状态的数值来自于模拟的数值,称为种子(seed)。随机数生成器每次生成随机数的时候,内部状态的值都会变化,这样才能产生不一样的随机数,如果每次熵和种子是一样的,生成的随机数也是相同的,所以熵和种子对于随机数生成器非常重要。

一个优秀的随机数生成器就在于寻找尽可能多的熵和种子,一旦熵和种子不够,随机数生成器就会停止运行。

2.2.3 常见的随机数生成器

1)使用外部熵生成随机数

        $ head -c 32 /dev/urandom | openssl enc -base64

2)伪随机数生成器算法

如果生成的随机数不是用于密码学,开发者可以自行设计一个生成算法,常见算法如表2-2所示。

表2-2 常见生成算法

大部分开发语言都有类库提供伪随机数生成算法,比如PHP语言可以通过下面的代码产生伪随机数:

        //初始化种子
        mt_srand();
        $randval = mt_rand();
        echo $randval;

OpenSSL命令行工具也能提供伪随机数,比如:

        $ openssl rand -base64 24

3)密码学随机数生成算法

在密码学中,可以通过其他密码学算法生成密码学可以使用的随机数,比如表2-3中的算法。

表2-3 密码学伪随机数生成算法

2.2.4 密码学算法中的随机数

密码学应用中很多场景会涉及随机数,不同的用途有不同的称呼,常见用途见表2-4。

表2-4 随机数常见用途

目前读者不用关心这些概念,后续章节会讲解,在不同的算法中,随机数的称呼也有差异。