Merge pull request #88 from DenioD/encryption
Message encryption for HushChat
This commit is contained in:
@@ -60,7 +60,8 @@ std::map<QString, ChatItem> ChatDataStore::getAllNewContactRequests()
|
|||||||
if (
|
if (
|
||||||
(c.second.isOutgoing() == false) &&
|
(c.second.isOutgoing() == false) &&
|
||||||
(c.second.getType() == "Cont") &&
|
(c.second.getType() == "Cont") &&
|
||||||
(c.second.isContact() == false)
|
(c.second.isContact() == false) &&
|
||||||
|
(c.second.getMemo().isEmpty())
|
||||||
)
|
)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ ContactItem::ContactItem(QString name, QString partnerAddress, QString myAddress
|
|||||||
_myAddress = myAddress;
|
_myAddress = myAddress;
|
||||||
_partnerAddress = partnerAddress;
|
_partnerAddress = partnerAddress;
|
||||||
_cid = cid;
|
_cid = cid;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactItem::ContactItem(QString name, QString partnerAddress, QString myAddress, QString cid, QString avatar)
|
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;
|
_partnerAddress = partnerAddress;
|
||||||
_cid = cid;
|
_cid = cid;
|
||||||
_avatar = avatar;
|
_avatar = avatar;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ContactItem::getName() const
|
QString ContactItem::getName() const
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ private:
|
|||||||
QString _name;
|
QString _name;
|
||||||
QString _cid;
|
QString _cid;
|
||||||
QString _avatar;
|
QString _avatar;
|
||||||
|
QString _pubkey;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ContactItem();
|
ContactItem();
|
||||||
|
|||||||
@@ -392,7 +392,7 @@ void AddressBook::readFromStorage()
|
|||||||
QDataStream in(&file); // read the data serialized from the file
|
QDataStream in(&file); // read the data serialized from the file
|
||||||
QString version;
|
QString version;
|
||||||
in >> version;
|
in >> version;
|
||||||
qDebug() << "Detected old addressbook format";
|
// qDebug() << "Detected old addressbook format";
|
||||||
// Convert old addressbook format v1 to v2
|
// Convert old addressbook format v1 to v2
|
||||||
QList<QList<QString>> stuff;
|
QList<QList<QString>> stuff;
|
||||||
in >> stuff;
|
in >> stuff;
|
||||||
@@ -408,7 +408,7 @@ void AddressBook::readFromStorage()
|
|||||||
allLabels.push_back(contact);
|
allLabels.push_back(contact);
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Read " << version << " Hush contacts from disk...";
|
// qDebug() << "Read " << version << " Hush contacts from disk...";
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -255,6 +255,13 @@ void ChatModel::addCid(QString tx, QString cid)
|
|||||||
this->cidMap[tx] = cid;
|
this->cidMap[tx] = cid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatModel::addHeader(QString tx, QString headerbytes)
|
||||||
|
{
|
||||||
|
this->headerMap[tx] = headerbytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ChatModel::addrequestZaddr(QString tx, QString requestZaddr)
|
void ChatModel::addrequestZaddr(QString tx, QString requestZaddr)
|
||||||
{
|
{
|
||||||
this->requestZaddrMap[tx] = requestZaddr;
|
this->requestZaddrMap[tx] = requestZaddr;
|
||||||
@@ -280,6 +287,24 @@ QString ChatModel::getCidByTx(QString tx)
|
|||||||
return QString("0xdeadbeef");
|
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)
|
QString ChatModel::getConfirmationByTx(QString tx)
|
||||||
{
|
{
|
||||||
for(auto& pair : this->confirmationsMap)
|
for(auto& pair : this->confirmationsMap)
|
||||||
@@ -325,7 +350,7 @@ void ChatModel::killConfirmationCache()
|
|||||||
this->confirmationsMap.clear();
|
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="";
|
QString header="";
|
||||||
@@ -338,6 +363,9 @@ QString MainWindow::createHeaderMemo(QString type, QString cid, QString zaddr,
|
|||||||
h["z"] = zaddr; // zaddr to respond to
|
h["z"] = zaddr; // zaddr to respond to
|
||||||
h["cid"] = cid; // conversation id
|
h["cid"] = cid; // conversation id
|
||||||
h["t"] = type; // Memo or incoming contact request
|
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);
|
j.setObject(h);
|
||||||
header = j.toJson();
|
header = j.toJson();
|
||||||
@@ -346,6 +374,7 @@ QString MainWindow::createHeaderMemo(QString type, QString cid, QString zaddr,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create a Tx from the current state of the Chat page.
|
// Create a Tx from the current state of the Chat page.
|
||||||
Tx MainWindow::createTxFromChatPage() {
|
Tx MainWindow::createTxFromChatPage() {
|
||||||
Tx tx;
|
Tx tx;
|
||||||
@@ -371,11 +400,98 @@ Tx MainWindow::createTxFromChatPage() {
|
|||||||
QString addr = c.getPartnerAddress();
|
QString addr = c.getPartnerAddress();
|
||||||
|
|
||||||
|
|
||||||
QString hmemo= createHeaderMemo(type,cid,myAddr);
|
|
||||||
QString memo = ui->memoTxtChat->toPlainText().trimmed();
|
|
||||||
|
|
||||||
tx.toAddrs.push_back(ToFields{addr, amt, hmemo});
|
/////////User input for chatmemos
|
||||||
tx.toAddrs.push_back(ToFields{addr, amt, memo});
|
QString memoplain = ui->memoTxtChat->toPlainText().trimmed();
|
||||||
|
|
||||||
|
/////////We convert the user input from QString to unsigned char*, so we can encrypt it later
|
||||||
|
int lengthmemo = memoplain.length();
|
||||||
|
|
||||||
|
char *memoplainchar = NULL;
|
||||||
|
memoplainchar = new char[lengthmemo+1];
|
||||||
|
strncpy(memoplainchar, memoplain.toLocal8Bit(), lengthmemo +1);
|
||||||
|
|
||||||
|
/////////We convert the CID from QString to unsigned char*, so we can encrypt it later
|
||||||
|
int lengthcid = cid.length();
|
||||||
|
|
||||||
|
char *cidchar = NULL;
|
||||||
|
cidchar = new char[lengthcid+1];
|
||||||
|
strncpy(cidchar, cid.toLocal8Bit(), lengthcid +1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
QString pubkey = this->getPubkeyByAddress(addr);
|
||||||
|
QString passphrase = this->getPassword();
|
||||||
|
QString hashEncryptionKey = passphrase;
|
||||||
|
int length = hashEncryptionKey.length();
|
||||||
|
|
||||||
|
qDebug()<<"Pubkey Erstellung :"<<pubkey;
|
||||||
|
|
||||||
|
////////////////Generate the secretkey for our message encryption
|
||||||
|
|
||||||
|
char *hashEncryptionKeyraw = NULL;
|
||||||
|
hashEncryptionKeyraw = new char[length+1];
|
||||||
|
strncpy(hashEncryptionKeyraw, hashEncryptionKey.toLocal8Bit(), length +1);
|
||||||
|
|
||||||
|
#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];
|
||||||
|
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
|
||||||
|
|
||||||
|
const QByteArray pubkeyBobArray = QByteArray::fromHex(pubkey.toLatin1());
|
||||||
|
const unsigned char *pubkeyBob = reinterpret_cast<const unsigned char *>(pubkeyBobArray.constData());
|
||||||
|
/////Create the shared key for sending the message
|
||||||
|
|
||||||
|
if (crypto_kx_server_session_keys(server_rx, server_tx,
|
||||||
|
pk, sk, pubkeyBob) != 0) {
|
||||||
|
/* Suspicious client public key, bail out */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////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<const char*>(header), crypto_secretstream_xchacha20poly1305_HEADERBYTES).toHex();
|
||||||
|
QString publickeyAlice = QByteArray(reinterpret_cast<const char*>(pk), crypto_kx_PUBLICKEYBYTES).toHex();
|
||||||
|
|
||||||
|
qDebug()<<"Headerbyte erstellung : "<<headerbytes;
|
||||||
|
|
||||||
|
QString hmemo= createHeaderMemo(type,cid,myAddr,headerbytes,publickeyAlice);
|
||||||
|
|
||||||
|
/////Ciphertext Memo
|
||||||
|
QString memo = QByteArray(reinterpret_cast<const char*>(ciphertext), CIPHERTEXT_LEN).toHex();
|
||||||
|
|
||||||
|
|
||||||
|
tx.toAddrs.push_back(ToFields{addr, amt, hmemo});
|
||||||
|
tx.toAddrs.push_back(ToFields{addr, amt, memo});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -604,6 +720,7 @@ Tx MainWindow::createTxForSafeContactRequest()
|
|||||||
CAmount totalAmt;
|
CAmount totalAmt;
|
||||||
QString amtStr = "0";
|
QString amtStr = "0";
|
||||||
CAmount amt;
|
CAmount amt;
|
||||||
|
QString headerbytes = "";
|
||||||
amt = CAmount::fromDecimalString("0");
|
amt = CAmount::fromDecimalString("0");
|
||||||
totalAmt = totalAmt + amt;
|
totalAmt = totalAmt + amt;
|
||||||
|
|
||||||
@@ -612,8 +729,40 @@ Tx MainWindow::createTxForSafeContactRequest()
|
|||||||
QString type = "Cont";
|
QString type = "Cont";
|
||||||
QString addr = contactRequest.getReceiverAddress();
|
QString addr = contactRequest.getReceiverAddress();
|
||||||
|
|
||||||
QString hmemo= createHeaderMemo(type,cid,myAddr);
|
|
||||||
QString memo = contactRequest.getMemo();
|
QString memo = contactRequest.getMemo();
|
||||||
|
// QString privkey = rpc->fetchPrivKey(myAddr);
|
||||||
|
QString passphrase = this->getPassword();
|
||||||
|
QString hashEncryptionKey = passphrase;
|
||||||
|
int length = hashEncryptionKey.length();
|
||||||
|
|
||||||
|
qDebug()<<"Encryption String :"<<hashEncryptionKey;
|
||||||
|
|
||||||
|
////////////////Generate the secretkey for our message encryption
|
||||||
|
char *hashEncryptionKeyraw = NULL;
|
||||||
|
hashEncryptionKeyraw = new char[length+1];
|
||||||
|
strncpy(hashEncryptionKeyraw, hashEncryptionKey.toLocal8Bit(), length +1);
|
||||||
|
#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<const char*>(pk), crypto_kx_PUBLICKEYBYTES).toHex();
|
||||||
|
|
||||||
|
qDebug()<<"Publickey created Request: "<<publicKey;
|
||||||
|
|
||||||
|
QString hmemo= createHeaderMemo(type,cid,myAddr,"", publicKey);
|
||||||
|
|
||||||
|
|
||||||
tx.toAddrs.push_back(ToFields{addr, amt, hmemo});
|
tx.toAddrs.push_back(ToFields{addr, amt, hmemo});
|
||||||
|
|||||||
@@ -35,8 +35,10 @@ class ChatModel
|
|||||||
std::map<QString, QString> requestZaddrMap;
|
std::map<QString, QString> requestZaddrMap;
|
||||||
std::map<QString, QString> confirmationsMap;
|
std::map<QString, QString> confirmationsMap;
|
||||||
std::map<int, std::tuple<QString, QString, QString>> sendrequestMap;
|
std::map<int, std::tuple<QString, QString, QString>> sendrequestMap;
|
||||||
|
std::map<QString, QString> headerMap;
|
||||||
std::map<QString, QString> AddressbyLabelMap;
|
std::map<QString, QString> AddressbyLabelMap;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ChatModel() {};
|
ChatModel() {};
|
||||||
ChatModel(std::map<QString, ChatItem> chatItems);
|
ChatModel(std::map<QString, ChatItem> chatItems);
|
||||||
@@ -52,10 +54,12 @@ class ChatModel
|
|||||||
void addMessage(ChatItem item);
|
void addMessage(ChatItem item);
|
||||||
void addMessage(QString timestamp, ChatItem item);
|
void addMessage(QString timestamp, ChatItem item);
|
||||||
void addCid(QString tx, QString cid);
|
void addCid(QString tx, QString cid);
|
||||||
|
void addHeader(QString tx, QString headerbytes);
|
||||||
void addrequestZaddr(QString tx, QString requestZaddr);
|
void addrequestZaddr(QString tx, QString requestZaddr);
|
||||||
void addconfirmations(QString tx, int confirmation);
|
void addconfirmations(QString tx, int confirmation);
|
||||||
void addSendRequest(int i, QString myAddr, QString cid, QString addr );
|
void addSendRequest(int i, QString myAddr, QString cid, QString addr );
|
||||||
QString getCidByTx(QString tx);
|
QString getCidByTx(QString tx);
|
||||||
|
QString getHeaderByTx(QString tx);
|
||||||
QString getrequestZaddrByTx(QString tx);
|
QString getrequestZaddrByTx(QString tx);
|
||||||
QString getConfirmationByTx(QString tx);
|
QString getConfirmationByTx(QString tx);
|
||||||
QString Addressbylabel(QString addr);
|
QString Addressbylabel(QString addr);
|
||||||
|
|||||||
@@ -908,10 +908,24 @@ void Controller::refreshTransactions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString memo;
|
QString memo;
|
||||||
|
QString cid;
|
||||||
|
QString headerbytes;
|
||||||
|
QString publickey;
|
||||||
if (!o["memo"].is_null()) {
|
if (!o["memo"].is_null()) {
|
||||||
memo = QString::fromStdString(o["memo"]);
|
memo = QString::fromStdString(o["memo"].get<json::string_t>());
|
||||||
|
|
||||||
|
if (memo.startsWith("{")) {
|
||||||
|
|
||||||
|
QJsonDocument headermemo = QJsonDocument::fromJson(memo.toUtf8());
|
||||||
|
|
||||||
|
cid = headermemo["cid"].toString();
|
||||||
|
headerbytes = headermemo["e"].toString();
|
||||||
|
|
||||||
|
chatModel->addCid(txid, cid);
|
||||||
|
chatModel->addHeader(txid, headerbytes);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
QString cid;
|
|
||||||
bool isNotarized;
|
bool isNotarized;
|
||||||
|
|
||||||
if (confirmations > getLag())
|
if (confirmations > getLag())
|
||||||
@@ -922,7 +936,163 @@ void Controller::refreshTransactions() {
|
|||||||
isNotarized = false;
|
isNotarized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatItem item = ChatItem(
|
if (chatModel->getCidByTx(txid) != QString("0xdeadbeef")){
|
||||||
|
|
||||||
|
cid = chatModel->getCidByTx(txid);
|
||||||
|
|
||||||
|
}else{
|
||||||
|
cid = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (chatModel->getHeaderByTx(txid) != QString("0xdeadbeef")){
|
||||||
|
|
||||||
|
headerbytes = chatModel->getHeaderByTx(txid);
|
||||||
|
|
||||||
|
|
||||||
|
}else{
|
||||||
|
headerbytes = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (main->getPubkeyByAddress(address) != QString("0xdeadbeef")){
|
||||||
|
|
||||||
|
publickey = main->getPubkeyByAddress(address);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}else{
|
||||||
|
publickey = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/////We need to filter out Memos smaller then the ciphertext size, or it will dump
|
||||||
|
|
||||||
|
if ((memo.startsWith("{") == false) && (headerbytes > 0))
|
||||||
|
{
|
||||||
|
|
||||||
|
QString passphrase = main->getPassword();
|
||||||
|
QString hashEncryptionKey = passphrase;
|
||||||
|
int length = hashEncryptionKey.length();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////Generate the secretkey for our message encryption
|
||||||
|
|
||||||
|
char *hashEncryptionKeyraw = NULL;
|
||||||
|
hashEncryptionKeyraw = new char[length+1];
|
||||||
|
strncpy(hashEncryptionKeyraw, hashEncryptionKey.toLocal8Bit(), length +1);
|
||||||
|
|
||||||
|
const QByteArray pubkeyBobArray = QByteArray::fromHex(publickey.toLatin1());
|
||||||
|
const unsigned char *pubkeyBob = reinterpret_cast<const unsigned char *>(pubkeyBobArray.constData());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)///////////
|
||||||
|
#define MESSAGEAS1_LEN length
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char hash1[crypto_kx_SEEDBYTES];
|
||||||
|
|
||||||
|
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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES];
|
||||||
|
|
||||||
|
|
||||||
|
////////////////Get the pubkey from Bob, so we can create the share key
|
||||||
|
|
||||||
|
|
||||||
|
/////Create the shared key for sending the message
|
||||||
|
|
||||||
|
if (crypto_kx_server_session_keys(server_rx, server_tx,
|
||||||
|
pk, sk, pubkeyBob) != 0) {
|
||||||
|
/* Suspicious client public key, bail out */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const QByteArray ba = QByteArray::fromHex(memo.toLatin1());
|
||||||
|
const unsigned char *encryptedMemo = reinterpret_cast<const unsigned char *>(ba.constData());
|
||||||
|
|
||||||
|
const QByteArray ba1 = QByteArray::fromHex(headerbytes.toLatin1());
|
||||||
|
const unsigned char *header = reinterpret_cast<const unsigned char *>(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
|
||||||
|
// crypto_secretstream_xchacha20poly1305_keygen(client_rx);
|
||||||
|
if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, server_tx) != 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<char*>(decrypted),MESSAGE1_LEN);
|
||||||
|
QString memodecrypt;
|
||||||
|
/////Now we can convert it to QString
|
||||||
|
if (ui->decryptionMessage->isChecked()){
|
||||||
|
memodecrypt = QString::fromUtf8( decryptedMemo.data(), decryptedMemo.size());
|
||||||
|
DataStore::getChatDataStore()->clear();
|
||||||
|
// this->refresh(true);
|
||||||
|
chat->renderChatBox(ui, ui->listChat,ui->memoSizeChat);
|
||||||
|
}else{ memodecrypt = memo;
|
||||||
|
DataStore::getChatDataStore()->clear();
|
||||||
|
// this->refresh(true);
|
||||||
|
chat->renderChatBox(ui, ui->listChat,ui->memoSizeChat);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////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,
|
||||||
|
QString(""),
|
||||||
|
QString(""),
|
||||||
|
cid,
|
||||||
|
txid,
|
||||||
|
confirmations,
|
||||||
|
true,
|
||||||
|
isNotarized,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
|
||||||
|
|
||||||
|
updateUIBalances();
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
|
||||||
|
ChatItem item = ChatItem(
|
||||||
datetime,
|
datetime,
|
||||||
address,
|
address,
|
||||||
QString(""),
|
QString(""),
|
||||||
@@ -937,11 +1107,9 @@ void Controller::refreshTransactions() {
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
|
DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
|
||||||
|
updateUIBalances();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
items.push_back(TransactionItemDetail{address, amount, memo});
|
items.push_back(TransactionItemDetail{address, amount, memo});
|
||||||
total_amount = total_amount + amount;
|
total_amount = total_amount + amount;
|
||||||
@@ -969,7 +1137,6 @@ void Controller::refreshTransactions() {
|
|||||||
model->markAddressUsed(address);
|
model->markAddressUsed(address);
|
||||||
|
|
||||||
QString memo;
|
QString memo;
|
||||||
QString test;
|
|
||||||
if (!it["memo"].is_null()) {
|
if (!it["memo"].is_null()) {
|
||||||
memo = QString::fromStdString(it["memo"]);
|
memo = QString::fromStdString(it["memo"]);
|
||||||
}
|
}
|
||||||
@@ -987,6 +1154,8 @@ void Controller::refreshTransactions() {
|
|||||||
txdata.push_back(tx);
|
txdata.push_back(tx);
|
||||||
|
|
||||||
QString type;
|
QString type;
|
||||||
|
QString publickey;
|
||||||
|
QString headerbytes;
|
||||||
QString cid;
|
QString cid;
|
||||||
int position;
|
int position;
|
||||||
QString requestZaddr;
|
QString requestZaddr;
|
||||||
@@ -1002,7 +1171,7 @@ void Controller::refreshTransactions() {
|
|||||||
chatModel->addAddressbylabel(address, requestZaddr);
|
chatModel->addAddressbylabel(address, requestZaddr);
|
||||||
} else{}
|
} else{}
|
||||||
|
|
||||||
|
}
|
||||||
if (chatModel->Addressbylabel(address) != QString("0xdeadbeef")){
|
if (chatModel->Addressbylabel(address) != QString("0xdeadbeef")){
|
||||||
|
|
||||||
isContact = true;
|
isContact = true;
|
||||||
@@ -1022,10 +1191,18 @@ void Controller::refreshTransactions() {
|
|||||||
cid = headermemo["cid"].toString();
|
cid = headermemo["cid"].toString();
|
||||||
type = headermemo["t"].toString();
|
type = headermemo["t"].toString();
|
||||||
requestZaddr = headermemo["z"].toString();
|
requestZaddr = headermemo["z"].toString();
|
||||||
|
headerbytes = headermemo["e"].toString();
|
||||||
|
publickey = headermemo["p"].toString();
|
||||||
|
|
||||||
chatModel->addCid(txid, cid);
|
chatModel->addCid(txid, cid);
|
||||||
chatModel->addrequestZaddr(txid, requestZaddr);
|
chatModel->addrequestZaddr(txid, requestZaddr);
|
||||||
|
chatModel->addHeader(txid, headerbytes);
|
||||||
|
|
||||||
|
if (publickey.length() > 10){
|
||||||
|
main->addPubkey(requestZaddr, publickey);
|
||||||
|
}
|
||||||
|
qDebug()<<"Scane HM Incoming:";
|
||||||
|
qDebug()<<"Scane HM Incoming:"<<publickey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1044,7 +1221,26 @@ void Controller::refreshTransactions() {
|
|||||||
requestZaddr = "";
|
requestZaddr = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
position = it["position"].get<json::number_integer_t>();
|
|
||||||
|
if (chatModel->getHeaderByTx(txid) != QString("0xdeadbeef")){
|
||||||
|
|
||||||
|
headerbytes = chatModel->getHeaderByTx(txid);
|
||||||
|
|
||||||
|
|
||||||
|
}else{
|
||||||
|
headerbytes = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (main->getPubkeyByAddress(requestZaddr) != QString("0xdeadbeef")){
|
||||||
|
|
||||||
|
publickey = main->getPubkeyByAddress(requestZaddr);
|
||||||
|
|
||||||
|
|
||||||
|
}else{
|
||||||
|
publickey = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
//position = it["position"].get<json::number_integer_t>();
|
||||||
|
|
||||||
bool isNotarized;
|
bool isNotarized;
|
||||||
|
|
||||||
@@ -1056,7 +1252,143 @@ void Controller::refreshTransactions() {
|
|||||||
isNotarized = false;
|
isNotarized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatItem item = ChatItem(
|
|
||||||
|
qDebug()<<"Kurz vor decryption:";
|
||||||
|
|
||||||
|
if ((memo.startsWith("{") == false) && (headerbytes > 20))
|
||||||
|
{
|
||||||
|
|
||||||
|
int lengthcid = cid.length();
|
||||||
|
QString passphrase = main->getPassword();
|
||||||
|
QString hashEncryptionKey = passphrase;
|
||||||
|
int length = hashEncryptionKey.length();
|
||||||
|
|
||||||
|
qDebug()<<"Encryption passphrase :"<<hashEncryptionKey;
|
||||||
|
|
||||||
|
char *hashEncryptionKeyraw = NULL;
|
||||||
|
hashEncryptionKeyraw = new char[length+1];
|
||||||
|
strncpy(hashEncryptionKeyraw, hashEncryptionKey.toLocal8Bit(), length +1);
|
||||||
|
|
||||||
|
//const QByteArray ba2 = QByteArray::fromHex(hashEncryptionKey.toLatin1());
|
||||||
|
// const unsigned char *hashEncryptionKeyraw = reinterpret_cast<const unsigned char *>(ba2.constData());
|
||||||
|
|
||||||
|
const QByteArray pubkeyBobArray = QByteArray::fromHex(publickey.toLatin1());
|
||||||
|
const unsigned char *pubkeyBob = reinterpret_cast<const unsigned char *>(pubkeyBobArray.constData());
|
||||||
|
|
||||||
|
|
||||||
|
#define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)///////////
|
||||||
|
#define MESSAGEAS1_LEN length
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char hash1[crypto_kx_SEEDBYTES];
|
||||||
|
|
||||||
|
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) {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
unsigned char client_rx[crypto_kx_SESSIONKEYBYTES], client_tx[crypto_kx_SESSIONKEYBYTES];
|
||||||
|
|
||||||
|
|
||||||
|
////////////////Get the pubkey from Bob, so we can create the share key
|
||||||
|
|
||||||
|
|
||||||
|
/////Create the shared key for sending the message
|
||||||
|
|
||||||
|
if (crypto_kx_client_session_keys(client_rx, client_tx,
|
||||||
|
pk, sk, pubkeyBob) != 0) {
|
||||||
|
/* Suspicious client public key, bail out */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const QByteArray ba = QByteArray::fromHex(memo.toLatin1());
|
||||||
|
const unsigned char *encryptedMemo = reinterpret_cast<const unsigned char *>(ba.constData());
|
||||||
|
|
||||||
|
const QByteArray ba1 = QByteArray::fromHex(headerbytes.toLatin1());
|
||||||
|
const unsigned char *header = reinterpret_cast<const unsigned char *>(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
|
||||||
|
// 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<char*>(decrypted),MESSAGE1_LEN);
|
||||||
|
|
||||||
|
/////Now we can convert it to QString
|
||||||
|
QString memodecrypt;
|
||||||
|
if (ui->decryptionMessage->isChecked()){
|
||||||
|
memodecrypt = QString::fromUtf8( decryptedMemo.data(), decryptedMemo.size());
|
||||||
|
DataStore::getChatDataStore()->clear();
|
||||||
|
// this->refresh(true);
|
||||||
|
chat->renderChatBox(ui, ui->listChat,ui->memoSizeChat);
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
memodecrypt = memo;
|
||||||
|
DataStore::getChatDataStore()->clear();
|
||||||
|
//this->refresh(true);
|
||||||
|
chat->renderChatBox(ui, ui->listChat,ui->memoSizeChat);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// }
|
||||||
|
//////////////Give us the output of the decrypted message as debug to see if it was successfully
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ChatItem item = ChatItem(
|
||||||
|
datetime,
|
||||||
|
address,
|
||||||
|
QString(""),
|
||||||
|
memodecrypt,
|
||||||
|
requestZaddr,
|
||||||
|
type,
|
||||||
|
cid,
|
||||||
|
txid,
|
||||||
|
confirmations,
|
||||||
|
false,
|
||||||
|
isNotarized,
|
||||||
|
isContact
|
||||||
|
);
|
||||||
|
DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
|
||||||
|
|
||||||
|
qDebug()<<"Pushe decrypte Items:";
|
||||||
|
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
qDebug()<<"Pushe plain Items 1:";
|
||||||
|
ChatItem item = ChatItem(
|
||||||
datetime,
|
datetime,
|
||||||
address,
|
address,
|
||||||
QString(""),
|
QString(""),
|
||||||
@@ -1070,12 +1402,16 @@ void Controller::refreshTransactions() {
|
|||||||
isNotarized,
|
isNotarized,
|
||||||
isContact
|
isContact
|
||||||
);
|
);
|
||||||
|
DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
|
||||||
|
|
||||||
DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
|
qDebug()<<"Pushe Plain items 2:";
|
||||||
}
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the total unspent amount that's pending. This will need to be
|
// Calculate the total unspent amount that's pending. This will need to be
|
||||||
// shown in the UI so the user can keep track of pending funds
|
// shown in the UI so the user can keep track of pending funds
|
||||||
@@ -1087,7 +1423,8 @@ void Controller::refreshTransactions() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getModel()->setTotalPending(totalPending);
|
|
||||||
|
getModel()->setTotalPending(totalPending);
|
||||||
|
|
||||||
// Update UI Balance
|
// Update UI Balance
|
||||||
updateUIBalances();
|
updateUIBalances();
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ public:
|
|||||||
void refreshGBPCAP();
|
void refreshGBPCAP();
|
||||||
void refreshAUDCAP();
|
void refreshAUDCAP();
|
||||||
|
|
||||||
|
|
||||||
void refreshChat(QListView *listWidget, QLabel *label);
|
void refreshChat(QListView *listWidget, QLabel *label);
|
||||||
void refreshContacts(QListView *listWidget);
|
void refreshContacts(QListView *listWidget);
|
||||||
|
|
||||||
|
|||||||
@@ -1062,6 +1062,26 @@ void MainWindow::exportSeed() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::addPubkey(QString requestZaddr, QString pubkey)
|
||||||
|
{
|
||||||
|
this->pubkeyMap[requestZaddr] = pubkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString MainWindow::getPubkeyByAddress(QString requestZaddr)
|
||||||
|
{
|
||||||
|
for(auto& pair : this->pubkeyMap)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->pubkeyMap.count(requestZaddr) > 0)
|
||||||
|
{
|
||||||
|
return this->pubkeyMap[requestZaddr];
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString("0xdeadbeef");
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::exportAllKeys() {
|
void MainWindow::exportAllKeys() {
|
||||||
exportKeys("");
|
exportKeys("");
|
||||||
}
|
}
|
||||||
@@ -1338,6 +1358,8 @@ void MainWindow::setupchatTab() {
|
|||||||
ui->memoTxtChat->setTextColor("Black");
|
ui->memoTxtChat->setTextColor("Black");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui->decryptionMessage->setChecked(true);
|
||||||
|
|
||||||
QObject::connect(ui->sendChatButton, &QPushButton::clicked, this, &MainWindow::sendChat);
|
QObject::connect(ui->sendChatButton, &QPushButton::clicked, this, &MainWindow::sendChat);
|
||||||
QObject::connect(ui->safeContactRequest, &QPushButton::clicked, this, &MainWindow::addContact);
|
QObject::connect(ui->safeContactRequest, &QPushButton::clicked, this, &MainWindow::addContact);
|
||||||
QObject::connect(ui->pushContact, &QPushButton::clicked, this , &MainWindow::renderContactRequest);
|
QObject::connect(ui->pushContact, &QPushButton::clicked, this , &MainWindow::renderContactRequest);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class Controller;
|
|||||||
class Settings;
|
class Settings;
|
||||||
class WSServer;
|
class WSServer;
|
||||||
class WormholeClient;
|
class WormholeClient;
|
||||||
|
class ChatModel;
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
@@ -52,7 +53,11 @@ public:
|
|||||||
QString doSendRequestTxValidations(Tx tx);
|
QString doSendRequestTxValidations(Tx tx);
|
||||||
QString getCid();
|
QString getCid();
|
||||||
QString getPassword();
|
QString getPassword();
|
||||||
|
std::map<QString, QString> pubkeyMap;
|
||||||
|
QString getPubkeyByAddress(QString requestZaddr);
|
||||||
void setPassword(QString Password);
|
void setPassword(QString Password);
|
||||||
|
void addPubkey(QString requestZaddr, QString pubkey);
|
||||||
|
|
||||||
|
|
||||||
void replaceWormholeClient(WormholeClient* newClient);
|
void replaceWormholeClient(WormholeClient* newClient);
|
||||||
bool isWebsocketListening();
|
bool isWebsocketListening();
|
||||||
@@ -90,7 +95,7 @@ public:
|
|||||||
|
|
||||||
void doClose();
|
void doClose();
|
||||||
void doClosePw();
|
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:
|
public slots:
|
||||||
void slot_change_theme(const QString& themeName);
|
void slot_change_theme(const QString& themeName);
|
||||||
|
|||||||
@@ -1703,6 +1703,19 @@
|
|||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QCheckBox" name="decryptionMessage">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>900</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>281</width>
|
||||||
|
<height>23</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Message encryption/decryption ON</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
<zorder>listContactWidget</zorder>
|
<zorder>listContactWidget</zorder>
|
||||||
<zorder>label_39</zorder>
|
<zorder>label_39</zorder>
|
||||||
<zorder>contactNameMemo</zorder>
|
<zorder>contactNameMemo</zorder>
|
||||||
@@ -1714,6 +1727,7 @@
|
|||||||
<zorder>listChat</zorder>
|
<zorder>listChat</zorder>
|
||||||
<zorder>memoTxtChat</zorder>
|
<zorder>memoTxtChat</zorder>
|
||||||
<zorder>sendChatButton</zorder>
|
<zorder>sendChatButton</zorder>
|
||||||
|
<zorder>decryptionMessage</zorder>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
Reference in New Issue
Block a user