File indexing completed on 2024-12-22 04:57:52

0001 /*
0002     SPDX-FileCopyrightText: 2011 Andre Somers
0003 
0004     SPDX-License-Identifier: BSD-3-Clause
0005 */
0006 
0007 #pragma once
0008 #include <QList>
0009 #include <QString>
0010 
0011 /**
0012   @short Simple encryption and decryption of strings and byte arrays
0013 
0014   This class provides a simple implementation of encryption and decryption
0015   of strings and byte arrays.
0016 
0017   @warning The encryption provided by this class is NOT strong encryption. It may
0018   help to shield things from curious eyes, but it will NOT stand up to someone
0019   determined to break the encryption. Don't say you were not warned.
0020 
0021   The class uses a 64 bit key. Simply create an instance of the class, set the key,
0022   and use the encryptToString() method to calculate an encrypted version of the input string.
0023   To decrypt that string again, use an instance of SimpleCrypt initialized with
0024   the same key, and call the decryptToString() method with the encrypted string. If the key
0025   matches, the decrypted version of the string will be returned again.
0026 
0027   If you do not provide a key, or if something else is wrong, the encryption and
0028   decryption function will return an empty string or will return a string containing nonsense.
0029   lastError() will return a value indicating if the method was successful, and if not, why not.
0030 
0031   SimpleCrypt is prepared for the case that the encryption and decryption
0032   algorithm is changed in a later version, by prepending a version identifier to the cypertext.
0033   */
0034 class O0SimpleCrypt
0035 {
0036 public:
0037     /**
0038       CompressionMode describes if compression will be applied to the data to be
0039       encrypted.
0040       */
0041     enum CompressionMode {
0042         CompressionAuto, /*!< Only apply compression if that results in a shorter plaintext. */
0043         CompressionAlways, /*!< Always apply compression. Note that for short inputs, a compression may result in longer data */
0044         CompressionNever /*!< Never apply compression. */
0045     };
0046     /**
0047       IntegrityProtectionMode describes measures taken to make it possible to detect problems with the data
0048       or wrong decryption keys.
0049 
0050       Measures involve adding a checksum or a cryptograhpic hash to the data to be encrypted. This
0051       increases the length of the resulting cypertext, but makes it possible to check if the plaintext
0052       appears to be valid after decryption.
0053     */
0054     enum IntegrityProtectionMode {
0055         ProtectionNone, /*!< The integrity of the encrypted data is not protected. It is not really possible to detect a wrong key, for instance. */
0056         ProtectionChecksum, /*!< A simple checksum is used to verify that the data is in order. If not, an empty string is returned. */
0057         ProtectionHash /*!< A cryptographic hash is used to verify the integrity of the data. This method produces a much stronger, but longer check */
0058     };
0059     /**
0060       Error describes the type of error that occurred.
0061       */
0062     enum Error {
0063         ErrorNoError, /*!< No error occurred. */
0064         ErrorNoKeySet, /*!< No key was set. You can not encrypt or decrypt without a valid key. */
0065         ErrorUnknownVersion, /*!< The version of this data is unknown, or the data is otherwise not valid. */
0066         ErrorIntegrityFailed /*!< The integrity check of the data failed. Perhaps the wrong key was used. */
0067     };
0068 
0069     /**
0070       Constructor.
0071 
0072       Constructs a SimpleCrypt instance without a valid key set on it.
0073      */
0074     O0SimpleCrypt();
0075     /**
0076       Constructor.
0077 
0078       Constructs a SimpleCrypt instance and initializes it with the given @arg key.
0079      */
0080     explicit O0SimpleCrypt(quint64 key);
0081 
0082     /**
0083       (Re-) initializes the key with the given @arg key.
0084       */
0085     void setKey(quint64 key);
0086     /**
0087       Returns true if SimpleCrypt has been initialized with a key.
0088       */
0089     bool hasKey() const
0090     {
0091         return !m_keyParts.isEmpty();
0092     }
0093 
0094     /**
0095       Sets the compression mode to use when encrypting data. The default mode is Auto.
0096 
0097       Note that decryption is not influenced by this mode, as the decryption recognizes
0098       what mode was used when encrypting.
0099       */
0100     void setCompressionMode(CompressionMode mode)
0101     {
0102         m_compressionMode = mode;
0103     }
0104 
0105     /**
0106       Returns the CompressionMode that is currently in use.
0107       */
0108     CompressionMode compressionMode() const
0109     {
0110         return m_compressionMode;
0111     }
0112 
0113     /**
0114       Sets the integrity mode to use when encrypting data. The default mode is Checksum.
0115 
0116       Note that decryption is not influenced by this mode, as the decryption recognizes
0117       what mode was used when encrypting.
0118       */
0119     void setIntegrityProtectionMode(IntegrityProtectionMode mode)
0120     {
0121         m_protectionMode = mode;
0122     }
0123 
0124     /**
0125       Returns the IntegrityProtectionMode that is currently in use.
0126       */
0127     IntegrityProtectionMode integrityProtectionMode() const
0128     {
0129         return m_protectionMode;
0130     }
0131 
0132     /**
0133       Returns the last error that occurred.
0134       */
0135     Error lastError() const
0136     {
0137         return m_lastError;
0138     }
0139 
0140     /**
0141       Encrypts the @arg plaintext string with the key the class was initialized with, and returns
0142       a cyphertext the result. The result is a base64 encoded version of the binary array that is the
0143       actual result of the string, so it can be stored easily in a text format.
0144       */
0145     QString encryptToString(const QString &plaintext);
0146     /**
0147       Encrypts the @arg plaintext QByteArray with the key the class was initialized with, and returns
0148       a cyphertext the result. The result is a base64 encoded version of the binary array that is the
0149       actual result of the encryption, so it can be stored easily in a text format.
0150       */
0151     QString encryptToString(const QByteArray &plaintext);
0152     /**
0153       Encrypts the @arg plaintext string with the key the class was initialized with, and returns
0154       a binary cyphertext in a QByteArray the result.
0155 
0156       This method returns a byte array, that is useable for storing a binary format. If you need
0157       a string you can store in a text file, use encryptToString() instead.
0158       */
0159     QByteArray encryptToByteArray(const QString &plaintext);
0160     /**
0161       Encrypts the @arg plaintext QByteArray with the key the class was initialized with, and returns
0162       a binary cyphertext in a QByteArray the result.
0163 
0164       This method returns a byte array, that is useable for storing a binary format. If you need
0165       a string you can store in a text file, use encryptToString() instead.
0166       */
0167     QByteArray encryptToByteArray(const QByteArray &plaintext);
0168 
0169     /**
0170       Decrypts a cyphertext string encrypted with this class with the set key back to the
0171       plain text version.
0172 
0173       If an error occurred, such as non-matching keys between encryption and decryption,
0174       an empty string or a string containing nonsense may be returned.
0175       */
0176     QString decryptToString(const QString &cyphertext);
0177     /**
0178       Decrypts a cyphertext string encrypted with this class with the set key back to the
0179       plain text version.
0180 
0181       If an error occurred, such as non-matching keys between encryption and decryption,
0182       an empty string or a string containing nonsense may be returned.
0183       */
0184     QByteArray decryptToByteArray(const QString &cyphertext);
0185     /**
0186       Decrypts a cyphertext binary encrypted with this class with the set key back to the
0187       plain text version.
0188 
0189       If an error occurred, such as non-matching keys between encryption and decryption,
0190       an empty string or a string containing nonsense may be returned.
0191       */
0192     QString decryptToString(const QByteArray &cypher);
0193     /**
0194       Decrypts a cyphertext binary encrypted with this class with the set key back to the
0195       plain text version.
0196 
0197       If an error occurred, such as non-matching keys between encryption and decryption,
0198       an empty string or a string containing nonsense may be returned.
0199       */
0200     QByteArray decryptToByteArray(const QByteArray &cypher);
0201 
0202     // enum to describe options that have been used for the encryption. Currently only one, but
0203     // that only leaves room for future extensions like adding a cryptographic hash...
0204     enum CryptoFlag {
0205         CryptoFlagNone = 0,
0206         CryptoFlagCompression = 0x01,
0207         CryptoFlagChecksum = 0x02,
0208         CryptoFlagHash = 0x04,
0209     };
0210     Q_DECLARE_FLAGS(CryptoFlags, CryptoFlag)
0211 private:
0212     void splitKey();
0213 
0214     quint64 m_key;
0215     QList<char> m_keyParts;
0216     CompressionMode m_compressionMode;
0217     IntegrityProtectionMode m_protectionMode;
0218     Error m_lastError;
0219 };
0220 Q_DECLARE_OPERATORS_FOR_FLAGS(O0SimpleCrypt::CryptoFlags)