python安全开发军规之四:使用安全的随机数生成器

背景

日常开发中,必然会碰到需要生成随机数的需求,比如生成图片验证码,短信验证码……随机数生成既然是这么简单的一个功能,开发必然也很简单,我们看看怎么生成一个随机数,这里以随机生成1-100的整数为例。

普通程序员的写法
In [7]:
import random
random.randint(1,100)
Out[7]:
83

只用了两行代码,程序员小Z就写出了一个随机数。

QA有话说

随机模块提供的随机生成器是伪随机数生成器。所谓伪随机数,是通过固定的算法生成的,其结果是确定的,可预见的。一般情况下,伪随机数的生成需要一个种子,如果没有特别设置,种子就是系统的时钟。简而言之,由于伪随机数算法固定,种子固定,那结果就是可推导和模拟的。那这里的随机也就不是真正的随机,只要在随机数生成过程中有一点偏差,破译者就能够利用偏差对保密信息进行破译。

实际上,在密码学上对随机性有三个分类:伪随机序列,密码学意义上的伪随机序列,真随机序列。

前面小Z写的程序就类属于伪随机序列,1-100中每个数出现的频率相等或近似相等。

而真随机序列则要求随机数不能重复产生,且不能由已知的任意数推导出来。意味着,即使在相同的操作条件下,用完全相同的输入,随机数生成器生成的两个随机数也是不一样的,即两次生成的结果是不重复的且完全独立的。

由于真随机序列大多需要硬件支持,有一种折衷的方案,也就是密码学意义上的伪随机序列。密码学意义的伪随机序列要求即使知道前一次的生成,不能预测下一次生成的随机数。

高级程序员的写法
In [8]:
import secrets
secret_generator=secrets.SystemRandom()
secret_generator.randint(1,100)
Out[8]:
8
小结

python在3.6版本添加了secrets模块,使用同步方法生成随机数据,以确保没有两个进程可以同时获得相同的数据。
这个模块的功能很多,可以进一步发掘,常用于敏感信息保护的场景,常用的有生成随机数,从确定序列中随机取值,生成token。