diff --git a/src/Model/ContactItem.cpp b/src/Model/ContactItem.cpp index 589ca9f..b542270 100644 --- a/src/Model/ContactItem.cpp +++ b/src/Model/ContactItem.cpp @@ -19,6 +19,7 @@ ContactItem::ContactItem(QString name, QString partnerAddress, QString myAddress _myAddress = myAddress; _partnerAddress = partnerAddress; _cid = cid; + } ContactItem::ContactItem(QString name, QString partnerAddress, QString myAddress, QString cid, QString avatar) @@ -28,6 +29,7 @@ ContactItem::ContactItem(QString name, QString partnerAddress, QString myAddress _partnerAddress = partnerAddress; _cid = cid; _avatar = avatar; + } QString ContactItem::getName() const diff --git a/src/Model/ContactItem.h b/src/Model/ContactItem.h index 63b4b39..e5e313d 100644 --- a/src/Model/ContactItem.h +++ b/src/Model/ContactItem.h @@ -16,6 +16,7 @@ private: QString _name; QString _cid; QString _avatar; + QString _pubkey; public: ContactItem(); diff --git a/src/chatmodel.cpp b/src/chatmodel.cpp index b033d7e..bc45d8b 100644 --- a/src/chatmodel.cpp +++ b/src/chatmodel.cpp @@ -255,6 +255,11 @@ void ChatModel::addCid(QString tx, QString cid) this->cidMap[tx] = cid; } +void ChatModel::addHeader(QString tx, QString headerbytes) +{ + this->headerMap[tx] = headerbytes; +} + void ChatModel::addrequestZaddr(QString tx, QString requestZaddr) { this->requestZaddrMap[tx] = requestZaddr; @@ -280,6 +285,21 @@ QString ChatModel::getCidByTx(QString tx) return QString("0xdeadbeef"); } +QString ChatModel::getHeaderByTx(QString tx) +{ + for(auto& pair : this->headerMap) + { + + } + + if(this->headerMap.count(tx) > 0) + { + return this->headerMap[tx]; + } + + return QString("0xdeadbeef"); +} + QString ChatModel::getConfirmationByTx(QString tx) { for(auto& pair : this->confirmationsMap) @@ -325,7 +345,7 @@ void ChatModel::killConfirmationCache() this->confirmationsMap.clear(); } -QString MainWindow::createHeaderMemo(QString type, QString cid, QString zaddr, int version=0, int headerNumber=1) +QString MainWindow::createHeaderMemo(QString type, QString cid, QString zaddr, QString headerbytes, QString publickey, int version=0, int headerNumber=1) { QString header=""; @@ -338,6 +358,9 @@ QString MainWindow::createHeaderMemo(QString type, QString cid, QString zaddr, h["z"] = zaddr; // zaddr to respond to h["cid"] = cid; // conversation id h["t"] = type; // Memo or incoming contact request + h["e"] = headerbytes; // Memo or incoming contact request + h["p"] = publickey; // Memo or incoming contact request + j.setObject(h); header = j.toJson(); @@ -346,6 +369,7 @@ QString MainWindow::createHeaderMemo(QString type, QString cid, QString zaddr, } + // Create a Tx from the current state of the Chat page. Tx MainWindow::createTxFromChatPage() { Tx tx; @@ -370,8 +394,7 @@ Tx MainWindow::createTxFromChatPage() { QString type = "Memo"; QString addr = c.getPartnerAddress(); - - QString hmemo= createHeaderMemo(type,cid,myAddr); + /////////User input for chatmemos QString memoplain = ui->memoTxtChat->toPlainText().trimmed(); @@ -390,58 +413,76 @@ Tx MainWindow::createTxFromChatPage() { cidchar = new char[lengthcid+1]; strncpy(cidchar, cid.toLocal8Bit(), lengthcid +1); -//////////////////////////////////////////////////Lets create Alice keys for the conversation/////////////////////////////////// - - /////////////////Alice Pubkey - #define MESSAGEAP ((const unsigned char *) cidchar)///////////static atm, in future we will use the CID here - #define MESSAGEAP_LEN lengthcid + - unsigned char alice_publickey[crypto_box_PUBLICKEYBYTES]; + QString pubkey = "test"; + QString passphrase = this->getPassword(); + QString hashEncryptionKey = passphrase; + int length = hashEncryptionKey.length(); - crypto_generichash(alice_publickey, sizeof alice_publickey, - MESSAGEAP, MESSAGEAP_LEN, - NULL, 0); - QString alice = QString::fromLocal8Bit((char*)alice_publickey); + qDebug()<<"Encryption String :"<(ba2.constData()); - unsigned char alice_secretkey[crypto_box_SECRETKEYBYTES]; + #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw) + #define MESSAGEAS1_LEN length + unsigned char hash[crypto_kx_SEEDBYTES]; - crypto_generichash(alice_secretkey, sizeof alice_secretkey, - MESSAGEAS, MESSAGEAS_LEN, - NULL, 0); + crypto_hash_sha256(hash,MESSAGEAS1, MESSAGEAS1_LEN); - /////////////////Bob Pubkey that Alice creates - #define MESSAGEBAP ((const unsigned char *) "Hallo")///////////static atm, in future we will use the CID here - #define MESSAGEBAP_LEN 5 - unsigned char bob_publickey[crypto_box_PUBLICKEYBYTES]; + unsigned char sk[crypto_kx_SECRETKEYBYTES]; + unsigned char pk[crypto_kx_PUBLICKEYBYTES]; + unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES]; + + if (crypto_kx_seed_keypair(pk,sk, + hash) !=0) { + } + ////////////////Get the pubkey from Bob, so we can create the share key - crypto_generichash(bob_publickey, sizeof bob_publickey, - MESSAGEBAP, MESSAGEBAP_LEN, - NULL, 0); + const QByteArray pubkeyBobArray = QByteArray::fromHex(pubkey.toLatin1()); + const unsigned char *pubkeyBob = reinterpret_cast(pubkeyBobArray.constData()); + /////Create the shared key for sending the message - ////////////Now lets encrypt the message Alice send to Bob////////////////////////////// - #define MESSAGE (const unsigned char *) memoplainchar - #define MESSAGE_LEN lengthmemo - #define CIPHERTEXT_LEN (crypto_box_MACBYTES + MESSAGE_LEN) - unsigned char ciphertext[CIPHERTEXT_LEN]; + if (crypto_kx_server_session_keys(server_rx, server_tx, + pk, sk, pubkeyBob) != 0) { + /* Suspicious client public key, bail out */ + } - //////Encrypt the message. ATM static keys, this will change! - if (crypto_box_easy(ciphertext, MESSAGE, MESSAGE_LEN, alice_publickey, - alice_publickey, alice_publickey) != 0) { - /* error */ - } - /////CIphertext Memo - QString memo = QByteArray(reinterpret_cast(ciphertext), CIPHERTEXT_LEN).toHex(); + + ////////////Now lets encrypt the message Alice send to Bob////////////////////////////// + #define MESSAGE (const unsigned char *) memoplainchar + #define MESSAGE_LEN lengthmemo + #define CIPHERTEXT_LEN (crypto_secretstream_xchacha20poly1305_ABYTES + MESSAGE_LEN) + unsigned char ciphertext[CIPHERTEXT_LEN]; + unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; + + crypto_secretstream_xchacha20poly1305_state state; + + /* Set up a new stream: initialize the state and create the header */ + crypto_secretstream_xchacha20poly1305_init_push(&state, header, server_tx); + + + /* Now, encrypt the first chunk. `c1` will contain an encrypted, + * authenticated representation of `MESSAGE_PART1`. */ + crypto_secretstream_xchacha20poly1305_push + (&state, ciphertext, NULL, MESSAGE, MESSAGE_LEN, NULL, 0, crypto_secretstream_xchacha20poly1305_TAG_FINAL); + + ////Create the HM for this message + QString headerbytes = QByteArray(reinterpret_cast(header), crypto_secretstream_xchacha20poly1305_HEADERBYTES).toHex(); + + QString hmemo= createHeaderMemo(type,cid,myAddr,"",headerbytes); + + /////Ciphertext Memo + QString memo = QByteArray(reinterpret_cast(ciphertext), CIPHERTEXT_LEN).toHex(); - tx.toAddrs.push_back(ToFields{addr, amt, hmemo}); - tx.toAddrs.push_back(ToFields{addr, amt, memo}); + tx.toAddrs.push_back(ToFields{addr, amt, hmemo}); + tx.toAddrs.push_back(ToFields{addr, amt, memo}); @@ -670,6 +711,7 @@ Tx MainWindow::createTxForSafeContactRequest() CAmount totalAmt; QString amtStr = "0"; CAmount amt; + QString headerbytes = ""; amt = CAmount::fromDecimalString("0"); totalAmt = totalAmt + amt; @@ -678,8 +720,38 @@ Tx MainWindow::createTxForSafeContactRequest() QString type = "Cont"; QString addr = contactRequest.getReceiverAddress(); - QString hmemo= createHeaderMemo(type,cid,myAddr); + QString memo = contactRequest.getMemo(); + // QString privkey = rpc->fetchPrivKey(myAddr); + QString passphrase = this->getPassword(); + QString hashEncryptionKey = passphrase; + int length = hashEncryptionKey.length(); + + qDebug()<<"Encryption String :"<(ba2.constData()); + #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw) + #define MESSAGEAS1_LEN length + + + unsigned char hash[crypto_kx_SEEDBYTES]; + + crypto_hash_sha256(hash,MESSAGEAS1, MESSAGEAS1_LEN); + + + unsigned char sk[crypto_kx_SECRETKEYBYTES]; + unsigned char pk[crypto_kx_PUBLICKEYBYTES]; + + if (crypto_kx_seed_keypair(pk,sk, + hash) !=0) { + } + + QString publicKey = QByteArray(reinterpret_cast(pk), crypto_kx_PUBLICKEYBYTES).toHex(); + + QString hmemo= createHeaderMemo(type,cid,myAddr,"", publicKey); tx.toAddrs.push_back(ToFields{addr, amt, hmemo}); diff --git a/src/chatmodel.h b/src/chatmodel.h index 1768b9f..b7203ad 100644 --- a/src/chatmodel.h +++ b/src/chatmodel.h @@ -35,6 +35,7 @@ class ChatModel std::map requestZaddrMap; std::map confirmationsMap; std::map> sendrequestMap; + std::map headerMap; std::map AddressbyLabelMap; public: @@ -52,10 +53,12 @@ class ChatModel void addMessage(ChatItem item); void addMessage(QString timestamp, ChatItem item); void addCid(QString tx, QString cid); + void addHeader(QString tx, QString headerbytes); void addrequestZaddr(QString tx, QString requestZaddr); void addconfirmations(QString tx, int confirmation); void addSendRequest(int i, QString myAddr, QString cid, QString addr ); QString getCidByTx(QString tx); + QString getHeaderByTx(QString tx); QString getrequestZaddrByTx(QString tx); QString getConfirmationByTx(QString tx); QString Addressbylabel(QString addr); diff --git a/src/controller.cpp b/src/controller.cpp index 342a24a..50bcdd6 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -907,27 +907,25 @@ void Controller::refreshTransactions() { this->refresh(true); } - // QString memo1; - QString memo; - QString cid; + QString cid; + QString headerbytes; + QString pubkey; if (!o["memo"].is_null()) { - QString memo = QString::fromStdString(o["memo"].get()); - + memo = QString::fromStdString(o["memo"].get()); + if (memo.startsWith("{")) { QJsonDocument headermemo = QJsonDocument::fromJson(memo.toUtf8()); cid = headermemo["cid"].toString(); - - + headerbytes = headermemo["e"].toString(); - chatModel->addCid(txid, cid); - + chatModel->addCid(txid, cid); + chatModel->addHeader(txid, headerbytes); } - - + bool isNotarized; if (confirmations > getLag()) @@ -942,62 +940,81 @@ void Controller::refreshTransactions() { cid = chatModel->getCidByTx(txid); + }else{ + cid = ""; + } + + + if (chatModel->getHeaderByTx(txid) != QString("0xdeadbeef")){ + + headerbytes = chatModel->getHeaderByTx(txid); + }else{ - cid = ""; + headerbytes = ""; } + qDebug()<<"Headerbytes :"< 0)) + { + /*for (auto &p : AddressBook::getInstance()->getAllAddressLabels()) + { - /////////////////Bob Secretkey + if (p.getPartnerAddress() == address) + { pubkey = p.getPubkey(); + }else {pubkey = ""; + }*/ + + //QString myAddr = p.getMyAddress(); + QString passphrase = main->getPassword(); + QString hashEncryptionKey = passphrase; + int length = hashEncryptionKey.length(); - #define MESSAGEAS ((const unsigned char *) "Hallo")///////////static atm, in future we will use the Passphrase here - #define MESSAGEAS_LEN 5 + qDebug()<<"Encryption String :"<(ba2.constData()); + #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw) + #define MESSAGEAS1_LEN length - /////////////////Bob Pubkey - #define MESSAGEBAP ((const unsigned char *) "Hallo")///////////static atm, in future we will use the CID here - #define MESSAGEBAP_LEN 5 - unsigned char bob_publickey[crypto_box_PUBLICKEYBYTES]; + #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)///////////static atm, in future we will use the Passphrase here + #define MESSAGEAS1_LEN 12 - crypto_generichash(bob_publickey, sizeof bob_publickey, - MESSAGEBAP, MESSAGEBAP_LEN, - NULL, 0); + + unsigned char hash1[crypto_kx_SECRETKEYBYTES]; + crypto_hash_sha256(hash1,MESSAGEAS1, MESSAGEAS1_LEN); + unsigned char sk[crypto_kx_SECRETKEYBYTES]; + unsigned char pk[crypto_kx_PUBLICKEYBYTES]; + + if (crypto_kx_seed_keypair(pk,sk, + hash1) !=0) { - /////We need to filter out Memos smaller then the ciphertext size, or it will dump + } - if ((memo.length() > 120) && (memo.startsWith("{") == false)) - { + unsigned char client_rx[crypto_kx_SESSIONKEYBYTES], client_tx[crypto_kx_SESSIONKEYBYTES]; + - const QByteArray ba = QByteArray::fromHex(memo.toLatin1()); const unsigned char *encryptedMemo = reinterpret_cast(ba.constData()); + const QByteArray ba1 = QByteArray::fromHex(headerbytes.toLatin1()); + const unsigned char *header = reinterpret_cast(ba1.constData()); + int encryptedMemoSize1 = ba.length(); + int headersize = ba1.length(); //////unsigned char* as message from QString #define MESSAGE2 (const unsigned char *) encryptedMemo @@ -1006,20 +1023,25 @@ void Controller::refreshTransactions() { #define CIPHERTEXT1_LEN encryptedMemoSize1 ///////Message length is smaller then the encrypted message - #define MESSAGE1_LEN encryptedMemoSize1 - crypto_box_MACBYTES + #define MESSAGE1_LEN encryptedMemoSize1 - crypto_secretstream_xchacha20poly1305_ABYTES //////Set the length of the decrypted message unsigned char decrypted[MESSAGE1_LEN]; + unsigned char tag[crypto_secretstream_xchacha20poly1305_TAG_FINAL]; + crypto_secretstream_xchacha20poly1305_state state; - ///////Decrypt the message - if (crypto_box_open_easy(decrypted, MESSAGE2, CIPHERTEXT1_LEN, alice_publickey, - alice_publickey, alice_publickey) != 0) { - /* message for Bob pretending to be from Alice has been forged! */ - } - /////Our decrypted message is now in decrypted. We need it as QString to render it /////Only the QString gives weird data, so convert first to std::string + // crypto_secretstream_xchacha20poly1305_keygen(client_rx); + if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, client_rx) != 0) { + /* Invalid header, no need to go any further */ + } + + if (crypto_secretstream_xchacha20poly1305_pull + (&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) { + /* Invalid/incomplete/corrupted ciphertext - abort */ + } std::string decryptedMemo(reinterpret_cast(decrypted),MESSAGE1_LEN); @@ -1047,7 +1069,7 @@ void Controller::refreshTransactions() { DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item); - + // } }else{ @@ -1068,8 +1090,8 @@ void Controller::refreshTransactions() { DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item); } + } - } items.push_back(TransactionItemDetail{address, amount, memo}); total_amount = total_amount + amount; } @@ -1114,6 +1136,8 @@ void Controller::refreshTransactions() { txdata.push_back(tx); QString type; + QString publickey; + QString headerbytes; QString cid; int position; QString requestZaddr; @@ -1149,9 +1173,12 @@ void Controller::refreshTransactions() { cid = headermemo["cid"].toString(); type = headermemo["t"].toString(); requestZaddr = headermemo["z"].toString(); + headerbytes = headermemo["e"].toString(); + publickey = headermemo["p"].toString(); chatModel->addCid(txid, cid); chatModel->addrequestZaddr(txid, requestZaddr); + chatModel->addHeader(txid, headerbytes); } @@ -1169,9 +1196,18 @@ void Controller::refreshTransactions() { requestZaddr = chatModel->getrequestZaddrByTx(txid); }else{ requestZaddr = ""; - } + } + + + if (chatModel->getHeaderByTx(txid) != QString("0xdeadbeef")){ - position = it["position"].get(); + headerbytes = chatModel->getHeaderByTx(txid); + + }else{ + headerbytes = ""; + } + + //position = it["position"].get(); bool isNotarized; @@ -1183,7 +1219,90 @@ void Controller::refreshTransactions() { isNotarized = false; } - ChatItem item = ChatItem( + + int lengthcid = cid.length(); + + char *cidchar = NULL; + cidchar = new char[lengthcid+1]; + strncpy(cidchar, cid.toLocal8Bit(), lengthcid +1); + + if ((memo.startsWith("{") == false) && (headerbytes > 0)) + { + + #define MESSAGEAS ((const unsigned char *) cidchar) + #define MESSAGEAS_LEN lengthcid + + unsigned char hash[crypto_secretstream_xchacha20poly1305_KEYBYTES]; + + crypto_hash_sha256(hash,MESSAGEAS, MESSAGEAS_LEN); + + const QByteArray ba = QByteArray::fromHex(memo.toLatin1()); + const unsigned char *encryptedMemo = reinterpret_cast(ba.constData()); + + const QByteArray ba1 = QByteArray::fromHex(headerbytes.toLatin1()); + const unsigned char *header = reinterpret_cast(ba1.constData()); + + int encryptedMemoSize1 = ba.length(); + int headersize = ba1.length(); + + //////unsigned char* as message from QString + #define MESSAGE2 (const unsigned char *) encryptedMemo + + ///////// length of the encrypted message + #define CIPHERTEXT1_LEN encryptedMemoSize1 + + ///////Message length is smaller then the encrypted message + #define MESSAGE1_LEN encryptedMemoSize1 - crypto_secretstream_xchacha20poly1305_ABYTES + + //////Set the length of the decrypted message + + unsigned char decrypted[MESSAGE1_LEN]; + unsigned char tag[crypto_secretstream_xchacha20poly1305_TAG_FINAL]; + crypto_secretstream_xchacha20poly1305_state state; + + /////Our decrypted message is now in decrypted. We need it as QString to render it + /////Only the QString gives weird data, so convert first to std::string + + if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, hash) != 0) { + /* Invalid header, no need to go any further */ + } + + if (crypto_secretstream_xchacha20poly1305_pull + (&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) { + /* Invalid/incomplete/corrupted ciphertext - abort */ + } + + std::string decryptedMemo(reinterpret_cast(decrypted),MESSAGE1_LEN); + + /////Now we can convert it to QString + QString memodecrypt = QString::fromUtf8( decryptedMemo.data(), decryptedMemo.size()); + + //////////////Give us the output of the decrypted message as debug to see if it was successfully + qDebug()<<"OUT decrypt:" << memodecrypt; + + + ChatItem item = ChatItem( + datetime, + address, + QString(""), + memodecrypt, + requestZaddr, + type, + cid, + txid, + confirmations, + false, + isNotarized, + isContact + ); + DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item); + + + + }else{ + + + ChatItem item = ChatItem( datetime, address, QString(""), @@ -1197,9 +1316,10 @@ void Controller::refreshTransactions() { isNotarized, isContact ); - - DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item); - } + DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item); + + } + } } } } diff --git a/src/mainwindow.h b/src/mainwindow.h index 56bfbc6..815fd84 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -90,7 +90,7 @@ public: void doClose(); void doClosePw(); - QString createHeaderMemo(QString type, QString cid, QString zaddr, int version, int headerNumber); + QString createHeaderMemo(QString type, QString cid, QString zaddr,QString headerbytes,QString publickey, int version, int headerNumber); public slots: void slot_change_theme(const QString& themeName);