From 94408fe9b752e10959ef0abfbeed63f4455bf28e Mon Sep 17 00:00:00 2001 From: Sagi Dayan Date: Tue, 2 Sep 2014 14:50:33 +0300 Subject: [PATCH 1/4] Delete QT user config - need to be add to gitignore --- jceGrade.pro.user | 267 ---------------------------------------------- 1 file changed, 267 deletions(-) delete mode 100644 jceGrade.pro.user diff --git a/jceGrade.pro.user b/jceGrade.pro.user deleted file mode 100644 index f606ccd..0000000 --- a/jceGrade.pro.user +++ /dev/null @@ -1,267 +0,0 @@ - - - - - - EnvironmentId - {27d037c7-80c2-4adc-9ebd-7fcaa787aa69} - - - ProjectExplorer.Project.ActiveTarget - 0 - - - ProjectExplorer.Project.EditorSettings - - true - false - true - - Cpp - - CppGlobal - - - - QmlJS - - QmlJSGlobal - - - 2 - UTF-8 - false - 4 - false - 80 - true - true - 1 - true - false - 0 - true - 0 - 8 - true - 1 - true - true - true - false - - - - ProjectExplorer.Project.PluginSettings - - - - ProjectExplorer.Project.Target.0 - - Desktop - Desktop - {5099a051-769d-496c-9c12-be2a0d9569cf} - 0 - 0 - 0 - - /home/sagi/Development/SocialDev/build-jceGrade-Desktop-Debug - - - true - qmake - - QtProjectManager.QMakeBuildStep - false - true - - false - - - true - Make - - Qt4ProjectManager.MakeStep - - -w - -r - - false - - - - 2 - Build - - ProjectExplorer.BuildSteps.Build - - - - true - Make - - Qt4ProjectManager.MakeStep - - -w - -r - - true - clean - - - 1 - Clean - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Debug - - Qt4ProjectManager.Qt4BuildConfiguration - 2 - true - - - /home/sagi/Development/SocialDev/build-jceGrade-Desktop-Release - - - true - qmake - - QtProjectManager.QMakeBuildStep - false - true - - false - - - true - Make - - Qt4ProjectManager.MakeStep - - -w - -r - - false - - - - 2 - Build - - ProjectExplorer.BuildSteps.Build - - - - true - Make - - Qt4ProjectManager.MakeStep - - -w - -r - - true - clean - - - 1 - Clean - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Release - - Qt4ProjectManager.Qt4BuildConfiguration - 0 - true - - 2 - - - 0 - Deploy - - ProjectExplorer.BuildSteps.Deploy - - 1 - Deploy locally - - ProjectExplorer.DefaultDeployConfiguration - - 1 - - - - false - false - false - false - true - 0.01 - 10 - true - 1 - 25 - - 1 - true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - 2 - - jceGrade - - Qt4ProjectManager.Qt4RunConfiguration:/home/sagi/Development/SocialDev/jceAverageCalculator/jceGrade.pro - - jceGrade.pro - false - false - - 3768 - false - true - false - false - true - - 1 - - - - ProjectExplorer.Project.TargetCount - 1 - - - ProjectExplorer.Project.Updater.FileVersion - 16 - - - Version - 16 - - From 11b4101c589e943b9ecaaf54d8fb414bfde3b747 Mon Sep 17 00:00:00 2001 From: Sagi Dayan Date: Sun, 7 Sep 2014 22:57:01 +0300 Subject: [PATCH 2/4] Added Featcher: Export calendar to CSV format for GoogleCalendar/iCal/Outlook at the gui - calendar tab - there is now an export to csv button. clicking it will prompt thr user to save the file on his system hard drive. the app will add the .csv extention. the csv file, will export only one week, starting from the begining of the first semester of 2015 (the one that is coming). in the future i will add a Held doc for exporting and importimg to the users calendar. cheers! --- jceGrade.pro | 6 +- main/CalendarTab/CalendarManager.cpp | 5 + main/CalendarTab/CalendarManager.h | 1 + main/mainscreen.cpp | 5 + main/mainscreen.h | 3 + main/mainscreen.ui | 9 +- src/jceData/CSV/csv_exporter.cpp | 145 ++++++++++++++++++++++++ src/jceData/CSV/csv_exporter.h | 26 +++++ src/jceData/Calendar/calendarSchedule.h | 2 +- 9 files changed, 198 insertions(+), 4 deletions(-) create mode 100644 src/jceData/CSV/csv_exporter.cpp create mode 100644 src/jceData/CSV/csv_exporter.h diff --git a/jceGrade.pro b/jceGrade.pro index a2c9e16..139040f 100644 --- a/jceGrade.pro +++ b/jceGrade.pro @@ -36,7 +36,8 @@ HEADERS += \ src/jceSettings/jceLoginHtmlScripts.h \ src/jceSettings/user.h \ src/jceData/Calendar/calendarCourse.h \ - src/jceData/Calendar/calendarSchedule.h + src/jceData/Calendar/calendarSchedule.h \ + src/jceData/CSV/csv_exporter.h SOURCES += \ main/CalendarTab/CalendarManager.cpp \ @@ -53,5 +54,6 @@ SOURCES += \ src/jceSettings/jcelogin.cpp \ src/jceSettings/user.cpp \ src/jceData/Calendar/calendarCourse.cpp \ - src/jceData/Calendar/calendarSchedule.cpp + src/jceData/Calendar/calendarSchedule.cpp \ + src/jceData/CSV/csv_exporter.cpp diff --git a/main/CalendarTab/CalendarManager.cpp b/main/CalendarTab/CalendarManager.cpp index ebb9899..addeaac 100644 --- a/main/CalendarTab/CalendarManager.cpp +++ b/main/CalendarTab/CalendarManager.cpp @@ -9,3 +9,8 @@ void CalendarManager::setCalendar(std::string html) { caliSchedPtr->setPage(html); } + +calendarSchedule *CalendarManager::getSch() +{ + return this->caliSchedPtr; +} diff --git a/main/CalendarTab/CalendarManager.h b/main/CalendarTab/CalendarManager.h index 042e831..e7a9737 100644 --- a/main/CalendarTab/CalendarManager.h +++ b/main/CalendarTab/CalendarManager.h @@ -16,6 +16,7 @@ public: void setCalendar(std::string html); void resetTable() { if (caliSchedPtr != NULL) caliSchedPtr->clearTableItems(); } + calendarSchedule* getSch(); private: calendarSchedule * caliSchedPtr; }; diff --git a/main/mainscreen.cpp b/main/mainscreen.cpp index bb26fc3..8e4bca3 100644 --- a/main/mainscreen.cpp +++ b/main/mainscreen.cpp @@ -291,3 +291,8 @@ void MainScreen::on_actionHow_To_triggered() ""); } + +void MainScreen::on_pushButton_2_clicked() +{ + CSV_Exporter::exportCalendar(this->calendar->getSch()); +} diff --git a/main/mainscreen.h b/main/mainscreen.h index 2ea31d2..0c68e4b 100644 --- a/main/mainscreen.h +++ b/main/mainscreen.h @@ -13,6 +13,7 @@ #include "./CourseTab/coursestablemanager.h" #include "./LoginTab/loginhandler.h" #include "./CalendarTab/CalendarManager.h" +#include "../src/jceData/CSV/csv_exporter.h" #define StatusIconHeight 35 namespace Ui { @@ -59,6 +60,8 @@ private slots: void on_checkBoxCoursesInfluence_toggled(bool checked); + void on_pushButton_2_clicked(); + private: void uiSetDisconnectMode(); diff --git a/main/mainscreen.ui b/main/mainscreen.ui index df3cece..a9c42a5 100644 --- a/main/mainscreen.ui +++ b/main/mainscreen.ui @@ -588,6 +588,13 @@ font-size: 15px; + + + + Export to CSV + + + @@ -619,7 +626,7 @@ font-size: 15px; 0 0 855 - 21 + 29 diff --git a/src/jceData/CSV/csv_exporter.cpp b/src/jceData/CSV/csv_exporter.cpp new file mode 100644 index 0000000..dc2159e --- /dev/null +++ b/src/jceData/CSV/csv_exporter.cpp @@ -0,0 +1,145 @@ +#include "csv_exporter.h" + +CSV_Exporter::CSV_Exporter() +{ + +} + +bool CSV_Exporter::exportCalendar(calendarSchedule *calSched) +{ + qDebug() << "Getting path for csv file from user..."; + QString filePath = getFileFath(); + if(filePath == NULL) //User canceled + { + qDebug() << "User pressed Cancel... returning false"; + return false; + } + qDebug() << "User Chose: " << filePath; + qDebug() << "Atempting to export the Schedule..."; + + QFile file(filePath); + if(!file.open(QIODevice::ReadWrite | QIODevice::Text)) + { + qDebug() << "unable to open/create the file... maybe permissions error."; + return false; + }//else + + QTextStream out(&file); + out << CSV_CALENDAR_HEADER << "\n"; + for (calendarCourse *coursePtr: *(calSched->getCourses())) + { + // Subject,Start Date,Start Time,End Date,End Time,Description,Location + int day = coursePtr->getDay(); + int startH = coursePtr->getHourBegin(); + int startM = coursePtr->getMinutesBegin(); + int endH = coursePtr->getHourEnd(); + int endM = coursePtr->getMinutesEnd(); + QString lecturer = QString(coursePtr->getLecturer().c_str()); //WHY YOU USED STD STRING?! + QString type = QString(coursePtr->getType().c_str()); + QString name = QString(coursePtr->getName().c_str()); + QString room = QString(coursePtr->getRoom().c_str()); + + QString line = makeLine(name, day, startH, startM, endH, endM, lecturer, room, type); + if(line != NULL) + out << line << char(0x0A); + } + + + out.flush(); + + + file.close(); + qDebug() << "Saved Successfuly! - HazZaA!"; + return true; + +} + +QString CSV_Exporter::getFileFath() +{ + QString fileName = QFileDialog::getSaveFileName(); + if(fileName == "") + return NULL; + fileName.append(".csv"); + return fileName; +} + +QString CSV_Exporter::makeLine(QString name, int day, int startH, int startM, int endH, int endM, QString lecturer, QString room, QString type) +{ + //Creating a CSV text line for Google Calendar/iCal/Outlook + // First day for semester 10/26/2014 + + QString CSV_line = ""; + QString subject = "\""; + subject.append(name); + subject.append(" - "); + subject.append(type); + subject.append("\""); + + QString date; + switch (day) { + case 1: + date = "10/26/2014"; + break; + case 2: + date = "10/27/2014"; + break; + case 3: + date = "10/28/2014"; + break; + case 4: + date = "10/29/2014"; + break; + case 5: + date = "10/30/2014"; + break; + case 6: + date = "10/31/2014"; + break; + default: + return NULL; + break; + } + + QString start; + start.append(QString::number(startH)); + start.append(":00"); + //start.append(QString::number(startM)); + start.append(":00"); + + QString end; + end.append(QString::number(endH)); + end.append(":"); + end.append(QString::number(endM)); + end.append(":00"); + + QString description = "\"מרצה "; + description.append(lecturer); + description.append("\n"); + description.append(" ב"); + description.append(room); + description.append("\""); + + //Create the Fucking Line + //Header: Subject,Start Date,Start Time,End Date,End Time,Description,Location + CSV_line.append(subject); + CSV_line.append(","); + + CSV_line.append(date); + CSV_line.append(","); + + CSV_line.append(start); + CSV_line.append(","); + + CSV_line.append(date); + CSV_line.append(","); + + CSV_line.append(end); + CSV_line.append(","); + + CSV_line.append(description); + CSV_line.append(","); + + CSV_line.append("\"JCE Jerusalem\""); + + return CSV_line; +} diff --git a/src/jceData/CSV/csv_exporter.h b/src/jceData/CSV/csv_exporter.h new file mode 100644 index 0000000..dec0783 --- /dev/null +++ b/src/jceData/CSV/csv_exporter.h @@ -0,0 +1,26 @@ +#ifndef CSV_EXPORTER_H +#define CSV_EXPORTER_H + +#include +#include +#include +#include +#include + +#include "../Calendar/calendarSchedule.h" + +#define CSV_CALENDAR_HEADER "Subject,Start Date,Start Time,End Date,End Time,Description,Location" + +class CSV_Exporter +{ +public: + CSV_Exporter(); + static bool exportCalendar(calendarSchedule* calSched); + + +private: + static QString getFileFath(); + static QString makeLine(QString name,int day,int startH,int startM,int endH,int endM,QString lecturer,QString room,QString type); +}; + +#endif // CSV_EXPORTER_H diff --git a/src/jceData/Calendar/calendarSchedule.h b/src/jceData/Calendar/calendarSchedule.h index df27daf..028afa1 100644 --- a/src/jceData/Calendar/calendarSchedule.h +++ b/src/jceData/Calendar/calendarSchedule.h @@ -20,7 +20,7 @@ public: calendarSchedule(); ~calendarSchedule() { clearTableItems(); } void setPage(std::string html); - void clearTableItems(); + void clearTableItems(); signals: From af10a074c08e3351e7f536454abb615caf9e480c Mon Sep 17 00:00:00 2001 From: Sagi Dayan Date: Sun, 7 Sep 2014 23:14:04 +0300 Subject: [PATCH 3/4] User Dialog Message to the export resaults --- main/mainscreen.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/main/mainscreen.cpp b/main/mainscreen.cpp index 8e4bca3..b7f4d6b 100644 --- a/main/mainscreen.cpp +++ b/main/mainscreen.cpp @@ -294,5 +294,17 @@ void MainScreen::on_actionHow_To_triggered() void MainScreen::on_pushButton_2_clicked() { - CSV_Exporter::exportCalendar(this->calendar->getSch()); + if(CSV_Exporter::exportCalendar(this->calendar->getSch())) + { + QMessageBox msgBox; + msgBox.setText("
Exported Successfuly!
HaazZaA!!"); + msgBox.exec(); + }else + { + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Critical); + msgBox.setText("
Something went wrong...
Maybe:
  • You Canceled
  • Unable to save the File - try again


" + "
In case of a serious problem, please file a bug report.
thank you. OpenJCE teem"); + msgBox.exec(); + } } From f63ac39fdc1222499e23af088299e1482b0d6c47 Mon Sep 17 00:00:00 2001 From: Sagi Dayan Date: Sun, 7 Sep 2014 23:44:27 +0300 Subject: [PATCH 4/4] Added Encription Lib From Qt-Project And Modified the shit out of it. Now the password should be encrypted. See that encrypt and decrypt key is the same key! cheers! --- jceGrade.pro | 6 +- src/appDatabase/savedata.cpp | 16 +- src/appDatabase/savedata.h | 4 + src/appDatabase/simplecrypt.cpp | 255 ++++++++++++++++++++++++++++++++ src/appDatabase/simplecrypt.h | 229 ++++++++++++++++++++++++++++ 5 files changed, 506 insertions(+), 4 deletions(-) create mode 100644 src/appDatabase/simplecrypt.cpp create mode 100644 src/appDatabase/simplecrypt.h diff --git a/jceGrade.pro b/jceGrade.pro index 139040f..3a9950b 100644 --- a/jceGrade.pro +++ b/jceGrade.pro @@ -37,7 +37,8 @@ HEADERS += \ src/jceSettings/user.h \ src/jceData/Calendar/calendarCourse.h \ src/jceData/Calendar/calendarSchedule.h \ - src/jceData/CSV/csv_exporter.h + src/jceData/CSV/csv_exporter.h \ + src/appDatabase/simplecrypt.h SOURCES += \ main/CalendarTab/CalendarManager.cpp \ @@ -55,5 +56,6 @@ SOURCES += \ src/jceSettings/user.cpp \ src/jceData/Calendar/calendarCourse.cpp \ src/jceData/Calendar/calendarSchedule.cpp \ - src/jceData/CSV/csv_exporter.cpp + src/jceData/CSV/csv_exporter.cpp \ + src/appDatabase/simplecrypt.cpp diff --git a/src/appDatabase/savedata.cpp b/src/appDatabase/savedata.cpp index edb1815..107f7fa 100644 --- a/src/appDatabase/savedata.cpp +++ b/src/appDatabase/savedata.cpp @@ -42,7 +42,7 @@ void SaveData::setUsername(QString username) void SaveData::setPassword(QString password) { - DB.insert("password", password); + DB.insert("password", encrypt(password)); save(); } @@ -65,7 +65,7 @@ QString SaveData::getUsername() QString SaveData::getPassword() { - return DB.value("password"); + return decrypte(DB.value("password")); } QString SaveData::getLocal() @@ -106,3 +106,15 @@ void SaveData::createDB() DB.insert("local", "default"); DB.insert("calendar", ""); } + +QString SaveData::encrypt(QString pass) +{ + SimpleCrypt crypto(Q_UINT64_C(0x0c2ad4a4acb9f027)); + return crypto.encryptToString(pass); +} + +QString SaveData::decrypte(QString pass) +{ + SimpleCrypt crypto(Q_UINT64_C(0x0c2ad4a4acb9f027)); + return crypto.decryptToString(pass); +} diff --git a/src/appDatabase/savedata.h b/src/appDatabase/savedata.h index 3952e22..f387282 100644 --- a/src/appDatabase/savedata.h +++ b/src/appDatabase/savedata.h @@ -29,6 +29,7 @@ #include #include #include +#include "simplecrypt.h" #define FILE_NAME "JAC_DB.dat" @@ -52,6 +53,9 @@ private: void load(); void save(); void createDB(); + QString encrypt(QString pass); + QString decrypte(QString pass); + }; #endif // SAVEDATA_H diff --git a/src/appDatabase/simplecrypt.cpp b/src/appDatabase/simplecrypt.cpp new file mode 100644 index 0000000..df882ef --- /dev/null +++ b/src/appDatabase/simplecrypt.cpp @@ -0,0 +1,255 @@ +/* +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 PROFITS; 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. +*/ + +/* + * Fixed By Sagi Dayan + */ +#include "simplecrypt.h" +#include +#include +#include +#include +#include + +SimpleCrypt::SimpleCrypt(): + m_key(0), + m_compressionMode(CompressionAuto), + m_protectionMode(ProtectionChecksum), + m_lastError(ErrorNoError) +{ + qsrand(uint(QDateTime::currentMSecsSinceEpoch() & 0xFFFF)); +} + +SimpleCrypt::SimpleCrypt(quint64 key): + m_key(key), + m_compressionMode(CompressionAuto), + m_protectionMode(ProtectionChecksum), + 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) +{ + QByteArray plaintextArray = plaintext.toUtf8(); + return encryptToByteArray(plaintextArray); +} + +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(cypher.toBase64()); + return cypherString; +} + +QString SimpleCrypt::encryptToString(QByteArray plaintext) +{ + QByteArray cypher = encryptToByteArray(plaintext); + QString cypherString = QString(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/appDatabase/simplecrypt.h b/src/appDatabase/simplecrypt.h new file mode 100644 index 0000000..7f1e80a --- /dev/null +++ b/src/appDatabase/simplecrypt.h @@ -0,0 +1,229 @@ +/* +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 PROFITS; 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. + */ + +/* + * Fixed By Sagi Dayan + */ +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