我使用Python脚本生成了一些随机数。我有序列的前40个数字。有没有办法恢复种子或找到序列中的下460个数字?

数字是使用以下代码生成的。

import random

i=1
mn = 1
mx = 2
while i<500:
    print(random.randint(mn,mx))
    mn=mn*2
    mx=mx*2
    i=i+1


评论

您知道它是如何初始化的吗? python的随机数生成器的内部状态相当大,因此在一般情况下,这些值可能还不够用,您似乎只有800位。如果您知道有一个Int甚至Long种子,那么会更容易。

据我了解,Python默认使用“ long(_hexlify(_urandom(2500)),16)”,如果失败,则使用“ long(time.time()* 256)”。 :(,所以很可能是第一个。

恐怕您不走运,您拥有800位信息,并且想要从强大的随机源中恢复19968位。

#1 楼


我有序列的前40个数字。有没有办法恢复种子或找到序列中的下460个数字?首先要知道的是Python的随机模块使用Mersenne Twister作为PRNG。那不是加密安全的RNG,实际上,只要您有足够的样本,就很容易恢复状态。

您使用的40个大小的大小不足以恢复完整的MT状态,并且找到那样的下一个输出。

在操作系统随机性不可用时,恢复Python所使用的时间种子绰绰有余。您可以在最近的时间里运行时间值的蛮力。但是,最新版本的Python 2/3会从urandom或类似的地方(如果有)初始化完整状态,并且无法用这么小的输出来反转。没问那个;)

评论


$ \ begingroup $
我没有从源头获得Windows上Python 2.7.14中随机初始化的方式。一方面,自动化实验反复在固定时间()调用的Python中重复运行两条代码(使用蝙蝠文件的重复时间09:00和具有适当特权的python.exe test.py)得出的结论是,时间()不是唯一的熵来源,如文档所述。另一方面,我无法找到使初始化更好的代码。在我对自己的理解充满信心之前,我已经删除了我所说的所有内容。
$ \ endgroup $
–fgrieu♦
17年12月12日在7:12

$ \ begingroup $
@fgrieu,是的,很抱歉,您认为那部分是正确的。实际上,Python 2.7也会在可用时从urandom初始化,方法是在导入random时构造一个random.Random对象。代码太糟糕了,所以难怪我们都感到困惑:每次随机对象创建时,Python _randommodule.c中的种子函数都会被调用两次-一次是从带有null / None种子参数的random_new,一次是从子类init-> seed已经是随机的种子参数。
$ \ endgroup $
–otus
17年12月12日14:12在

$ \ begingroup $
附言。用作后备时间的时间函数是python的time.time,在大多数系统上具有亚秒级的精度。
$ \ endgroup $
–otus
17年12月12日在14:18

$ \ begingroup $
啊,谢谢,我在random.py中错过了上一层;如果发生一些运行时事故,那么混乱,并以静默回退的方式完成,比正常行为更糟糕。
$ \ endgroup $
–fgrieu♦
17年12月12日在17:50

#2 楼

Python使用Mersenne扭曲程序PRNG,尽管它并不安全,但它确实具有较大的状态。
这里有40个数字,第一个数字为您提供1位,随后的每个数字都有一个额外的位,总共为800位。
这比MT-19937的内部状态小得多。

此页面说明了如何查找python PRNG的内部状态:
https://jazzy.id .au / 2010/09/22 / cracking_random_number_generators_part_3.html
步骤1从中获取了624个整数,即使它们是完整整数也要超过40个。

例如,如果您知道有一个Integer种子或此类种子,则您有足够的信息,并且也可以通过计算获得。