Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
671 views
in Technique[技术] by (71.8m points)

random - Making OpenSSL generate deterministic key

I'm trying to make openssl generate deterministic private and public RSA key-pair. The idea is that I fill my seedbuf with a HASH of some device dependent data, and use that as a seed. But seeding the RAND does not seem to work, the keys are still randomized.

For various reasons I don't want to just generate the key once, and then store it, I only want the private key to exist in memory.

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;
}

So basically I want the "RSA_generate_key_ex" function to return same key-pair, each time it is seeded with same input.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Making openssl generate deterministic key...

I don't believe you can do it out of the box. By default, OpenSSL uses md_rand, and that auto seeds itself. Calling rand_seed internally calls rand_add, which adds to the state (rather than discarding/replacing state). You can find the source for md_rand in crypto/rand/md_rand.c.

If you build with FIPS enabled, then there are deterministic random bit generators from NIST's SP 800-90. However, I seem to recall they operate in similar fashion to md_rand. That is, you can add to internal state, but you can't really control it. You can find the source in crypto/rand/rand_lib.c.

I think you have one option. You can create you own my_rand. Base it on a block cipher or hash. On startup, seed it with device dependent data, and then return the deterministic bytes.

Now, to get functions like RSA_generate_key_ex to use your PRNG, you have to package it in an OpenSSL ENGINE. Richard Levitte of OpenSSL has a nice two-series blog at Engine Building Lesson 1: A Minimum Useless Engine and Engine Building Lesson 2: An Example MD5 Engine on the OpenSSL blog.

Once you package it with an engine, you can use it like so. After you set the random method with ENGINE_METHOD_RAND, you will be using your algorithm.

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
", err);
    abort(); /* failed */
}

int rc = ENGINE_init(eng);
err = ERR_get_error();

if(0 == rc) {
    fprintf(stderr, "ENGINE_init failed, err = 0x%lx
", 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
", err);
    abort(); /* failed */
}

If you want to look at a ENGINE implementation, take a look at the rdrand engine in crypto/engine/eng_rdrand.c. There's not much to the engine, and it will be easy to copy/paste. Be sure to add your new engine to the Makefile in crypto/engine/Makefile.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...