简体   繁体   English

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

[英]RAND_bytes doesn't give the same result from the same seed

I'm trying to program custom RSA key pair generation algorithm using OpenSSL. 我正在尝试使用OpenSSL编写自定义RSA密钥对生成算法。 I've used the PKCS5_PBKDF2_HMAC_SHA1 function to generate PRNG seed, so, I've used this seed as RAND_seed input. 我已经使用PKCS5_PBKDF2_HMAC_SHA1函数生成PRNG种子,因此,我已将此种子用作RAND_seed输入。

Unfortunately every time I call RAND_bytes , with the same seed, I obtain different random numbers, but this isn't the expected behaviour, because as say the answer at How can one securely generate an asymmetric key pair from a short passphrase? 不幸的是,每当我使用相同的种子调用RAND_bytes ,我会获得不同的随机数,但这不是预期的行为,因为如何回答“ 如何从短密码中安全地生成非对称密钥对?” the random number generator is deterministic (same seed same output). 随机数发生器是确定性的(相同的种子相同的输出)。

Below is the test case. 以下是测试用例。 I've declared also constant seed, but the generation is never deterministic. 我已经宣布了恒定的种子,但这一代人从来都不是确定性的。

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

Where is the error? 错误在哪里?

This is not an error. 这不是错误。 The OpenSSL random number generator does some seeding on its own using good sources of randomness. OpenSSL随机数生成器使用良好的随机源自行完成一些播种。

So using the same seed value in RAND_seed does not guarantee the same sequence of random numbers. 因此,在RAND_seed中使用相同的种子值并不能保证相同的随机数序列。 This is a Good Thing because it makes them less predictable and therefore more secure. 这是一件好事,因为它使它们更难预测,因此更安全。

From the man page for 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); 

RAND_add() mixes the num bytes at buf into the PRNG state. RAND_add()bufnum个字节混合到PRNG状态。 Thus, if the data at buf are unpredictable to an adversary, this increases the uncertainty about the state and makes the PRNG output less predictable. 因此,如果buf处的数据对于对手是不可预测的,则这增加了关于状态的不确定性并且使得PRNG输出不太可预测。 Suitable input comes from user interaction (random key presses, mouse movements) and certain hardware events. 合适的输入来自用户交互(随机按键,鼠标移动)和某些硬件事件。 The entropy argument is (the lower bound of) an estimate of how much randomness is contained in buf, measured in bytes. entropy参数是(下限)buf中包含多少随机性的估计值,以字节为单位。 Details about sources of randomness and how to estimate their entropy can be found in the literature, eg RFC 1750. 关于随机性来源以及如何估计其熵的细节可以在文献中找到,例如RFC 1750。

RAND_add() may be called with sensitive data such as user entered passwords. 可以使用敏感数据(例如用户输入的密码RAND_add()调用RAND_add() The seed values cannot be recovered from the PRNG output. 无法从PRNG输出恢复种子值。

OpenSSL makes sure that the PRNG state is unique for each thread. OpenSSL确保PRNG状态对于每个线程都是唯一的。 On systems that provide "/dev/urandom", the randomness device is used to seed the PRNG transparently. 在提供“/ dev / urandom”的系统上,随机性设备用于透明地播种PRNG。 However, on all other systems, the application is responsible for seeding the PRNG by calling RAND_add() , RAND_egd(3) or RAND_load_file(3) . 但是,在所有其他系统上,应用程序负责通过调用RAND_add()RAND_egd(3)RAND_load_file(3)来播种PRNG。

RAND_seed() is equivalent to RAND_add() when num == entropy . RAND_seed()等效于RAND_add()num == entropy

So if your system has /dev/urandom , it will be used as the initial seed for the PRNG. 因此,如果您的系统具有/dev/urandom ,它将用作PRNG的初始种子。

Openssl's int RAND_bytes(unsigned char *buf, int num); Openssl的int RAND_bytes(unsigned char *buf, int num); tries to make things as random as it can. 试图让事情尽可能随意。 That is apparently a feature you don't want, and are instead looking for a repeatable pseudorandom sequence 这显然是您不想要的功能,而是寻找可重复的伪随机序列

But Openssl also has 但是Openssl也有

int RAND_pseudo_bytes(unsigned char *buf, int num);

which is probably what you are looking for, the pseudo part, to give you the repeatable sequence. 这可能是你正在寻找的, 部分,给你可重复的序列。

https://linux.die.net/man/3/rand_pseudo_bytes https://linux.die.net/man/3/rand_pseudo_bytes

Force openssl's RNGs to return a repeatable byte sequence 强制openssl的RNG返回可重复的字节序列

As an aside, if you are doing RSA, a repeatable random sequence isn't all that good, because what you are looking for are two large primes. 顺便说一下,如果你正在做RSA,一个可重复的随机序列并不是那么好,因为你要找的是两个大素数。 Doing a large PRNG number, then testing for prime is probably a bad idea. 做一个大的PRNG号码,然后测试素数可能是一个坏主意。 Half of them will be divisible by 2! 其中一半将被2整除! :) :)

If I recall correctly, you need to pick a good starting number, make it odd by ORing with 1, then test for prime, and if it is not, increment by 4 and try again. 如果我没记错的话,你需要选择一个好的起始编号,通过ORing 1使其变为奇数,然后测试素数,如果不是,则增加4并再试一次。

Once you find them, you probably will not want to do it again using repeatable PRNG bytes to start your search. 一旦找到它们,您可能不希望再使用可重复的PRNG字节来开始搜索。

And while I'm pretty sure this is for a learning project, but if all you want is a RSA key pair from openssl check out 虽然我很确定这是一个学习项目,但如果您想要的是一个来自openssl的RSA密钥对,请查看

https://stackoverflow.com/a/5246045/6047952 https://stackoverflow.com/a/5246045/6047952

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM