使openssl生成确定性密钥

时间:2014-03-31 10:40:53

标签: openssl

我正在尝试使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”函数返回相同的密钥对,每次使用相同的输入进行播种。

2 个答案:

答案 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 EngineEngine 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"