RAND_bytes 不会从相同的种子给出相同的结果

Cre*_*one 4 c openssl pbkdf2

我正在尝试使用 OpenSSL 编写自定义 RSA 密钥对生成算法。我使用该PKCS5_PBKDF2_HMAC_SHA1函数生成 PRNG 种子,因此,我使用该种子作为 RAND_seed 输入。

不幸的是,每次我使用RAND_bytes相同的种子调用 时,我都会获得不同的随机数,但这不是预期的行为,因为正如如何从短密码中安全地生成非对称密钥对?随机数生成器是确定性的(相同的种子相同的输出)。

下面是测试用例。我也声明了恒定的种子,但生成从来都不是确定性的。

unsigned int seed = 0x00beef00;
unsigned int rnum[5];
RAND_seed(&seed, sizeof(seed));
RAND_bytes((unsigned char *)&rnum[0], sizeof(rnum));
Run Code Online (Sandbox Code Playgroud)

错误在哪里?

dbu*_*ush 5

这不是一个错误。OpenSSL 随机数生成器使用良好的随机源自行进行一些播种。

因此使用相同的种子值并RAND_seed不能保证随机数序列相同。这是一件好事,因为它使它们更难以预测,因此更安全。

从手册页RAND_seed

    #include <openssl/rand.h>

    void RAND_seed(const void *buf, int num);

    void RAND_add(const void *buf, int num, double entropy);

    int  RAND_status(void);

    int  RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam);
    void RAND_screen(void);
Run Code Online (Sandbox Code Playgroud)

RAND_add()numat 的字节混合buf到 PRNG 状态。因此,如果对手无法预测 处的数据buf,就会增加状态的不确定性,并使 PRNG 输出更不可预测。合适的输入来自用户交互(随机按键、鼠标移动)和某些硬件事件。该entropy 参数是对 buf 中包含多少随机性的估计(下限),以字节为单位。有关随机性来源以及如何估计其熵的详细信息可以在文献中找到,例如 RFC 1750。

RAND_add()可能会使用敏感数据(例如用户输入的密码)进行调用。无法从 PRNG 输出中恢复种子值。

OpenSSL 确保每个线程的 PRNG 状态都是唯一的。 在提供“/dev/urandom”的系统上,随机设备用于透明地播种 PRNG。但是,在所有其他系统上,应用程序负责通过调用 RAND_add()RAND_egd(3)或 来播种 PRNG RAND_load_file(3)

RAND_seed()相当于RAND_add()num == entropy.

因此,如果您的系统有/dev/urandom,它将被用作 PRNG 的初始种子。

  • @CrescenzoMugione PRNG 是确定性的。这里的区别在于 OpenSSL 透明地使用来自“/dev/urandom”的随机数据为 PRNG 播种。可以多次调用“RAND_seed”或“RAND_add”来添加种子数据。因此,当您调用这些函数之一时,给定的种子缓冲区将“添加”到从“/dev/random”提取的数据中。这有助于增加随机性并使任何生成的字节不可预测。 (2认同)