File indexing completed on 2025-01-19 03:55:38

0001 /*
0002 Copyright (c) 2011, Andre Somers
0003 All rights reserved.
0004 
0005 Redistribution and use in source and binary forms, with or without
0006 modification, are permitted provided that the following conditions are met:
0007     * Redistributions of source code must retain the above copyright
0008       notice, this list of conditions and the following disclaimer.
0009     * Redistributions in binary form must reproduce the above copyright
0010       notice, this list of conditions and the following disclaimer in the
0011       documentation and/or other materials provided with the distribution.
0012     * Neither the name of the Rathenau Instituut, Andre Somers nor the
0013       names of its contributors may be used to endorse or promote products
0014       derived from this software without specific prior written permission.
0015 
0016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
0017 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0018 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0019 DISCLAIMED. IN NO EVENT SHALL ANDRE SOMERS BE LIABLE FOR ANY
0020 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0021 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0022 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0023 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0024 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0025 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0026 */
0027 
0028 #ifndef SIMPLECRYPT_H
0029 #define SIMPLECRYPT_H
0030 #include <QString>
0031 #include <QVector>
0032 #include <QFlags>
0033 #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
0034 #include <QRandomGenerator>
0035 #endif
0036 #include "o0baseauth.h"
0037 
0038 /**
0039   @short Simple encryption and decryption of strings and byte arrays
0040 
0041   This class provides a simple implementation of encryption and decryption
0042   of strings and byte arrays.
0043 
0044   @warning The encryption provided by this class is NOT strong encryption. It may
0045   help to shield things from curious eyes, but it will NOT stand up to someone
0046   determined to break the encryption. Don't say you were not warned.
0047 
0048   The class uses a 64 bit key. Simply create an instance of the class, set the key,
0049   and use the encryptToString() method to calculate an encrypted version of the input string.
0050   To decrypt that string again, use an instance of SimpleCrypt initialized with
0051   the same key, and call the decryptToString() method with the encrypted string. If the key
0052   matches, the decrypted version of the string will be returned again.
0053 
0054   If you do not provide a key, or if something else is wrong, the encryption and
0055   decryption function will return an empty string or will return a string containing nonsense.
0056   lastError() will return a value indicating if the method was succesful, and if not, why not.
0057 
0058   SimpleCrypt is prepared for the case that the encryption and decryption
0059   algorithm is changed in a later version, by prepending a version identifier to the cypertext.
0060   */
0061 class O0_EXPORT O0SimpleCrypt
0062 {
0063 public:
0064     /**
0065       CompressionMode describes if compression will be applied to the data to be
0066       encrypted.
0067       */
0068     enum CompressionMode {
0069         CompressionAuto,    /*!< Only apply compression if that results in a shorter plaintext. */
0070         CompressionAlways,  /*!< Always apply compression. Note that for short inputs, a compression may result in longer data */
0071         CompressionNever    /*!< Never apply compression. */
0072     };
0073     /**
0074       IntegrityProtectionMode describes measures taken to make it possible to detect problems with the data
0075       or wrong decryption keys.
0076 
0077       Measures involve adding a checksum or a cryptograhpic hash to the data to be encrypted. This
0078       increases the length of the resulting cypertext, but makes it possible to check if the plaintext
0079       appears to be valid after decryption.
0080     */
0081     enum IntegrityProtectionMode {
0082         ProtectionNone,    /*!< The integerity of the encrypted data is not protected. It is not really possible to detect a wrong key, for instance. */
0083         ProtectionChecksum,/*!< A simple checksum is used to verify that the data is in order. If not, an empty string is returned. */
0084         ProtectionHash     /*!< A cryptographic hash is used to verify the integrity of the data. This method produces a much stronger, but longer check */
0085     };
0086     /**
0087       Error describes the type of error that occured.
0088       */
0089     enum Error {
0090         ErrorNoError,         /*!< No error occurred. */
0091         ErrorNoKeySet,        /*!< No key was set. You can not encrypt or decrypt without a valid key. */
0092         ErrorUnknownVersion,  /*!< The version of this data is unknown, or the data is otherwise not valid. */
0093         ErrorIntegrityFailed  /*!< The integrity check of the data failed. Perhaps the wrong key was used. */
0094     };
0095 
0096     /**
0097       Constructor.
0098 
0099       Constructs a SimpleCrypt instance without a valid key set on it.
0100      */
0101     O0SimpleCrypt();
0102     /**
0103       Constructor.
0104 
0105       Constructs a SimpleCrypt instance and initializes it with the given @arg key.
0106      */
0107     explicit O0SimpleCrypt(quint64 key);
0108 
0109     /**
0110       (Re-) initializes the key with the given @arg key.
0111       */
0112     void setKey(quint64 key);
0113     /**
0114       Returns true if SimpleCrypt has been initialized with a key.
0115       */
0116     bool hasKey() const {return !m_keyParts.isEmpty();}
0117 
0118     /**
0119       Sets the compression mode to use when encrypting data. The default mode is Auto.
0120 
0121       Note that decryption is not influenced by this mode, as the decryption recognizes
0122       what mode was used when encrypting.
0123       */
0124     void setCompressionMode(CompressionMode mode) {m_compressionMode = mode;}
0125     /**
0126       Returns the CompressionMode that is currently in use.
0127       */
0128     CompressionMode compressionMode() const {return m_compressionMode;}
0129 
0130     /**
0131       Sets the integrity mode to use when encrypting data. The default mode is Checksum.
0132 
0133       Note that decryption is not influenced by this mode, as the decryption recognizes
0134       what mode was used when encrypting.
0135       */
0136     void setIntegrityProtectionMode(IntegrityProtectionMode mode) {m_protectionMode = mode;}
0137     /**
0138       Returns the IntegrityProtectionMode that is currently in use.
0139       */
0140     IntegrityProtectionMode integrityProtectionMode() const {return m_protectionMode;}
0141 
0142     /**
0143       Returns the last error that occurred.
0144       */
0145     Error lastError() const {return m_lastError;}
0146 
0147     /**
0148       Encrypts the @arg plaintext string with the key the class was initialized with, and returns
0149       a cyphertext the result. The result is a base64 encoded version of the binary array that is the
0150       actual result of the string, so it can be stored easily in a text format.
0151       */
0152     QString encryptToString(const QString& plaintext) ;
0153     /**
0154       Encrypts the @arg plaintext QByteArray with the key the class was initialized with, and returns
0155       a cyphertext the result. The result is a base64 encoded version of the binary array that is the
0156       actual result of the encryption, so it can be stored easily in a text format.
0157       */
0158     QString encryptToString(QByteArray plaintext) ;
0159     /**
0160       Encrypts the @arg plaintext string with the key the class was initialized with, and returns
0161       a binary cyphertext in a QByteArray the result.
0162 
0163       This method returns a byte array, that is useable for storing a binary format. If you need
0164       a string you can store in a text file, use encryptToString() instead.
0165       */
0166     QByteArray encryptToByteArray(const QString& plaintext) ;
0167     /**
0168       Encrypts the @arg plaintext QByteArray with the key the class was initialized with, and returns
0169       a binary cyphertext in a QByteArray the result.
0170 
0171       This method returns a byte array, that is useable for storing a binary format. If you need
0172       a string you can store in a text file, use encryptToString() instead.
0173       */
0174     QByteArray encryptToByteArray(QByteArray plaintext) ;
0175 
0176     /**
0177       Decrypts a cyphertext string encrypted with this class with the set key back to the
0178       plain text version.
0179 
0180       If an error occured, such as non-matching keys between encryption and decryption,
0181       an empty string or a string containing nonsense may be returned.
0182       */
0183     QString decryptToString(const QString& cyphertext) ;
0184     /**
0185       Decrypts a cyphertext string encrypted with this class with the set key back to the
0186       plain text version.
0187 
0188       If an error occured, such as non-matching keys between encryption and decryption,
0189       an empty string or a string containing nonsense may be returned.
0190       */
0191     QByteArray decryptToByteArray(const QString& cyphertext) ;
0192     /**
0193       Decrypts a cyphertext binary encrypted with this class with the set key back to the
0194       plain text version.
0195 
0196       If an error occured, such as non-matching keys between encryption and decryption,
0197       an empty string or a string containing nonsense may be returned.
0198       */
0199     QString decryptToString(QByteArray cypher) ;
0200     /**
0201       Decrypts a cyphertext binary encrypted with this class with the set key back to the
0202       plain text version.
0203 
0204       If an error occured, such as non-matching keys between encryption and decryption,
0205       an empty string or a string containing nonsense may be returned.
0206       */
0207     QByteArray decryptToByteArray(QByteArray cypher) ;
0208 
0209     //enum to describe options that have been used for the encryption. Currently only one, but
0210     //that only leaves room for future extensions like adding a cryptographic hash...
0211     enum CryptoFlag{CryptoFlagNone = 0,
0212                     CryptoFlagCompression = 0x01,
0213                     CryptoFlagChecksum = 0x02,
0214                     CryptoFlagHash = 0x04
0215                    };
0216     Q_DECLARE_FLAGS(CryptoFlags, CryptoFlag)
0217 private:
0218 
0219     void splitKey();
0220 
0221     quint64 m_key;
0222     QVector<char> m_keyParts;
0223     CompressionMode m_compressionMode;
0224     IntegrityProtectionMode m_protectionMode;
0225     Error m_lastError;
0226 #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
0227     QRandomGenerator m_rand;
0228 #endif
0229 };
0230 Q_DECLARE_OPERATORS_FOR_FLAGS(O0SimpleCrypt::CryptoFlags)
0231 
0232 #endif // SimpleCrypt_H