random_bytes_engine生成密钥时每次输出相同结果是什么原因?如何解决?
问题根因
- 你定义的
std::default_random_engine随机引擎使用默认构造函数初始化,没有传入随机种子,C++标准规定默认构造的伪随机引擎每次都会使用固定的默认种子,因此每次运行生成的随机数序列完全一致,最终得到的密钥自然完全相同。 - 额外注意:
std::default_random_engine属于非密码学安全的伪随机数生成器,本身设计目标是满足统计、模拟等非敏感场景的性能需求,即使添加随机种子,也不适合用于生成加密场景的密钥、初始化向量等敏感数据,生成的序列容易被攻击者预测。
解决方案
分两种场景给出适配方案:
1. 非加密场景临时修复(仅用于测试、非敏感场景)
给随机引擎传入随机来源的种子即可,最方便的是使用std::random_device生成种子,修改后的代码如下:
template <size_t N> void generate_random_key(uint8_t(&iv_buff)[N]) { using random_bytes_engine = std::independent_bits_engine<std::default_random_engine, CHAR_BIT, size_t>; std::random_device rd; // 用真随机种子初始化随机引擎 random_bytes_engine rbe(rd()); std::generate(std::begin(iv_buff), std::end(iv_buff), [&rbe]() { return static_cast<uint8_t>(rbe()); }); }
2. 加密场景正确实现
加密场景需要使用密码学安全的随机数源,直接基于std::random_device生成所有密钥字节即可,主流操作系统的std::random_device实现都是基于操作系统内核提供的真随机源,符合加密安全要求,实现代码如下:
template <size_t N> void generate_random_key(uint8_t(&iv_buff)[N]) { std::random_device rd; for (size_t i = 0; i < N; ++i) { iv_buff[i] = static_cast<uint8_t>(rd()); } }
如果担心部分平台std::random_device的伪实现问题,可以直接调用操作系统原生的加密随机接口:
- Linux/macOS:调用
getrandom()系统调用或者读取/dev/urandom - Windows:调用
BCryptGenRandom接口
内容的提问来源于stack exchange,提问作者nop
相关产品推荐
相关产品推荐

