Simple encryption
Simple encryption with SimpleCrypt
Sometimes, you have to store some information that you may want to protect against casual observation. Think about passwords for remote services, for instance. Strong cryptography is obviously the best solution, but it can be hard to use those in the right way, they tend to pull in more libraries, and frankly, it may just be overkill for the situation.
- Note: additional details are available in SimpleCrypt_algorithm_details
- Note: a usage example can be found here Simple_Crypt_IO_Device
A word of warning
The class presented in this article does not provide strong encryption!
It will protect your data from casual observers, but it will not stand up to dedicated hackers trying to break your secrets. I am not a cryptography expert. Use the code here at your own risk. I am not to be held responsible for any damages that may, directly or indirectly, happen because of your use of this code. Don’t say you were not warned.
Introducing SimpleCrypt
The idea of
SimpleCrypt
is to provide some basic cryptographic capabilities for simple encryption. Only symmetric encryption is supported (that is: only with the same key for encryption and decryption), and there is no API for streaming data in and out like you often see with more advanced cyphers. If you need stronger cryptography, streaming cyphers or asymmetric keys, take a look at QCA [delta.affinix.com] instead. The
SimpleCrypt
class takes a 64 bits key in the form of a quint64. If you use a fixed key build into your program, you can do something like this to initialize your
SimpleCrypt
object: You can also use the
setKey()
method to set a key on the class.
Selecting a suitable key
To get such random numbers, you might use this service [random.org] and pick four of the 2 byte hexadecimals that you concatenate together as done above. That works better than trying to make up something semi-random yourself. Of course, you can also use other means to get to a quint64 key, such as using some hash of a password and reducing that to 64 bits.
SimpleCrypt in use
Once setup, you can use
SimpleCrypt
to actually encrypt or decrypt data. For the encrypt functions, both the plaintext that you input as the cyphertext that is being outputted can be either a
QString
or a
QByteArray
. The reverse applies to the decrypt functions. That results in four encrypt methods, and four corresponding decrypt methods:
Encryption methods
QString encryptToString(const QString& plaintext)
QString encryptToString(QByteArray plaintext)
QByteArray encryptToByteArray(const QString& plaintext)
QByteArray encryptToByteArray(QByteArray plaintext)
Decryption methods
QString decryptToString(const QString& plaintext)
QString decryptToString(QByteArray plaintext)
QByteArray decryptToByteArray(const QString& plaintext)
QByteArray decryptToByteArray(QByteArray plaintext)
Use with QStrings
The code above encrypts a
QString
to a
QString
, and then decrypts that string again to a new
QString
.
Use with binary data
If you want to encrypt your own binary data, you might do something like this:
Note the use of the data protection feature. I would recommend that you use at least the
ProtectionChecksum
level of protection (enabled by default) if you work with binary data, as streaming invalid binary data into your program can lead to big problems.
On the other end, you can now do:
The code above might crash if the integrity of the data is not guaranteed, for instance by the use of a wrong password. Using the highest level of protection is probably OK here, as we have quite a big blob of data already, so adding the overhead of adding a 20 byte SHA1 cryptographic hash is justifiable.
Compression
For long strings, it can be beneficial to use compression before encryption. Not only does the length of the string decrease, the input will be a bit more random-looking too, resulting in a harder to break cyphertext (at least, in principle, see the warning at the top of this page.) However, for short strings, applying compression can lead to an increase in the string length.
SimpleCrypt
supports three modes for compression before encryption. You can force to always use compression, to never use compression, or to automatically choose the shortest version (either the compressed one or the uncompressed one). The last option is the default option. Note that setting this only affects encryption. For decryption,
SimpleCrypt
automatically decompresses the data if compression was used for the encryption.
The code
simplecrypt.h
simplecrypt.cpp
You can copy/paste the code above into your own simplecrypt.h and simplecrypt.cpp files to use it.
Details on the algorithm
The algorithm and data format used in this class, have been detailed on a separate page. On that page, you can find byte-for-byte descriptions of how the cypher text is constructed from the plain text.
Future extensions
I, or somebody else, may choose to extend
SimpleCrypt
in the future, or fix a weakness of some kind. To make that possible without loosing the option to read your older encrypted data, the generated cyphertext contains a version number. The idea is that future versions of this code will have a higher version number, but will keep supporting the decryption of cyphertexts with a lower version number. The current version number is 2. Note that these version numbers need not coincide with code version numbers, as a change in the code does not always result in a change in the actual encryption.
Versions
The current code is version 3 of the code.
Version 3
- Fixed embarrassing mistake with only using 4 out of 8 of the key bytes. Thanks to Gerolf for noticing!
Version 2
- Renamed flags to avoid clashes
- Upped version number to 2, but did not retain backwards comparability
- Added optional data integrity protection using either a checksum or a cryptographic hash
- Added error reporting (making is necessary to make the encryption and decryption functions non-const)
Version 1
This marks the first public release.
Feedback
I would really welcome feedback on this class, both on the API and on the crypto algorithm itself. If you spot big weaknesses, please let me know. This class is meant for simple encryption needs, but that does not mean that we need to leave gaping security holes in the code, of course. Please use this forum topic [developer.qt.nokia.com] for feedback.