我正在尝试使用 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)
错误在哪里?
这不是一个错误。OpenSSL 随机数生成器使用良好的随机源自行进行一些播种。
因此使用相同的种子值并RAND_seed不能保证随机数序列相同。这是一件好事,因为它使它们更难以预测,因此更安全。
从手册页RAND_seed:
Run Code Online (Sandbox Code Playgroud)#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);
RAND_add()将numat 的字节混合buf到 PRNG 状态。因此,如果对手无法预测 处的数据buf,就会增加状态的不确定性,并使 PRNG 输出更不可预测。合适的输入来自用户交互(随机按键、鼠标移动)和某些硬件事件。该entropy参数是对 buf 中包含多少随机性的估计(下限),以字节为单位。有关随机性来源以及如何估计其熵的详细信息可以在文献中找到,例如 RFC 1750。
RAND_add()可能会使用敏感数据(例如用户输入的密码)进行调用。无法从 PRNG 输出中恢复种子值。OpenSSL 确保每个线程的 PRNG 状态都是唯一的。 在提供“/dev/urandom”的系统上,随机设备用于透明地播种 PRNG。但是,在所有其他系统上,应用程序负责通过调用
RAND_add()、RAND_egd(3)或 来播种 PRNGRAND_load_file(3)。
RAND_seed()相当于RAND_add()当num == entropy.
因此,如果您的系统有/dev/urandom,它将被用作 PRNG 的初始种子。