Implement import/export of megolm session keys (#358)

This commit is contained in:
Konstantinos Sideris 2018-09-15 23:52:14 +03:00
parent cf71a5858c
commit a9ddc3b3d3
5 changed files with 195 additions and 27 deletions

View file

@ -18,7 +18,11 @@
#include <QApplication>
#include <QComboBox>
#include <QDebug>
#include <QFileDialog>
#include <QInputDialog>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QPushButton>
#include <QScrollArea>
#include <QSettings>
@ -233,43 +237,60 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
auto encryptionLayout_ = new QVBoxLayout;
encryptionLayout_->setContentsMargins(0, OptionMargin, 0, OptionMargin);
encryptionLayout_->setAlignment(Qt::AlignVCenter | Qt::AlignBottom);
QFont monospaceFont = QFont(font);
monospaceFont.setFamily("Courier New");
monospaceFont.setStyleHint(QFont::Courier);
monospaceFont.setPointSizeF(monospaceFont.pointSizeF() * 0.9);
auto deviceIdWidget = new QHBoxLayout;
deviceIdWidget->setContentsMargins(0, OptionMargin, 0, OptionMargin);
auto deviceIdLayout = new QHBoxLayout;
deviceIdLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin);
auto deviceIdLabel = new QLabel(tr("Device ID"), this);
deviceIdLabel->setFont(font);
deviceIdValue_ = new QLabel();
deviceIdValue_ = new QLabel{this};
deviceIdValue_->setTextInteractionFlags(Qt::TextSelectableByMouse);
deviceIdValue_->setFont(monospaceFont);
deviceIdWidget->addWidget(deviceIdLabel, 1);
deviceIdWidget->addWidget(deviceIdValue_);
deviceIdLayout->addWidget(deviceIdLabel, 1);
deviceIdLayout->addWidget(deviceIdValue_);
auto deviceFingerprintWidget = new QHBoxLayout;
deviceFingerprintWidget->setContentsMargins(0, OptionMargin, 0, OptionMargin);
auto deviceFingerprintLayout = new QHBoxLayout;
deviceFingerprintLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin);
auto deviceFingerprintLabel = new QLabel(tr("Device Fingerprint"), this);
deviceFingerprintLabel->setFont(font);
deviceFingerprintValue_ = new QLabel();
deviceFingerprintValue_ = new QLabel{this};
deviceFingerprintValue_->setTextInteractionFlags(Qt::TextSelectableByMouse);
deviceFingerprintValue_->setFont(monospaceFont);
deviceFingerprintWidget->addWidget(deviceFingerprintLabel, 1);
deviceFingerprintWidget->addWidget(deviceFingerprintValue_);
deviceFingerprintLayout->addWidget(deviceFingerprintLabel, 1);
deviceFingerprintLayout->addWidget(deviceFingerprintValue_);
encryptionLayout_->addLayout(deviceIdWidget);
encryptionLayout_->addLayout(deviceFingerprintWidget);
auto sessionKeysLayout = new QHBoxLayout;
sessionKeysLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin);
auto sessionKeysLabel = new QLabel(tr("Session Keys"), this);
sessionKeysLabel->setFont(font);
sessionKeysLayout->addWidget(sessionKeysLabel, 1);
auto sessionKeysImportBtn = new FlatButton(tr("IMPORT"), this);
connect(
sessionKeysImportBtn, &QPushButton::clicked, this, &UserSettingsPage::importSessionKeys);
auto sessionKeysExportBtn = new FlatButton(tr("EXPORT"), this);
connect(
sessionKeysExportBtn, &QPushButton::clicked, this, &UserSettingsPage::exportSessionKeys);
sessionKeysLayout->addWidget(sessionKeysExportBtn);
sessionKeysLayout->addWidget(sessionKeysImportBtn);
encryptionLayout_->addLayout(deviceIdLayout);
encryptionLayout_->addLayout(deviceFingerprintLayout);
encryptionLayout_->addWidget(new HorizontalLine(this));
encryptionLayout_->addLayout(sessionKeysLayout);
font.setWeight(65);
auto encryptionLabel_ = new QLabel(tr("ENCRYPTION"), this);
encryptionLabel_->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
encryptionLabel_->setFont(font);
// encryptionLabel_->setContentsMargins(0, 50, 0, 0);
auto general_ = new QLabel(tr("GENERAL"), this);
general_->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
@ -310,7 +331,6 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
mainLayout_->addWidget(encryptionLabel_, 1, Qt::AlignLeft | Qt::AlignBottom);
mainLayout_->addWidget(new HorizontalLine(this));
mainLayout_->addLayout(encryptionLayout_);
mainLayout_->addStretch(1);
auto scrollArea_ = new QScrollArea(this);
scrollArea_->setFrameShape(QFrame::NoFrame);
@ -452,3 +472,89 @@ UserSettingsPage::restoreThemeCombo() const
else
themeCombo_->setCurrentIndex(2);
}
void
UserSettingsPage::importSessionKeys()
{
auto fileName = QFileDialog::getOpenFileName(this, tr("Open Sessions File"), "", "");
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox::warning(this, tr("Error"), file.errorString());
return;
}
auto bin = file.peek(file.size());
auto payload = std::string(bin.data(), bin.size());
bool ok;
auto password = QInputDialog::getText(this,
tr("File Password"),
tr("Enter the passphrase to decrypt the file:"),
QLineEdit::Password,
"",
&ok);
if (!ok || password.isEmpty()) {
QMessageBox::warning(this, tr("Error"), tr("The password cannot be empty"));
return;
}
try {
auto sessions = mtx::crypto::decrypt_exported_sessions(
mtx::crypto::base642bin(payload), password.toStdString());
cache::client()->importSessionKeys(std::move(sessions));
} catch (const std::exception &e) {
QMessageBox::warning(this, tr("Error"), e.what());
} catch (const lmdb::error &e) {
QMessageBox::warning(this, tr("Error"), e.what());
} catch (const nlohmann::json::exception &e) {
QMessageBox::warning(this, tr("Error"), e.what());
}
}
void
UserSettingsPage::exportSessionKeys()
{
qDebug() << "exporting session keys";
// Open password dialog.
bool ok;
auto password = QInputDialog::getText(this,
tr("File Password"),
tr("Enter passphrase to encrypt your session keys:"),
QLineEdit::Password,
"",
&ok);
if (!ok || password.isEmpty()) {
QMessageBox::warning(this, tr("Error"), tr("The password cannot be empty"));
return;
}
// Open file dialog to save the file.
auto fileName =
QFileDialog::getSaveFileName(this, tr("File to save the exported session keys"), "", "");
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
QMessageBox::warning(this, tr("Error"), file.errorString());
return;
}
// Export sessions & save to file.
try {
auto encrypted_blob = mtx::crypto::encrypt_exported_sessions(
cache::client()->exportSessionKeys(), password.toStdString());
auto b64 = mtx::crypto::bin2base64(encrypted_blob);
file.write(b64.data(), b64.size());
} catch (const std::exception &e) {
QMessageBox::warning(this, tr("Error"), e.what());
} catch (const lmdb::error &e) {
QMessageBox::warning(this, tr("Error"), e.what());
} catch (const nlohmann::json::exception &e) {
QMessageBox::warning(this, tr("Error"), e.what());
}
}