diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 27c1745..d3e0842 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -562,6 +562,7 @@ void MainWindow::connectApp() { QObject::connect(con.btnDisconnect, &QPushButton::clicked, [=]() { AppDataServer::saveNonceHex(NonceType::REMOTE, QString("00").repeated(24)); + AppDataServer::saveNonceHex(NonceType::LOCAL, QString("00").repeated(24)); }); d.exec(); diff --git a/src/websockets.cpp b/src/websockets.cpp index e9e583d..fb7e9e1 100644 --- a/src/websockets.cpp +++ b/src/websockets.cpp @@ -45,7 +45,7 @@ void WSServer::processTextMessage(QString message) if (pClient) { auto json = AppDataServer::processMessage(message, m_mainWindow); if (!json.isEmpty()) - pClient->sendTextMessage(json.toJson()); + pClient->sendTextMessage(AppDataServer::encryptOutgoing(json.toJson())); } } @@ -100,59 +100,104 @@ void AppDataServer::saveNonceHex(NonceType nt, QString noncehex) { } } -QJsonDocument AppDataServer::processMessage(QString message, MainWindow* mainWindow) { - // First, extract the command from the message - auto msg = QJsonDocument::fromJson(message.toUtf8()); +QString AppDataServer::encryptOutgoing(QString msg) { + QString localNonceHex = getNonceHex(NonceType::LOCAL); - // First check if the message is encrpted - if (msg.object().contains("nonce")) { - // Decrypt and then process - QString noncehex = msg.object().value("nonce").toString(); - QString encryptedhex = msg.object().value("payload").toString(); + unsigned char* noncebin = new unsigned char[crypto_secretbox_NONCEBYTES]; + sodium_hex2bin(noncebin, crypto_secretbox_NONCEBYTES, localNonceHex.toStdString().c_str(), localNonceHex.length(), + NULL, NULL, NULL); + + // Increment the nonce +2 and save + sodium_increment(noncebin, crypto_secretbox_NONCEBYTES); + sodium_increment(noncebin, crypto_secretbox_NONCEBYTES); + + char* newLocalNonce = new char[crypto_secretbox_NONCEBYTES*2 + 1]; + sodium_memzero(newLocalNonce, crypto_secretbox_NONCEBYTES*2 + 1); + sodium_bin2hex(newLocalNonce, crypto_secretbox_NONCEBYTES*2+1, noncebin, crypto_box_NONCEBYTES); - // Check to make sure that the nonce is greater than the last known remote nonce - QString lastRemoteHex = getNonceHex(NonceType::REMOTE); - unsigned char* lastRemoteBin = new unsigned char[crypto_secretbox_NONCEBYTES]; - sodium_hex2bin(lastRemoteBin, crypto_secretbox_NONCEBYTES, lastRemoteHex.toStdString().c_str(), lastRemoteHex.length(), - NULL, NULL, NULL); + qDebug() << "Local nonce was " << localNonceHex << " now is " << QString(newLocalNonce); + saveNonceHex(NonceType::LOCAL, QString(newLocalNonce)); - unsigned char* noncebin = new unsigned char[crypto_secretbox_NONCEBYTES]; - sodium_hex2bin(noncebin, crypto_secretbox_NONCEBYTES, noncehex.toStdString().c_str(), noncehex.length(), - NULL, NULL, NULL); + unsigned char* secret = new unsigned char[crypto_secretbox_KEYBYTES]; + crypto_hash_sha256(secret, (const unsigned char*)"secret", QString("secret").length()); - assert(sodium_compare(lastRemoteBin, noncebin, crypto_secretbox_NONCEBYTES) == -1); - assert(crypto_secretbox_KEYBYTES == crypto_hash_sha256_BYTES); + int msgSize = strlen(msg.toStdString().c_str()); + unsigned char* encrpyted = new unsigned char[ msgSize + crypto_secretbox_MACBYTES]; + + crypto_secretbox_easy(encrpyted, (const unsigned char *)msg.toStdString().c_str(), msgSize, noncebin, secret); + + int encryptedHexSize = (msgSize + crypto_secretbox_MACBYTES) * 2 + 1; + char * encryptedHex = new char[encryptedHexSize]; + sodium_memzero(encryptedHex, encryptedHexSize); + sodium_bin2hex(encryptedHex, encryptedHexSize, encrpyted, msgSize + crypto_secretbox_MACBYTES); + + qDebug() << "Encrypted to " << QString(encryptedHex); + + auto json = QJsonDocument(QJsonObject{ + {"nonce", QString(newLocalNonce)}, + {"payload", QString(encryptedHex)} + }); + + return json.toJson(); +} - // Update the last seem remote hex - saveNonceHex(NonceType::REMOTE, noncehex); +QString AppDataServer::decryptMessage(QJsonDocument msg) { + // Decrypt and then process + QString noncehex = msg.object().value("nonce").toString(); + QString encryptedhex = msg.object().value("payload").toString(); - unsigned char* secret = new unsigned char[crypto_secretbox_KEYBYTES]; - crypto_hash_sha256(secret, (const unsigned char*)"secret", QString("secret").length()); + // Check to make sure that the nonce is greater than the last known remote nonce + QString lastRemoteHex = getNonceHex(NonceType::REMOTE); + unsigned char* lastRemoteBin = new unsigned char[crypto_secretbox_NONCEBYTES]; + sodium_hex2bin(lastRemoteBin, crypto_secretbox_NONCEBYTES, lastRemoteHex.toStdString().c_str(), lastRemoteHex.length(), + NULL, NULL, NULL); - unsigned char* encrypted = new unsigned char[encryptedhex.length() / 2]; - sodium_hex2bin(encrypted, encryptedhex.length() / 2, encryptedhex.toStdString().c_str(), encryptedhex.length(), - NULL, NULL, NULL); + unsigned char* noncebin = new unsigned char[crypto_secretbox_NONCEBYTES]; + sodium_hex2bin(noncebin, crypto_secretbox_NONCEBYTES, noncehex.toStdString().c_str(), noncehex.length(), + NULL, NULL, NULL); - int decryptedLen = encryptedhex.length() / 2 - crypto_secretbox_MACBYTES; - unsigned char* decrypted = new unsigned char[decryptedLen]; - crypto_secretbox_open_easy(decrypted, encrypted, encryptedhex.length() / 2, noncebin, secret); + assert(sodium_compare(lastRemoteBin, noncebin, crypto_secretbox_NONCEBYTES) == -1); + assert(crypto_secretbox_KEYBYTES == crypto_hash_sha256_BYTES); - char* decryptedStr = new char[decryptedLen + 1]; - sodium_memzero(decryptedStr, decryptedLen + 1); - memcpy(decryptedStr, decrypted, decryptedLen); + // Update the last seem remote hex + saveNonceHex(NonceType::REMOTE, noncehex); - QString payload = QString(decryptedStr); + unsigned char* secret = new unsigned char[crypto_secretbox_KEYBYTES]; + crypto_hash_sha256(secret, (const unsigned char*)"secret", QString("secret").length()); - qDebug() << "Decrypted to: " << payload; + unsigned char* encrypted = new unsigned char[encryptedhex.length() / 2]; + sodium_hex2bin(encrypted, encryptedhex.length() / 2, encryptedhex.toStdString().c_str(), encryptedhex.length(), + NULL, NULL, NULL); - delete[] secret; - delete[] lastRemoteBin; - delete[] noncebin; - delete[] encrypted; - delete[] decrypted; - delete[] decryptedStr; - - return processMessage(payload, mainWindow); + int decryptedLen = encryptedhex.length() / 2 - crypto_secretbox_MACBYTES; + unsigned char* decrypted = new unsigned char[decryptedLen]; + crypto_secretbox_open_easy(decrypted, encrypted, encryptedhex.length() / 2, noncebin, secret); + + char* decryptedStr = new char[decryptedLen + 1]; + sodium_memzero(decryptedStr, decryptedLen + 1); + memcpy(decryptedStr, decrypted, decryptedLen); + + QString payload = QString(decryptedStr); + + qDebug() << "Decrypted to: " << payload; + + delete[] secret; + delete[] lastRemoteBin; + delete[] noncebin; + delete[] encrypted; + delete[] decrypted; + delete[] decryptedStr; + + return payload; +} + +QJsonDocument AppDataServer::processMessage(QString message, MainWindow* mainWindow) { + // First, extract the command from the message + auto msg = QJsonDocument::fromJson(message.toUtf8()); + + // First check if the message is encrpted + if (msg.object().contains("nonce")) { + return processMessage(decryptMessage(msg), mainWindow); } if (!msg.object().contains("command")) { @@ -305,4 +350,4 @@ QJsonDocument AppDataServer::processGetTransactions(MainWindow* mainWindow) { // ============================== // AppDataModel // ============================== -AppDataModel* AppDataModel::instance = NULL; \ No newline at end of file +AppDataModel* AppDataModel::instance = NULL; diff --git a/src/websockets.h b/src/websockets.h index a168f27..f3e1b84 100644 --- a/src/websockets.h +++ b/src/websockets.h @@ -42,6 +42,10 @@ public: static QJsonDocument processMessage(QString message, MainWindow* mainWindow); static QJsonDocument processGetInfo(MainWindow* mainWindow); static QJsonDocument processGetTransactions(MainWindow* mainWindow); + + static QString decryptMessage(QJsonDocument msg); + static QString encryptOutgoing(QString msg); + static QString getSecretHex(); static QString getNonceHex(NonceType nt); static void saveNonceHex(NonceType nt, QString noncehex);