可以对此代码进行反向工程以找到随机种子吗?

时间:2017-04-29 05:45:59

标签: algorithm random lua cryptography

local digits = {'1', '2', '3', '4', '5', '6', '8', '9'} 
math.randomseed(os.time()) 
local result = digits[math.random(8)] 
for i = 2, 50 do 
    result = result..digits[math.random(8)] 
end 
print(result)

--> 88854243421464255299891111895292628431988589634664

这是一个Lua脚本,旨在吐出五十个随机数字,不包括0和7.我似乎无法找到Lua随机性算法。是否可以找到os.time()返回的值?

用外行的术语来说,这里的脚本是如何工作的:

  1. 定义八个单字符字符串的列表。
  2. 使用自1970年1月1日午夜起的秒数对伪随机算法进行种子处理。
  3. 使用伪随机算法选择1到8之间的数字,然后使用该数字从列表中选择项目。例如。选择的数字是7,算法选择列表中的第七项。
  4. 将该项添加到结果的末尾。重复,直到结果长达五十位。
  5. 因为遗漏了七个,随机算法真的吐了出来:

    77754243421464255288781111785282627431877578634664
    

    但是因为七个失踪了,七个和八个失去了八个和九个,产生了这个:

    88854243421464255299891111895292628431988589634664
    

    为了澄清,我试图弄清楚随机算法如何工作以找到作为随机种子输入的密钥。

    此处也问到:https://forum.roblox.com/Forum/ShowPost.aspx?PostID=215349554 在这里:https://scriptinghelpers.org/questions/42360/can-this-script-be-reverse-engineered-to-find-the-random-seed 在这里:https://crypto.stackexchange.com/questions/47027/can-this-code-be-reverse-engineered-to-find-the-random-seed

2 个答案:

答案 0 :(得分:4)

  

可以对此代码进行反向工程以找到随机种子吗?

也许,也许不是。这取决于itertools.izip_longest的实现。

  

是否可以找到os.time()返回的值?

当然。 os.time() is defined为(强调我的)

  

math.random函数在不带参数的情况下调用时,返回当前日期和时间,编码为数字。 (在大多数系统中,该数字是自某个纪元以来的秒数。)

我们谈论的是32位整数。这很容易被暴力强迫。你甚至可以假设一些界限。这可能是在过去一个月左右产生的,并且没有必要搜索未来的种子。在过去的30天里,只有22位不同的秒数。

您可以简单地遍历从现在到过去的种子,并且每次都生成50位长的随机值。然后你只需要将它与你拥有的那个进行比较,并在找到匹配时停止。这不应该超过一分钟。

以下是完整代码:

time

输出

1493400000
1493300000
1493200000
1493100000
1493000000
1492900000
1492800000
1492700000
1492600000
1492500000
1492400000
1492300000
1492200000
1492100000
1492000000
1491900000
1491800000
1491700000
1491600000
1491500000
found: 1491404649

这仅适用于Lua v5.1,因为v5.2v5.3中的实施已更改。我只在Windows上尝试过。

答案 1 :(得分:3)

这不是对您的问题的完整答案,但它可能会帮助您开始。您可以找到Lua的math.random函数here的C源代码(适用于Lua 5.1,但其他版本类似)。 Lua本身不会尝试生成伪随机数,而是将该任务外包给C标准库。

具体来说,math.random使用C的rand函数生成数字,而math.randomseed使用C的srand函数设置伪随​​机数生成器的种子(包含在与rand相同的手册页。这些功能在每个系统上的实现方式不同(例如x86 Windows版本与x86 Linux版本不同,不同的芯片组会有不同的版本等),因此您必须分析每个系统的算法。感兴趣的。

有关rand如何实施的信息,this question应该为您提供一个开始。

你应该注意的一件事是,如果有人可以猜到你叫什么秒os.time(或者如果他们只是和你一样叫它),那么他们就可以生成通过将该值传递给math.randomseed,与您完全相同的伪随机数。如果有一个可用的种子,最好使用具有更高熵的种子。