代码之家  ›  专栏  ›  技术社区  ›  Brian

在C++中找出随机数生成器的种子

  •  5
  • Brian  · 技术社区  · 15 年前

    我有一个非托管C++控制台应用程序,其中我使用sRAND()和RAND()。我不需要这个来解决一个特定的问题,但我很好奇:是否将原始种子传递给srand()并存储在内存中可以查询的某个位置?有什么办法知道种子是什么吗?

    4 回复  |  直到 15 年前
        1
  •  7
  •   P Shved    15 年前

    不需要存储种子,只返回最后一个随机数。

    下面是来自手册页的示例:

           static unsigned long next = 1;
    
           /* RAND_MAX assumed to be 32767 */
           int myrand(void) {
               next = next * 1103515245 + 12345;
               return((unsigned)(next/65536) % 32768);
           }
    
           void mysrand(unsigned seed) {
               next = seed;
           }
    
        2
  •  3
  •   Justin    15 年前

    如果有一个简单的线性同余生成器,其中有多个值,则生成一个方程组:

     v1 = ( seed * a + b ) % m
     v2 = (   v1 * a + b ) % m;
     v3 = (   v2 * a + b ) % m;
    ... 
    

    如果您知道第一个值,您可以按顺序向后:

    seed = (v1 - b)/a (mod m)
    

    你不知道种子的唯一性,你只知道它的mod m(这通常是好的,因为(0<seed<m)无论如何)如果v1-b是负的,你需要加上m直到它再次是正的。

    你也可以看看 Chinese Remainder Theorem ,尽管不是完全匹配。

        3
  •  0
  •   Salman A    15 年前

    我不知道您的程序集熟练程度是什么,也不知道您是否可以访问非托管应用程序的源代码/调试符号,但是除了这种技巧之外,没有可行的方法来确定原始种子值。随机数生成器的全部目的是想办法给你一个不可预测的数字-任何两个对rand()的给定调用之间的关系不应该被推导出来。在加密性强的伪随机数生成器中,能够基于生成的随机数猜测种子被认为是一个严重的缺陷。

    最简单的方法是在调试器下启动应用程序并设置断点 srand() 调用-然后看看传递的参数。

    下一步是拆解应用程序,找出srand调用的情况。它完全有可能是与当前时间一起播种的——然后你可以尝试一堆猜测(你可能可以缩小到几千个左右),看看是否有人给出了应用程序正在使用的相同的随机数序列。(当然,这假设您有某种方式知道生成的随机值是什么)。也有可能种子总是像“0”一样愚蠢。

        4
  •  0
  •   Guss    15 年前

    理论上,not-种子值用于计算下一个随机值,该值(理论上)用于为下一个随机数种子,依此类推。

    安全方面,能够窥视种子(无论是原始的还是新的)是一个严重的安全问题,所以我希望您不应该查看它,即使它必须存储在某个地方。