Extract public key from EVP_PKEY keypair?
Asked Answered
F

2

10

I am implementing an encryption / decryption scheme in my application using OpenSSL's high-level EVP_*() functions, so I can easily switch the actual algorithms used without having to change the API calls.

I can create a key pair with relative ease:

// dumbed down, no error checking for brevity
EVP_PKEY * pkey;
// can change EVP_PKEY_RSA to something else here
EVP_PKEY_CTX * context = EVP_PKEY_CTX_new_id( EVP_PKEY_RSA, NULL );
EVP_PKEY_keygen_init( ctx );
// could set parameters here
EVP_PKEY_keygen( context, &pkey );
// ...
EVP_PKEY_CTX_free( context );

pkey now holds a key pair, i.e. both secret and public key. That's fine for the secret side of things, but obviously I would like to extract only the public key component for use on the public side of things.

I was able to find RSA-specific functions, but nothing using the high-level EVP_*() API.

Help?

Fishbolt answered 27/8, 2014 at 13:25 Comment(7)
What is your question? "extract only the public key component for use on the public side of things" is kind of ambiguous. Do you want to know how to get a public key from a PKEY? Or do you want to know how to save a public key? Or something else?Inkerman
@jww: I thought the question was unambiguous... I would like to get an EVP_PKEY data structure that contains only the public key component.Fishbolt
"I would like to get an EVP_PKEY data structure that contains only the public key component" - that's going to take some work because OpenSSL is not setup that way for the EVP_* gear (it can be done, but it takes some work). Usually you write out a DER or PEM encoded key (public or private). Have you looked at the functions in pem(3) gear. With the *_bio functions, you can write to file or memory. Take a look at, for example, <openssl src>/apps/rsautl.c (for the RSA case).Inkerman
@jwiw: Will do, thanks for the pointers. (This is my first close encounter with OpenSSL, so it's entirely possible that I am barking up the wrong tree here.)Fishbolt
In essence, you have to round trip a EVP_PKEY. During the trip, you have to get the key in its native format (like RSA* or DSA*) and convert it from private to public. Then you send it back to an EVP_PKEY. But like I said, if all you need is an DER or PEM encoded key to distribute, use the stuff in pem(3).Inkerman
how did you make out on this? I have some free time and can show you how to round trip a key if interested. I don't have code handy, so I'd have to write it.Inkerman
@jww: This is currently nine-to-five, and I have decided to go with symmetric encoding for the time being. I'll probably write up my own answer once I get around to it. (I'm not particularly quick, but persistant about these things.)Fishbolt
T
4

You could use following methods to separate public key and private key for future use.

int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
                    unsigned char *kstr, int klen,
                    pem_password_cb *cb, void *u);

 int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
                    unsigned char *kstr, int klen,
                    pem_password_cb *cb, void *u);
EVP_PKEY *PEM_read_bio_PUBKEY(BIO *bp, EVP_PKEY **x,
                    pem_password_cb *cb, void *u);

 EVP_PKEY *PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x,
                    pem_password_cb *cb, void *u);

 int PEM_write_bio_PUBKEY(BIO *bp, EVP_PKEY *x);
 int PEM_write_PUBKEY(FILE *fp, EVP_PKEY *x);

For detailed information, please refer to <openssl/pem.h>.

Terryl answered 22/3, 2017 at 9:17 Comment(0)
S
2

It's may be, you should use i2d_PUBKEY_bio() or similar function.

Swear answered 30/12, 2014 at 14:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.