如何使用 boost::random_device 生成加密安全的 64 位整数

How do I use boost::random_device to generate a cryptographically secure 64 bit integer?

本文关键字:安全 加密 整数 boost 何使用 random device      更新时间:2023-10-16

我想做这样的事情:

boost::random_device rd;
boost::random::mt19937_64 gen(rd());
boost::random::uniform_int_distribution<unsigned long long> dis;
uint64_t value = dis(gen);

但我读到梅森捻线机在密码学上并不安全。但是,我也读到random_device可能是,如果它从/dev/urandom 中提取数据,这可能是在 linux 平台(我的主要平台(上。因此,如果random_device是不确定随机的,并且用于播种 mersenne twister(如上所示(,这是否也使 mersenne twister 在加密上是安全的(即使它本身不是(?

我在这个领域有点新手,所以任何建议都值得赞赏。

那么,如何生成可存储在uint64_t中的加密安全 64 位数字?

谢谢

本。

分析你的问题比看起来更难:

你用 rd() 播种 mersenne twister,它返回一个unsigned int,因此(在大多数平台上(最多包含 32 个随机位。

从这一点开始,Mersenne Twister所做的一切都由这32位决定。

这意味着value只能采用 2**32 个不同的值,如果存在任何攻击媒介通过蛮力攻击您使用此数字所做的任何事情,这可能是一个问题。事实上,Mersenne Twister 的播种例程甚至可能减少第一个结果的可能值的数量,因为它在其完整状态下分布了 32 个随机位(为了确保不是这种情况,您必须分析种子例程提升用途(。

然而,在这种情况下,mersenne twister 的主要弱点(其状态可以在看到 624 个数字后导出(甚至不感兴趣,因为您生成的序列非常短(1 个值(。

生成 64 个加密安全位

假设unsigned int等效于平台上的uint32_t,您可以使用boost::random_device轻松生成 64 个加密安全的随机位:

boost::random_device rd;
std::uint64_t value = rd();
value = (value << 32) | rd();

这是相当安全的,因为Linux和Windows的实现都使用操作系统自己的加密安全随机源。

使用任意分布生成加密安全值

虽然以前的方法效果很好,但您可能希望使用更灵活的解决方案。这很容易做到,因为你实际上也可以使用Boost提供的随机分布random_device。一个简单的例子是像这样重写以前的解决方案:

boost::random_device rd;
boost::random::uniform_int_distribution<std::uint64_t> dis;
std::uint64_t value = dis(rd);

(虽然理论上也可以提供更健壮的解决方案,如果前一个实际上不包含 [0, 2**32] 中的数字(,但这在实践中不是问题。

与生成器的绑定分布

为了提高可用性,您经常会发现使用 boost::bind 将发行版和生成器绑定在一起。由于boost::bind复制了它的参数,并且复制 ctor 被删除了boost::random_device,你需要使用一个小技巧:

boost::random_device rd;
boost::random::uniform_int_distribution<std::uint64_t> dis;
boost::function<std::uint64_t()> gen = boost::bind(dis, boost::ref(rd));
std::uint64_t value = gen();

将随机设备仅用于种子设定在加密上并不真正安全。然后将问题简化为找出初始种子,这是一个大大减少的问题。相反,直接使用随机设备。

val = dis(rd(;

为了提高安全性,请使用 /dev/random 而不是 /dev/urandom 初始化随机设备。 如果没有足够的"熵",/dev/random会阻塞,直到发生一些随机的事情。但是,它可能要慢得多。

顺便说一句,假设您有一个高质量的 C++11 实现,它不会返回 entropy 函数的虚假值,如果您尝试删除依赖项,使用 C++11 可能是更好的主意。

编辑:显然有一些关于/dev/random是否比/dev/urandom更好的争论。我向你推荐这个。