How does one access the raw ECDH public key, private key and params inside OpenSSL's EVP_PKEY structure?
c, diffie-hellman, elliptic-curve, openssl, pki
Solution
To answer my own question, there's a different path for the private key and the public key.
To serialize the public key:
- Pass the EVP_PKEY to EVP_PKEY_get1_EC_KEY() to get an EC_KEY.
- Pass the EC_KEY to EC_KEY_get0_public_key() to get an EC_POINT.
- Pass the EC_POINT to EC_POINT_point2oct() to get octets, which are just unsigned char *.
To deserialize the public key:
- Pass the octets to EC_POINT_oct2point() to get an EC_POINT.
- Pass the EC_POINT to EC_KEY_set_public_key() to get an EC_KEY.
- Pass the EC_KEY to EVP_PKEY_set1_EC_KEY to get an EVP_KEY.
To serialize the private key:
- Pass the EVP_PKEY to EVP_PKEY_get1_EC_KEY() to get an EC_KEY.
- Pass the EC_KEY to EC_KEY_get0_private_key() to get a BIGNUM.
- Pass the BIGNUM to BN_bn2mpi() to get an mpi, which is a format written to unsigned char *.
To deserialize the private key:
- Pass the mpi to BN_mpi2bn() to get a BIGNUM.
- Pass the BIGNUM to EC_KEY_set_private_key() to get an EC_KEY.
- Pass the EC_KEY to EVP_PKEY_set1_EC_KEY to get an EVP_KEY.
It is also possible to convert the BIGNUM to hex, decimal, or "bin", although I think that mpi used the fewest bytes.
Problem
I'm using OpenSSL's c library to generate an elliptic curve Diffie-Hellman (ECDH) key pair, following the first code sample here. It glosses over the actual exchange of public keys with this line: ``` peerkey = get_peerkey(pkey); ``` The `pkey` variable and the return value are both of type `EVP *`. `pkey` contains the public key, private key, and params generated earlier, and the return value only contains the peer's public key. So this raises three questions: - How would `get_peerkey()` actually extract just the public key from `pkey` for sending to the peer? - How would the code extract the private key and params from `pKey` to store them for later use after the key exchange? - How would `get_peerkey()` generate a new `EVP_PKEY` structure from the peer's raw public key? I've seen the OpenSSL functions `EVP_PKEY_print_public()`, `EVP_PKEY_print_private()`, and `EVP_PKEY_print_params()` but these are for generating human-readable output. And I haven't found any equivalent for converting a human-readable public key back into an `EVP_PKEY` structure.