使 OpenSSL 生成确定性密钥

Jak*_*obJ 6 random openssl

我试图让 openssl 生成确定性的私有和公共 RSA 密钥对。这个想法是我用一些设备相关数据的哈希填充我的种子缓冲区,并将其用作种子。但是播种 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;
}
Run Code Online (Sandbox Code Playgroud)

所以基本上我希望“RSA_generate_key_ex”函数返回相同的密钥对,每次用相同的输入播种。

jww*_*jww 6

使 openssl 生成确定性密钥...

我不相信你可以开箱即用。默认情况下,OpenSSL 使用md_rand, 并且自动种子本身。调用rand_seed内部调用rand_add,这增加了的状态(而不是丢弃/更换状态)。您可以找到md_randin的来源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 在引擎构建第 1 课:最小无用引擎引擎构建第 2 课: OpenSSL 博客上的示例 MD5 引擎中有一个很好的两系列博客。

一旦你把它和引擎打包在一起,你就可以像这样使用它。使用 设置随机方法后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 */
}
Run Code Online (Sandbox Code Playgroud)

如果你想看看一个ENGINE实现,看看该rdrand发动机crypto/engine/eng_rdrand.c。引擎没有太多内容,复制/粘贴很容易。请务必将新引擎添加到Makefilein 中crypto/engine/Makefile


use*_*ser 6

如果您正在寻找一种不一定使用 OpenSSL 生成确定性密钥的方法,GnuTLS可能可以提供帮助:

certtool --generate-privkey --outfile privkey.pem --key-type=rsa --sec-param=high --seed=0000000000000000000000000000000000000000000000000000000000000000
Run Code Online (Sandbox Code Playgroud)

--seed至少在当前版本中使用意味着使用--provable算法生成 (FIPS PUB186-4)。

生成的privkey.pem将为 RSA-PSS 格式,您可以使用以下命令将其转换为原始 RSA 格式:

certtool --to-rsa --load-privkey privkey.pem --outfile privkey.key
Run Code Online (Sandbox Code Playgroud)

然后,如果需要,您可以从任一格式的密钥生成自签名证书:

certtool --generate-self-signed --load-privkey privkey.key --outfile signed.crt --template cert.cfg
Run Code Online (Sandbox Code Playgroud)

如果您也希望使此步骤具有确定性或避免每次运行命令时回答问题,请将--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"
Run Code Online (Sandbox Code Playgroud)