我系统上的RAND_MAX是32767。
我需要生成数百万个密码。我计划如下:
printf("%d%d",rand()+1,rand()+1);
这是一个很好的方法吗?经过多少次迭代后我才能找到重复?
答案 0 :(得分:2)
首先,您应该使用安全随机数生成器。如果你不这样做,那么有人可以简单地请求几个密码,强制种子然后重新计算之前和之后生成的每个密码。
伪随机数具有非常高的循环大小。当输入生成的随机数的先前状态时,发生循环。之后,伪随机数将无限重复。然而,安全随机发生器的周期大小非常巨大,实际上它们永远不会重新生成相同的状态并进入一个周期。 rand
的周期大小取决于实现,但可能相对较低 - 这也是不使用它的另一个原因。
当然,如果你的密码很短,字母很小(可接受的符号范围),那么密码本身就更有可能重复出现。在随机数生成器中查找类似的模式比使RNG进入先前状态更可能。例如,由于生日悖论,检索先前生成的字节值将相对较快地发生。
因此,您找到副本的速度与特定密码生成器相关联。对于数百万个密码,您需要创建一个非常强大的密码(您显示的密码不是一个强密码)。如果要确保密码是唯一的,可以将密码或哈希值存储在密码表中。请记住,在密码上存储哈希值与存储密码本身(!)具有相似的安全性。
最好不要删除唯一性要求并将密码与用户ID相关联。如果您想拥有唯一的PIN码,请创建一个正确大小的可能PIN码列表,然后执行Fisher-Yates shuffle(当然,再次使用安全的随机数生成器)。
答案 1 :(得分:2)
修改强>:
由@chux公开(见下面的评论),我的原始答案(基于“生日攻击”)忽略了与文本连接相关的可能重复,因此非常乐观。
我的原始答案也忽略了使用的随机生成器(rand
)中的缺陷,如Oliver Charlesworth所示。
因此,我对39,320次迭代的原始答案应该被认为是一种过于乐观的最佳案例。
更接近(但不准确)的近似值是27,320次迭代。
<强>原始强>:
根据“生日攻击”计算,每次“随机”数字的组合很可能在1.2 * sqr_root(32,767 * 32,767)= 39,320 迭代后重复。
这意味着您应该在代码生成39,321个密码时发现冲突。
但是,由于rand
不具有加密安全性,因此您的密码从一开始就不安全(种子可能会受到损害,导致整个集合变得具有确定性。