diff --git a/CMakeLists.txt b/CMakeLists.txt
index be7f5c3ec..aa9a5aaa5 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -388,6 +388,7 @@ set(APP_SOURCES
src/miscellaneous/autosaver.cpp
src/miscellaneous/mutex.cpp
src/miscellaneous/databasecleaner.cpp
+ src/miscellaneous/simplecrypt/simplecrypt.cpp
# EXCEPTIONS sources.
src/exceptions/applicationexception.cpp
diff --git a/resources/text/CHANGELOG b/resources/text/CHANGELOG
index 04456dbb3..b8344d912 100644
--- a/resources/text/CHANGELOG
+++ b/resources/text/CHANGELOG
@@ -2,6 +2,7 @@
2.5.0
Added:
+ - Password in feeds & proxy & MySQL are now saved in encrypted form. This means that all passwords from RSS Guard older than 2.5.0 are lost!!! Set your passwords again.
- Fancy & modern popup notifications (turned on by default).
- Enhanced information in download manager.
- Added ability to change font for internal message viewer.
diff --git a/src/core/feedsmodel.cpp b/src/core/feedsmodel.cpp
index d7e127867..1835f8d1b 100755
--- a/src/core/feedsmodel.cpp
+++ b/src/core/feedsmodel.cpp
@@ -391,7 +391,7 @@ bool FeedsModel::addFeed(FeedsModelFeed *feed, FeedsModelRootItem *parent) {
query_add_feed.bindValue(QSL(":url"), feed->url());
query_add_feed.bindValue(QSL(":protected"), (int) feed->passwordProtected());
query_add_feed.bindValue(QSL(":username"), feed->username());
- query_add_feed.bindValue(QSL(":password"), feed->password());
+ query_add_feed.bindValue(QSL(":password"), TextFactory::encrypt(feed->password()));
query_add_feed.bindValue(QSL(":update_type"), (int) feed->autoUpdateType());
query_add_feed.bindValue(QSL(":update_interval"), feed->autoUpdateInitialInterval());
query_add_feed.bindValue(QSL(":type"), (int) feed->type());
@@ -440,7 +440,7 @@ bool FeedsModel::editFeed(FeedsModelFeed *original_feed, FeedsModelFeed *new_fee
query_update_feed.bindValue(QSL(":url"), new_feed->url());
query_update_feed.bindValue(QSL(":protected"), (int) new_feed->passwordProtected());
query_update_feed.bindValue(QSL(":username"), new_feed->username());
- query_update_feed.bindValue(QSL(":password"), new_feed->password());
+ query_update_feed.bindValue(QSL(":password"), TextFactory::encrypt(new_feed->password()));
query_update_feed.bindValue(QSL(":update_type"), (int) new_feed->autoUpdateType());
query_update_feed.bindValue(QSL(":update_interval"), new_feed->autoUpdateInitialInterval());
query_update_feed.bindValue(QSL(":type"), new_feed->type());
diff --git a/src/core/feedsmodelfeed.cpp b/src/core/feedsmodelfeed.cpp
index 3637def27..f7fd54d98 100755
--- a/src/core/feedsmodelfeed.cpp
+++ b/src/core/feedsmodelfeed.cpp
@@ -23,6 +23,7 @@
#include "miscellaneous/textfactory.h"
#include "miscellaneous/settings.h"
#include "miscellaneous/iconfactory.h"
+#include "miscellaneous/simplecrypt/simplecrypt.h"
#include "network-web/networkfactory.h"
#include
@@ -608,7 +609,7 @@ FeedsModelFeed::FeedsModelFeed(const QSqlRecord &record) : FeedsModelRootItem(NU
setUrl(record.value(FDS_DB_URL_INDEX).toString());
setPasswordProtected(record.value(FDS_DB_PROTECTED_INDEX).toBool());
setUsername(record.value(FDS_DB_USERNAME_INDEX).toString());
- setPassword(record.value(FDS_DB_PASSWORD_INDEX).toString());
+ setPassword(TextFactory::decrypt(record.value(FDS_DB_PASSWORD_INDEX).toString()));
setAutoUpdateType(static_cast(record.value(FDS_DB_UPDATE_TYPE_INDEX).toInt()));
setAutoUpdateInitialInterval(record.value(FDS_DB_UPDATE_INTERVAL_INDEX).toInt());
updateCounts();
diff --git a/src/core/feedsselection.h b/src/core/feedsselection.h
index 3caebc6f4..43658ad94 100644
--- a/src/core/feedsselection.h
+++ b/src/core/feedsselection.h
@@ -36,7 +36,7 @@ class FeedsSelection {
FeedsSelection(const FeedsSelection &other);
virtual ~FeedsSelection();
- SelectionMode mode();
+ SelectionMode mode();
FeedsModelRootItem *selectedItem() const;
QString generateListOfIds();
diff --git a/src/definitions/definitions.h.in b/src/definitions/definitions.h.in
index aebd05a72..9e568255b 100755
--- a/src/definitions/definitions.h.in
+++ b/src/definitions/definitions.h.in
@@ -85,6 +85,7 @@
#define NOTIFICATION_ICON_SIZE 64
#define GOOGLE_SEARCH_URL "https://www.google.com/search?q=%1&ie=utf-8&oe=utf-8"
#define GOOGLE_SUGGEST_URL "http://suggestqueries.google.com/complete/search?output=toolbar&hl=en&q=%1"
+#define DUMMY_DUMMY_DUMMY 0xaec852f1
#define FEED_INITIAL_OPML_PATTERN "feeds-%1.opml"
diff --git a/src/gui/dialogs/formsettings.cpp b/src/gui/dialogs/formsettings.cpp
index 15abd8f31..88f68aab4 100755
--- a/src/gui/dialogs/formsettings.cpp
+++ b/src/gui/dialogs/formsettings.cpp
@@ -28,6 +28,7 @@
#include "miscellaneous/systemfactory.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/skinfactory.h"
+#include "miscellaneous/textfactory.h"
#include "network-web/webfactory.h"
#include "network-web/webbrowsernetworkaccessmanager.h"
#include "network-web/silentnetworkaccessmanager.h"
@@ -450,7 +451,7 @@ void FormSettings::loadProxy() {
m_ui->m_cmbProxyType->setCurrentIndex(m_ui->m_cmbProxyType->findData(selected_proxy_type));
m_ui->m_txtProxyHost->setText(settings->value(GROUP(Proxy), SETTING(Proxy::Host)).toString());
m_ui->m_txtProxyUsername->setText(settings->value(GROUP(Proxy), SETTING(Proxy::Username)).toString());
- m_ui->m_txtProxyPassword->setText(settings->value(GROUP(Proxy), SETTING(Proxy::Password)).toString());
+ m_ui->m_txtProxyPassword->setText(TextFactory::decrypt(settings->value(GROUP(Proxy), SETTING(Proxy::Password)).toString()));
m_ui->m_spinProxyPort->setValue(settings->value(GROUP(Proxy), SETTING(Proxy::Port)).toInt());
}
@@ -460,7 +461,7 @@ void FormSettings::saveProxy() {
settings->setValue(GROUP(Proxy), Proxy::Type, m_ui->m_cmbProxyType->itemData(m_ui->m_cmbProxyType->currentIndex()));
settings->setValue(GROUP(Proxy), Proxy::Host, m_ui->m_txtProxyHost->text());
settings->setValue(GROUP(Proxy), Proxy::Username, m_ui->m_txtProxyUsername->text());
- settings->setValue(GROUP(Proxy), Proxy::Password, m_ui->m_txtProxyPassword->text());
+ settings->setValue(GROUP(Proxy), Proxy::Password, TextFactory::encrypt(m_ui->m_txtProxyPassword->text()));
settings->setValue(GROUP(Proxy), Proxy::Port, m_ui->m_spinProxyPort->value());
// Reload settings for all network access managers.
@@ -541,7 +542,7 @@ void FormSettings::loadDataStorage() {
m_ui->m_txtMysqlHostname->lineEdit()->setText(settings->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString());
m_ui->m_txtMysqlUsername->lineEdit()->setText(settings->value(GROUP(Database), SETTING(Database::MySQLUsername)).toString());
- m_ui->m_txtMysqlPassword->lineEdit()->setText(settings->value(GROUP(Database), SETTING(Database::MySQLPassword)).toString());
+ m_ui->m_txtMysqlPassword->lineEdit()->setText(TextFactory::decrypt(settings->value(GROUP(Database), SETTING(Database::MySQLPassword)).toString()));
m_ui->m_txtMysqlDatabase->lineEdit()->setText(settings->value(GROUP(Database), SETTING(Database::MySQLDatabase)).toString());
m_ui->m_spinMysqlPort->setValue(settings->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt());
@@ -577,7 +578,7 @@ void FormSettings::saveDataStorage() {
// Save MySQL.
settings->setValue(GROUP(Database), Database::MySQLHostname, m_ui->m_txtMysqlHostname->lineEdit()->text());
settings->setValue(GROUP(Database), Database::MySQLUsername, m_ui->m_txtMysqlUsername->lineEdit()->text());
- settings->setValue(GROUP(Database), Database::MySQLPassword, m_ui->m_txtMysqlPassword->lineEdit()->text());
+ settings->setValue(GROUP(Database), Database::MySQLPassword, TextFactory::encrypt(m_ui->m_txtMysqlPassword->lineEdit()->text()));
settings->setValue(GROUP(Database), Database::MySQLDatabase, m_ui->m_txtMysqlDatabase->lineEdit()->text());
settings->setValue(GROUP(Database), Database::MySQLPort, m_ui->m_spinMysqlPort->value());
}
diff --git a/src/miscellaneous/databasefactory.cpp b/src/miscellaneous/databasefactory.cpp
index c3e9c676c..6e0d98ff4 100755
--- a/src/miscellaneous/databasefactory.cpp
+++ b/src/miscellaneous/databasefactory.cpp
@@ -19,6 +19,7 @@
#include "miscellaneous/iofactory.h"
#include "miscellaneous/application.h"
+#include "miscellaneous/textfactory.h"
#include
#include
@@ -537,7 +538,7 @@ QSqlDatabase DatabaseFactory::mysqlConnection(const QString &connection_name) {
database.setHostName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString());
database.setPort(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt());
database.setUserName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLUsername)).toString());
- database.setPassword(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPassword)).toString());
+ database.setPassword(TextFactory::decrypt(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPassword)).toString()));
database.setDatabaseName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLDatabase)).toString());
}
@@ -563,7 +564,7 @@ QSqlDatabase DatabaseFactory::mysqlInitializeDatabase(const QString &connection_
database.setHostName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString());
database.setPort(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt());
database.setUserName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLUsername)).toString());
- database.setPassword(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPassword)).toString());
+ database.setPassword(TextFactory::decrypt(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPassword)).toString()));
if (!database.open()) {
qFatal("MySQL database was NOT opened. Delivered error message: '%s'",
diff --git a/src/miscellaneous/simplecrypt/simplecrypt.cpp b/src/miscellaneous/simplecrypt/simplecrypt.cpp
new file mode 100644
index 000000000..73e844959
--- /dev/null
+++ b/src/miscellaneous/simplecrypt/simplecrypt.cpp
@@ -0,0 +1,246 @@
+/*
+Copyright (c) 2011, Andre Somers
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the Rathenau Instituut, Andre Somers nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL ANDRE SOMERS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR #######; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "miscellaneous/simplecrypt/simplecrypt.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+SimpleCrypt::SimpleCrypt():
+ m_key(0),
+ m_compressionMode(CompressionAlways),
+ m_protectionMode(ProtectionHash),
+ m_lastError(ErrorNoError) {
+ qsrand(uint(QDateTime::currentMSecsSinceEpoch() & 0xFFFF));
+}
+
+SimpleCrypt::SimpleCrypt(quint64 key):
+ m_key(key),
+ m_compressionMode(CompressionAlways),
+ m_protectionMode(ProtectionHash),
+ m_lastError(ErrorNoError) {
+ qsrand(uint(QDateTime::currentMSecsSinceEpoch() & 0xFFFF));
+ splitKey();
+}
+
+void SimpleCrypt::setKey(quint64 key) {
+ m_key = key;
+ splitKey();
+}
+
+void SimpleCrypt::splitKey() {
+ m_keyParts.clear();
+ m_keyParts.resize(8);
+ for (int i=0;i<8;i++) {
+ quint64 part = m_key;
+
+ for (int j=i; j>0; j--) {
+ part = part >> 8;
+ }
+
+ part = part & 0xff;
+ m_keyParts[i] = static_cast(part);
+ }
+}
+
+QByteArray SimpleCrypt::encryptToByteArray(const QString& plaintext) {
+ return encryptToByteArray(plaintext.toUtf8());
+}
+
+QByteArray SimpleCrypt::encryptToByteArray(QByteArray plaintext) {
+ if (m_keyParts.isEmpty()) {
+ qWarning() << "No key set.";
+ m_lastError = ErrorNoKeySet;
+ return QByteArray();
+ }
+
+ QByteArray ba = plaintext;
+ CryptoFlags flags = CryptoFlagNone;
+
+ if (m_compressionMode == CompressionAlways) {
+ ba = qCompress(ba, 9); //maximum compression
+ flags |= CryptoFlagCompression;
+ }
+ else if (m_compressionMode == CompressionAuto) {
+ QByteArray compressed = qCompress(ba, 9);
+
+ if (compressed.count() < ba.count()) {
+ ba = compressed;
+ flags |= CryptoFlagCompression;
+ }
+ }
+
+ QByteArray integrityProtection;
+ if (m_protectionMode == ProtectionChecksum) {
+ flags |= CryptoFlagChecksum;
+ QDataStream s(&integrityProtection, QIODevice::WriteOnly);
+ s << qChecksum(ba.constData(), ba.length());
+ }
+ else if (m_protectionMode == ProtectionHash) {
+ flags |= CryptoFlagHash;
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ hash.addData(ba);
+ integrityProtection += hash.result();
+ }
+
+ //prepend a random char to the string
+ char randomChar = char(qrand() & 0xFF);
+ ba = randomChar + integrityProtection + ba;
+
+ int pos(0);
+ char lastChar(0);
+ int cnt = ba.count();
+
+ while (pos < cnt) {
+ ba[pos] = ba.at(pos) ^ m_keyParts.at(pos % 8) ^ lastChar;
+ lastChar = ba.at(pos);
+ ++pos;
+ }
+
+ QByteArray resultArray;
+ resultArray.append(char(0x03)); //version for future updates to algorithm
+ resultArray.append(char(flags)); //encryption flags
+ resultArray.append(ba);
+
+ m_lastError = ErrorNoError;
+ return resultArray;
+}
+
+QString SimpleCrypt::encryptToString(const QString& plaintext) {
+ QByteArray plaintextArray = plaintext.toUtf8();
+ QByteArray cypher = encryptToByteArray(plaintextArray);
+ QString cypherString = QString::fromLatin1(cypher.toBase64());
+ return cypherString;
+}
+
+QString SimpleCrypt::encryptToString(QByteArray plaintext) {
+ QByteArray cypher = encryptToByteArray(plaintext);
+ QString cypherString = QString::fromLatin1(cypher.toBase64());
+ return cypherString;
+}
+
+QString SimpleCrypt::decryptToString(const QString &cyphertext) {
+ QByteArray cyphertextArray = QByteArray::fromBase64(cyphertext.toLatin1());
+ QByteArray plaintextArray = decryptToByteArray(cyphertextArray);
+ QString plaintext = QString::fromUtf8(plaintextArray, plaintextArray.size());
+
+ return plaintext;
+}
+
+QString SimpleCrypt::decryptToString(QByteArray cypher) {
+ QByteArray ba = decryptToByteArray(cypher);
+ QString plaintext = QString::fromUtf8(ba, ba.size());
+
+ return plaintext;
+}
+
+QByteArray SimpleCrypt::decryptToByteArray(const QString& cyphertext) {
+ QByteArray cyphertextArray = QByteArray::fromBase64(cyphertext.toLatin1());
+ QByteArray ba = decryptToByteArray(cyphertextArray);
+
+ return ba;
+}
+
+QByteArray SimpleCrypt::decryptToByteArray(QByteArray cypher) {
+ if (m_keyParts.isEmpty()) {
+ qWarning() << "No key set.";
+ m_lastError = ErrorNoKeySet;
+ return QByteArray();
+ }
+
+ QByteArray ba = cypher;
+
+ if (cypher.count() < 3) {
+ return QByteArray();
+ }
+
+ char version = ba.at(0);
+
+ if (version !=3) { //we only work with version 3
+ m_lastError = ErrorUnknownVersion;
+ qWarning() << "Invalid version or not a cyphertext.";
+ return QByteArray();
+ }
+
+ CryptoFlags flags = CryptoFlags(ba.at(1));
+
+ ba = ba.mid(2);
+ int pos(0);
+ int cnt(ba.count());
+ char lastChar = 0;
+
+ while (pos < cnt) {
+ char currentChar = ba[pos];
+ ba[pos] = ba.at(pos) ^ lastChar ^ m_keyParts.at(pos % 8);
+ lastChar = currentChar;
+ ++pos;
+ }
+
+ ba = ba.mid(1); //chop off the random number at the start
+
+ bool integrityOk(true);
+ if (flags.testFlag(CryptoFlagChecksum)) {
+ if (ba.length() < 2) {
+ m_lastError = ErrorIntegrityFailed;
+ return QByteArray();
+ }
+ quint16 storedChecksum;
+ {
+ QDataStream s(&ba, QIODevice::ReadOnly);
+ s >> storedChecksum;
+ }
+ ba = ba.mid(2);
+ quint16 checksum = qChecksum(ba.constData(), ba.length());
+ integrityOk = (checksum == storedChecksum);
+ } else if (flags.testFlag(CryptoFlagHash)) {
+ if (ba.length() < 20) {
+ m_lastError = ErrorIntegrityFailed;
+ return QByteArray();
+ }
+ QByteArray storedHash = ba.left(20);
+ ba = ba.mid(20);
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ hash.addData(ba);
+ integrityOk = (hash.result() == storedHash);
+ }
+
+ if (!integrityOk) {
+ m_lastError = ErrorIntegrityFailed;
+ return QByteArray();
+ }
+
+ if (flags.testFlag(CryptoFlagCompression))
+ ba = qUncompress(ba);
+
+ m_lastError = ErrorNoError;
+ return ba;
+}
diff --git a/src/miscellaneous/simplecrypt/simplecrypt.h b/src/miscellaneous/simplecrypt/simplecrypt.h
new file mode 100644
index 000000000..9ba232e25
--- /dev/null
+++ b/src/miscellaneous/simplecrypt/simplecrypt.h
@@ -0,0 +1,227 @@
+/*
+Copyright (c) 2011, Andre Somers
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the Rathenau Instituut, Andre Somers nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL ANDRE SOMERS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR #######; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef SIMPLECRYPT_H
+#define SIMPLECRYPT_H
+
+#include
+#include
+#include
+
+
+/**
+ @short Simple encryption and decryption of strings and byte arrays
+
+ This class provides a simple implementation of encryption and decryption
+ of strings and byte arrays.
+
+ @warning The encryption provided by this class is NOT strong encryption. It may
+ help to shield things from curious eyes, but it will NOT stand up to someone
+ determined to break the encryption. Don't say you were not warned.
+
+ The class uses a 64 bit key. Simply create an instance of the class, set the key,
+ and use the encryptToString() method to calculate an encrypted version of the input string.
+ To decrypt that string again, use an instance of SimpleCrypt initialized with
+ the same key, and call the decryptToString() method with the encrypted string. If the key
+ matches, the decrypted version of the string will be returned again.
+
+ If you do not provide a key, or if something else is wrong, the encryption and
+ decryption function will return an empty string or will return a string containing nonsense.
+ lastError() will return a value indicating if the method was succesful, and if not, why not.
+
+ SimpleCrypt is prepared for the case that the encryption and decryption
+ algorithm is changed in a later version, by prepending a version identifier to the cypertext.
+ */
+class SimpleCrypt {
+ public:
+ /**
+ CompressionMode describes if compression will be applied to the data to be
+ encrypted.
+ */
+ enum CompressionMode {
+ CompressionAuto, /*!< Only apply compression if that results in a shorter plaintext. */
+ CompressionAlways, /*!< Always apply compression. Note that for short inputs, a compression may result in longer data */
+ CompressionNever /*!< Never apply compression. */
+ };
+ /**
+ IntegrityProtectionMode describes measures taken to make it possible to detect problems with the data
+ or wrong decryption keys.
+
+ Measures involve adding a checksum or a cryptograhpic hash to the data to be encrypted. This
+ increases the length of the resulting cypertext, but makes it possible to check if the plaintext
+ appears to be valid after decryption.
+ */
+ enum IntegrityProtectionMode {
+ ProtectionNone, /*!< The integerity of the encrypted data is not protected. It is not really possible to detect a wrong key, for instance. */
+ ProtectionChecksum,/*!< A simple checksum is used to verify that the data is in order. If not, an empty string is returned. */
+ ProtectionHash /*!< A cryptographic hash is used to verify the integrity of the data. This method produces a much stronger, but longer check */
+ };
+ /**
+ Error describes the type of error that occured.
+ */
+ enum Error {
+ ErrorNoError, /*!< No error occurred. */
+ ErrorNoKeySet, /*!< No key was set. You can not encrypt or decrypt without a valid key. */
+ ErrorUnknownVersion, /*!< The version of this data is unknown, or the data is otherwise not valid. */
+ ErrorIntegrityFailed, /*!< The integrity check of the data failed. Perhaps the wrong key was used. */
+ };
+
+ /**
+ Constructor.
+
+ Constructs a SimpleCrypt instance without a valid key set on it.
+ */
+ SimpleCrypt();
+ /**
+ Constructor.
+
+ Constructs a SimpleCrypt instance and initializes it with the given @arg key.
+ */
+ explicit SimpleCrypt(quint64 key);
+
+ /**
+ (Re-) initializes the key with the given @arg key.
+ */
+ void setKey(quint64 key);
+ /**
+ Returns true if SimpleCrypt has been initialized with a key.
+ */
+ bool hasKey() const {return !m_keyParts.isEmpty();}
+
+ /**
+ Sets the compression mode to use when encrypting data. The default mode is Auto.
+
+ Note that decryption is not influenced by this mode, as the decryption recognizes
+ what mode was used when encrypting.
+ */
+ void setCompressionMode(CompressionMode mode) {m_compressionMode = mode;}
+ /**
+ Returns the CompressionMode that is currently in use.
+ */
+ CompressionMode compressionMode() const {return m_compressionMode;}
+
+ /**
+ Sets the integrity mode to use when encrypting data. The default mode is Checksum.
+
+ Note that decryption is not influenced by this mode, as the decryption recognizes
+ what mode was used when encrypting.
+ */
+ void setIntegrityProtectionMode(IntegrityProtectionMode mode) {m_protectionMode = mode;}
+ /**
+ Returns the IntegrityProtectionMode that is currently in use.
+ */
+ IntegrityProtectionMode integrityProtectionMode() const {return m_protectionMode;}
+
+ /**
+ Returns the last error that occurred.
+ */
+ Error lastError() const {return m_lastError;}
+
+ /**
+ Encrypts the @arg plaintext string with the key the class was initialized with, and returns
+ a cyphertext the result. The result is a base64 encoded version of the binary array that is the
+ actual result of the string, so it can be stored easily in a text format.
+ */
+ QString encryptToString(const QString& plaintext) ;
+ /**
+ Encrypts the @arg plaintext QByteArray with the key the class was initialized with, and returns
+ a cyphertext the result. The result is a base64 encoded version of the binary array that is the
+ actual result of the encryption, so it can be stored easily in a text format.
+ */
+ QString encryptToString(QByteArray plaintext) ;
+ /**
+ Encrypts the @arg plaintext string with the key the class was initialized with, and returns
+ a binary cyphertext in a QByteArray the result.
+
+ This method returns a byte array, that is useable for storing a binary format. If you need
+ a string you can store in a text file, use encryptToString() instead.
+ */
+ QByteArray encryptToByteArray(const QString& plaintext) ;
+ /**
+ Encrypts the @arg plaintext QByteArray with the key the class was initialized with, and returns
+ a binary cyphertext in a QByteArray the result.
+
+ This method returns a byte array, that is useable for storing a binary format. If you need
+ a string you can store in a text file, use encryptToString() instead.
+ */
+ QByteArray encryptToByteArray(QByteArray plaintext) ;
+
+ /**
+ Decrypts a cyphertext string encrypted with this class with the set key back to the
+ plain text version.
+
+ If an error occured, such as non-matching keys between encryption and decryption,
+ an empty string or a string containing nonsense may be returned.
+ */
+ QString decryptToString(const QString& cyphertext) ;
+ /**
+ Decrypts a cyphertext string encrypted with this class with the set key back to the
+ plain text version.
+
+ If an error occured, such as non-matching keys between encryption and decryption,
+ an empty string or a string containing nonsense may be returned.
+ */
+ QByteArray decryptToByteArray(const QString& cyphertext) ;
+ /**
+ Decrypts a cyphertext binary encrypted with this class with the set key back to the
+ plain text version.
+
+ If an error occured, such as non-matching keys between encryption and decryption,
+ an empty string or a string containing nonsense may be returned.
+ */
+ QString decryptToString(QByteArray cypher) ;
+ /**
+ Decrypts a cyphertext binary encrypted with this class with the set key back to the
+ plain text version.
+
+ If an error occured, such as non-matching keys between encryption and decryption,
+ an empty string or a string containing nonsense may be returned.
+ */
+ QByteArray decryptToByteArray(QByteArray cypher) ;
+
+ //enum to describe options that have been used for the encryption. Currently only one, but
+ //that only leaves room for future extensions like adding a cryptographic hash...
+ enum CryptoFlag{CryptoFlagNone = 0,
+ CryptoFlagCompression = 0x01,
+ CryptoFlagChecksum = 0x02,
+ CryptoFlagHash = 0x04
+ };
+
+ Q_DECLARE_FLAGS(CryptoFlags, CryptoFlag)
+
+ private:
+ void splitKey();
+
+ quint64 m_key;
+ QVector m_keyParts;
+ CompressionMode m_compressionMode;
+ IntegrityProtectionMode m_protectionMode;
+ Error m_lastError;
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(SimpleCrypt::CryptoFlags)
+
+#endif // SimpleCrypt_H
diff --git a/src/miscellaneous/textfactory.cpp b/src/miscellaneous/textfactory.cpp
index 02fdcfc3f..219f754e9 100755
--- a/src/miscellaneous/textfactory.cpp
+++ b/src/miscellaneous/textfactory.cpp
@@ -18,6 +18,7 @@
#include "miscellaneous/textfactory.h"
#include "definitions/definitions.h"
+#include "miscellaneous/simplecrypt/simplecrypt.h"
#include
#include
@@ -108,6 +109,14 @@ QDateTime TextFactory::parseDateTime(qint64 milis_from_epoch) {
return QDateTime::fromMSecsSinceEpoch(milis_from_epoch);
}
+QString TextFactory::encrypt(const QString &text) {
+ return SimpleCrypt(DUMMY_DUMMY_DUMMY).encryptToString(text);
+}
+
+QString TextFactory::decrypt(const QString &text) {
+ return SimpleCrypt(DUMMY_DUMMY_DUMMY).decryptToString(text);
+}
+
QString TextFactory::shorten(const QString &input, int text_length_limit) {
if (input.size() > text_length_limit) {
return input.left(text_length_limit - ELLIPSIS_LENGTH) + QString(ELLIPSIS_LENGTH, QL1C('.'));
diff --git a/src/miscellaneous/textfactory.h b/src/miscellaneous/textfactory.h
index 47b231aa6..458620b00 100644
--- a/src/miscellaneous/textfactory.h
+++ b/src/miscellaneous/textfactory.h
@@ -47,6 +47,9 @@ class TextFactory {
// NOTE: This apparently returns date/time in localtime.
static QDateTime parseDateTime(qint64 milis_from_epoch);
+ static QString encrypt(const QString &text);
+ static QString decrypt(const QString &text);
+
// Shortens input string according to given length limit.
static QString shorten(const QString &input, int text_length_limit = TEXT_TITLE_LIMIT);
};
diff --git a/src/network-web/basenetworkaccessmanager.cpp b/src/network-web/basenetworkaccessmanager.cpp
index c2bd27dc9..45bfaf81b 100755
--- a/src/network-web/basenetworkaccessmanager.cpp
+++ b/src/network-web/basenetworkaccessmanager.cpp
@@ -18,6 +18,7 @@
#include "network-web/basenetworkaccessmanager.h"
#include "miscellaneous/application.h"
+#include "miscellaneous/textfactory.h"
#include
#include
@@ -54,7 +55,7 @@ void BaseNetworkAccessManager::loadSettings() {
new_proxy.setHostName(settings->value(GROUP(Proxy), SETTING(Proxy::Host)).toString());
new_proxy.setPort(settings->value(GROUP(Proxy), SETTING(Proxy::Port)).toInt());
new_proxy.setUser(settings->value(GROUP(Proxy), SETTING(Proxy::Username)).toString());
- new_proxy.setPassword(settings->value(GROUP(Proxy), SETTING(Proxy::Password)).toString());
+ new_proxy.setPassword(TextFactory::decrypt(settings->value(GROUP(Proxy), SETTING(Proxy::Password)).toString()));
setProxy(new_proxy);
}