Allow temp secrets for connections
This commit is contained in:
@@ -127,6 +127,8 @@ void MainWindow::closeEvent(QCloseEvent* event) {
|
|||||||
s.setValue("baltablegeometry", ui->balancesTable->horizontalHeader()->saveState());
|
s.setValue("baltablegeometry", ui->balancesTable->horizontalHeader()->saveState());
|
||||||
s.setValue("tratablegeometry", ui->transactionsTable->horizontalHeader()->saveState());
|
s.setValue("tratablegeometry", ui->transactionsTable->horizontalHeader()->saveState());
|
||||||
|
|
||||||
|
s.sync();
|
||||||
|
|
||||||
// Let the RPC know to shut down any running service.
|
// Let the RPC know to shut down any running service.
|
||||||
rpc->shutdownZcashd();
|
rpc->shutdownZcashd();
|
||||||
|
|
||||||
|
|||||||
@@ -83,8 +83,12 @@ QString AppDataServer::getSecretHex() {
|
|||||||
void AppDataServer::saveNewSecret(QString secretHex) {
|
void AppDataServer::saveNewSecret(QString secretHex) {
|
||||||
QSettings s;
|
QSettings s;
|
||||||
s.setValue("mobileapp/secret", secretHex);
|
s.setValue("mobileapp/secret", secretHex);
|
||||||
|
|
||||||
|
s.sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString AppDataServer::tempSecret;
|
||||||
|
|
||||||
void AppDataServer::connectAppDialog(QWidget* parent) {
|
void AppDataServer::connectAppDialog(QWidget* parent) {
|
||||||
QDialog d(parent);
|
QDialog d(parent);
|
||||||
Ui_MobileAppConnector con;
|
Ui_MobileAppConnector con;
|
||||||
@@ -115,26 +119,23 @@ void AppDataServer::connectAppDialog(QWidget* parent) {
|
|||||||
char* secretHex = new char[crypto_secretbox_KEYBYTES*2 + 1];
|
char* secretHex = new char[crypto_secretbox_KEYBYTES*2 + 1];
|
||||||
sodium_bin2hex(secretHex, crypto_secretbox_KEYBYTES*2+1, secretBin, crypto_secretbox_KEYBYTES);
|
sodium_bin2hex(secretHex, crypto_secretbox_KEYBYTES*2+1, secretBin, crypto_secretbox_KEYBYTES);
|
||||||
|
|
||||||
saveNewSecret(secretHex);
|
|
||||||
|
|
||||||
QString secretStr(secretHex);
|
QString secretStr(secretHex);
|
||||||
|
tempSecret = secretStr;
|
||||||
|
|
||||||
QString codeStr = uri + "," + secretHex;
|
QString codeStr = uri + "," + secretStr;
|
||||||
|
|
||||||
con.lblConnStr->setText(codeStr);
|
con.lblConnStr->setText(codeStr);
|
||||||
con.qrcode->setQrcodeString(codeStr);
|
con.qrcode->setQrcodeString(codeStr);
|
||||||
con.lblRemoteNonce->setText(AppDataServer::getNonceHex(NonceType::REMOTE));
|
con.lblRemoteNonce->setText(AppDataServer::getNonceHex(NonceType::REMOTE));
|
||||||
con.lblLocalNonce->setText(AppDataServer::getNonceHex(NonceType::LOCAL));
|
con.lblLocalNonce->setText(AppDataServer::getNonceHex(NonceType::LOCAL));
|
||||||
|
|
||||||
AppDataServer::saveNonceHex(NonceType::REMOTE, QString("00").repeated(24));
|
|
||||||
AppDataServer::saveNonceHex(NonceType::LOCAL, QString("00").repeated(24));
|
|
||||||
|
|
||||||
QObject::connect(con.btnDisconnect, &QPushButton::clicked, [=]() {
|
QObject::connect(con.btnDisconnect, &QPushButton::clicked, [=]() {
|
||||||
AppDataServer::saveNonceHex(NonceType::REMOTE, QString("00").repeated(24));
|
AppDataServer::saveNonceHex(NonceType::REMOTE, QString("00").repeated(24));
|
||||||
AppDataServer::saveNonceHex(NonceType::LOCAL, QString("00").repeated(24));
|
AppDataServer::saveNonceHex(NonceType::LOCAL, QString("00").repeated(24));
|
||||||
});
|
});
|
||||||
|
|
||||||
d.exec();
|
d.exec();
|
||||||
|
tempSecret = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AppDataServer::getNonceHex(NonceType nt) {
|
QString AppDataServer::getNonceHex(NonceType nt) {
|
||||||
@@ -158,6 +159,7 @@ void AppDataServer::saveNonceHex(NonceType nt, QString noncehex) {
|
|||||||
else {
|
else {
|
||||||
s.setValue("mobileapp/remotenonce", noncehex);
|
s.setValue("mobileapp/remotenonce", noncehex);
|
||||||
}
|
}
|
||||||
|
s.sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AppDataServer::encryptOutgoing(QString msg) {
|
QString AppDataServer::encryptOutgoing(QString msg) {
|
||||||
@@ -212,7 +214,7 @@ QString AppDataServer::encryptOutgoing(QString msg) {
|
|||||||
return json.toJson();
|
return json.toJson();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AppDataServer::decryptMessage(QJsonDocument msg, QString secretHex) {
|
QString AppDataServer::decryptMessage(QJsonDocument msg, QString secretHex, bool skipNonceCheck) {
|
||||||
// Decrypt and then process
|
// Decrypt and then process
|
||||||
QString noncehex = msg.object().value("nonce").toString();
|
QString noncehex = msg.object().value("nonce").toString();
|
||||||
QString encryptedhex = msg.object().value("payload").toString();
|
QString encryptedhex = msg.object().value("payload").toString();
|
||||||
@@ -227,8 +229,15 @@ QString AppDataServer::decryptMessage(QJsonDocument msg, QString secretHex) {
|
|||||||
sodium_hex2bin(noncebin, crypto_secretbox_NONCEBYTES, noncehex.toStdString().c_str(), noncehex.length(),
|
sodium_hex2bin(noncebin, crypto_secretbox_NONCEBYTES, noncehex.toStdString().c_str(), noncehex.length(),
|
||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL);
|
||||||
|
|
||||||
assert(sodium_compare(lastRemoteBin, noncebin, crypto_secretbox_NONCEBYTES) == -1);
|
|
||||||
assert(crypto_secretbox_KEYBYTES == crypto_hash_sha256_BYTES);
|
assert(crypto_secretbox_KEYBYTES == crypto_hash_sha256_BYTES);
|
||||||
|
if (!skipNonceCheck) {
|
||||||
|
if (sodium_compare(lastRemoteBin, noncebin, crypto_secretbox_NONCEBYTES) != -1) {
|
||||||
|
// Refuse to accept a lower nonce, return an error
|
||||||
|
delete[] lastRemoteBin;
|
||||||
|
delete[] noncebin;
|
||||||
|
return "error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update the last seem remote hex
|
// Update the last seem remote hex
|
||||||
saveNonceHex(NonceType::REMOTE, noncehex);
|
saveNonceHex(NonceType::REMOTE, noncehex);
|
||||||
@@ -248,7 +257,6 @@ QString AppDataServer::decryptMessage(QJsonDocument msg, QString secretHex) {
|
|||||||
QString payload;
|
QString payload;
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
payload = "error";
|
payload = "error";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
char* decryptedStr = new char[decryptedLen + 1];
|
char* decryptedStr = new char[decryptedLen + 1];
|
||||||
sodium_memzero(decryptedStr, decryptedLen + 1);
|
sodium_memzero(decryptedStr, decryptedLen + 1);
|
||||||
@@ -280,14 +288,42 @@ void AppDataServer::processMessage(QString message, MainWindow* mainWindow, QWeb
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto decrypted = decryptMessage(msg, getSecretHex());
|
auto decrypted = decryptMessage(msg, getSecretHex());
|
||||||
if (decrypted == "error") {
|
|
||||||
// If the dialog is open, then there might be a temporary, new secret key. Attempt to decrypt
|
// If the decryption failed, maybe this is a new connection, so see if the dialog is open and a
|
||||||
// with that.
|
// temp secret is in place
|
||||||
|
|
||||||
|
auto replyWithError = [=]() {
|
||||||
auto r = QJsonDocument(QJsonObject{
|
auto r = QJsonDocument(QJsonObject{
|
||||||
{"error", "Encrption error"}
|
{"error", "Encryption error"}
|
||||||
}).toJson();
|
}).toJson();
|
||||||
pClient->sendTextMessage(r);
|
pClient->sendTextMessage(r);
|
||||||
return;
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (decrypted == "error") {
|
||||||
|
// If the dialog is open, then there might be a temporary, new secret key. Attempt to decrypt
|
||||||
|
// with that.
|
||||||
|
if (!tempSecret.isEmpty()) {
|
||||||
|
decrypted = decryptMessage(msg, tempSecret, true);
|
||||||
|
if (decrypted == "error") {
|
||||||
|
// Oh, well. Just return an error
|
||||||
|
replyWithError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// This is a new connection. So, update the nonces and the secret
|
||||||
|
saveNewSecret(tempSecret);
|
||||||
|
AppDataServer::saveNonceHex(NonceType::REMOTE, QString("00").repeated(24));
|
||||||
|
AppDataServer::saveNonceHex(NonceType::LOCAL, QString("00").repeated(24));
|
||||||
|
|
||||||
|
// Fall through to processDecryptedMessage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
replyWithError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
processDecryptedMessage(decrypted, mainWindow, pClient);
|
processDecryptedMessage(decrypted, mainWindow, pClient);
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public:
|
|||||||
static void processGetInfo(MainWindow* mainWindow, QWebSocket* pClient);
|
static void processGetInfo(MainWindow* mainWindow, QWebSocket* pClient);
|
||||||
static void processGetTransactions(MainWindow* mainWindow, QWebSocket* pClient);
|
static void processGetTransactions(MainWindow* mainWindow, QWebSocket* pClient);
|
||||||
|
|
||||||
static QString decryptMessage(QJsonDocument msg, QString secretHex);
|
static QString decryptMessage(QJsonDocument msg, QString secretHex, bool skipNonceCheck = false);
|
||||||
static QString encryptOutgoing(QString msg);
|
static QString encryptOutgoing(QString msg);
|
||||||
|
|
||||||
static QString getSecretHex();
|
static QString getSecretHex();
|
||||||
@@ -54,6 +54,9 @@ public:
|
|||||||
|
|
||||||
static QString getNonceHex(NonceType nt);
|
static QString getNonceHex(NonceType nt);
|
||||||
static void saveNonceHex(NonceType nt, QString noncehex);
|
static void saveNonceHex(NonceType nt, QString noncehex);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static QString tempSecret;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AppDataModel {
|
class AppDataModel {
|
||||||
|
|||||||
Reference in New Issue
Block a user