From a131bbc16599d3692aa7fe139b9faac69220f635 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Mon, 11 Dec 2023 23:52:44 +0100 Subject: [PATCH] airgap: make view-only details compatible with ANONERO --- src/MainWindow.cpp | 4 ++ src/dialog/URDialog.cpp | 65 +------------------------ src/dialog/URDialog.h | 12 +---- src/dialog/ViewOnlyDialog.cpp | 24 ++++++--- src/dialog/ViewOnlyDialog.h | 1 + src/dialog/ViewOnlyDialog.ui | 2 +- src/qrcode/scanner/QrCodeScanDialog.cpp | 4 ++ src/wizard/PageWalletRestoreKeys.cpp | 25 +++++++--- src/wizard/PageWalletRestoreKeys.ui | 2 +- 9 files changed, 48 insertions(+), 91 deletions(-) diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index dd2d1100..c08972cb 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -1040,6 +1040,10 @@ void MainWindow::showKeysDialog() { } void MainWindow::showViewOnlyDialog() { + if (!this->verifyPassword()) { + return; + } + ViewOnlyDialog dialog{m_wallet, this}; dialog.exec(); } diff --git a/src/dialog/URDialog.cpp b/src/dialog/URDialog.cpp index 8d624b23..b60d03f5 100644 --- a/src/dialog/URDialog.cpp +++ b/src/dialog/URDialog.cpp @@ -10,28 +10,12 @@ #include "utils/Utils.h" #include "WalletManager.h" -URDialog::URDialog(QWidget *parent, const std::string &data, bool scanOnly) +URDialog::URDialog(QWidget *parent) : WindowModalDialog(parent) , ui(new Ui::URDialog) { ui->setupUi(this); - if (!data.empty()) { - ui->btn_loadFile->setVisible(false); - ui->btn_loadClipboard->setVisible(false); - ui->tabWidget->setTabVisible(1, false); - - QScreen *currentScreen = QApplication::screenAt(this->geometry().center()); - if (!currentScreen) { - currentScreen = QApplication::primaryScreen(); - } - int availableHeight = currentScreen->availableGeometry().height() - 200; - this->resize(availableHeight, availableHeight); - - ui->widgetUR->setData("xmr-viewonly", data); - return; - } - connect(ui->btn_loadFile, &QPushButton::clicked, [this]{ QString fn = QFileDialog::getOpenFileName(this, "Load file", QDir::homePath(), "All Files (*)"); if (fn.isEmpty()) { @@ -75,41 +59,6 @@ URDialog::URDialog(QWidget *parent, const std::string &data, bool scanOnly) return; } - if (ui->widgetScanner->getURType() == "xmr-viewonly") { - std::string urData = ui->widgetScanner->getURData(); - while (true) { - bool ok; - QString password = QInputDialog::getText(this, "Encrypt view-only details", "Enter one-time password to decrypt view-only details with", QLineEdit::Password, "", &ok); - if (!ok) { - break; - } - - QString data = WalletManager::decryptWithPassword(urData, password); - if (!data.startsWith("Secret view key")) { - Utils::showError(this, "Unable to load view-only details", "Invalid password"); - continue; - } - - QRegularExpression viewOnlyDetails( - "Secret view key: (?[0-9a-f]{64})\nAddress: (?
\\w+)\nRestore height: (?\\d+)\nWallet name: (?\\w+)\n", - QRegularExpression::CaseInsensitiveOption | QRegularExpression::DotMatchesEverythingOption); - QRegularExpressionMatch match = viewOnlyDetails.match(data); - - if (!match.hasMatch()) { - Utils::showError(this, "Unable to load view-only details", "Unexpected data"); - continue; - } - - m_viewOnlyDetails.address = match.captured("address"); - m_viewOnlyDetails.key = match.captured("key").toLower(); - m_viewOnlyDetails.restoreHeight = match.captured("restoreheight").toInt(); - m_viewOnlyDetails.walletName = QString("%1_view_only").arg(match.captured("walletname")); - - this->accept(); - return; - } - } - if (ui->radio_clipboard->isChecked()) { Utils::copyToClipboard(QString::fromStdString(ui->widgetScanner->getURData())); Utils::showInfo(this, "Data copied to clipboard"); @@ -138,22 +87,10 @@ URDialog::URDialog(QWidget *parent, const std::string &data, bool scanOnly) ui->widgetScanner->reset(); }); - if (scanOnly) { - ui->tabWidget->setCurrentIndex(1); - ui->tabWidget->setTabVisible(0, false); - ui->radio_clipboard->setVisible(false); - ui->radio_file->setVisible(false); - return; - } - ui->radio_file->setChecked(true); ui->tabWidget->setCurrentIndex(0); this->resize(600, 700); } -ViewOnlyDetails URDialog::getViewOnlyDetails() { - return m_viewOnlyDetails; -} - URDialog::~URDialog() = default; \ No newline at end of file diff --git a/src/dialog/URDialog.h b/src/dialog/URDialog.h index faa3d973..0b8dbd8e 100644 --- a/src/dialog/URDialog.h +++ b/src/dialog/URDialog.h @@ -12,26 +12,16 @@ namespace Ui { class URDialog; } -struct ViewOnlyDetails { - QString address; - QString key; - int restoreHeight = 0; - QString walletName; -}; - class URDialog : public WindowModalDialog { Q_OBJECT public: - explicit URDialog(QWidget *parent, const std::string &data = "", bool scanOnly = false); + explicit URDialog(QWidget *parent); ~URDialog() override; - ViewOnlyDetails getViewOnlyDetails(); - private: QScopedPointer ui; - ViewOnlyDetails m_viewOnlyDetails; }; diff --git a/src/dialog/ViewOnlyDialog.cpp b/src/dialog/ViewOnlyDialog.cpp index 12438b20..d67685d4 100644 --- a/src/dialog/ViewOnlyDialog.cpp +++ b/src/dialog/ViewOnlyDialog.cpp @@ -11,6 +11,8 @@ #include "URDialog.h" #include "utils/Utils.h" #include "WalletManager.h" +#include "qrcode/QrCode.h" +#include "dialog/QrCodeDialog.h" ViewOnlyDialog::ViewOnlyDialog(Wallet *wallet, QWidget *parent) : WindowModalDialog(parent) @@ -26,14 +28,8 @@ ViewOnlyDialog::ViewOnlyDialog(Wallet *wallet, QWidget *parent) connect(ui->btn_Copy, &QPushButton::clicked, this, &ViewOnlyDialog::copyToClipboard); connect(ui->btn_Save, &QPushButton::clicked, this, &ViewOnlyDialog::onWriteViewOnlyWallet); connect(ui->btn_transmitOverUR, &QPushButton::clicked, [this] { - bool ok; - QString password = QInputDialog::getText(this, "Encrypt view-only details", "Enter one-time password to encrypt view-only details with", QLineEdit::Password, "", &ok); - if (!ok) { - return; - } - - std::string encrypted = WalletManager::encryptWithPassword(this->toString(), password); - URDialog dialog{this, encrypted}; + QrCode qr(this->toJsonString(), QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::HIGH); + QrCodeDialog dialog{this, &qr, "View-Only details"}; dialog.exec(); }); @@ -74,6 +70,18 @@ QString ViewOnlyDialog::toString() { return text; } +QString ViewOnlyDialog::toJsonString() { + QVariantMap data; + data["version"] = 0, + data["primaryAddress"] = m_wallet->address(0, 0); + data["privateViewKey"] = m_wallet->getSecretViewKey(); + data["restoreHeight"] = m_wallet->getWalletCreationHeight(); + data["walletName"] = m_wallet->walletName(); + + auto obj = QJsonDocument::fromVariant(data); + return obj.toJson(QJsonDocument::Compact); +} + void ViewOnlyDialog::copyToClipboard() { Utils::copyToClipboard(this->toString()); } diff --git a/src/dialog/ViewOnlyDialog.h b/src/dialog/ViewOnlyDialog.h index 1ba44db3..ca3ba8e3 100644 --- a/src/dialog/ViewOnlyDialog.h +++ b/src/dialog/ViewOnlyDialog.h @@ -26,6 +26,7 @@ private slots: private: QString toString(); + QString toJsonString(); void copyToClipboard(); QScopedPointer ui; diff --git a/src/dialog/ViewOnlyDialog.ui b/src/dialog/ViewOnlyDialog.ui index a09d9da8..d998a1c4 100644 --- a/src/dialog/ViewOnlyDialog.ui +++ b/src/dialog/ViewOnlyDialog.ui @@ -90,7 +90,7 @@ - Transmit over UR + Show QR diff --git a/src/qrcode/scanner/QrCodeScanDialog.cpp b/src/qrcode/scanner/QrCodeScanDialog.cpp index e2bbd891..db9ddcaa 100644 --- a/src/qrcode/scanner/QrCodeScanDialog.cpp +++ b/src/qrcode/scanner/QrCodeScanDialog.cpp @@ -21,6 +21,10 @@ QrCodeScanDialog::QrCodeScanDialog(QWidget *parent, bool scan_ur) this->setWindowTitle("Scan QR code"); ui->widget_scanner->startCapture(scan_ur); + + connect(ui->widget_scanner, &QrCodeScanWidget::finished, [this]{ + this->accept(); + }); } QString QrCodeScanDialog::decodedString() { diff --git a/src/wizard/PageWalletRestoreKeys.cpp b/src/wizard/PageWalletRestoreKeys.cpp index ba694155..f22c98f8 100644 --- a/src/wizard/PageWalletRestoreKeys.cpp +++ b/src/wizard/PageWalletRestoreKeys.cpp @@ -13,6 +13,7 @@ #include "constants.h" #include "dialog/URDialog.h" #include "libwalletqt/WalletManager.h" +#include "scanner/QrCodeScanDialog.h" PageWalletRestoreKeys::PageWalletRestoreKeys(WizardFields *fields, QWidget *parent) : QWizardPage(parent) @@ -43,15 +44,27 @@ PageWalletRestoreKeys::PageWalletRestoreKeys(WizardFields *fields, QWidget *pare connect(ui->btnOptions, &QPushButton::clicked, this, &PageWalletRestoreKeys::onOptionsClicked); connect(ui->combo_walletType, &QComboBox::currentTextChanged, this, &PageWalletRestoreKeys::showInputLines); connect(ui->btn_scanUR, &QPushButton::clicked, [this] { - URDialog dialog{this, "", true}; + QrCodeScanDialog dialog{this, false}; dialog.exec(); - ViewOnlyDetails details = dialog.getViewOnlyDetails(); - ui->line_address->setText(details.address); + + QString json = dialog.decodedString(); + if (json.isEmpty()) { + return; + } + + QJsonParseError error; + auto doc = QJsonDocument::fromJson(json.toUtf8(), &error); + if (error.error != QJsonParseError::NoError) { + Utils::showError(this, "Unable to load view-only details", QString("Can't parse JSON: %1").arg(error.errorString())); + return; + } + + ui->line_address->setText(doc["primaryAddress"].toString()); ui->line_address->setCursorPosition(0); - ui->line_viewkey->setText(details.key); + ui->line_viewkey->setText(doc["privateViewKey"].toString()); ui->line_viewkey->setCursorPosition(0); - m_fields->restoreHeight = details.restoreHeight; - m_fields->walletName = details.walletName; + m_fields->restoreHeight = doc["restoreHeight"].toInt(); + m_fields->walletName = doc["walletName"].toString() + "_view_only"; }); } diff --git a/src/wizard/PageWalletRestoreKeys.ui b/src/wizard/PageWalletRestoreKeys.ui index 716c06fc..0e65cdaa 100644 --- a/src/wizard/PageWalletRestoreKeys.ui +++ b/src/wizard/PageWalletRestoreKeys.ui @@ -218,7 +218,7 @@ - Scan UR + Scan QR -- 2.52.0