Simple file encryption and decryption implementation in Qt

Greetings, respectable habrasociety.

Recently I encountered the need to encrypt and decrypt files in a Qt project. The main condition is simplicity and transparency, since, in essence, you need to replace the work with files via QFile with something that can write data in encrypted form and read it from an encrypted file. As a result, a small class was born. Then there was a desire to share it with the public, maybe someone will come in handy and save time, or maybe someone will finalize it and change their lives for the better.

The main point, as I said, was a simple and transparent work with the class. Those. the class should be able to write data immediately in an encrypted form, as well as read the original data from an encrypted file.

Someone already familiar with Qt, and in particular with QIODevice, knows what a powerful tool for working with input-output devices. Therefore, almost immediately it was decided to take this class as a basis and inherit from it. I will not dwell on this point in detail, I only note that the main “magic” is to redefine methods
qint64 QIODevice::writeData(const char *data, qint64 len)
qint64 QIODevice::readData(char *data, qint64 len)
respectively, for recording data and reading them.

To specify which file to work with, the class user has several methods:
1) Pass the file path
2) Pass the pointer to the QFileDevice object.

If you're wondering why QFileDevice and not QFile, then the answer is simple. So that you can pass such a useful class as QSaveFile .

After that, the question became relevant, which tool to use directly to encrypt and decrypt data? After a short study, it was decided to stop at the OpenSSL library because, firstly, it is one of the leaders in the world of data encryption, and secondly, our project has already used this library for other tasks.

Therefore, when choosing an encryption algorithm, it was decided to use a symmetric algorithm, because It allows you to quickly encrypt data in blocks. An important requirement for the class being implemented was the ability to write to a file from anywhere. In this regard, I had to keep in mind that the encrypted data was not dependent on previous or subsequent data. In light of all the restrictions, it was decided to choose the AES algorithm with ECB mode(see update). This mode allows you to get the independence of a particular data block from the rest, however, the level of security of course falls. I had to come to terms with this. It is worth noting that now the user can choose the key bit size of 128, 192 or 256 bits (the lower the bit size, the faster the algorithm works, but it becomes less secure). For encryption using OpenSSL, high-level EVP encryption methods were used .

During the implementation of the class, the idea came up to make a certain header for the encrypted file and store some necessary things, for example, a hash from the password and salt in order to control their correctness when opening the file. Naturally, in any case, with the wrong password and salt, the user will not be able to read the file normally, but we decided to check it at the time of opening the file so that the user was sure that if he opened the correctly encrypted file, he would work with the correct source data.

Of the interesting points, it is worth noting that the class can work with ordinary files. If you do not specify a password, then we will work with the file as if we were working with a regular QFile.

To understand the work with the class, I made two test projects.
The first project contains basic file operations. For comparison, the QFile class object is used, the results of which are checked with the developed class.
The second project shows how it can be useful to organize work with encrypted files for the end user. The project implements encryption of the image selected by the user and its subsequent display in QWebView - the file is encrypted, but the user sees the original image.

Using the class is very simple - copy 2 files (cryptfiledevice.cpp and cryptfiledevice.h) into your project and you can already work with it.

Dependencies at the moment:
1) Qt> = 5.1.0 (since SHA3 is used for the password and salt hash)
2) A compiler that supports c ++ 11

The class and test projects were tested on Windows 7 (x86, x64), Ubuntu (x64) and MacOS X Mavericks.

There are still some thoughts that I would like to realize in the future. This is an implementation of the remove, rename, exists methods, similar to QFile, so as not to include QFile if it is not needed. Also, I would like to add a method that allows the user to determine whether this file is encrypted or not. I hope that in the near future hands will reach, and I will add this functionality.
Plus, you can think about working with other algorithms.

I uploaded the sources in the public domain on GitHub under the MIT license. Take, use, improve on health. You can send all suggestions and wishes by email or write in the issue tracker (all information is in README on GitHub).

Link to GitHub: CryptFileDevice


Thanks to all concerned , I did not expect that there would be a lot of feedback with suggestions and wishes.
I tried to take into account the majority opinion.
Changed AES-ECB to AES-CTR, thereby increasing encryption security (thanks to Disasm ).
All fixes are uploaded to GitHub .

Also popular now: