mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 11:00:48 +03:00
Add download keys from secret storage
This commit is contained in:
parent
9d2177afe2
commit
994c28ea95
4 changed files with 131 additions and 1 deletions
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QImageReader>
|
#include <QImageReader>
|
||||||
|
#include <QInputDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QShortcut>
|
#include <QShortcut>
|
||||||
|
@ -64,6 +65,8 @@ constexpr size_t MAX_ONETIME_KEYS = 50;
|
||||||
Q_DECLARE_METATYPE(std::optional<mtx::crypto::EncryptedFile>)
|
Q_DECLARE_METATYPE(std::optional<mtx::crypto::EncryptedFile>)
|
||||||
Q_DECLARE_METATYPE(std::optional<RelatedInfo>)
|
Q_DECLARE_METATYPE(std::optional<RelatedInfo>)
|
||||||
Q_DECLARE_METATYPE(mtx::presence::PresenceState)
|
Q_DECLARE_METATYPE(mtx::presence::PresenceState)
|
||||||
|
Q_DECLARE_METATYPE(mtx::secret_storage::AesHmacSha2KeyDescription)
|
||||||
|
Q_DECLARE_METATYPE(SecretsToDecrypt)
|
||||||
|
|
||||||
ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
|
@ -79,6 +82,8 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
qRegisterMetaType<std::optional<mtx::crypto::EncryptedFile>>();
|
qRegisterMetaType<std::optional<mtx::crypto::EncryptedFile>>();
|
||||||
qRegisterMetaType<std::optional<RelatedInfo>>();
|
qRegisterMetaType<std::optional<RelatedInfo>>();
|
||||||
qRegisterMetaType<mtx::presence::PresenceState>();
|
qRegisterMetaType<mtx::presence::PresenceState>();
|
||||||
|
qRegisterMetaType<mtx::secret_storage::AesHmacSha2KeyDescription>();
|
||||||
|
qRegisterMetaType<SecretsToDecrypt>();
|
||||||
|
|
||||||
topLayout_ = new QHBoxLayout(this);
|
topLayout_ = new QHBoxLayout(this);
|
||||||
topLayout_->setSpacing(0);
|
topLayout_->setSpacing(0);
|
||||||
|
@ -136,6 +141,12 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
splitter->addWidget(content_);
|
splitter->addWidget(content_);
|
||||||
splitter->restoreSizes(parent->width());
|
splitter->restoreSizes(parent->width());
|
||||||
|
|
||||||
|
connect(this,
|
||||||
|
&ChatPage::downloadedSecrets,
|
||||||
|
this,
|
||||||
|
&ChatPage::decryptDownloadedSecrets,
|
||||||
|
Qt::QueuedConnection);
|
||||||
|
|
||||||
connect(this, &ChatPage::connectionLost, this, [this]() {
|
connect(this, &ChatPage::connectionLost, this, [this]() {
|
||||||
nhlog::net()->info("connectivity lost");
|
nhlog::net()->info("connectivity lost");
|
||||||
isConnected_ = false;
|
isConnected_ = false;
|
||||||
|
@ -1208,3 +1219,45 @@ ChatPage::connectCallMessage()
|
||||||
view_manager_,
|
view_manager_,
|
||||||
qOverload<const QString &, const T &>(&TimelineViewManager::queueCallMessage));
|
qOverload<const QString &, const T &>(&TimelineViewManager::queueCallMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ChatPage::decryptDownloadedSecrets(mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
|
||||||
|
const SecretsToDecrypt &secrets)
|
||||||
|
{
|
||||||
|
QString text = QInputDialog::getText(
|
||||||
|
ChatPage::instance(),
|
||||||
|
QCoreApplication::translate("CrossSigningSecrets", "Decrypt secrets"),
|
||||||
|
keyDesc.name.empty()
|
||||||
|
? QCoreApplication::translate(
|
||||||
|
"CrossSigningSecrets",
|
||||||
|
"Enter your recovery key or passphrase to decrypt your secrets:")
|
||||||
|
: QCoreApplication::translate(
|
||||||
|
"CrossSigningSecrets",
|
||||||
|
"Enter your recovery key or passphrase called %1 to decrypt your secrets:")
|
||||||
|
.arg(QString::fromStdString(keyDesc.name)),
|
||||||
|
QLineEdit::Password);
|
||||||
|
|
||||||
|
if (text.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto decryptionKey = mtx::crypto::key_from_recoverykey(text.toStdString(), keyDesc);
|
||||||
|
|
||||||
|
if (!decryptionKey)
|
||||||
|
decryptionKey = mtx::crypto::key_from_passphrase(text.toStdString(), keyDesc);
|
||||||
|
|
||||||
|
if (!decryptionKey) {
|
||||||
|
QMessageBox::information(
|
||||||
|
ChatPage::instance(),
|
||||||
|
QCoreApplication::translate("CrossSigningSecrets", "Decrytion failed"),
|
||||||
|
QCoreApplication::translate("CrossSigningSecrets",
|
||||||
|
"Failed to decrypt secrets with the "
|
||||||
|
"provided recovery key or passphrase"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &[secretName, encryptedSecret] : secrets) {
|
||||||
|
auto decrypted = mtx::crypto::decrypt(encryptedSecret, *decryptionKey, secretName);
|
||||||
|
if (!decrypted.empty())
|
||||||
|
cache::storeSecret(secretName, decrypted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <mtx/events/encrypted.hpp>
|
#include <mtx/events/encrypted.hpp>
|
||||||
#include <mtx/events/member.hpp>
|
#include <mtx/events/member.hpp>
|
||||||
#include <mtx/events/presence.hpp>
|
#include <mtx/events/presence.hpp>
|
||||||
|
#include <mtx/secret_storage.hpp>
|
||||||
|
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
|
@ -72,6 +73,8 @@ namespace popups {
|
||||||
class UserMentions;
|
class UserMentions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using SecretsToDecrypt = std::map<std::string, mtx::secret_storage::AesHmacSha2EncryptedData>;
|
||||||
|
|
||||||
class ChatPage : public QWidget
|
class ChatPage : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -117,6 +120,8 @@ public slots:
|
||||||
void unbanUser(QString userid, QString reason);
|
void unbanUser(QString userid, QString reason);
|
||||||
|
|
||||||
void receivedSessionKey(const std::string &room_id, const std::string &session_id);
|
void receivedSessionKey(const std::string &room_id, const std::string &session_id);
|
||||||
|
void decryptDownloadedSecrets(mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
|
||||||
|
const SecretsToDecrypt &secrets);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void connectionLost();
|
void connectionLost();
|
||||||
|
@ -185,6 +190,9 @@ signals:
|
||||||
void receivedDeviceVerificationReady(const mtx::events::msg::KeyVerificationReady &message);
|
void receivedDeviceVerificationReady(const mtx::events::msg::KeyVerificationReady &message);
|
||||||
void receivedDeviceVerificationDone(const mtx::events::msg::KeyVerificationDone &message);
|
void receivedDeviceVerificationDone(const mtx::events::msg::KeyVerificationDone &message);
|
||||||
|
|
||||||
|
void downloadedSecrets(mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
|
||||||
|
const SecretsToDecrypt &secrets);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void logout();
|
void logout();
|
||||||
void removeRoom(const QString &room_id);
|
void removeRoom(const QString &room_id);
|
||||||
|
|
67
src/Olm.cpp
67
src/Olm.cpp
|
@ -1243,8 +1243,73 @@ request_cross_signing_keys()
|
||||||
request(mtx::secret_storage::secrets::cross_signing_user_signing);
|
request(mtx::secret_storage::secrets::cross_signing_user_signing);
|
||||||
request(mtx::secret_storage::secrets::megolm_backup_v1);
|
request(mtx::secret_storage::secrets::megolm_backup_v1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void
|
||||||
|
unlock_secrets(const std::string &key,
|
||||||
|
const std::map<std::string, mtx::secret_storage::AesHmacSha2EncryptedData> &secrets)
|
||||||
|
{
|
||||||
|
http::client()->secret_storage_key(
|
||||||
|
key,
|
||||||
|
[secrets](mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
|
||||||
|
mtx::http::RequestErr err) {
|
||||||
|
if (err) {
|
||||||
|
nhlog::net()->error("Failed to download secret storage key");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit ChatPage::instance()->downloadedSecrets(keyDesc, secrets);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
download_cross_signing_keys()
|
download_cross_signing_keys()
|
||||||
{}
|
{
|
||||||
|
using namespace mtx::secret_storage;
|
||||||
|
http::client()->secret_storage_secret(
|
||||||
|
secrets::megolm_backup_v1, [](Secret secret, mtx::http::RequestErr err) {
|
||||||
|
std::optional<Secret> backup_key;
|
||||||
|
if (!err)
|
||||||
|
backup_key = secret;
|
||||||
|
|
||||||
|
http::client()->secret_storage_secret(
|
||||||
|
secrets::cross_signing_self_signing,
|
||||||
|
[backup_key](Secret secret, mtx::http::RequestErr err) {
|
||||||
|
std::optional<Secret> self_signing_key;
|
||||||
|
if (!err)
|
||||||
|
self_signing_key = secret;
|
||||||
|
|
||||||
|
http::client()->secret_storage_secret(
|
||||||
|
secrets::cross_signing_user_signing,
|
||||||
|
[backup_key, self_signing_key](Secret secret,
|
||||||
|
mtx::http::RequestErr err) {
|
||||||
|
std::optional<Secret> user_signing_key;
|
||||||
|
if (!err)
|
||||||
|
user_signing_key = secret;
|
||||||
|
|
||||||
|
std::map<std::string,
|
||||||
|
std::map<std::string, AesHmacSha2EncryptedData>>
|
||||||
|
secrets;
|
||||||
|
|
||||||
|
if (backup_key && !backup_key->encrypted.empty())
|
||||||
|
secrets[backup_key->encrypted.begin()->first]
|
||||||
|
[secrets::megolm_backup_v1] =
|
||||||
|
backup_key->encrypted.begin()->second;
|
||||||
|
if (self_signing_key && !self_signing_key->encrypted.empty())
|
||||||
|
secrets[self_signing_key->encrypted.begin()->first]
|
||||||
|
[secrets::cross_signing_self_signing] =
|
||||||
|
self_signing_key->encrypted.begin()->second;
|
||||||
|
if (user_signing_key && !user_signing_key->encrypted.empty())
|
||||||
|
secrets[user_signing_key->encrypted.begin()->first]
|
||||||
|
[secrets::cross_signing_user_signing] =
|
||||||
|
user_signing_key->encrypted.begin()->second;
|
||||||
|
|
||||||
|
for (const auto &[key, secrets] : secrets)
|
||||||
|
unlock_secrets(key, secrets);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace olm
|
} // namespace olm
|
||||||
|
|
|
@ -1029,6 +1029,10 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
|
||||||
olm::request_cross_signing_keys();
|
olm::request_cross_signing_keys();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(crossSigningDownloadBtn, &QPushButton::clicked, this, []() {
|
||||||
|
olm::download_cross_signing_keys();
|
||||||
|
});
|
||||||
|
|
||||||
connect(backBtn_, &QPushButton::clicked, this, [this]() {
|
connect(backBtn_, &QPushButton::clicked, this, [this]() {
|
||||||
settings_->save();
|
settings_->save();
|
||||||
emit moveBack();
|
emit moveBack();
|
||||||
|
|
Loading…
Reference in a new issue