Как получить доступ к открытым открытым ключам ECDH, закрытому ключу и параметрам в структуре OpenSSL EVP_PKEY?

Я использую библиотеку OpenSSL c для генерации пары ключей эллиптической кривой Diffie-Hellman (ECDH), следуя примеру первого кода здесь. Он замалчивает фактический обмен открытыми ключами с этой строкой:

peerkey = get_peerkey(pkey);

Переменная pkey и возвращаемое значение имеют тип EVP *. pkey содержит открытый ключ, закрытый ключ и параметры, сгенерированные ранее, а возвращаемое значение содержит только открытый открытый ключ. Поэтому возникает три вопроса:

  • Как бы get_peerkey() извлечь только открытый ключ из pkey для отправки в peer?
  • Как бы код извлекал закрытый ключ и параметры из pkey для их сохранения для последующего использования после обмена ключами?
  • Как get_peerkey() сгенерировать новую структуру EVP_PKEY из открытого открытого ключа peer?

Я видел функции 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.
  • Передайте EC_KEY в EC_KEY_get0_public_key(), чтобы получить EC_POINT.
  • Передайте EC_POINT в EC_POINT_point2oct(), чтобы получить октеты, которые просто не обозначены char *.

Для десериализации открытого ключа:

  • Передайте октеты в EC_POINT_oct2point(), чтобы получить EC_POINT.
  • Передайте EC_POINT в EC_KEY_set_public_key(), чтобы получить EC_KEY.
  • Передайте EC_KEY в EVP_PKEY_set1_EC_KEY, чтобы получить EVP_KEY.

Сериализовать закрытый ключ:

  • Передайте EVP_PKEY в EVP_PKEY_get1_EC_KEY(), чтобы получить EC_KEY.
  • Передайте EC_KEY в EC_KEY_get0_private_key(), чтобы получить BIGNUM.
  • Передайте BIGNUM в BN_bn2mpi(), чтобы получить mpi, который является форматом, написанным для unsigned char *.

Чтобы десериализовать закрытый ключ:

  • Передайте mpi в BN_mpi2bn(), чтобы получить BIGNUM.
  • Передайте BIGNUM в EC_KEY_set_private_key(), чтобы получить EC_KEY.
  • Передайте EC_KEY в EVP_PKEY_set1_EC_KEY, чтобы получить EVP_KEY.

Также возможно преобразовать BIGNUM в шестнадцатеричный, десятичный или "bin", хотя я думаю, что mpi использовало наименьшие байты.