Troll Sama bin Laden
Troll Sama bin Laden

Reputation: 71

How to send EVP_PKEY to other party?

I am struggling with the OpenSSL API for C++ at the moment. I'm using the EVP functions to generate a RSA keypair which then is used to encrypt the AES key that was used for encrypting the data (hybrid encryption).

Key generation:

EVP_PKEY* keypair = NULL;
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
EVP_PKEY_keygen_init(ctx);
EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 4096);
EVP_PKEY_keygen(ctx, &keypair);
EVP_PKEY_CTX_free(ctx);

Now I have a keypair. When Encrypting a message on my own machine via EVP_SealInit / EVP_SealUpdate / EVP_SealFinal there is no problem. Same for the decrypting process. I simply give keypair as an argument to the SealInit / OpenInit function.

But consider that I want to generate a keypair and send the public or private key as a char* over a socket to another person: how do I do that?

One way I found in the Internet is using PEM_write_bio_PUBKEY or PEM_write_bio_PrivateKey to convert the Keys to char*. When trying it seemed to work. But I'm still not 100% sure. So Please look at my code and tell me if those functions are the way to go:

unsigned char* publicKey;
BIO* bio = BIO_new(BIO_s_mem());
PEM_write_bio_PUBKEY(bio, keypair);
RSAmakeString(&publicKey, bio);

unsigned char* privateKey;
BIO* bio = BIO_new(BIO_s_mem());
PEM_write_bio_PrivateKey(bio, keypair, NULL, NULL, 0, 0, NULL);
RSAmakeString(&privateKey, bio);

The other thing is how do I convert the char* back to EVP_PKEY*? Are there any functions? Because if I want to use SealInit with my public Key on another computer I have to convert it back from a char* to an EVP_PKEY*, so I can use it in the function. Any suggestions?

Upvotes: 4

Views: 3306

Answers (1)

jww
jww

Reputation: 102205

But consider that I want to generate a keypair and send the public or private key as a char* over a socket to another person: how do I do that?

You need something for serialization and wire formats or a presentation format. Your public key and encrypted messages will likely have 0 characters, which appear as embedded NULL. So you need to have both a buffer and explicit length .

Use Google's ProtocolBuffers, Binary JSON, or even ASN.1/DER encoding. I think Google's ProtocolBuffers are message oriented, so they won't return a message until the complete message is available.

You could also Hex, Base32 or Base64 encode it. But you still need to communicate a length so the receiving party knows they got the whole message. On a local LAN you will probably never experience a problem. Over the Internet you will probably get occasional failures as your perform short reads on occasion.

Your thoughts on PEM_write_bio_PUBKEY are effectively Base64 encoding the key, so it suffers the same potential problem as Hex, Base32 or Base64 encoding.


how do I convert the char* back to EVP_PKEY

Well, you probably won't be using a char* based on your changes above. Once you refine the design, you should probably ask a new question.

But at the moment, and given you saved the key with PEM_write_bio_PUBKEY and PEM_write_bio_PrivateKey, then you would use PEM_read_bio_PUBKEY or PEM_read_bio_PrivateKey, respectively. Also see OpenSSL's PEM man page.


Related to C++, here are some tricks when working with OpenSSL. If you are using C++11, then unique_ptr really makes it easy to work with some OpenSSL objects.

Upvotes: 1

Related Questions