2017-01-07 4 views
2

Я мог бы использовать функцию PEM_read_RSA_PUBKEY, чтобы легко прочитать файл PEM . Однако у меня есть открытый ключ, который я встроил в исполняемый файл, и я бы предпочел не создавать временный файл. Чтение на данном примере/Учебник: http://hayageek.com/rsa-encryption-decryption-openssl-c/ я придумал следующее решение:Как прочитать открытый ключ RSA из строки формата PEM с использованием API OpenSSL?

#include <openssl/rsa.h> 
#include <openssl/pem.h> 
#include <openssl/bio.h> 

#include <QFile> 
#include <QByteArray> 

#include <stdexcept> 
#include <cassert> 
#include <cstring> 

RSA* createRSA(const char* key) 
{ 
    RSA *rsa = nullptr; 
    BIO *keybio ; 
    keybio = BIO_new_mem_buf(key, -1); // !!! 
    if (!keybio) 
    { 
     throw std::runtime_error("Failed to create key BIO"); 
    } 
    rsa = PEM_read_bio_RSA_PUBKEY(keybio, nullptr, nullptr, nullptr); // !!! 
    if(!rsa) 
    { 
     throw std::runtime_error("Failed to create RSA"); 
    } 
    BIO_free(keybio); // !!! 
    return rsa; 
} 

int main() 
{ 
    QFile publicKeyFile(":/public.pem"); 
    publicKeyFile.open(QIODevice::ReadOnly); 
    auto data = publicKeyFile.readAll(); 

    RSA* rsa = createRSA(data.data()); 

    EVP_PKEY* verificationKey = EVP_PKEY_new(); 
    auto rc = EVP_PKEY_assign_RSA(verificationKey, RSAPublicKey_dup(rsa)); 
    assert(rc == 1); 

    if(verificationKey) 
     EVP_PKEY_free(verificationKey); 

    return 0; 
} 

Однако у меня есть много сомнений:

  1. BIO_new_mem_buf принимает параметр const void*, я могу просто пройти const char* ? Я не понял этого даже из docs.
  2. При вызове функции PEM_read_bio_RSA_PUBKEY, оригинальный пример называет это следующим образом: rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL); , которые я не понимаю, даже после прочтения docs. Я считаю, что в качестве второго аргумента я должен передать nullptr.
  3. Должен ли я позвонить RSA_free по возвращенному указателю RSA? valgrind не видит утечки памяти, выполняю ли я это или нет.
  4. Должен ли я позвонить BIO_free(keybio); после того, как я закончил с BIO? valgrind видит утечку памяти, если я этого не делаю, и в учебнике этот вызов отсутствовал. Если я позвоню BIO_free(keybio);, это будет означать, что PEM_read_bio_RSA_PUBKEY скопировал данные из BIO, а не просто привязал к нему. Но если это так, разве я не должен освобождать RSA?

Любые советы приветствуются. Я не знаю, что реально.

ответ

1

Ответы на каждый из ваших вопросов:

  1. Да, вы можете пройти const char*, он брошен.
  2. PEM_read_bio_RSA_PUBKEY создает для вас структуру RSA. Аргумент (если не null) используется для хранения указателя на него, который будет таким же, как возвращаемое значение. Он используется для упрощенного кодирования: if (!PEM_read_bio_RSA_PUBKEY(keybio, &rsa, nullptr, nullptr)) { /* error */ }

  3. Да, вы должны его отпустить, используя RSA_free.

  4. Да, вам тоже нужно отпустить его.

P.S .: Документация OpenSSL немного сложна, поскольку существует много подобных функций, которые могут варьироваться только в алгоритме, структурах или формате данных. В конце man page есть раздел Описание, где они объясняются, устраняя особенности каждого варианта. Но да, это довольно сложно найти с хорошим учебником или примерами.

Смежные вопросы