C RAND_字节不';同一粒种子不能产生同样的结果
我正在尝试使用OpenSSL编程自定义RSA密钥对生成算法。我使用了C RAND_字节不';同一粒种子不能产生同样的结果,c,openssl,pbkdf2,C,Openssl,Pbkdf2,我正在尝试使用OpenSSL编程自定义RSA密钥对生成算法。我使用了PKCS5_PBKDF2_HMAC_SHA1函数来生成PRNG种子,因此,我将此种子用作RAND_种子输入 不幸的是,每次我调用RAND_bytes,使用相同的种子,我都会得到不同的随机数,但这不是预期的行为,因为正如所说,随机数生成器的答案是确定性的(相同的种子,相同的输出) 下面是测试用例。我也声明了常量种子,但生成永远不是确定性的 unsigned int seed = 0x00beef00; unsigned int r
PKCS5_PBKDF2_HMAC_SHA1
函数来生成PRNG种子,因此,我将此种子用作RAND_种子输入
不幸的是,每次我调用RAND_bytes
,使用相同的种子,我都会得到不同的随机数,但这不是预期的行为,因为正如所说,随机数生成器的答案是确定性的(相同的种子,相同的输出)
下面是测试用例。我也声明了常量种子,但生成永远不是确定性的
unsigned int seed = 0x00beef00;
unsigned int rnum[5];
RAND_seed(&seed, sizeof(seed));
RAND_bytes((unsigned char *)&rnum[0], sizeof(rnum));
错误在哪里?这不是错误。OpenSSL随机数生成器使用良好的随机性源自行进行一些种子设定 因此,在
RAND_seed
中使用相同的种子值不能保证相同的随机数序列。这是一件好事,因为它使它们更不可预测,因此更安全
从RAND_seed
的手册页:
#包括
void RAND_seed(const void*buf,int num);
void RAND_add(const void*buf,int num,双熵);
国际随机状态(无效);
int RAND_事件(UINT iMsg、WPARAM WPARAM、LPARAM LPARAM);
无效随机屏幕(无效);
RAND_add()。因此,如果
buf
的数据对于对手来说是不可预测的,这会增加
状态的不确定性使得PRNG输出更少
可预测的适当的输入来自用户交互(随机键
按键、鼠标移动)和某些硬件事件。熵
参数是对随机性的估计(下限)
包含在buf中,以字节为单位。资料来源详情
随机性和如何估计它们的熵可以在
文献,如RFC 1750
RAND\u add()
密码。无法从PRNG恢复种子值
输出
OpenSSL确保每个线程的PRNG状态是唯一的。
在提供“/dev/uradom”的系统上,随机性设备是
用于透明地为PRNG播种。但是,在所有其他系统上,
应用程序负责通过调用
RAND\u add()
,RAND\u egd(3)
或RAND\u load\u文件(3)
RAND\u seed()
等同于RAND\u add()
当num==entropy
时
因此,如果您的系统具有/dev/uradom
,它将用作PRNG的初始种子。Openssl的int RAND_字节(无符号字符*buf,int num)代码>尝试使事情尽可能随机。这显然是一个你不想要的特性,而是寻找一个可重复的伪随机序列
但是Openssl也有很多优点
int RAND\u伪字节(无符号字符*buf,int num)代码>
这可能就是你想要的,伪序列,给你一个可重复的序列
另一方面,如果你在做RSA,一个可重复的随机序列并不是那么好,因为你要找的是两个大素数。做一个大的PRNG数,然后测试素数可能是个坏主意。其中一半可以被2整除:)
如果我没记错的话,你需要选择一个好的起始数字,用1进行ORing,使之成为奇数,然后测试素数,如果不是,则增加4,然后再试一次
一旦找到它们,您可能就不想再使用可重复的PRNG字节开始搜索了
虽然我很确定这是一个学习项目,但如果你想要的只是openssl中的RSA密钥对,请检查一下
您好,谢谢您的回复,我尝试了RAND_伪字节,但它总是为同一种子提供随机输出。我需要为相同的输入生成相同的输出,因为我的密钥对对于单个设备必须是唯一的,由一些参数标识。RAND\u pseudo\u bytes
将PID、时间等混合到其状态中。分叉也混合在新的状态。检查源文件中是否有。@jww我从中尝试了测试程序,得到了一个可重复的序列。我的版本与您的源代码版本有什么不同,我不能说。但是一个可重复的伪随机序列对于Monte Carlo程序之类的东西是有用的,所以我很惊讶这种能力是否已经被证明了lost@CrescenzoMugione. 即使你得到了一个可重复的序列,你也得到了一个非常弱的系统。这类似于Debian曾经犯过的错误,他们的openssh只生成32K唯一的会话密钥,因为最终他们的种子仅仅基于PID。像MAC地址这样的东西甚至不是好的秘密,因为你子网上的每个人都可以得到它。请记住,约翰·冯·诺伊曼曾经说过:“任何考虑产生随机数字的算术方法的人,当然都处于罪恶状态。”[嗨,感谢你的回答,从主题中可以看出,“PRNG是确定性的(相同的种子意味着相同的输出序列)并产生随机位。”@PRNG是确定性的。这里的区别是OpenSSL透明地使用来自/dev/uradom
随机种子或随机种子添加的随机数据为PRNG种子。可以多次调用以添加种子数据。因此,当您调用其中一个函数时,给定的种子缓冲区将添加到数据中来自/dev/random
。这有助于增加随机性,并使任何生成的字节不可预测。假设您使用默认的RAND
引擎,请检查源代码。另请参阅关于堆栈溢出。简短的是,您必须创建一个OpenSSL引擎
。要创建自定义引擎,请参阅和onOpenSSL博客。
#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);