From 2dd865bcbf240fdea21af177472ba1959ffd4357 Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Fri, 11 Sep 2026 16:39:31 +0300 Subject: [PATCH] Update decryption flow UI IB-8830 Signed-off-by: Raul Metsma --- client/Application.cpp | 3 +- client/CDocSupport.cpp | 42 +++++----------- client/CryptoDoc.cpp | 46 ++++------------- client/CryptoDoc.h | 11 ++--- client/MainWindow.cpp | 7 +-- client/QCryptoBackend.cpp | 10 +--- client/QCryptoBackend.h | 1 - client/common_enums.h | 3 -- client/translations/en.ts | 32 ++---------- client/translations/et.ts | 32 ++---------- client/widgets/AddressItem.cpp | 56 ++++++++++++--------- client/widgets/AddressItem.h | 9 ++-- client/widgets/AddressItem.ui | 27 ++++++++-- client/widgets/ContainerPage.cpp | 85 +++++++++++--------------------- client/widgets/ContainerPage.h | 16 +++--- client/widgets/Item.cpp | 1 - client/widgets/Item.h | 1 - client/widgets/ItemList.cpp | 3 -- client/widgets/ItemList.h | 2 - client/widgets/MainAction.cpp | 12 ++--- client/widgets/MainAction.h | 7 +-- 21 files changed, 143 insertions(+), 263 deletions(-) diff --git a/client/Application.cpp b/client/Application.cpp index 69ec96d52..bcf075aa3 100644 --- a/client/Application.cpp +++ b/client/Application.cpp @@ -570,8 +570,9 @@ Application::~Application() connect(this, &Application::TSLLoadingFinished, &e, &QEventLoop::quit); if( !d->ready ) e.exec(); - digidoc::terminate(); delete d; + d = nullptr; + digidoc::terminate(); QDesktopServices::unsetUrlHandler(QStringLiteral("browse")); QDesktopServices::unsetUrlHandler(QStringLiteral("mailto")); diff --git a/client/CDocSupport.cpp b/client/CDocSupport.cpp index 727566adf..8024d421f 100644 --- a/client/CDocSupport.cpp +++ b/client/CDocSupport.cpp @@ -127,12 +127,8 @@ getDecryptResultStatus(const std::vector &result, std::unique_ptr& dst, const std::vector &data, bool oaep, unsigned int idx) { - if (!backend) { - auto val = QCryptoBackend::getBackend(qApp->cryptoManager()->tokenauth()); - if (!val) - return getDecryptStatus(val.error()); - backend.reset(val.value()); - } + if (!backend) + return BACKEND_ERROR; QByteArray decryptedKey = backend->decrypt(toByteArray(data), oaep); dst.assign(decryptedKey.cbegin(), decryptedKey.cend()); return getDecryptResultStatus(dst, std::move(backend)); @@ -147,12 +143,8 @@ DDCryptoBackend::deriveConcatKDF(std::vector& dst, const std::vectorcryptoManager()->tokenauth()); - if (!val) - return getDecryptStatus(val.error()); - backend.reset(val.value()); - } + if (!backend) + return BACKEND_ERROR; QByteArray decryptedKey = backend->deriveConcatKDF(toByteArray(publicKey), SHA_MTH.value(digest), toByteArray(algorithmID), toByteArray(partyUInfo), toByteArray(partyVInfo)); dst.assign(decryptedKey.cbegin(), decryptedKey.cend()); @@ -162,12 +154,8 @@ DDCryptoBackend::deriveConcatKDF(std::vector& dst, const std::vector& dst, const std::vector &key_material, const std::vector &salt, unsigned int idx) { - if (!backend) { - auto val = QCryptoBackend::getBackend(qApp->cryptoManager()->tokenauth()); - if (!val) - return getDecryptStatus(val.error()); - backend.reset(val.value()); - } + if (!backend) + return BACKEND_ERROR; QByteArray decryptedKey = backend->deriveHMACExtract(toByteArray(key_material), toByteArray(salt), ECC_KEY_LEN); dst.assign(decryptedKey.cbegin(), decryptedKey.cend()); return getDecryptResultStatus(dst, std::move(backend)); @@ -279,7 +267,7 @@ libcdoc::result_t DDNetworkBackend::sendKey( if (expiry_ts) { uint64_t expiry = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now() + std::chrono::months(6)); expiry_ts = std::min(expiry_ts, expiry); - req.setRawHeader("x-expiry-time", QDateTime::fromSecsSinceEpoch(expiry_ts).toString(Qt::ISODate).toLatin1()); + req.setRawHeader("x-expiry-time", QDateTime::fromSecsSinceEpoch(expiry_ts, Qt::UTC).toString(Qt::ISODate).toLatin1()); } if (!checkConnection()) { last_error = "No connection"; @@ -330,19 +318,17 @@ DDNetworkBackend::fetchKey(std::vector &result, const std::string &url, return BACKEND_ERROR; } - TokenData auth = qApp->cryptoManager()->tokenauth(); - auto val = QCryptoBackend::getBackend(auth); - if (!val) - return getDecryptStatus(val.error()); - std::unique_ptr backend(val.value()); - - auto authKey = backend->getKey(); + if (!crypto.backend) { + last_error = "No authentication backend"; + return BACKEND_ERROR; + } + auto authKey = crypto.backend->getKey(); if (!authKey.handle()) { last_error = "Cannot create authentication key"; return BACKEND_ERROR; } QScopedPointer nam( - CheckConnection::setupNAM(req, auth.cert(), authKey, Settings::CDOC2_GET_CERT)); + CheckConnection::setupNAM(req, crypto.backend->cert(), authKey, Settings::CDOC2_GET_CERT)); QEventLoop e; QNetworkReply *reply = nam->get(req); connect(reply, &QNetworkReply::finished, &e, &QEventLoop::quit); @@ -356,8 +342,6 @@ DDNetworkBackend::fetchKey(std::vector &result, const std::string &url, QByteArray key_material = QByteArray::fromBase64(json.value(QLatin1String("ephemeral_key_material")).toString().toLatin1()); result.assign(key_material.cbegin(), key_material.cend()); - crypto.setBackend(std::move(backend)); - return libcdoc::OK; } diff --git a/client/CryptoDoc.cpp b/client/CryptoDoc.cpp index d3d4a0720..8915f4c12 100644 --- a/client/CryptoDoc.cpp +++ b/client/CryptoDoc.cpp @@ -246,16 +246,6 @@ bool CryptoDoc::addEncryptionKey(const CKey& key) { return true; } -bool CryptoDoc::canDecrypt(const QSslCertificate &cert) { - if (!d->reader) - return false; - if (cert.isNull()) - return false; - QByteArray der = cert.toDer(); - return d->reader->getLockForCert( - std::vector(der.cbegin(), der.cend())) >= 0; -} - void CryptoDoc::clear(const QString &file, int version) { d->documents->clearTempFolder(); @@ -270,7 +260,7 @@ ContainerState CryptoDoc::state() const return d->isEncrypted() ? EncryptedContainer : UnencryptedContainer; } -bool CryptoDoc::decrypt(const libcdoc::Lock *lock, const QByteArray& secret) +bool CryptoDoc::decrypt(const libcdoc::Lock &lock, const QByteArray& secret, std::unique_ptr &&backend) { if(!d->reader) { @@ -281,31 +271,10 @@ bool CryptoDoc::decrypt(const libcdoc::Lock *lock, const QByteArray& secret) return false; } - int lock_idx = -1; + // libcdoc addresses the lock by its position; labels can repeat, the lock itself is unique const std::vector &locks = d->reader->getLocks(); - if (lock == nullptr) { - QByteArray der = qApp->cryptoManager()->tokenauth().cert().toDer(); - lock_idx = d->reader->getLockForCert( - std::vector(der.cbegin(), der.cend())); - if (lock_idx < 0) { - WarningDialog::create() - ->withTitle(tr("Failed to decrypt document")) - ->withText(tr("You do not have the key to decrypt this document")) - ->open(); - return false; - } - lock = &locks.at(lock_idx); - } else { - for (lock_idx = 0; lock_idx < locks.size(); lock_idx++) { - if (lock->label == locks[lock_idx].label) { - lock = &locks.at(lock_idx); - break; - } - } - if (lock_idx >= locks.size()) - lock_idx = -1; - } - if (!lock || (lock->isSymmetric() && secret.isEmpty())) { + auto it = std::ranges::find(locks, lock); + if (it == locks.cend() || (lock.isSymmetric() && secret.isEmpty())) { WarningDialog::create() ->withTitle(tr("Failed to decrypt document")) ->withText(tr("You do not have the key to decrypt this document")) @@ -313,6 +282,11 @@ bool CryptoDoc::decrypt(const libcdoc::Lock *lock, const QByteArray& secret) return false; } + auto lock_idx = unsigned(std::distance(locks.cbegin(), it)); + d->crypto.setBackend(std::move(backend)); + auto resetBackend = qScopeGuard([this] { + d->crypto.setBackend({}); + }); d->crypto.secret.assign(secret.cbegin(), secret.cend()); TempListConsumer cons; @@ -334,7 +308,7 @@ bool CryptoDoc::decrypt(const libcdoc::Lock *lock, const QByteArray& secret) const std::string &msg = d->reader->getLastErrorStr(); switch (result) { case libcdoc::WRONG_KEY: - str = (lock->type == libcdoc::Lock::PASSWORD) ? tr("Wrong password.") : tr("Wrong key."); + str = (lock.type == libcdoc::Lock::PASSWORD) ? tr("Wrong password.") : tr("Wrong key."); break; case libcdoc::HASH_MISMATCH: case libcdoc::DATA_FORMAT_ERROR: diff --git a/client/CryptoDoc.h b/client/CryptoDoc.h index be9ca121a..983d3572a 100644 --- a/client/CryptoDoc.h +++ b/client/CryptoDoc.h @@ -22,16 +22,14 @@ #include "common_enums.h" #include "DocumentModel.h" -#include #include #include -#include -#include +#include + #include -#include -class QSslKey; +class QCryptoBackend; Q_DECLARE_LOGGING_CATEGORY(CRYPTO) @@ -61,9 +59,8 @@ class CryptoDoc final: public QObject bool supportsSymmetricKeys() const; bool addEncryptionKey(const CKey& key); - bool canDecrypt(const QSslCertificate &cert); void clear(const QString &file = {}, int version = -1); - bool decrypt(const libcdoc::Lock *lock, const QByteArray& secret); + bool decrypt(const libcdoc::Lock &lock, const QByteArray& secret, std::unique_ptr &&backend); bool encrypt(const QString &filename = {}, const QString& label = {}, const QByteArray& secret = {}); DocumentModel* documentModel() const; QString fileName() const; diff --git a/client/MainWindow.cpp b/client/MainWindow.cpp index 911397e5d..089db65a3 100644 --- a/client/MainWindow.cpp +++ b/client/MainWindow.cpp @@ -92,7 +92,6 @@ MainWindow::MainWindow( QWidget *parent ) // Refresh ID card info in card widget connect(qApp->cryptoManager(), &QCryptoManager::cacheChanged, this, &MainWindow::updateSelector); - connect(qApp->cryptoManager(), &QCryptoManager::authDataChanged, ui->cryptoContainerPage, &ContainerPage::tokenChanged); // Refresh card info on "My EID" page connect(qApp->cryptoManager()->smartcard(), &QSmartCard::tokenChanged, this, &MainWindow::updateMyEID); @@ -120,7 +119,6 @@ MainWindow::MainWindow( QWidget *parent ) connect(ui->infoStack, &MyEidInfo::changePinClicked, this, &MainWindow::changePinClicked); connect(ui->cardInfo, &CardWidget::selected, ui->selector, &QToolButton::toggle); - ui->cryptoContainerPage->tokenChanged(qApp->cryptoManager()->tokenauth()); updateMyEID(qApp->cryptoManager()->smartcard()->tokenData()); updateMyEid(qApp->cryptoManager()->smartcard()->data()); } @@ -273,7 +271,7 @@ void MainWindow::navigateToPage( Pages page, const QStringList &files, bool crea if(navigate) { cryptoDoc = std::move(cryptoContainer); - ui->cryptoContainerPage->transition(cryptoDoc.get(), qApp->cryptoManager()->tokenauth().cert()); + ui->cryptoContainerPage->transition(cryptoDoc.get()); } } @@ -334,7 +332,7 @@ void MainWindow::convertToCDoc() cryptoDoc = std::move(cryptoContainer); digiDoc.reset(); - ui->cryptoContainerPage->transition(cryptoDoc.get(), qApp->cryptoManager()->tokenauth().cert()); + ui->cryptoContainerPage->transition(cryptoDoc.get()); selectPage(CryptoDetails); FadeInNotification::success(ui->topBar, tr("Converted to crypto container!")); @@ -645,7 +643,6 @@ void MainWindow::updateMyEid(const QSmartCardData &data) pin1Blocked || pin1Locked || pin2Blocked || pin2Locked || pukBlocked); - ui->cryptoContainerPage->cardChanged(data.authCert(), pin1Blocked || pin1Locked); using enum WarningText::WarningType; if(pin1Locked) diff --git a/client/QCryptoBackend.cpp b/client/QCryptoBackend.cpp index dd15c5c93..fd6a033d7 100644 --- a/client/QCryptoBackend.cpp +++ b/client/QCryptoBackend.cpp @@ -222,9 +222,8 @@ TokenData QCryptoManager::tokensign() const { QReadLocker locker(&d->lock); retu void QCryptoManager::selectCard(const TokenData &token) { - bool isSign = SslCertificate(token.cert()).keyUsage().contains(SslCertificate::NonRepudiation); - TokenData other; { + bool isSign = SslCertificate(token.cert()).keyUsage().contains(SslCertificate::NonRepudiation); QWriteLocker locker(&d->lock); if(isSign) d->sign = token; @@ -240,14 +239,9 @@ void QCryptoManager::selectCard(const TokenData &token) d->auth = t; else d->sign = t; - other = t; break; } } - if(!isSign) - Q_EMIT authDataChanged(token); - else if(!other.isNull()) - Q_EMIT authDataChanged(other); d->smartcard.reloadCard(token, false); } @@ -308,8 +302,6 @@ void QCryptoManager::refresh() if(cacheChangedFlag) Q_EMIT cacheChanged(); - if(aold != anew) - Q_EMIT authDataChanged(anew); if(sold != snew) d->smartcard.reloadCard(snew, false); else if(aold != anew) diff --git a/client/QCryptoBackend.h b/client/QCryptoBackend.h index 023de026e..b99d45079 100644 --- a/client/QCryptoBackend.h +++ b/client/QCryptoBackend.h @@ -98,7 +98,6 @@ class QCryptoManager final : public QThread Q_SIGNALS: void cacheChanged(); - void authDataChanged(const TokenData &token); private: friend class QCryptoBackend; diff --git a/client/common_enums.h b/client/common_enums.h index 183c1f227..f0f73eaa5 100644 --- a/client/common_enums.h +++ b/client/common_enums.h @@ -40,11 +40,8 @@ enum Actions : unsigned char { ContainerCancel, ContainerClearWarning, ContainerConvert, - ContainerEncrypt, - EncryptContainer, EncryptContainerSuccess, - DecryptContainer, DecryptContainerSuccess, SignatureAdd, diff --git a/client/translations/en.ts b/client/translations/en.ts index 341ccfaa4..07cb0b1d3 100644 --- a/client/translations/en.ts +++ b/client/translations/en.ts @@ -78,10 +78,6 @@ AddressItem - - (Yourself) - (Yourself) - digi-ID digi-ID @@ -513,6 +509,10 @@ It is removed along with the container. It is removed along with the container. + + Failed to decrypt document + Failed to decrypt document + In order to view Validity Confirmation Sheet there has to be at least one printer installed! In order to view Validity Confirmation Sheet there has to be at least one printer installed! @@ -1019,10 +1019,6 @@ DigiDoc is created for managing Estonian eIDs and is the official digital signing and encryption application. DigiDoc is created for managing Estonian eIDs and is the official digital signing and encryption application. - - Skip introductions - Skip introductions → - The DigiDoc application allows you to: The DigiDoc application allows you to: @@ -1123,10 +1119,6 @@ Continue Continue - - View introduction - View introduction - View next intro View next intro @@ -1135,18 +1127,6 @@ Enter the application Enter the application - - Go to signing intro - Go to signing intro - - - Go to EID intro - Go to EID intro - - - Go to encryption intro - Go to encryption intro - "My eID" also provides a good overview of the status and contact information of the ID card inserted in the card reader. "My eID" also provides a good overview of the status and contact information of the ID card inserted in the card reader. @@ -1348,10 +1328,6 @@ LDAP server is unavailable. Encrypt Encrypt - - Decrypt - Decrypt - Sign Sign diff --git a/client/translations/et.ts b/client/translations/et.ts index 93976315f..0754fdb9d 100644 --- a/client/translations/et.ts +++ b/client/translations/et.ts @@ -78,10 +78,6 @@ AddressItem - - (Yourself) - (Sina ise) - digi-ID digi-ID @@ -513,6 +509,10 @@ It is removed along with the container. Koos sellega eemaldatakse ka ümbrik. + + Failed to decrypt document + Dokumendi dekrüpteerimine ebaõnnestus + In order to view Validity Confirmation Sheet there has to be at least one printer installed! Digitaalallkirjade kinnituslehe kuvamiseks peab olema arvutis vähemalt üks printer seadistatud! @@ -1019,10 +1019,6 @@ DigiDoc is created for managing Estonian eIDs and is the official digital signing and encryption application. DigiDoc on loodud Eesti eID-de haldamiseks ja on ametlik rakendus dokumentide digitaalseks allkirjastamiseks ja krüpteerimiseks. - - Skip introductions - Jäta tutvustused vahele → - The DigiDoc application allows you to: DigiDoc rakendus võimaldab Sinul: @@ -1123,10 +1119,6 @@ Continue Jätka - - View introduction - Vaata tutvustust - View next intro Järgmine tutvustus @@ -1135,18 +1127,6 @@ Enter the application Sisene rakendusse - - Go to signing intro - Mine allkirjastamise tutvustuse juurde - - - Go to EID intro - Mine eID tutvustuse juurde - - - Go to encryption intro - Mine krüpteerimise tutvustuse juurde - "My eID" also provides a good overview of the status and contact information of the ID card inserted in the card reader. "Minu eID" annab ka hea ülevaate kaardilugejasse sisestatud ID-kaardi staatusest ja kontaktandmetest. @@ -1348,10 +1328,6 @@ LDAP serveriga ei saa ühendust. Encrypt Krüpteeri - - Decrypt - Dekrüpteeri - Sign Allkirjasta diff --git a/client/widgets/AddressItem.cpp b/client/widgets/AddressItem.cpp index ebeb6d029..e32cba0f7 100644 --- a/client/widgets/AddressItem.cpp +++ b/client/widgets/AddressItem.cpp @@ -20,31 +20,31 @@ #include "AddressItem.h" #include "ui_AddressItem.h" +#include "Application.h" #include "CryptoDoc.h" +#include "QCryptoBackend.h" #include "SslCertificate.h" +#include "TokenData.h" #include "dialogs/KeyDialog.h" #include using namespace ria::qdigidoc4; -class AddressItem::Private: public Ui::AddressItem +struct AddressItem::Private: public Ui::AddressItem { -public: - Private(const CKey& _key) : key(_key) {} - - QString code; CKey key; + QString code; QString label; QDateTime expireDate; - bool yourself = false; + TokenData token; + ContainerState state = Uninitialized; }; AddressItem::AddressItem(const CKey &key, Type type, QWidget *parent) : Item(parent) - , ui(new Private(key)) + , ui(new Private{.key = key}) { - ui->key = key; ui->setupUi(this); if(type == Icon) ui->icon->load(QStringLiteral(":/images/icon_Krypto_small.svg")); @@ -89,14 +89,14 @@ AddressItem::AddressItem(const CKey &key, Type type, QWidget *parent) connect(ui->add, &QToolButton::clicked, this, [this]{ emit add(this);}); connect(ui->remove, &QToolButton::clicked, this, [this]{ emit remove(this);}); - connect(ui->decrypt, &QToolButton::clicked, this, [this] { - emit decrypt(&ui->key.lock); - }); + connect(ui->decrypt, &QToolButton::clicked, this, [this] { emit decrypt(ui->token); }); + connect(qApp->cryptoManager(), &QCryptoManager::cacheChanged, this, &AddressItem::setDecryptVisible); + setName(); setIdType(); ui->add->setVisible(type == Add); ui->remove->setVisible(type != Add); - ui->decrypt->setVisible(ui->key.lock.type == libcdoc::Lock::PASSWORD); + setDecryptVisible(); } AddressItem::~AddressItem() @@ -122,15 +122,6 @@ const CKey& AddressItem::getKey() const return ui->key; } -void AddressItem::idChanged(const SslCertificate &cert) { - ui->yourself = false; - if (ui->key.lock.isPKI()) { - const auto &key = ui->key.lock.getBytes(libcdoc::Lock::RCPT_KEY); - ui->yourself = cert.publicKey().toDer() == QByteArray::fromRawData((const char*)key.data(), key.size()); - } - setName(); -} - void AddressItem::initTabOrder(QWidget *item) { setTabOrder(item, ui->name); @@ -149,18 +140,39 @@ void AddressItem::mouseReleaseEvent(QMouseEvent * /*event*/) { (new KeyDialog(ui->key, this))->open(); } +TokenData AddressItem::tokenForLock(const libcdoc::Lock &lock) +{ + if(!lock.isPKI()) + return {}; + const auto &key = lock.getBytes(libcdoc::Lock::RCPT_KEY); + QByteArray rcpt = QByteArray::fromRawData((const char*)key.data(), key.size()); + for(const TokenData &token: qApp->cryptoManager()->cache()) + if(SslCertificate(token.cert()).publicKeyDer() == rcpt) + return token; + return {}; +} + +void AddressItem::setDecryptVisible() +{ + ui->token = tokenForLock(ui->key.lock); + ui->decrypt->setVisible(ui->state == EncryptedContainer && + (ui->key.lock.type == libcdoc::Lock::PASSWORD || !ui->token.isNull())); +} + void AddressItem::setName() { ui->name->setText(QStringLiteral("%1 %2") - .arg(ui->label.toHtmlEscaped(), (ui->yourself ? ui->code + tr(" (Yourself)") : ui->code).toHtmlEscaped())); + .arg(ui->label.toHtmlEscaped(), ui->code.toHtmlEscaped())); if(ui->name->text().isEmpty()) ui->name->hide(); } void AddressItem::stateChange(ContainerState state) { + ui->state = state; if(ui->add->isHidden()) ui->remove->setVisible(state == UnencryptedContainer); + setDecryptVisible(); } void AddressItem::setIdType(const SslCertificate &cert) { diff --git a/client/widgets/AddressItem.h b/client/widgets/AddressItem.h index 265782648..e37b28131 100644 --- a/client/widgets/AddressItem.h +++ b/client/widgets/AddressItem.h @@ -22,6 +22,7 @@ #include "widgets/Item.h" struct CKey; +class TokenData; namespace libcdoc { struct Lock; } @@ -41,21 +42,23 @@ class AddressItem final : public Item ~AddressItem() final; const CKey& getKey() const; - void idChanged(const SslCertificate &cert) final; void initTabOrder(QWidget *item) final; QWidget* lastTabWidget() final; void stateChange(ria::qdigidoc4::ContainerState state) final; signals: - void decrypt(const libcdoc::Lock *lock); + void decrypt(const TokenData &token); private: void changeEvent(QEvent *event) final; void mouseReleaseEvent(QMouseEvent *event) final; + void setDecryptVisible(); void setName(); void setIdType(); void setIdType(const SslCertificate& cert); - class Private; + static TokenData tokenForLock(const libcdoc::Lock &lock); + + struct Private; Private *ui; }; diff --git a/client/widgets/AddressItem.ui b/client/widgets/AddressItem.ui index a67c48600..4635c1379 100644 --- a/client/widgets/AddressItem.ui +++ b/client/widgets/AddressItem.ui @@ -47,7 +47,7 @@ QLabel[label="good"] { color: #1A641B; background: #EAF8EA; } -#add, #decrypt { +#add { padding: 9px 8px; font-size: 12px; font-weight: 700; @@ -55,13 +55,30 @@ border-radius: 4px; border: none; color: #2F70B6; } -#add:hover, #add:focus, -#decrypt:hover, #decrypt:focus { +#add:hover, #add:focus { background-color: #EAF1F8; } -#add:pressed, #decrypt:pressed { +#add:pressed { background-color: #BFD3E8; } +#decrypt { +padding: 10px 12px; +font-size: 14px; +font-weight: 700; +border-radius: 4px; +border: none; +color: #FFFFFF; +background-color: #2F70B6; +} +#decrypt:hover, #decrypt:focus { +background-color: #2B66A6; +} +#decrypt:pressed { +background-color: #215081; +} +#decrypt:disabled { +background-color: #82A9D3; +} #remove:hover, #remove:focus { icon: url(:/images/icon_remove_hover.svg); } @@ -110,7 +127,7 @@ icon: url(:/images/icon_remove_clicked.svg); Qt::TabFocus - MARI MAASIKAS MUSTIKAS 48405050123 (Sina ise) + MARI MAASIKAS MUSTIKAS 48405050123 true diff --git a/client/widgets/ContainerPage.cpp b/client/widgets/ContainerPage.cpp index 9cf7447c7..5ffac56d8 100644 --- a/client/widgets/ContainerPage.cpp +++ b/client/widgets/ContainerPage.cpp @@ -66,7 +66,6 @@ ContainerPage::ContainerPage(QWidget *parent) connect(btn, &QAbstractButton::clicked, this, [this,code] { emit action(code); }); }; - connect(mainAction, &MainAction::action, this, &ContainerPage::action); connect(ui->cancel, &QPushButton::clicked, this, [this] { window()->setWindowFilePath({}); window()->setWindowTitle(tr("DigiDoc4 Client")); @@ -114,18 +113,6 @@ ContainerPage::~ContainerPage() delete ui; } -void ContainerPage::cardChanged(const SslCertificate &cert, bool isBlocked) -{ - emit ui->rightPane->idChanged(cert); - this->isBlocked = isBlocked; - emit certChanged(cert); -} - -void ContainerPage::tokenChanged(const TokenData &token) -{ - cardChanged(token.cert(), token.data(QStringLiteral("blocked")).toBool()); -} - void ContainerPage::clear(int code) { ui->leftPane->clear(); @@ -165,11 +152,12 @@ void ContainerPage::changeEvent(QEvent* event) QWidget::changeEvent(event); } -void ContainerPage::decrypt(CryptoDoc *container, const libcdoc::Lock *lock, const QByteArray &secret) { +void ContainerPage::decrypt(CryptoDoc *container, const libcdoc::Lock &lock, const QByteArray &secret, + std::unique_ptr &&backend) { WaitDialogHolder waitDialog(this, tr("Decrypting")); - if (!container->decrypt(lock, secret)) + if (!container->decrypt(lock, secret, std::move(backend))) return; - transition(container, QSslCertificate{}); + transition(container); emit action(DecryptContainerSuccess); } @@ -201,21 +189,18 @@ void ContainerPage::encrypt(CryptoDoc *container) { QString label; QByteArray secret; - QSslCertificate cert; if(isPasswordEncryption()) { PasswordDialog p(PasswordDialog::Mode::ENCRYPT, this); if(!p.exec()) return; label = p.label(); secret = p.secret(); - } else { - cert = qApp->cryptoManager()->tokenauth().cert(); } WaitDialogHolder waitDialog(this, tr("Encrypting")); if(!container->encrypt(container->fileName(), label, secret)) return; - transition(container, cert); + transition(container); emit action(EncryptContainerSuccess); } @@ -232,7 +217,7 @@ bool ContainerPage::isPasswordEncryption() const return !ui->encryptMethodArea->isHidden() && ui->encryptMethod->currentIndex() == 1; } -void ContainerPage::transition(CryptoDoc *container, const QSslCertificate &cert) +void ContainerPage::transition(CryptoDoc *container) { disconnect(ui->leftPane, &ItemList::removed, container, nullptr); connect(ui->leftPane, &ItemList::removed, container, [this, container](int index) { @@ -258,12 +243,6 @@ void ContainerPage::transition(CryptoDoc *container, const QSslCertificate &cert ui->rightPane->removeItem(index); mainAction->setEnabled(isEncryptEnabled(container)); }); - disconnect(this, &ContainerPage::certChanged, container, nullptr); - connect(this, &ContainerPage::certChanged, container, [this, container](const SslCertificate &cert) { - isSupported = container->state() & UnencryptedContainer || container->canDecrypt(cert); - if(container->state() & EncryptedContainer) - mainAction->setEnabled(isSupported && !isBlocked); - }); disconnect(ui->changeLocation, &QPushButton::clicked, container, nullptr); connect(ui->changeLocation, &QPushButton::clicked, container, [container, this] { QString to = FileDialog::getSaveFileName(this, FileDialog::tr("Move file"), container->fileName()); @@ -283,24 +262,14 @@ void ContainerPage::transition(CryptoDoc *container, const QSslCertificate &cert connect(ui->encryptMethod, &QTabBar::currentChanged, container, [this, container] { mainAction->setEnabled(isEncryptEnabled(container)); }); - disconnect(mainAction, &MainAction::action, container, nullptr); - connect(mainAction, &MainAction::action, container, [container, this](int action) { - switch (action) - { - case EncryptContainer: + disconnect(mainAction, &MainAction::clicked, container, nullptr); + connect(mainAction, &MainAction::clicked, container, [container, this] { + if(container->state() == UnencryptedContainer) encrypt(container); - break; - case DecryptContainer: - decrypt(container, nullptr, {}); - break; - default: - break; - } }); clear(ContainerClearWarning); ui->encryptMethod->setCurrentIndex(0); - isSupported = container->state() & UnencryptedContainer || container->canDecrypt(cert); setHeader(container->fileName()); ui->leftPane->init(fileName, QT_TRANSLATE_NOOP("ItemList", "Encrypted files")); ui->rightPane->init(ItemList::ItemAddress, QT_TRANSLATE_NOOP("ItemList", "Recipients")); @@ -309,15 +278,23 @@ void ContainerPage::transition(CryptoDoc *container, const QSslCertificate &cert hasUnsupported = hasUnsupported || (key.rcpt_cert.isNull() && !key.lock.isValid()); auto *addr = new AddressItem(key, AddressItem::Icon, ui->rightPane); ui->rightPane->addWidget(addr); - connect(addr, &AddressItem::decrypt, container, [container, key, this] { - if (key.lock.type != libcdoc::Lock::Type::PASSWORD) - return; - PasswordDialog p(PasswordDialog::Mode::DECRYPT, this); - auto params = libcdoc::Lock::parseLabel(key.lock.label); - p.setLabel(QString::fromStdString(params.contains("label") ? params["label"] : key.lock.label)); - if (!p.exec()) - return; - decrypt(container, &key.lock, p.secret()); + connect(addr, &AddressItem::decrypt, container, [container, key, this](const TokenData &token) { + if (key.lock.type == libcdoc::Lock::Type::PASSWORD) { + PasswordDialog p(PasswordDialog::Mode::DECRYPT, this); + auto params = libcdoc::Lock::parseLabel(key.lock.label); + p.setLabel(QString::fromStdString(params.contains("label") ? params["label"] : key.lock.label)); + if (!p.exec()) + return; + decrypt(container, key.lock, p.secret(), {}); + } + else if(auto val = QCryptoBackend::getBackend(token)) + decrypt(container, key.lock, {}, std::unique_ptr(val.value())); + else if(val.error() != QCryptoBackend::PinCanceled) { + WarningDialog::create(this) + ->withTitle(tr("Failed to decrypt document")) + ->withText(QCryptoBackend::errorString(val.error())) + ->exec(); + } }); } if(hasUnsupported) @@ -397,6 +374,8 @@ void ContainerPage::transition(DigiDoc* container) connect(container, &DigiDoc::destroyed, this, [this] { clear(ContainerClearWarning); }); + disconnect(mainAction, &MainAction::clicked, this, nullptr); + connect(mainAction, &MainAction::clicked, this, [this] { emit action(SignatureAdd); }); clear(ContainerClearWarning); std::map errors; @@ -517,20 +496,16 @@ void ContainerPage::updatePanes(ria::qdigidoc4::ContainerState state, CryptoDoc case SignedContainer: if(isSupported) { - mainAction->showAction(SignatureAdd); + mainAction->setEncrypt(false); mainAction->setEnabled(true); } else mainAction->hide(); break; case UnencryptedContainer: - mainAction->showAction(EncryptContainer); + mainAction->setEncrypt(true); mainAction->setEnabled(isEncryptEnabled(crypto_container)); break; - case EncryptedContainer: - mainAction->showAction(DecryptContainer); - mainAction->setEnabled(isSupported && !isBlocked); - break; default: mainAction->hide(); break; diff --git a/client/widgets/ContainerPage.h b/client/widgets/ContainerPage.h index e9f051425..a65389ff3 100644 --- a/client/widgets/ContainerPage.h +++ b/client/widgets/ContainerPage.h @@ -23,16 +23,15 @@ #include "common_enums.h" +#include + namespace libcdoc { struct Lock; } namespace Ui { class ContainerPage; } class CryptoDoc; class DigiDoc; class MainAction; -class QSslCertificate; -class SignatureItem; -class SslCertificate; -class TokenData; +class QCryptoBackend; struct WarningText; class ContainerPage final : public QWidget @@ -43,23 +42,21 @@ class ContainerPage final : public QWidget explicit ContainerPage( QWidget *parent = nullptr ); ~ContainerPage() final; - void cardChanged(const SslCertificate &cert, bool isBlocked = false); - void tokenChanged(const TokenData &token); void setHeader(const QString &file); void togglePrinting(bool enable); - void transition(CryptoDoc *container, const QSslCertificate &cert); + void transition(CryptoDoc *container); void transition(DigiDoc* container); Q_SIGNALS: void action(int code); void addFiles(const QStringList &files); - void certChanged(const SslCertificate &cert); void warning(const WarningText &warningText); private: void changeEvent(QEvent* event) final; void clear(int code); - void decrypt(CryptoDoc *container, const libcdoc::Lock *lock, const QByteArray &secret); + void decrypt(CryptoDoc *container, const libcdoc::Lock &lock, const QByteArray &secret, + std::unique_ptr &&backend); template bool deleteConfirm(C *c, int index); void elideFileName(); @@ -77,5 +74,4 @@ class ContainerPage final : public QWidget const char *cancelText = QT_TR_NOOP("Cancel"); const char *convertText = QT_TR_NOOP("Encrypt"); bool isSupported = false; - bool isBlocked = false; }; diff --git a/client/widgets/Item.cpp b/client/widgets/Item.cpp index d20755a5a..7441d42b6 100644 --- a/client/widgets/Item.cpp +++ b/client/widgets/Item.cpp @@ -23,7 +23,6 @@ #include #include -void Item::idChanged(const SslCertificate & /* cert */) {} void Item::initTabOrder(QWidget * /* item */) {} QWidget* Item::lastTabWidget() { return this; } diff --git a/client/widgets/Item.h b/client/widgets/Item.h index 3c540e381..49e433dad 100644 --- a/client/widgets/Item.h +++ b/client/widgets/Item.h @@ -31,7 +31,6 @@ class Item : public StyledWidget public: using StyledWidget::StyledWidget; - virtual void idChanged(const SslCertificate &cert); virtual void initTabOrder(QWidget *item); virtual QWidget* lastTabWidget(); diff --git a/client/widgets/ItemList.cpp b/client/widgets/ItemList.cpp index 42f7b305a..c8613ba35 100644 --- a/client/widgets/ItemList.cpp +++ b/client/widgets/ItemList.cpp @@ -34,7 +34,6 @@ ItemList::ItemList(QWidget *parent) ui->infoIcon->hide(); ui->add->hide(); connect(ui->add, &QToolButton::clicked, this, &ItemList::add); - connect(this, &ItemList::idChanged, this, [this](const SslCertificate &cert){ this->cert = cert; }); } ItemList::~ItemList() @@ -77,9 +76,7 @@ void ItemList::addWidget(Item *widget, int index, QWidget *tabIndex) } ui->itemLayout->insertWidget(index, widget); connect(widget, &Item::remove, this, &ItemList::remove); - connect(this, &ItemList::idChanged, widget, &Item::idChanged); widget->stateChange(state); - widget->idChanged(cert); widget->show(); items.push_back(widget); widget->initTabOrder(tabIndex); diff --git a/client/widgets/ItemList.h b/client/widgets/ItemList.h index fa595c492..4df0021a2 100644 --- a/client/widgets/ItemList.h +++ b/client/widgets/ItemList.h @@ -60,7 +60,6 @@ class ItemList : public QScrollArea signals: void add(); void addItem(int code); - void idChanged(const SslCertificate &cert); void keysSelected(QList keys); void removed(int row); @@ -82,7 +81,6 @@ class ItemList : public QScrollArea const char *title = ""; const char *addTitle = ""; const char *headerText = ""; - SslCertificate cert; friend class AddRecipients; }; diff --git a/client/widgets/MainAction.cpp b/client/widgets/MainAction.cpp index 19c6cbc1e..57b2828e0 100644 --- a/client/widgets/MainAction.cpp +++ b/client/widgets/MainAction.cpp @@ -48,7 +48,6 @@ background-color: #82A9D3; })")); parent->installEventFilter(this); move(parent->width() - width(), parent->height() - height()); - connect(this, &QPushButton::clicked, this, [this]{ emit action(_action); }); } void MainAction::changeEvent(QEvent* event) @@ -65,19 +64,14 @@ bool MainAction::eventFilter(QObject *watched, QEvent *event) return QWidget::eventFilter(watched, event); } -void MainAction::showAction(Actions action) +void MainAction::setEncrypt(bool encrypt) { - _action = action; + isEncrypt = encrypt; update(); show(); } void MainAction::update() { - switch(_action) - { - case EncryptContainer: return setText(tr("Encrypt")); - case DecryptContainer: return setText(tr("Decrypt")); - default: return setText(tr("Sign")); - } + setText(isEncrypt ? tr("Encrypt") : tr("Sign")); } diff --git a/client/widgets/MainAction.h b/client/widgets/MainAction.h index ac56446e3..2abe63168 100644 --- a/client/widgets/MainAction.h +++ b/client/widgets/MainAction.h @@ -30,15 +30,12 @@ class MainAction final : public QPushButton public: explicit MainAction(QWidget *parent); - void showAction(ria::qdigidoc4::Actions action); - -signals: - void action(ria::qdigidoc4::Actions action); + void setEncrypt(bool encrypt); private: void changeEvent(QEvent* event) override; bool eventFilter(QObject *watched, QEvent *event) override; void update(); - ria::qdigidoc4::Actions _action; + bool isEncrypt = false; };