diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 5170a41a..99d14685 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -103,18 +103,15 @@ Page { id: deviceVerificationDialog DeviceVerification {} } - Component{ - id: deviceVerificationFlow - DeviceVerificationFlow {} - } Connections { target: timelineManager onNewDeviceVerificationRequest: { - var newFlow = deviceVerificationFlow.createObject(timelineRoot, - {userId : userId,sender: false,deviceId : deviceId,tranId:transactionId}); - deviceVerificationList.add(newFlow.tranId); + flow.userId = userId; + flow.sender = false; + flow.deviceId = deviceId; + flow.tranId = transactionId; var dialog = deviceVerificationDialog.createObject(timelineRoot, - {flow: newFlow,sender: false}); + {flow: flow,sender: false}); dialog.show(); } } diff --git a/resources/qml/device-verification/DeviceVerification.qml b/resources/qml/device-verification/DeviceVerification.qml index ad0edeb7..316fbe40 100644 --- a/resources/qml/device-verification/DeviceVerification.qml +++ b/resources/qml/device-verification/DeviceVerification.qml @@ -78,7 +78,7 @@ ApplicationWindow { onClicked: { dialog.close(); flow.cancelVerification(); - deviceVerificationList.remove(flow.tranId); + // deviceVerificationList.remove(flow.tranId); delete flow; } } @@ -135,7 +135,7 @@ ApplicationWindow { onClicked: { dialog.close(); flow.cancelVerification(); - deviceVerificationList.remove(flow.tranId); + // deviceVerificationList.remove(flow.tranId); delete flow; } } @@ -179,7 +179,7 @@ ApplicationWindow { onClicked: { dialog.close(); flow.cancelVerification(); - deviceVerificationList.remove(flow.tranId); + // deviceVerificationList.remove(flow.tranId); delete flow; } } @@ -211,15 +211,15 @@ ApplicationWindow { Layout.alignment: Qt.AlignHCenter Label { font.pixelSize: Qt.application.font.pixelSize * 2 - text: "1234" + text: flow.sasList[0] } Label { font.pixelSize: Qt.application.font.pixelSize * 2 - text: "1234" + text: flow.sasList[1] } Label { font.pixelSize: Qt.application.font.pixelSize * 2 - text: "1234" + text: flow.sasList[2] } } @@ -230,7 +230,7 @@ ApplicationWindow { onClicked: { dialog.close(); flow.cancelVerification(); - deviceVerificationList.remove(flow.tranId); + // deviceVerificationList.remove(flow.tranId); delete flow; } } @@ -345,7 +345,7 @@ ApplicationWindow { ColumnLayout { id: col anchors.bottom: parent.bottom - property var emoji: emojis.mapping[Math.floor(Math.random()*64)] + property var emoji: emojis.mapping[flow.sasList[index]] Label { //height: font.pixelSize * 2 Layout.alignment: Qt.AlignHCenter @@ -369,7 +369,7 @@ ApplicationWindow { onClicked: { dialog.close(); flow.cancelVerification(); - deviceVerificationList.remove(flow.tranId); + // deviceVerificationList.remove(flow.tranId); delete flow; } } @@ -413,7 +413,7 @@ ApplicationWindow { onClicked: { dialog.close(); flow.cancelVerification(); - deviceVerificationList.remove(flow.tranId); + // deviceVerificationList.remove(flow.tranId); delete flow; } } @@ -451,7 +451,7 @@ ApplicationWindow { text: "Close" onClicked: { dialog.close() - deviceVerificationList.remove(flow.tranId); + // deviceVerificationList.remove(flow.tranId); delete flow; } } @@ -486,7 +486,7 @@ ApplicationWindow { text: "Close" onClicked: { dialog.close() - deviceVerificationList.remove(flow.tranId); + // deviceVerificationList.remove(flow.tranId); delete flow; } } @@ -521,7 +521,7 @@ ApplicationWindow { text: "Close" onClicked: { dialog.close() - deviceVerificationList.remove(flow.tranId); + // deviceVerificationList.remove(flow.tranId); delete flow; } } diff --git a/src/DeviceVerificationFlow.cpp b/src/DeviceVerificationFlow.cpp index efb9882b..607cc279 100644 --- a/src/DeviceVerificationFlow.cpp +++ b/src/DeviceVerificationFlow.cpp @@ -15,32 +15,80 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *) { timeout = new QTimer(this); timeout->setSingleShot(true); - if (this->sender == true) - this->transaction_id = http::client()->generate_txn_id(); + this->sas = olm::client()->sas_init(); connect(timeout, &QTimer::timeout, this, [this]() { emit timedout(); this->deleteLater(); }); + connect(ChatPage::instance(), - &ChatPage::recievedDeviceVerificationAccept, - this, - [this](const mtx::events::collections::DeviceEvents &message) { - auto msg = - std::get>(message); - if (msg.content.transaction_id == this->transaction_id) { - std::cout << "Recieved Event Accept" << std::endl; - } - }); - connect(ChatPage::instance(), - &ChatPage::recievedDeviceVerificationRequest, + &ChatPage::recievedDeviceVerificationStart, this, [this](const mtx::events::collections::DeviceEvents &message) { auto msg = - std::get>(message); + std::get>(message); if (msg.content.transaction_id == this->transaction_id) { - std::cout << "Recieved Event Request" << std::endl; + if (std::find(msg.content.key_agreement_protocols.begin(), + msg.content.key_agreement_protocols.end(), + "curve25519-hkdf-sha256") != + msg.content.key_agreement_protocols.end() && + std::find(msg.content.hashes.begin(), + msg.content.hashes.end(), + "sha256") != msg.content.hashes.end() && + (std::find(msg.content.message_authentication_codes.begin(), + msg.content.message_authentication_codes.end(), + "hmac-sha256") != + msg.content.message_authentication_codes.end() || + std::find(msg.content.message_authentication_codes.begin(), + msg.content.message_authentication_codes.end(), + "hkdf-hmac-sha256") != + msg.content.message_authentication_codes.end()) && + (std::find(msg.content.short_authentication_string.begin(), + msg.content.short_authentication_string.end(), + mtx::events::msg::SASMethods::Decimal) != + msg.content.short_authentication_string.end() || + std::find(msg.content.short_authentication_string.begin(), + msg.content.short_authentication_string.end(), + mtx::events::msg::SASMethods::Emoji) != + msg.content.short_authentication_string.end())) { + this->sendVerificationKey(); // Not sure about this maybe + // those optional methods + this->canonical_json = nlohmann::json(msg); + } else { + this->cancelVerification(); + } } }); + connect( + ChatPage::instance(), + &ChatPage::recievedDeviceVerificationAccept, + this, + [this](const mtx::events::collections::DeviceEvents &message) { + auto msg = + std::get>(message); + if (msg.content.transaction_id == this->transaction_id) { + if ((msg.content.method == + mtx::events::msg::VerificationMethods::SASv1) && + (msg.content.key_agreement_protocol == "curve25519-hkdf-sha256") && + (msg.content.hash == "sha256") && + ((msg.content.message_authentication_code == "hkdf-hmac-sha256") || + (msg.content.message_authentication_code == "hmac-sha256"))) { + this->commitment = msg.content.commitment; + if (std::find(msg.content.short_authentication_string.begin(), + msg.content.short_authentication_string.end(), + mtx::events::msg::SASMethods::Emoji) != + msg.content.short_authentication_string.end()) { + this->method = DeviceVerificationFlow::Method::Emoji; + } else { + this->method = DeviceVerificationFlow::Method::Decimal; + } + this->mac_method = msg.content.message_authentication_code; + this->sendVerificationKey(); + } else { + this->cancelVerification(); + } + } + }); connect(ChatPage::instance(), &ChatPage::recievedDeviceVerificationCancel, this, @@ -48,19 +96,55 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *) auto msg = std::get>(message); if (msg.content.transaction_id == this->transaction_id) { - std::cout << "Recieved Event Cancel" << std::endl; - } - }); - connect(ChatPage::instance(), - &ChatPage::recievedDeviceVerificationKey, - this, - [this](const mtx::events::collections::DeviceEvents &message) { - auto msg = - std::get>(message); - if (msg.content.transaction_id == this->transaction_id) { - std::cout << "Recieved Event Key" << std::endl; + emit verificationCanceled(); } }); + connect( + ChatPage::instance(), + &ChatPage::recievedDeviceVerificationKey, + this, + [this](const mtx::events::collections::DeviceEvents &message) { + auto msg = std::get>(message); + if (msg.content.transaction_id == this->transaction_id) { + this->sas->set_their_key(msg.content.key); + std::string info; + if (this->sender == true) { + info = "MATRIX_KEY_VERIFICATION_SAS|" + + http::client()->user_id().to_string() + "|" + + http::client()->device_id() + "|" + + this->sas->public_key() + "|" + + this->toClient.to_string() + "|" + + this->deviceId.toStdString() + "|" + msg.content.key + + "|" + this->transaction_id; + } else { + info = "MATRIX_KEY_VERIFICATION_SAS|" + + this->toClient.to_string() + "|" + + this->deviceId.toStdString() + "|" + msg.content.key + + "|" + http::client()->user_id().to_string() + "|" + + http::client()->device_id() + "|" + + this->sas->public_key() + "|" + this->transaction_id; + } + + if (this->method == DeviceVerificationFlow::Method::Emoji) { + this->sasList = this->sas->generate_bytes_emoji(info); + } else if (this->method == DeviceVerificationFlow::Method::Decimal) { + this->sasList = this->sas->generate_bytes_decimal(info); + } + if (this->sender == false) { + emit this->verificationRequestAccepted(this->method); + this->sendVerificationKey(); + } else { + if (this->commitment == + mtx::crypto::bin2base64_unpadded(mtx::crypto::sha256( + msg.content.key + + this->canonical_json["content"].dump()))) { + emit this->verificationRequestAccepted(this->method); + } else { + this->cancelVerification(); + } + } + } + }); connect(ChatPage::instance(), &ChatPage::recievedDeviceVerificationMac, this, @@ -104,6 +188,12 @@ DeviceVerificationFlow::getSender() return this->sender; } +std::vector +DeviceVerificationFlow::getSasList() +{ + return this->sasList; +} + void DeviceVerificationFlow::setTransactionId(QString transaction_id_) { @@ -133,6 +223,8 @@ void DeviceVerificationFlow::setSender(bool sender_) { this->sender = sender_; + if (this->sender == true) + this->transaction_id = http::client()->generate_txn_id(); } //! accepts a verification @@ -147,23 +239,26 @@ DeviceVerificationFlow::acceptVerificationRequest() req.key_agreement_protocol = "curve25519-hkdf-sha256"; req.hash = "sha256"; req.message_authentication_code = "hkdf-hmac-sha256"; - req.short_authentication_string = {mtx::events::msg::SASMethods::Decimal, - mtx::events::msg::SASMethods::Emoji}; - req.commitment = ""; - - emit this->verificationRequestAccepted(this->method); + if (this->method == DeviceVerificationFlow::Method::Emoji) + req.short_authentication_string = {mtx::events::msg::SASMethods::Emoji}; + else if (this->method == DeviceVerificationFlow::Method::Decimal) + req.short_authentication_string = {mtx::events::msg::SASMethods::Decimal}; + req.commitment = mtx::crypto::bin2base64_unpadded( + mtx::crypto::sha256(this->sas->public_key() + this->canonical_json.dump())); body[this->toClient][this->deviceId.toStdString()] = req; + std::cout << "Accepting the Verification" << std::endl; + std::cout << json(body) << std::endl; + http::client() ->send_to_device( - this->transaction_id, body, [this](mtx::http::RequestErr err) { + this->transaction_id, body, [](mtx::http::RequestErr err) { if (err) nhlog::net()->warn("failed to accept verification request: {} {}", err->matrix_error.error, static_cast(err->status_code)); - emit this->verificationRequestAccepted(rand() % 2 ? Emoji : Decimal); }); } //! starts the verification flow @@ -183,6 +278,7 @@ DeviceVerificationFlow::startVerificationRequest() mtx::events::msg::SASMethods::Emoji}; body[this->toClient][this->deviceId.toStdString()] = req; + this->canonical_json = nlohmann::json(req); http::client() ->send_to_devicewarn("failed to start verification request: {} {}", err->matrix_error.error, static_cast(err->status_code)); - std::cout << nlohmann::json(body).dump(2) << std::endl; }); } //! sends a verification request @@ -236,6 +331,8 @@ DeviceVerificationFlow::cancelVerification() body[this->toClient][deviceId.toStdString()] = req; + emit this->verificationCanceled(); + http::client() ->send_to_device( @@ -254,7 +351,7 @@ DeviceVerificationFlow::sendVerificationKey() mtx::requests::ToDeviceMessages body; mtx::events::msg::KeyVerificationKey req; - req.key = ""; + req.key = this->sas->public_key(); req.transaction_id = this->transaction_id; body[this->toClient][deviceId.toStdString()] = req; diff --git a/src/DeviceVerificationFlow.h b/src/DeviceVerificationFlow.h index b651394b..bddf8edd 100644 --- a/src/DeviceVerificationFlow.h +++ b/src/DeviceVerificationFlow.h @@ -7,6 +7,8 @@ class QTimer; +using sas_ptr = std::unique_ptr; + class DeviceVerificationFlow : public QObject { Q_OBJECT @@ -16,6 +18,7 @@ class DeviceVerificationFlow : public QObject Q_PROPERTY(QString userId READ getUserId WRITE setUserId) Q_PROPERTY(QString deviceId READ getDeviceId WRITE setDeviceId) Q_PROPERTY(Method method READ getMethod WRITE setMethod) + Q_PROPERTY(std::vector sasList READ getSasList) public: enum Method @@ -30,6 +33,7 @@ public: QString getUserId(); QString getDeviceId(); Method getMethod(); + std::vector getSasList(); void setTransactionId(QString transaction_id_); bool getSender(); void setUserId(QString userID); @@ -37,6 +41,8 @@ public: void setMethod(Method method_); void setSender(bool sender_); + nlohmann::json canonical_json; + public slots: //! sends a verification request void sendVerificationRequest(); @@ -66,6 +72,10 @@ private: bool sender; QTimer *timeout = nullptr; + sas_ptr sas; + std::string mac_method; std::string transaction_id; + std::string commitment; mtx::identifiers::User toClient; + std::vector sasList; }; diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 22fe4d6d..aaefaed4 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -170,32 +170,44 @@ TimelineViewManager::TimelineViewManager(QSharedPointer userSettin &ChatPage::decryptSidebarChanged, this, &TimelineViewManager::updateEncryptedDescriptions); - connect(dynamic_cast(parent), - &ChatPage::recievedDeviceVerificationRequest, - this, - [this](const mtx::events::collections::DeviceEvents &message) { - auto msg = - std::get>(message); - QString tranID = QString::fromStdString(msg.content.transaction_id); - QString deviceId = QString::fromStdString(msg.content.from_device); - QString userId = QString::fromStdString(msg.sender); - if (!(this->dvList->exist(tranID))) { - emit newDeviceVerificationRequest(tranID, userId, deviceId); - } - }); - connect(dynamic_cast(parent), - &ChatPage::recievedDeviceVerificationStart, - this, - [this](const mtx::events::collections::DeviceEvents &message) { - auto msg = - std::get>(message); - QString tranID = QString::fromStdString(msg.content.transaction_id); - QString deviceId = QString::fromStdString(msg.content.from_device); - QString userId = QString::fromStdString(msg.sender); - if (!(this->dvList->exist(tranID))) { - emit newDeviceVerificationRequest(tranID, userId, deviceId); - } - }); + connect( + dynamic_cast(parent), + &ChatPage::recievedDeviceVerificationRequest, + this, + [this](const mtx::events::collections::DeviceEvents &message) { + auto msg = + std::get>(message); + auto flow = new DeviceVerificationFlow(this); + if (!(this->dvList->exist(QString::fromStdString(msg.content.transaction_id)))) { + if (std::find(msg.content.methods.begin(), + msg.content.methods.end(), + mtx::events::msg::VerificationMethods::SASv1) != + msg.content.methods.end()) { + emit newDeviceVerificationRequest( + std::move(flow), + QString::fromStdString(msg.content.transaction_id), + QString::fromStdString(msg.sender), + QString::fromStdString(msg.content.from_device)); + } + } + }); + connect( + dynamic_cast(parent), + &ChatPage::recievedDeviceVerificationStart, + this, + [this](const mtx::events::collections::DeviceEvents &message) { + auto msg = + std::get>(message); + auto flow = new DeviceVerificationFlow(this); + flow->canonical_json = nlohmann::json(msg.content); + if (!(this->dvList->exist(QString::fromStdString(msg.content.transaction_id)))) { + emit newDeviceVerificationRequest( + std::move(flow), + QString::fromStdString(msg.content.transaction_id), + QString::fromStdString(msg.sender), + QString::fromStdString(msg.content.from_device)); + } + }); } void diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 70912715..946461f9 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -67,7 +67,10 @@ signals: void initialSyncChanged(bool isInitialSync); void replyingEventChanged(QString replyingEvent); void replyClosed(); - void newDeviceVerificationRequest(QString transactionId, QString userId, QString deviceId); + void newDeviceVerificationRequest(DeviceVerificationFlow *flow, + QString transactionId, + QString userId, + QString deviceId); public slots: void updateReadReceipts(const QString &room_id, const std::vector &event_ids);