QT OpenSSL AES 256 CBC Шифрование программы при попытке записи в файл - PullRequest
0 голосов
/ 15 ноября 2018

Я пишу небольшую программу для шифрования файлов с использованием алгоритма OpenSSL AES 256 CBC. Я попробовал часть шифрования и дешифрования текстов, которые я ввел сам, и все работает нормально. Теперь я пытаюсь открыть filess для шифрования, затем сохранить зашифрованный файл и получаю ошибку времени выполнения либо при вызове функции write, либо после нее, в зависимости от ключа или размер файла я думаю. Я не знаю, что я делаю не так, не могли бы вы взглянуть на код и указать мне на ошибку. Заранее спасибо.

Класс шифрования:

    int Encryption::Init(unsigned char *key_data, int key_data_len, unsigned char *salt, EVP_CIPHER_CTX *e_ctx,
             EVP_CIPHER_CTX *d_ctx)
{
  int i, nrounds = 5;
  unsigned char key[32], iv[32];

  /*
   * Gen key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the supplied key material.
   * nrounds is the number of times the we hash the material. More rounds are more secure but
   * slower.
   */
  i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, key_data, key_data_len, nrounds, key, iv);
  if (i != 32) {
    qDebug()<<"The key isn't 256 bit";
    return -1;
  }

  EVP_CIPHER_CTX_init(e_ctx);
  EVP_EncryptInit_ex(e_ctx, EVP_aes_256_cbc(), NULL, key, iv);
  EVP_CIPHER_CTX_init(d_ctx);
  EVP_DecryptInit_ex(d_ctx, EVP_aes_256_cbc(), NULL, key, iv);

  return 0;
}

unsigned char* Encryption:: Encrypt(EVP_CIPHER_CTX *e, unsigned char *plaintext, int *len)
{
  /* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE -1 bytes */
  int c_len = *len + AES_BLOCK_SIZE, f_len = 0;
  unsigned char *ciphertext = (unsigned char*)malloc(c_len);

  /* allows reusing of 'e' for multiple encryption cycles */
  EVP_EncryptInit_ex(e, NULL, NULL, NULL, NULL);

  /* update ciphertext, c_len is filled with the length of ciphertext generated,
    *len is the size of plaintext in bytes */
  EVP_EncryptUpdate(e, ciphertext, &c_len, plaintext, *len);
  /* update ciphertext with the final remaining bytes */
  EVP_EncryptFinal_ex(e, ciphertext+c_len, &f_len);

  *len = c_len + f_len;
  return ciphertext;
}

unsigned char* Encryption::Decrypt(EVP_CIPHER_CTX *e, unsigned char *ciphertext, int *len)
{
  /* plaintext will always be equal to or lesser than length of ciphertext*/
  int p_len = *len, f_len = 0;
  unsigned char *plaintext = (unsigned char*)malloc(p_len);
  EVP_DecryptInit_ex(e, NULL, NULL, NULL, NULL);
  EVP_DecryptUpdate(e, plaintext, &p_len, ciphertext, *len);
  EVP_DecryptFinal_ex(e, plaintext+p_len, &f_len);


  *len = p_len + f_len;
  return plaintext;
}

unsigned char *Encryption::ReadFile(QString fileName)
{
    QByteArray data;
    QFile file(fileName);
    if(!file.open(QFile::ReadOnly))
    {
        qCritical() << file.errorString();
        return (unsigned char*) (data.constData());
    }

    data = file.readAll();
    file.close();
    return (unsigned char*) (data.constData());
}

void Encryption::WriteFile(QString fileName, unsigned char* data)
{
    QFile file(fileName);
    if(!file.open(QFile::WriteOnly))
    {
        qCritical() << file.errorString();
        return;
    }

    file.write((const char*)data,strlen((const char*)data));
    file.close();
}

MainWindow:

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    QString Extension;
    qint64 size;
    fileName = QFileDialog::getOpenFileName(this);
    if(!fileName.isEmpty())
    {
        size = QFileInfo(fileName).size();
        Extension = QFileInfo(fileName).suffix();
        ui->label->setText(fileName);
        ui->label_2->setText(QString::number(size)+" Bytes");
        ui->label_3->setText(Extension);
    }


}

void MainWindow::on_pushButton_2_clicked()
{
    Encryption AES;
    unsigned char* plaintext;
    QString SavedfileName = QFileDialog::getSaveFileName(this,
            tr("Save Encryption file"), "",
            tr("All Files (*)"));

    if(!fileName.isEmpty())
    {
        plaintext = AES.ReadFile(fileName);
        EVP_CIPHER_CTX *en, *de;
        en = EVP_CIPHER_CTX_new();
        de = EVP_CIPHER_CTX_new();

        unsigned int salt[] = {12345, 54321};
        unsigned char *key_data;
        int key_data_len, i;

        key_data = (unsigned char*)ui->lineEdit->text().constData();
        key_data_len = strlen((const char*)key_data);



        /* gen key and iv. init the cipher ctx object */
        if (AES.Init(key_data, key_data_len, (unsigned char *)&salt, en, de)) {
          printf("Couldn't initialize AES cipher\n");
        }

          unsigned char *ciphertext;
          int olen, len;

          /* The enc/dec functions deal with binary data and not C strings. strlen() will
             return length of the string without counting the '\0' string marker. We always
             pass in the marker byte to the encrypt/decrypt functions so that after decryption
             we end up with a legal C string */
          olen = len = strlen((const char*)plaintext)+1;



          ciphertext = AES.Encrypt(en, plaintext, &len);

          if (SavedfileName.isEmpty()){
              QMessageBox::information(this, tr("Unable to open encryption file!"),tr("Please enter a name to the encryption file."));
                  return;}
          else {
              QFile file(SavedfileName);
              if (!file.open(QIODevice::WriteOnly)) {
                  QMessageBox::information(this, tr("Unable to open file"),
                      file.errorString());
                  return;
              }
              else{
                  AES.WriteFile(SavedfileName,ciphertext);
              }
          }


          free(ciphertext);
          free(plaintext);

        EVP_CIPHER_CTX_free(en);
        EVP_CIPHER_CTX_free(de);



    }

}

void MainWindow::on_pushButton_3_clicked()
{
    //plaintext = AES.Decrypt(de, ciphertext, &len);
}

один раз программа вылетала при свободном (зашифрованном) вызове со следующим:

Отладочная информация

Другая информация об отладке при сбое

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Если вы получаете ошибку сегмента во время освобождения (char *), это означает, что вы неправильно распределили память.перед вызовом функций aes необходимо выделить память для открытого и зашифрованного текста

plaintext=(char *) malloc(sizeof(char)); 

ciphertext= (char *) malloc(sizeof(char)); 
0 голосов
/ 15 ноября 2018

QTextStream будет разумным вариантом для операций с файлами.

void Encryption::WriteFile(QString fileName, unsigned char* data)
{
    QFile file(fileName);
    if(!file.open(QFile::WriteOnly))
    {
        qCritical() << file.errorString();
        return;
    }
    QTextStream outSt(&file);

    outSt<< data;



    //file.write((const char*)data,strlen((const char*)data));
    file.close();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...