1

I have 2 questions:

  1. How can I generate private/public key pairs with c++ and openssl? I don't want them saved to a file. I want the values to be available to my c++ program.
  2. Given a private key, how can I regenerate its public key with c++ and openssl?

For the first question, I need to do something like this, except in c++.

$ openssl ecparam -name secp256k1 -genkey | openssl ec -text
read EC key
Private-Key: (256 bit)
priv:
    0c:25:3a:f2:dc:5b:07:b0:45:9c:ad:ac:13:e1:ef:
    14:50:68:cc:cc:6b:8b:09:66:1b:8d:c1:a4:f8:e8:
    ab:df
pub:
    04:8c:a7:6e:b0:23:8f:ad:c9:b0:4b:35:b7:65:1d:
    4d:67:1b:6a:5d:be:9e:84:14:99:97:4f:bf:d2:46:
    16:0f:14:e3:71:08:13:2c:c1:3b:95:1a:38:92:1c:
    cf:79:5d:9b:2e:18:64:47:8e:1f:4c:b2:5e:42:f4:
    47:1d:e4:81:d5
ASN1 OID: secp256k1
writing EC key
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIAwlOvLcWwewRZytrBPh7xRQaMzMa4sJZhuNwaT46KvfoAcGBSuBBAAK
oUQDQgAEjKdusCOPrcmwSzW3ZR1NZxtqXb6ehBSZl0+/0kYWDxTjcQgTLME7lRo4
khzPeV2bLhhkR44fTLJeQvRHHeSB1Q==
-----END EC PRIVATE KEY-----

The only thing I've been able to find are limited examples which got me nowhere. Here is what I have (with error checking removed for readability).

EVP_PKEY_CTX* pkey_context = EVP_PKEY_CTX_new_id (EVP_PKEY_EC, NULL);
EVP_PKEY_keygen_init (pkey_context);
EVP_PKEY_CTX_set_ec_paramgen_curve_nid (pkey_context, NID_secp256k1);
EVP_PKEY *pkey = NULL;
EVP_PKEY_keygen (pkey_context, &pkey);
cout << "pkey = " << pkey << "\n";
EVP_PKEY_CTX_free (pkey_context);

The result of this code is:

pkey = 0x55f94ba2ca10

It prints the pointer to the variable, but I can't even find a definition of EVP_PKEY, so I have no way of knowing what is in that object.

Any help in figuring this out, or pointing me to better documentation, would be greatly appreciated.

1

1 Answer 1

2

Usually you'd just pass around the EVP_PKEY structure to other OpenSSL calls.

To put the secret into memory, you can use

char* secret_key;
BIO* bio_priv = BIO_new(BIO_s_mem());
PEM_write_bio_PrivateKey(bio_priv, pkey, NULL, NULL, 0, NULL, NULL);
BIO_get_mem_data(bio_priv, &secret_key);
...
BIO_free(bio_priv);

This will set secret_key to point at the data inside bio_priv (before it is freed) containing the secret key. You can similarly use PEM_write_bio_PUBKEY to get the public key.

Also note there is a cryptography library designed specifically for the secp256k1 curve and Bitcoin, which is used by Bitcoin Core, so you could use that instead of OpenSSL. It can be found here.

1
  • 1
    Note PEM_write*_PrivateKey (since 1.0.0 in 2010) writes PKCS8-format (PEM label 'PRIVATE KEY'). OP's 'something like' is vague, but if they specifically want the SECG format 'EC PRIVATE KEY' use PEM_write*_ECPrivateKey instead. On the publickey side, setting compression (or not) may be important, and openssl commandline never uses the 'bare' X9/SECG format(s) but Bitcoin does -- a lot. Dec 26, 2021 at 11:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.