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?

jww
  • 97,681
  • 90
  • 411
  • 885
DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • 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? – jww Aug 27 '14 at 14:15
  • @jww: I thought the question was unambiguous... I would like to get an `EVP_PKEY` data structure that contains *only* the public key component. – DevSolar Aug 27 '14 at 14:26
  • *"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)`](http://www.openssl.org/docs/crypto/pem.html) gear. With the `*_bio` functions, you can write to file or memory. Take a look at, for example, `/apps/rsautl.c` (for the RSA case). – jww Aug 27 '14 at 15:00
  • @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.) – DevSolar Aug 27 '14 at 15:11
  • 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)`. – jww Aug 27 '14 at 15:28
  • 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. – jww Aug 28 '14 at 01:57
  • @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.) – DevSolar Aug 28 '14 at 04:51

2 Answers2

5

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>.

DevSolar
  • 67,862
  • 21
  • 134
  • 209
Jared
  • 822
  • 1
  • 10
  • 18
2

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