试图写一个8位的可逆PRNG,而不是一个密码

时间:2012-01-10 18:51:12

标签: random prng

我正在尝试构建一个字节的PRNG,其中我可以获取一组字节(例如,10或15个字节)并返回将产生该字节列表的种子列表。我不关心密码学,但它必须大致均匀分布,它必须达到所有可能的2 ^ 8组合,并且它必须偶尔能够重复一个数字而不会卡住。

问题是,我读过的大多数算法都使用了密码,这可能意味着它不允许重复,或者它们使用模数或非循环移位来诱导损失并且使功能的逆转最多也是不切实际的。此外,如果算法使用计数,则很难向后工作,因为字节列表输入不会知道内部PRNG计数器在生成时的内容。

我意识到我正在寻找的是一个吃蛋糕和吃得太多的情况,但我想确保没有其他解决方案我错过了。

在搜索时,我遇到了this post,它有类似的要求。我是用C#编写的,但实际上,语法并不重要。

我自己尝试编写的每个算法都是一个密码,因此无法重复和/或不均匀分布。我使用了反演,循环移位和种子掩蔽。

2 个答案:

答案 0 :(得分:1)

这有用吗?

#include <stdio.h>

int seed = 1;

int next() {
    seed = 1664525*seed + 1013904223;
    return (seed & 0xff) ^ (seed>>8 & 0xff) ^ (seed>>16 & 0xff) ^ (seed>>24 & 0xff);
}   

int main() {
    int i;
    for(i = 0; i < 1000; i++) {
        printf("%d\n", next());
    }   
}  

由于它基于具有完整周期的线性同余生成器(LCG),因此每个种子最终将生成每个字节。似乎有重复。它继承了潜在LCG的一致性。

答案 1 :(得分:0)

我的顾问修改了PRNG(基于L'Ecuyer的clcg4)是可逆的,以支持我们小组的HPC模拟工作。您可以阅读这些here

基本上,它“撤消”已完成的工作,并且正如您可能已经猜到的那样,这可能需要“撤消”随机数生成,然后沿着不同的计算路径再次重新生成这些相同的值。您可以查看此代码herehere。这是BSD许可的代码。