跳至主要内容

博文

精选博文

C++ | 如何安全地初始化 std::mt19937

C++ | 如何安全地初始化 std::mt19937 背景 在看到 C++ Seeding Surprises ᴮᵃᶜᵏᵘᵖ 这篇文章之前,我一直使用如下代码初始化 std::mt19937 : std::mt19937 mtr(std::random_device{}()); 问题 std::random_device 可能根本不是随机的 旧版 MinGW 中的 GCC 将其实现为确定性的,参见 std::random_device not working properly ᴮᵃᶜᵏᵘᵖ ,这一问题已在 MinGW GCC 9.2 中修复。 std::random_device 的值域不够大 std::random_device 的值域同 unsigned int ,在我的环境中为 [0,2^{32}-1] ,提供了 32 位的随机性。 然而, 2^{32} 并不是一个很大的数字。我们进行了一组 测试 ᴮᵃᶜᵏᵘᵖ ,在 1.75 秒内遍历了 10^6 个数据,因此预计可以在 2.09 小时内遍历完 2^{32} 种情况。 众所周知,只要知道种子,就可以预测整个随机序列。因此,对于需要高安全性的用例来说,32 位的种子远远不够。 需要高安全性的用例应当使用 密码学安全伪随机数生成器 ᴮᵃᶜᵏᵘᵖ 。 std::seed_seq 的实现不靠谱 上面的代码中,我们只给 std::mt19937 提供了一个 32 位整数,但是 Mersenne Twister 的状态包含 624 个 32 位整数(参见 维基百科 ᴮᵃᶜᵏᵘᵖ ),因此标准库会使用 std::seed_seq 来扩充状态。 然而 std::seed_seq 的实现有问题。 在使用 32 位整数进行播种时,包括 7 和 13 在内的大约 \frac{2^{32}}e 个数永远不可能作为 std::mt19937 生成的第一个数。如果你运行如下代码,函数 send_detailed_tracking_info_secretly 永远不会被调用。 std::mt19937 mtr(std::random_device{}()); if (mtr() == 7) /* lucky seven! you

最新博文

Solving the Easy Stream 3 Problem in the DASCTF Cybersecurity Competition

转载 | 王开岭:是「国家」错了

Blogger × Cloudflare Workers:轻松解决 Blogger 在国内的连接问题

书摘 | 沉默的大多数

分享 | 乌撒之猫

分享 | 看镜有感