一文读懂随机数
随机数
背景
本文将来聊一下密码学当中的随机数的概念,先来看一个小故事吧。
小明有写日记的习惯,但是呢,小明写的日记又不想让别人看到,因此呢,聪明的小明制作了一个特殊的日记本,这个日记本有一个密码的功能,在每次输入正确密码之后,都会随机换一个新的密码,然后这个新密码呢,对于小明来说是可以知道的,其他人即使知道了前面小明输入的密码,也无法猜测下一次的密码,这看起来小明这个日记本设计的比较完美。
小明用了很久,感觉自己可真是太聪明了,于是放心大胆的把日记本放在任意位置, 结果呢, 意外发生了, 小红在总结了一下小明之前输入的密码之后,发现了随机密码生成的规律,于是呢,小红也可以看到这个日记的内容了。
故事纯属虚构, 大家不要当真哈, 图个乐子就好了。
小明在设计日记本的时候呢,就用到了随机数这个思想,只是呢,由于小明选择的伪随机数生成的算法不是特别好,因此呢,让小红给发现了规律,这样小明的日记本自然就不安全了。
接下来呢,一起来看一下随机数的相关知识。
随机数作用
对于随机数在密码学当中有什么用呢,我们来回忆一下之前讲到过的密码学知识里面,那些地方需要用到随机数。
- 密钥生成, 对于对称加密的密钥来说, 生成密钥最好是用随机的
- 初始化向量的生成
- 盐的生成(比如说之前提到过的PBE)
随机数的性质
- 随机性: 这一点比较好理解,也就是说他没有什么规律,完全是杂乱的序列
- 不可预测性: 这个意思是指的,假设已知前面的输出,无法预测下一个输出,就比如文章开头提到的例子,小红通过观察小明之前的输出得到了规律,这实际上就是可预测的
- 不可重现性: 不可能出现相同的序列
伪随机数生成器
对于密码学而言,用到的最多的实际上是伪随机数,因为真正的随机数实际上是比较难以实现的,一般真随机数大多通过硬件来实现,而对于软件而言,大多的实现方案是伪随机数,因此接下来具体聊一聊伪随机数的概念。
伪随机数生成器
简单解释一下对于伪随机数生成器的结构,种子呢,不要想歪了,这个不是你们理解的那种种子,这个实际上可以理解为一个初始值,对于初始值来说,这个要进行保密,如果攻击者知道了种子,而然而然的就可以生成出同样的伪随机序列了。
下面一部分呢,就是整个伪随机数生成器结构的核心,具体的伪随机数生成算法,这个算法呢,可以通过种子来生成一系列的随机序列。
一个具体的伪随机数生成算法: 线性同余法
「线性同余法」是一个应用广泛的伪随机数生成器算法,但是这个算法是非密码学安全的,不要用这个算法生成的随机数用于密码相关的领域。
下面我们来具体的看一下这个算法,
解释一下这个公式的每个元素的含义, A和C呢都是常量,对于是上一次随机序列的输出,根据上面介绍的伪随机数生成器的结构,我们可以知道也就是种子。
线性同余法
代码实现
对于线性同余法来说,这个伪随机数生成器还是比较容易实现的,还是老规矩,采用rust来写一下这个算法吧。
fn linear_congruential_method(r: u32, a: u32, c: u32, m: u32) -> u32 { a.wrapping_mul(r).wrapping_add(c) % m } #[cfg(test)] mod test { use crate::lcm::linear_congruential_method; #[test] fn test() { let r0 = 6; let a = 3; let c = 0; let m = 7; let r1 = linear_congruential_method(r0, a, c, m); println!("{}", r1); let r2 = linear_congruential_method(r1, a, c, m); println!("{}", r2); } }
小结
本文简单的介绍了一下随机数的概念,然后给出了一个非密码学安全的随机数生成器--线性同余法,一定注意,这个方法不要用在密码学相关用途蛤。