2015-02-28 4 views
1

Я пытаюсь сделать публичное шифрование с помощью OpenSSL с использованием RSA и его функций верхнего уровня огибающей. Однако я не могу показаться, что обхватил их, и я получаю ошибку сегментации. Этот сгущенный код из моего проекта воспроизводит проблему:Ошибка сегментации при попытке использования функций EVP в OpenSSL

#include <iostream> 
#include <string> 

#include <openssl/evp.h> 
#include <openssl/pem.h> 
#include <openssl/err.h> 
#include <openssl/rand.h> 

int main() 
{ 
    EVP_CIPHER_CTX *rsaCtx; 
    rsaCtx = new EVP_CIPHER_CTX; 

    unsigned char *ek; 
    size_t ekl; 
    unsigned char *iv; 
    size_t ivl; 

    EVP_PKEY *keypair; 
    keypair = NULL; 

    EVP_CIPHER_CTX_init(rsaCtx); 

    EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); 
    EVP_PKEY_keygen_init(ctx); 
    EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048); 
    EVP_PKEY_keygen(ctx, &keypair); 
    EVP_PKEY_CTX_free(ctx); 

    ek = new unsigned char[EVP_PKEY_size(keypair)]; 
    iv = new unsigned char[EVP_MAX_IV_LENGTH]; 
    ivl = EVP_MAX_IV_LENGTH; 

    std::string cipherText; 
    std::string plainText = "A STRING"; 
    size_t encMsgLen = 0; 
    size_t blockLen = 0; 

    EVP_SealInit(rsaCtx, EVP_aes_256_cbc(), &ek, (int*)ekl, iv, &keypair, 1); 
    EVP_SealUpdate(rsaCtx, (unsigned char*)cipherText.c_str() + encMsgLen, (int*)&blockLen, (const unsigned char*)plainText.c_str(), (int)plainText.size() + 1); 
    encMsgLen += blockLen; 
    EVP_SealFinal(rsaCtx, (unsigned char*)cipherText.c_str() + encMsgLen, (int*)&blockLen); 
    encMsgLen += blockLen; 
    EVP_CIPHER_CTX_cleanup(rsaCtx); 

    EVP_PKEY_free(keypair); 
    delete[] ek; 
    delete[] iv; 
    delete rsaCtx; 

    std::cout << cipherText; 

    return 0; 
} 

я получаю ошибку сегментации на линии EVP_SealInit(rsaCtx, EVP_aes_256_cbc(), &ek, (int*)ekl, iv, &keypair, 1);

Что я делаю не так?

ответ

2

ekl - size_t, и вы отправляете его на номер (int*).

docs for EVP_SealInit говорят:

Фактический размер каждого зашифрованного секретного ключа записывается в массив EKL.

Вы просто проездом один ключ, так передавая адрес одного целого достаточно, но вы должны передать адрес этого целого, например:

EVP_SealInit(rsaCtx, EVP_aes_256_cbc(), &ek, reinterpret_cast<int*>(&ekl), iv, &keypair, 1);

В качестве альтернативы, просто объявить ekl как int в первую очередь, и вы можете избежать ролях:

int ekl; 
//... 
EVP_SealInit(rsaCtx, EVP_aes_256_cbc(), &ek, &ekl, iv, &keypair, 1); 

Я удивлен ваш компилятор Бесполезный Предупреждение об использовании неинициализированной локальной переменной.

ОБНОВЛЕНИЕ: Есть еще некоторые проблемы с этим кодом, кроме ошибки сегментации.

Вы пропускание буфера из пустого std::string (cipherText) в EVP_SealUpdate и EVP_SealFinal. Это не будет работать вообще и может привести к сбою или повреждению памяти, если в буфере недостаточно места.

Вы должны объявить буфер подходящего размера для вывода, возможно, как std::vector<unsigned char> cipherText(bufferSize);, и передать &cipherText[0], чтобы получить указатель на первый элемент.

Данные в cipherText не являются удобочитаемыми для человека строками, это двоичные данные, а std::cout не подходит для отображения его.

Некоторые более общие замечания:

  • Избегайте C-стиль слепков в C++, и где можно написать код так, что вам не нужно, чтобы бросить на все (например, объявить целые числа, как int, а не size_t если это то, что ожидаются API).
  • Избегайте явного управления памятью с помощью new и delete, где вы можете, например. используя std::vector<unsigned char> для буферов.

Предлагаю взглянуть на документацию для этих функций еще раз или на другие примеры в Интернете для их использования.Кроме того, напишите некоторый код, который делает шаг дешифрования, чтобы вы могли проверить правильность округления текста.

+0

Спасибо за ваш ответ, это устранило ошибку сегментации, но теперь я просто получаю пустую строку в качестве вывода. Что может быть неправильным? –

+0

Я обновил информацию о том, что здесь не так. Если этого недостаточно, чтобы помочь вам решить другие проблемы, я предлагаю задать новый вопрос о том, как правильно использовать функции «EVP_Seal *», так как это действительно отдельный вопрос, а также означает, что вы с большей вероятностью получить ответ на эту конкретную проблему. – softwariness

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

  • Нет связанных вопросов^_^