Я пишу небольшую программу для шифрования файлов с использованием алгоритма 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);
}
один раз программа вылетала при свободном (зашифрованном) вызове со следующим:
Отладочная информация
Другая информация об отладке при сбое