如何在OpenSSL的EVP_PKEY结构中访问原始ECDH公钥,私钥和参数?

我正在使用OpenSSL的c库生成椭圆曲线Diffie-Hellman(ECDH)密钥对,遵循此处的第一个代码示例。 它掩盖了这一行的实际公钥交换:

peerkey = get_peerkey(pkey); 

pkey变量和返回值都是EVP *类型。 pkey包含先前生成的公钥,私钥和params,返回值仅包含对等方的公钥。 所以这提出了三个问题:

  1. get_peerkey()实际上如何从get_peerkey()提取公钥,以便发送给对等方?
  2. 代码如何从pKey提取私钥和params来存储它们以便在密钥交换后供以后使用?
  3. get_peerkey()如何从对等方的原始公钥生成新的EVP_PKEY结构?

我见过OpenSSL函数EVP_PKEY_print_public()EVP_PKEY_print_private()EVP_PKEY_print_params()但它们用于生成人类可读的输出。 我还没有发现将人类可读的公钥转换回EVP_PKEY结构的任何等价物。

为了回答我自己的问题,私钥和公钥有不同的路径。

要序列化公钥:

  1. 将EVP_PKEY传递给EVP_PKEY_get1_EC_KEY()以获取EC_KEY。
  2. 将EC_KEY传递给EC_KEY_get0_public_key()以获取EC_POINT。
  3. 将EC_POINT传递给EC_POINT_point2oct()以获取八位字节,这只是无符号的char *。

要反序列化公钥:

  1. 将八位字节传递给EC_POINT_oct2point()以获取EC_POINT。
  2. 将EC_POINT传递给EC_KEY_set_public_key()以获取EC_KEY。
  3. 将EC_KEY传递给EVP_PKEY_set1_EC_KEY以获取EVP_KEY。

要序列化私钥:

  1. 将EVP_PKEY传递给EVP_PKEY_get1_EC_KEY()以获取EC_KEY。
  2. 将EC_KEY传递给EC_KEY_get0_private_key()以获取BIGNUM。
  3. 将BIGNUM传递给BN_bn2mpi()以获取mpi,这是一种写入unsigned char *的格式。

要反序列化私钥:

  1. 将mpi传递给BN_mpi20bn()以获得BIGNUM。
  2. 将BIGNUM传递给EC_KEY_set_private_key()以获取EC_KEY。
  3. 将EC_KEY传递给EVP_PKEY_set1_EC_KEY以获取EVP_KEY。

也可以将BIGNUM转换为hex,十进制或“bin”,尽管我认为mpi使用的字节最少。