diff --git a/src/filters/notesortfilterproxymodel.cpp b/src/filters/notesortfilterproxymodel.cpp index 4e30a162..293e40c0 100644 --- a/src/filters/notesortfilterproxymodel.cpp +++ b/src/filters/notesortfilterproxymodel.cpp @@ -51,7 +51,7 @@ bool NoteSortFilterProxyModel::filterAcceptsRow(qint32 source_row, const QModelI // obsolete/unused bool NoteSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { - QLOG_DEBUG() << "lessThan"; + //QLOG_DEBUG() << "lessThan"; QVariant leftData = this->sourceModel()->data(left); QVariant rightData = this->sourceModel()->data(right); diff --git a/src/threads/encrypt.h b/src/threads/encrypt.h new file mode 100644 index 00000000..628bfffb --- /dev/null +++ b/src/threads/encrypt.h @@ -0,0 +1,213 @@ +#include "vigenere.h" +#include +#include +#include + + +class Base64 +{ +public: + static std::string encode(const std::vector& data); + static std::vector decode(const std::string& data); +}; + + +const char fillchar = '='; + + // 00000000001111111111222222 + // 01234567890123456789012345 +static std::string cvt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + // 22223333333333444444444455 + // 67890123456789012345678901 + "abcdefghijklmnopqrstuvwxyz" + + // 555555556666 + // 234567890123 + "0123456789+/"; + +// +//----< convert vector of bytes to std::string >--------------------- + +std::string Base64::encode(const std::vector& data) +{ + std::string::size_type i; + char c; + unsigned int len = data.size(); + std::string ret; + + for (i = 0; i < len; ++i) + { + c = (data[i] >> 2) & 0x3f; + ret.append(1, cvt[c]); + c = (data[i] << 4) & 0x3f; + if (++i < len) + c |= (data[i] >> 4) & 0x0f; + + ret.append(1, cvt[c]); + if (i < len) + { + c = (data[i] << 2) & 0x3f; + if (++i < len) + c |= (data[i] >> 6) & 0x03; + + ret.append(1, cvt[c]); + } + else + { + ++i; + ret.append(1, fillchar); + } + + if (i < len) + { + c = data[i] & 0x3f; + ret.append(1, cvt[c]); + } + else + { + ret.append(1, fillchar); + } + } + + return(ret); +} +// +//----< convert std::string to vector of bytes >--------------------- + +std::vector Base64::decode(const std::string& data) +{ + std::string::size_type i; + char c; + char c1; + std::string::size_type len = data.length(); + std::vector ret; + + for (i = 0; i < len; ++i) + { + c = (char) cvt.find(data[i]); + ++i; + c1 = (char) cvt.find(data[i]); + c = (c << 2) | ((c1 >> 4) & 0x3); + ret.push_back(c); + if (++i < len) + { + c = data[i]; + if (fillchar == c) + break; + c = (char) cvt.find(c); + c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf); + ret.push_back(c1); + } + if (++i < len) + { + c1 = data[i]; + if (fillchar == c1) + break; + c1 = (char) cvt.find(c1); + c = ((c << 6) & 0xc0) | c1; + ret.push_back(c); + } + } + return(ret); +} + + +// encrypt + +std::string encrypt(std::string& msg, std::string& key) +{ + std::vector msg2(msg.begin(), msg.end()); + std::string b64_str = Base64::encode(msg2); + std::string vigenere_msg = encrypt_vigenere(b64_str, key); + return vigenere_msg; +} + +// https://stackoverflow.com/questions/17316506/strip-invalid-utf8-from-string-in-c-c +std::string sanitize_utf8(std::string& str) +{ + int i,f_size=str.size(); + unsigned char c,c2,c3,c4; + string to; + to.reserve(f_size); + + for(i=0 ; i127 && c2<192){//valid 2byte UTF8 + if(c==194 && c2<160){//control char, skipping + ; + }else{ + to.append(1,c); + to.append(1,c2); + } + i++; + continue; + } + }else if(c<240 && i+2127 && c2<192 && c3>127 && c3<192){//valid 3byte UTF8 + to.append(1,c); + to.append(1,c2); + to.append(1,c3); + i+=2; + continue; + } + }else if(c<245 && i+3127 && c2<192 && c3>127 && c3<192 && c4>127 && c4<192){//valid 4byte UTF8 + to.append(1,c); + to.append(1,c2); + to.append(1,c3); + to.append(1,c4); + i+=3; + continue; + } + } + //invalid UTF8, converting ASCII (c>245 || string too short for multi-byte)) + to.append(1,(unsigned char)195); + to.append(1,c-64); + } + return to; +} + + +std::string decrypt(std::string& encrypted_msg, std::string& key) +{ + std::string newKey = extend_key(encrypted_msg, key); + std::string b64_encoded_str = decrypt_vigenere(encrypted_msg, newKey); + std::vector b64_decode_vec = Base64::decode(b64_encoded_str); + std::string b64_decode_str(b64_decode_vec.begin(), b64_decode_vec.end()); + return sanitize_utf8(b64_decode_str); +} diff --git a/src/threads/syncrunner.cpp b/src/threads/syncrunner.cpp index c00695d7..0eabcb40 100644 --- a/src/threads/syncrunner.cpp +++ b/src/threads/syncrunner.cpp @@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ***********************************************************************************/ #include +#include #include "syncrunner.h" #include "src/global.h" @@ -34,6 +35,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "src/communication/communicationmanager.h" #include "src/communication/communicationerror.h" #include "src/sql/nsqlquery.h" +#include "encrypt.h" + +#define CRYPT_KEY "6aabbb3efbd1ff6d606061684e9749cd476763a8" extern Global global; @@ -583,6 +587,30 @@ void SyncRunner::syncRemoteNotes(QList notes, qint32 account) { for (int i = 0; i < notes.size() && keepRunning; i++) { Note t = notes[i]; + + //QLOG_DEBUG() << t.content; + + // decrypt ============================================= + int crypt_s = t.content->indexOf("||crypt||"); + if (crypt_s!=-1) { + int crypt_e = t.content->indexOf(""); + QString cryptq = t.content->mid(crypt_s + 9, crypt_e - crypt_s - 9); + cryptq.remove(QChar('\n')); + + //QLOG_DEBUG() << cryptq; + + string crypt = cryptq.toStdString(); + string crypt_key = CRYPT_KEY; + string msg = decrypt(crypt, crypt_key); + + notes[i].content = QString::fromUtf8(msg.c_str()); + + t = notes[i]; + + //QLOG_DEBUG() << t.content; + } + // ====================================================== + qint32 lid = noteTable.getLid(t.guid); if (lid > 0) { // Find out if it is a conflicting change @@ -1184,6 +1212,29 @@ qint32 SyncRunner::uploadPersonalNotes() { Note note; noteTable.get(note, validLids[i], true, true); + // encrypt content ============================ + //QLOG_DEBUG() << note.content; + + int crypt_tag = note.content->indexOf("{{encrypt}}"); + + if (crypt_tag != -1){ + string msg = note.content->toStdString(); + string crypt_key = CRYPT_KEY; + string crypt = encrypt(msg, crypt_key); + + note.content = QString::fromUtf8(crypt.c_str()); + + note.content = "\n"\ + ""\ + "\n"\ + "||crypt||" + + note.content + + ""; + + //QLOG_DEBUG() << note.content; + } + ////============================================ + qint32 oldUsn = 0; if (note.updateSequenceNum.isSet()) oldUsn = note.updateSequenceNum; diff --git a/src/threads/vigenere.h b/src/threads/vigenere.h new file mode 100644 index 00000000..123efd98 --- /dev/null +++ b/src/threads/vigenere.h @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include + +using namespace std; + +std::string AVAILABLE_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +int index(char c) { + for(int ii = 0; ii < AVAILABLE_CHARS.size(); ii++) { + if(AVAILABLE_CHARS[ii] == c) { + // std::cout << ii << " " << c << std::endl; + return ii; + } + } + return -1; +} + + +std::string extend_key(std::string& msg, std::string& key) { + //generating new key + int msgLen = msg.size(); + std::string newKey(msgLen, 'x'); + int keyLen = key.size(), i, j; + for(i = 0, j = 0; i < msgLen; ++i, ++j){ + if(j == keyLen) + j = 0; + + newKey[i] = key[j]; + } + newKey[i] = '\0'; + return newKey; +} + + +std::string encrypt_vigenere(std::string& msg, std::string& key) { + int msgLen = msg.size(), keyLen = key.size(), i, j; + std::string encryptedMsg(msgLen, 'x'); + // char newKey[msgLen], encryptedMsg[msgLen], decryptedMsg[msgLen]; + + std::string newKey = extend_key(msg, key); + + //encryption + for(i = 0; i < msgLen; ++i) { + // std::cout << msg[i] << " " << isalnum(msg[i]) << std::endl; + if(isalnum(msg[i]) or msg[i] == ' ') { + encryptedMsg[i] = AVAILABLE_CHARS[((index(msg[i]) + index(newKey[i])) % AVAILABLE_CHARS.size())]; + } else { + encryptedMsg[i] = msg[i]; + } + } + + encryptedMsg[i] = '\0'; + return encryptedMsg; +} + +std::string decrypt_vigenere(std::string& encryptedMsg, std::string& newKey) { + // decryption + int msgLen = encryptedMsg.size(); + std::string decryptedMsg(msgLen, 'x'); + int i; + for(i = 0; i < msgLen; ++i) { + if(isalnum(encryptedMsg[i]) or encryptedMsg[i] == ' ') { + decryptedMsg[i] = AVAILABLE_CHARS[(((index(encryptedMsg[i]) - index(newKey[i])) + AVAILABLE_CHARS.size()) % AVAILABLE_CHARS.size())]; + } else { + decryptedMsg[i] = encryptedMsg[i]; + } + } + decryptedMsg[i] = '\0'; + return decryptedMsg; +} +