我想做这样的事情:
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位数?
谢谢,
本。
答案 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值)。
假设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。