我正在尝试使openssl生成确定性的私有和公共RSA密钥对。我的想法是,我用一些设备相关数据的HASH填充我的seedbuf,并将其用作种子。但播种RAND似乎不起作用,关键仍然是随机的。
出于各种原因,我不想只生成一次密钥,然后存储它,我只希望私钥存在于内存中。
RAND_seed(seedbuf, sizeof(seedbuf));
bne = BN_new();
if (1 != BN_set_word(bne,e)) {
goto free_stuff;
}
keypair = RSA_new();
if(1 != RSA_generate_key_ex(keypair, KEY_LENGTH, bne, NULL)) {
goto free_stuff;
}
所以基本上我希望“RSA_generate_key_ex”函数返回相同的密钥对,每次使用相同的输入进行播种。
答案 0 :(得分:4)
使openssl生成确定性密钥......
我不相信你可以开箱即用。默认情况下,OpenSSL使用md_rand
,并自动播种。在内部调用rand_seed
会调用rand_add
,这会增加状态(而不是丢弃/替换状态)。您可以在md_rand
中找到crypto/rand/md_rand.c
的来源。
如果您使用FIPS
进行构建,那么NIST的SP 800-90就会有确定性的随机位生成器。但是,我似乎记得它们的运作方式与md_rand
类似。也就是说,您可以添加到内部状态,但您无法真正控制它。您可以在crypto/rand/rand_lib.c
找到来源。
我认为你有一个选择。您可以创建自己的my_rand
。基于块密码或散列。在启动时,使用设备相关数据为其播种,然后返回确定性字节。
现在,要使RSA_generate_key_ex
等函数使用您的PRNG,您必须将其打包在OpenSSL ENGINE
中。 OpenSSL的Richard Levitte在OpenSSL博客上的Engine Building Lesson 1: A Minimum Useless Engine和Engine Building Lesson 2: An Example MD5 Engine有一个不错的双系列博客。
使用引擎打包后,您可以像这样使用它。使用ENGINE_METHOD_RAND
设置随机方法后,您将使用算法。
ENGINE* eng = ENGINE_by_id("my_rand");
unsigned long err = ERR_get_error();
if(NULL == eng) {
fprintf(stderr, "ENGINE_by_id failed, err = 0x%lx\n", err);
abort(); /* failed */
}
int rc = ENGINE_init(eng);
err = ERR_get_error();
if(0 == rc) {
fprintf(stderr, "ENGINE_init failed, err = 0x%lx\n", err);
abort(); /* failed */
}
rc = ENGINE_set_default(eng, ENGINE_METHOD_RAND);
err = ERR_get_error();
if(0 == rc) {
fprintf(stderr, "ENGINE_set_default failed, err = 0x%lx\n", err);
abort(); /* failed */
}
如果您想查看ENGINE
实施,请查看rdrand
中的crypto/engine/eng_rdrand.c
引擎。引擎并不多,复制/粘贴也很容易。请务必将新引擎添加到Makefile
中的crypto/engine/Makefile
。
答案 1 :(得分:-1)
如果您正在寻找一种不一定使用OpenSSL生成确定性密钥的方法,GnuTLS可能会提供帮助:
certtool --generate-privkey --outfile privkey.pem --key-type=rsa --sec-param=high --seed=0000000000000000000000000000000000000000000000000000000000000000
至少在当前版本中使用--seed
意味着使用--provable
算法生成(FIPS PUB186-4)。
生成的privkey.pem
将采用RSA-PSS格式,您可以使用以下命令将其转换为原始RSA格式:
certtool --to-rsa --load-privkey privkey.pem --outfile privkey.key
然后,如果需要,可以通过两种格式的密钥生成自签名证书:
certtool --generate-self-signed --load-privkey privkey.key --outfile signed.crt --template cert.cfg
如果您也想使此步骤具有确定性,或者在每次运行命令时都避免回答问题,请将--template cert.cfg
参数添加到最后一个命令中。使cert.cfg
文件能够确定生成的最低内容为:
serial = 1
activation_date = "2019-01-01 00:00:00 UTC"
expiration_date = "2029-01-01 00:00:00 UTC"