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

时间:2014-04-29 18:14:58

标签: c++ boost random cryptography mersenne-twister

我想做这样的事情:

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

但是我读过一个mersenne twister不是加密安全的。但是,我还读过一个random_device,如果它从/ dev / urandom中提取数据,这可能是在linux平台(我的主平台)上。因此,如果random_device是非确定性随机的并且它用于播种mersenne twister(如上所示),那么这是否也使得mersenne twister在密码学上安全(即使它本身,它不是)?

我在这个舞台上有点新手所以任何建议都值得赞赏。

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

谢谢,

本。

2 个答案:

答案 0 :(得分:8)

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

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

mersenne twister从这一点开始做的一切都取决于那些32位。

这意味着value只能占用2 ** 32个不同的值,如果存在任何攻击向量攻击你使用此数字执行的任何攻击向量,这可能是一个问题。实际上,mersenne twister的播种程序甚至可以减少第一个结果的可能值的数量,因为它将32个随机位分配到其完整状态(为了确保不是这种情况,您必须分析种子例程提升使用)。

在这种情况下,mersenne twister(its state can be derived after seeing 624 numbers)的主要弱点甚至没有意义,因为你生成的序列太短(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 use the operating system's own cryptographically secure randomness sources的实现。

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

虽然之前的功能足够好,但您可能希望获得更灵活的解决方案。这很容易实现,你可以实际使用随机分配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复制了它的参数,并且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();

答案 1 :(得分:-1)

仅仅用于播种的随机设备实际上并不具有加密安全性。然后将问题减少到找出初始种子,这是一个大大减少的问题。相反,直接使用随机设备。

  

val = dis(rd);

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

顺便说一句,假设你有一个高质量的C ++ 11实现,它没有返回entropy函数的伪值,那么使用C ++ 11可能是一个更好的主意,如果你试图删除的依赖关系。

编辑:显然,关于/ dev / random是否比/ dev / urandom更好,存在一些争论。我推荐你this