OpenSSL: попробуйте декодировать данные DER

У меня есть следующий код Python, который создает часть данных DER «x25519_pubic_der».

#!/usr/bin/python3

from cryptography.hazmat.primitives.asymmetric import x25519
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat

x25519_key = x25519.X25519PrivateKey.generate()
x25519_public_der = x25519_key.public_key().public_bytes(Encoding.DER,
                                                         PublicFormat.SubjectPublicKeyInfo)

Я пытаюсь декодировать этот фрагмент данных обратно в исходные двоичные биты, используя код C, но безуспешно. Ниже приведена одна тестовая программа (при условии, что данные переданы правильно, а также длина).

const unsigned char* ptr = x25519_public_der;
ASN1_OCTET_STRING* octet_string = d2i_ASN1_OCTET_STRING(NULL, &ptr, x25519_public_der_len);
if (!octet_string) {
   fprintf(stderr, "Error decoding DER data to binary bytes\n");
   return 1;
}

Я подозреваю, что PublicFormat.SubjectPublicKeyInfo может добавить дополнительную кодировку, или я не использую правильную функцию d2i_ (?), только предположение...

По сути, x25519_public_der содержит 44 байта, и я хочу восстановить его до 32 байтов с помощью программирования на C. Я думаю, что этот вопрос может быть актуальным: Как мне передать открытый ключ x25519 длиной 44 байта, созданный openssl, в CryptoKit, для которого требуется длина ключа 32 байта, но у меня недостаточно опыта для реализации его на C.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поскольку необработанный открытый ключ расположен в конце ключа SPKI/DER X25519, можно просто использовать последние 32 байта.


Более общий подход — импортировать ключ SPKI/DER как EVP_PKEY и извлечь необработанный ключ с помощью EVP_PKEY_get_raw_public_key, например. начиная с OpenSSL v3.0 (для простоты, без обработки исключений):

const char spki_der[] = { 0x30, 0x2A, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x6E, 0x03, 0x21, 0x00, 0xBB, 0x13, 0xF6, 0x6B, 0x4E, 0xC0, 0x9E, 0xE2, 0xD5, 0xC6, 0xE5, 0x49, 0xDF, 0xE9, 0x06, 0x41, 0x4A, 0x79, 0x99, 0x98, 0xE1, 0xE3, 0x93, 0x46, 0x13, 0xD6, 0xBE, 0xD3, 0xC2, 0xEE, 0x9E, 0x66 };
const unsigned char* data = (const unsigned char*)spki_der;
size_t datalen = sizeof(spki_der);

// Import SPKI/DER X25519 key
OSSL_DECODER_CTX* dctx;
EVP_PKEY* pkeyPub = NULL;
dctx = OSSL_DECODER_CTX_new_for_pkey(&pkeyPub, "DER", NULL, "X25519", OSSL_KEYMGMT_SELECT_PUBLIC_KEY, NULL, NULL);
OSSL_DECODER_from_data(dctx, &data, &datalen);

// Export raw X25519 key (32 bytes)
unsigned char rawPub[32];
size_t rawPubLen = 32;
EVP_PKEY_get_raw_public_key(pkeyPub, rawPub, &rawPubLen); // rawPub: 0xbb13f66b4ec09ee2d5c6e549dfe906414a799998e1e3934613d6bed3c2ee9e66

Для полноты картины:
OSSL_DECODER_CTX_new_for_pkey() можно использовать для импорта общедоступных (5-й параметр: OSSL_KEYMGMT_SELECT_PUBLIC_KEY) и частных (5-й параметр: OSSL_KEYMGMT_SELECT_KEYPAIR) ключей разных типов (4-й параметр, например "X25519") и кодировок (2-й параметр, например "PEM" или "DER").
Для закрытых ключей необходимо использовать EVP_PKEY_get_raw_private_key() для экспорта необработанного ключа.
В зависимости от OSSL_DECODER_from_... можно выбирать разные источники данных.

Другие вопросы по теме