5

我想做这样的事情:

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 位数字?

谢谢,

本。

4

2 回答 2

8

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

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

从这一点开始,mersenne twister 所做的一切都是由这 32 位决定的。

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

然而,在这种情况下,梅森捻线器的主要弱点(它的状态可以在看到 624 个数字后得出)甚至不感兴趣,因为您生成的序列非常短(1 个值)。

生成 64 个加密安全位

假设这unsigned int相当于uint32_t在您的平台上,您可以使用以下命令轻松生成 64 个加密安全随机位boost::random_device

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();
于 2014-04-29T18:44:17.810 回答
-1

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

val = dis(rd);

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

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

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

于 2014-04-29T18:39:41.410 回答