mil*_*los 1 c++ random cryptography
我正在尝试预测由C++ rand()函数生成的数字。这是代码的链接,它可能使用:单击
这是我模拟rand() 的代码:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
srand(time(0));
unsigned a = rand();
unsigned b = rand();
cout << (a * 1103515245U + 12345U) % 0x7fffffffU << '\n';
cout << b << '\n'; // they should match, right? But they don't...
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么我的值与b不匹配?
如果TYPE_0选择了生成器,glibc 仅使用旧的线性同余生成器,如您在链接的代码中所见。(默认情况下,它使用TYPE_3generator。)这是 RNG 缓冲区大小为 8 字节的唯一情况。您可以使用以下命令强制执行旧行为initstate:
char state[8];
initstate(time(0), state, 8);
unsigned a = rand();
unsigned b = rand();
cout << (a * 1103515245u + 12345u) % 0x7fffffffu << '\n';
Run Code Online (Sandbox Code Playgroud)
然后你经常得到相同的数字,当你没有时,它只会被抵消一个。粗略一看,我还没有能够准确地弄清楚为什么会发生这种差异(稍后可能会编辑),但我怀疑进行一些恶作剧。
编辑:好的,我想通了。glibcrand内部使用有符号算术,它使用&而不是%模数。如果(a * 1103515245 + 12345)变为负数,这将产生一位差异。如果你写
int a = rand();
int b = rand();
cout << (a * 1103515245 + 12345) & 0x7fffffff << '\n';
Run Code Online (Sandbox Code Playgroud)
那么你总是得到相同的结果。嗯,真的a而且b应该是int32_t为了最大的便携性,但我怀疑这不是问题。因为无论如何,库的内部结构和可移植性是一种失败的原因。