From 28fbc1ff0d5a71c1e8f2c7329ee42a4309dbfb1d Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Thu, 7 Nov 2024 15:19:41 +0200 Subject: [PATCH 1/4] Icon --- client/images/icon_Krypto_small.svg | 18 +++--------------- client/widgets/AddressItem.ui | 8 ++++---- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/client/images/icon_Krypto_small.svg b/client/images/icon_Krypto_small.svg index 4fbcff5ef..bd81fc770 100644 --- a/client/images/icon_Krypto_small.svg +++ b/client/images/icon_Krypto_small.svg @@ -1,16 +1,4 @@ - - - - icon_Krüpto_small - Created with Sketch. - - - - - - - - - - + + + diff --git a/client/widgets/AddressItem.ui b/client/widgets/AddressItem.ui index ecbe557e1..9f641e565 100644 --- a/client/widgets/AddressItem.ui +++ b/client/widgets/AddressItem.ui @@ -77,14 +77,14 @@ color: #727679; - 17 - 19 + 32 + 32 - 17 - 19 + 32 + 32 From 4b061df99dad00a8502d6c5d6604fee1d39b901e Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Wed, 13 Nov 2024 13:48:24 +0200 Subject: [PATCH 2/4] Unsupported algorithm or recipient type CDOC-3 Signed-off-by: Raul Metsma --- client/CDoc1.cpp | 41 +++++++++++-------------------- client/CDoc1.h | 4 +-- client/CDoc2.cpp | 22 +++++++---------- client/Crypto.cpp | 3 ++- client/Crypto.h | 3 +-- client/CryptoDoc.cpp | 5 ++++ client/CryptoDoc.h | 9 +++++-- client/MainWindow.cpp | 23 +++++++++++------ client/QCNG.cpp | 4 +-- client/QCNG.h | 2 +- client/QCryptoBackend.h | 4 +-- client/QPKCS11.cpp | 4 +-- client/QPKCS11.h | 2 +- client/common_enums.h | 4 ++- client/dialogs/KeyDialog.cpp | 6 +---- client/translations/en.ts | 31 ++++++++++++++--------- client/translations/et.ts | 31 ++++++++++++++--------- client/translations/ru.ts | 31 ++++++++++++++--------- client/widgets/AddressItem.cpp | 4 +++ client/widgets/ContainerPage.cpp | 33 +++++++++++++++---------- client/widgets/ContainerPage.h | 2 +- client/widgets/FileList.cpp | 5 +++- client/widgets/Item.cpp | 42 ++++++++++++++++++++++++++++++++ client/widgets/Item.h | 16 ++++++++++++ client/widgets/WarningItem.cpp | 6 +++++ 25 files changed, 217 insertions(+), 120 deletions(-) diff --git a/client/CDoc1.cpp b/client/CDoc1.cpp index 78596edaa..338797151 100644 --- a/client/CDoc1.cpp +++ b/client/CDoc1.cpp @@ -41,8 +41,6 @@ const QString CDoc1::AES128GCM_MTH = QStringLiteral("http://www.w3.org/2009/xmle const QString CDoc1::AES192GCM_MTH = QStringLiteral("http://www.w3.org/2009/xmlenc11#aes192-gcm"); const QString CDoc1::AES256GCM_MTH = QStringLiteral("http://www.w3.org/2009/xmlenc11#aes256-gcm"); const QString CDoc1::RSA_MTH = QStringLiteral("http://www.w3.org/2001/04/xmlenc#rsa-1_5"); -const QString CDoc1::KWAES128_MTH = QStringLiteral("http://www.w3.org/2001/04/xmlenc#kw-aes128"); -const QString CDoc1::KWAES192_MTH = QStringLiteral("http://www.w3.org/2001/04/xmlenc#kw-aes192"); const QString CDoc1::KWAES256_MTH = QStringLiteral("http://www.w3.org/2001/04/xmlenc#kw-aes256"); const QString CDoc1::CONCATKDF_MTH = QStringLiteral("http://www.w3.org/2009/xmlenc11#ConcatKDF"); const QString CDoc1::AGREEMENT_MTH = QStringLiteral("http://www.w3.org/2009/xmlenc11#ECDH-ES"); @@ -66,7 +64,6 @@ const QHash CDoc1::ENC_MTH{ const QHash CDoc1::SHA_MTH{ {SHA256_MTH, QCryptographicHash::Sha256}, {SHA384_MTH, QCryptographicHash::Sha384}, {SHA512_MTH, QCryptographicHash::Sha512} }; -const QHash CDoc1::KWAES_SIZE{{KWAES128_MTH, 16}, {KWAES192_MTH, 24}, {KWAES256_MTH, 32}}; CDoc1::CDoc1(const QString &path) : QFile(path) @@ -108,7 +105,6 @@ CDoc1::CDoc1(const QString &path) return; CKey key; - key.id = xml.attributes().value(QLatin1String("Id")).toString(); key.recipient = xml.attributes().value(QLatin1String("Recipient")).toString(); while(!xml.atEnd()) { @@ -117,18 +113,17 @@ CDoc1::CDoc1(const QString &path) break; if(!xml.isStartElement()) continue; - // EncryptedData/KeyInfo/KeyName - if(xml.name() == QLatin1String("KeyName")) - key.name = xml.readElementText(); - // EncryptedData/KeyInfo/EncryptedKey/EncryptionMethod - else if(xml.name() == QLatin1String("EncryptionMethod")) - key.method = xml.attributes().value(QLatin1String("Algorithm")).toString(); + if(xml.name() == QLatin1String("EncryptionMethod")) + { + auto method = xml.attributes().value(QLatin1String("Algorithm")); + key.unsupported = std::max(key.unsupported, method != KWAES256_MTH && method != RSA_MTH); + } // EncryptedData/KeyInfo/EncryptedKey/KeyInfo/AgreementMethod else if(xml.name() == QLatin1String("AgreementMethod")) - key.agreement = xml.attributes().value(QLatin1String("Algorithm")).toString(); + key.unsupported = std::max(key.unsupported, xml.attributes().value(QLatin1String("Algorithm")) != AGREEMENT_MTH); // EncryptedData/KeyInfo/EncryptedKey/KeyInfo/AgreementMethod/KeyDerivationMethod else if(xml.name() == QLatin1String("KeyDerivationMethod")) - key.derive = xml.attributes().value(QLatin1String("Algorithm")).toString(); + key.unsupported = std::max(key.unsupported, xml.attributes().value(QLatin1String("Algorithm")) != CONCATKDF_MTH); // EncryptedData/KeyInfo/EncryptedKey/KeyInfo/AgreementMethod/KeyDerivationMethod/ConcatKDFParams else if(xml.name() == QLatin1String("ConcatKDFParams")) { @@ -273,16 +268,13 @@ CKey CDoc1::canDecrypt(const QSslCertificate &cert) const { if(!ENC_MTH.contains(method) || k.cert != cert || - k.cipher.isEmpty()) + k.cipher.isEmpty() || + k.unsupported) continue; - if(cert.publicKey().algorithm() == QSsl::Rsa && - k.method == RSA_MTH) + if(cert.publicKey().algorithm() == QSsl::Rsa) return k; if(cert.publicKey().algorithm() == QSsl::Ec && - !k.publicKey.isEmpty() && - KWAES_SIZE.contains(k.method) && - k.derive == CONCATKDF_MTH && - k.agreement == AGREEMENT_MTH) + !k.publicKey.isEmpty()) return k; } return {}; @@ -432,8 +424,6 @@ bool CDoc1::save(const QString &path) for(const CKey &k: qAsConst(keys)) { writeElement(w, DENC, QStringLiteral("EncryptedKey"), [&]{ - if(!k.id.isEmpty()) - w.writeAttribute(QStringLiteral("Id"), k.id); if(!k.recipient.isEmpty()) w.writeAttribute(QStringLiteral("Recipient"), k.recipient); QByteArray cipher; @@ -446,8 +436,6 @@ bool CDoc1::save(const QString &path) {QStringLiteral("Algorithm"), RSA_MTH}, }); writeElement(w, DS, QStringLiteral("KeyInfo"), [&]{ - if(!k.name.isEmpty()) - w.writeTextElement(DS, QStringLiteral("KeyName"), k.name); writeElement(w, DS, QStringLiteral("X509Data"), [&]{ writeBase64Element(w, DS, QStringLiteral("X509Certificate"), k.cert.toDer()); }); @@ -464,14 +452,13 @@ bool CDoc1::save(const QString &path) QByteArray oid = Crypto::curve_oid(peerPKey); QByteArray SsDer = Crypto::toPublicKeyDer(priv.get()); - const QString encryptionMethod = KWAES256_MTH; QString concatDigest = SHA384_MTH; switch((SsDer.size() - 1) / 2) { case 32: concatDigest = SHA256_MTH; break; case 48: concatDigest = SHA384_MTH; break; default: concatDigest = SHA512_MTH; break; } - QByteArray encryptionKey = Crypto::concatKDF(SHA_MTH[concatDigest], KWAES_SIZE[encryptionMethod], + QByteArray encryptionKey = Crypto::concatKDF(SHA_MTH[concatDigest], sharedSecret, props.value(QStringLiteral("DocumentFormat")).toUtf8() + SsDer + k.cert.toDer()); #ifndef NDEBUG qDebug() << "ENC Ss" << SsDer.toHex(); @@ -484,7 +471,7 @@ bool CDoc1::save(const QString &path) return; writeElement(w, DENC, QStringLiteral("EncryptionMethod"), { - {QStringLiteral("Algorithm"), encryptionMethod}, + {QStringLiteral("Algorithm"), KWAES256_MTH}, }); writeElement(w, DS, QStringLiteral("KeyInfo"), [&]{ writeElement(w, DENC, QStringLiteral("AgreementMethod"), { @@ -553,7 +540,7 @@ QByteArray CDoc1::transportKey(const CKey &key) if(key.isRSA) return backend->decrypt(key.cipher, false); return backend->deriveConcatKDF(key.publicKey, SHA_MTH[key.concatDigest], - int(KWAES_SIZE[key.method]), key.AlgorithmID, key.PartyUInfo, key.PartyVInfo); + key.AlgorithmID, key.PartyUInfo, key.PartyVInfo); }); if(decryptedKey.isEmpty()) { diff --git a/client/CDoc1.h b/client/CDoc1.h index 82d333c1d..5cf1f46a6 100644 --- a/client/CDoc1.h +++ b/client/CDoc1.h @@ -57,12 +57,10 @@ class CDoc1 final: public CDoc, private QFile static const QString AES128CBC_MTH, AES192CBC_MTH, AES256CBC_MTH, AES128GCM_MTH, AES192GCM_MTH, AES256GCM_MTH, - KWAES128_MTH, KWAES192_MTH, KWAES256_MTH, SHA256_MTH, SHA384_MTH, SHA512_MTH, - RSA_MTH, CONCATKDF_MTH, AGREEMENT_MTH; + RSA_MTH, CONCATKDF_MTH, AGREEMENT_MTH, KWAES256_MTH; static const QString DS, DENC, DSIG11, XENC11; static const QString MIME_ZLIB, MIME_DDOC, MIME_DDOC_OLD; static const QHash ENC_MTH; static const QHash SHA_MTH; - static const QHash KWAES_SIZE; }; diff --git a/client/CDoc2.cpp b/client/CDoc2.cpp index f0645e708..853af318d 100644 --- a/client/CDoc2.cpp +++ b/client/CDoc2.cpp @@ -432,13 +432,15 @@ CDoc2::CDoc2(const QString &path) for(const auto *recipient: *recipients){ if(recipient->fmk_encryption_method() != FMKEncryptionMethod::XOR) { + keys.append(CKey::Unsupported); qWarning() << "Unsupported FMK encryption method: skipping"; continue; } - auto fillRecipient = [&] (auto key, bool isRSA) { + auto fillRecipient = [&] (auto key, bool isRSA, bool unsupported = false) { CKey k(toByteArray(key->recipient_public_key()), isRSA); k.recipient = toString(recipient->key_label()); k.cipher = toByteArray(recipient->encrypted_fmk()); + k.unsupported = unsupported; return k; }; switch(recipient->capsule_type()) @@ -446,12 +448,7 @@ CDoc2::CDoc2(const QString &path) case Capsule::ECCPublicKeyCapsule: if(const auto *key = recipient->capsule_as_ECCPublicKeyCapsule()) { - if(key->curve() != EllipticCurve::secp384r1) - { - qWarning() << "Unsupported ECC curve: skipping"; - continue; - } - CKey k = fillRecipient(key, false); + CKey k = fillRecipient(key, false, key->curve() != EllipticCurve::secp384r1); k.publicKey = toByteArray(key->sender_public_key()); keys.append(std::move(k)); } @@ -467,8 +464,8 @@ CDoc2::CDoc2(const QString &path) case Capsule::KeyServerCapsule: if(const auto *server = recipient->capsule_as_KeyServerCapsule()) { - auto fillKeyServer = [&] (auto key, bool isRSA) { - CKey k = fillRecipient(key, isRSA); + auto fillKeyServer = [&] (auto key, bool isRSA, bool unsupported = false) { + CKey k = fillRecipient(key, isRSA, unsupported); k.keyserver_id = toString(server->keyserver_id()); k.transaction_id = toString(server->transaction_id()); return k; @@ -477,21 +474,20 @@ CDoc2::CDoc2(const QString &path) { case ServerDetailsUnion::ServerEccDetails: if(const auto *eccDetails = server->recipient_key_details_as_ServerEccDetails()) - { - if(eccDetails->curve() == EllipticCurve::secp384r1) - keys.append(fillKeyServer(eccDetails, false)); - } + keys.append(fillKeyServer(eccDetails, false, eccDetails->curve() != EllipticCurve::secp384r1)); break; case ServerDetailsUnion::ServerRsaDetails: if(const auto *rsaDetails = server->recipient_key_details_as_ServerRsaDetails()) keys.append(fillKeyServer(rsaDetails, true)); break; default: + keys.append(CKey::Unsupported); qWarning() << "Unsupported Key Server Details: skipping"; } } break; default: + keys.append(CKey::Unsupported); qWarning() << "Unsupported Key Details: skipping"; } } diff --git a/client/Crypto.cpp b/client/Crypto.cpp index 607e961ec..ac6b2ad73 100644 --- a/client/Crypto.cpp +++ b/client/Crypto.cpp @@ -144,10 +144,11 @@ QByteArray Crypto::cipher(const EVP_CIPHER *cipher, const QByteArray &key, QByte return data; } -QByteArray Crypto::concatKDF(QCryptographicHash::Algorithm hashAlg, quint32 keyDataLen, const QByteArray &z, const QByteArray &otherInfo) +QByteArray Crypto::concatKDF(QCryptographicHash::Algorithm hashAlg, const QByteArray &z, const QByteArray &otherInfo) { if(z.isEmpty()) return z; + quint32 keyDataLen = 32; auto hashLen = quint32(QCryptographicHash::hashLength(hashAlg)); auto reps = quint32(std::ceil(double(keyDataLen) / double(hashLen))); QCryptographicHash md(hashAlg); diff --git a/client/Crypto.h b/client/Crypto.h index 58e8972bd..7ed6d00ca 100644 --- a/client/Crypto.h +++ b/client/Crypto.h @@ -53,8 +53,7 @@ class Crypto static QByteArray aes_wrap(const QByteArray &key, const QByteArray &data, bool encrypt); static QByteArray cipher(const EVP_CIPHER *cipher, const QByteArray &key, QByteArray &data, bool encrypt); static QByteArray curve_oid(EVP_PKEY *key); - static QByteArray concatKDF(QCryptographicHash::Algorithm digestMethod, - quint32 keyDataLen, const QByteArray &z, const QByteArray &otherInfo); + static QByteArray concatKDF(QCryptographicHash::Algorithm digestMethod, const QByteArray &z, const QByteArray &otherInfo); static QByteArray derive(EVP_PKEY *priv, EVP_PKEY *pub); static QByteArray encrypt(EVP_PKEY *pub, int padding, const QByteArray &data); static QByteArray expand(const QByteArray &key, const QByteArray &info, int len = 32); diff --git a/client/CryptoDoc.cpp b/client/CryptoDoc.cpp index 2d04f1f25..442ebf6a8 100644 --- a/client/CryptoDoc.cpp +++ b/client/CryptoDoc.cpp @@ -217,6 +217,10 @@ QString CDocumentModel::save(int row, const QString &path) const return fileName; } +CKey::CKey(Tag) + : unsupported(true) +{} + CKey::CKey(const QSslCertificate &c) { setCert(c); @@ -247,6 +251,7 @@ void CKey::setCert(const QSslCertificate &c) } + CryptoDoc::CryptoDoc( QObject *parent ) : QObject(parent) , d(new Private) diff --git a/client/CryptoDoc.h b/client/CryptoDoc.h index 8929550ed..fc490392e 100644 --- a/client/CryptoDoc.h +++ b/client/CryptoDoc.h @@ -32,7 +32,12 @@ class QSslKey; class CKey { public: + enum Tag + { + Unsupported, + }; CKey() = default; + CKey(Tag); CKey(QByteArray _key, bool _isRSA): key(std::move(_key)), isRSA(_isRSA) {} CKey(const QSslCertificate &cert); bool operator==(const CKey &other) const { return other.key == key; } @@ -41,10 +46,10 @@ class CKey QByteArray key, cipher, publicKey; QSslCertificate cert; - bool isRSA = false; + bool isRSA = false, unsupported = false; QString recipient; // CDoc1 - QString agreement, concatDigest, derive, method, id, name; + QString concatDigest; QByteArray AlgorithmID, PartyUInfo, PartyVInfo; // CDoc2 QByteArray encrypted_kek; diff --git a/client/MainWindow.cpp b/client/MainWindow.cpp index cacd59833..2fbb8d71b 100644 --- a/client/MainWindow.cpp +++ b/client/MainWindow.cpp @@ -115,17 +115,17 @@ MainWindow::MainWindow( QWidget *parent ) // Refresh ID card info in card widget connect(qApp->signer(), &QSigner::cacheChanged, this, &MainWindow::updateSelector); connect(&QPCSC::instance(), &QPCSC::statusChanged, this, &MainWindow::updateSelector); - connect(qApp->signer(), &QSigner::signDataChanged, this, [=](const TokenData &token){ + connect(qApp->signer(), &QSigner::signDataChanged, this, [this](const TokenData &token) { updateSelectorData(token); updateMyEID(token); ui->signContainerPage->cardChanged(token.cert()); }); - connect(qApp->signer(), &QSigner::authDataChanged, this, [=](const TokenData &token){ + connect(qApp->signer(), &QSigner::authDataChanged, this, [this](const TokenData &token) { updateSelectorData(token); updateMyEID(token); ui->cryptoContainerPage->cardChanged(token.cert()); if(cryptoDoc) - ui->cryptoContainerPage->update(cryptoDoc->canDecrypt(token.cert()), cryptoDoc); + ui->cryptoContainerPage->update(cryptoDoc, token.cert()); }); QPCSC::instance().start(); @@ -143,7 +143,7 @@ MainWindow::MainWindow( QWidget *parent ) connect(ui->signContainerPage, &ContainerPage::addFiles, this, [this](const QStringList &files) { openFiles(files, true); } ); connect(ui->signContainerPage, &ContainerPage::fileRemoved, this, &MainWindow::removeSignatureFile); connect(ui->signContainerPage, &ContainerPage::removed, this, &MainWindow::removeSignature); - connect(ui->signContainerPage, &ContainerPage::warning, this, [this](const WarningText &warningText) { + connect(ui->signContainerPage, &ContainerPage::warning, this, [this](WarningText warningText) { ui->warnings->showWarning(warningText); ui->signature->warningIcon(true); }); @@ -153,6 +153,10 @@ MainWindow::MainWindow( QWidget *parent ) connect(ui->cryptoContainerPage, &ContainerPage::fileRemoved, this, &MainWindow::removeCryptoFile); connect(ui->cryptoContainerPage, &ContainerPage::keysSelected, this, &MainWindow::updateKeys); connect(ui->cryptoContainerPage, &ContainerPage::removed, this, &MainWindow::removeAddress); + connect(ui->cryptoContainerPage, &ContainerPage::warning, this, [this](WarningText warningText) { + ui->warnings->showWarning(warningText); + ui->crypto->warningIcon(true); + }); connect(ui->accordion, &Accordion::changePin1Clicked, this, &MainWindow::changePin1Clicked); connect(ui->accordion, &Accordion::changePin2Clicked, this, &MainWindow::changePin2Clicked); @@ -547,6 +551,10 @@ void MainWindow::onCryptoAction(int action, const QString &/*id*/, const QString cryptoDoc->saveCopy(target); break; } + case ClearCryptoWarning: + ui->crypto->warningIcon(false); + ui->warnings->closeWarnings(CryptoDetails); + break; case ContainerEmail: if( cryptoDoc ) containerToEmail( cryptoDoc->fileName() ); @@ -682,6 +690,7 @@ void MainWindow::openContainer(bool signature) void MainWindow::resetCryptoDoc(CryptoDoc *doc) { + ui->crypto->warningIcon(false); ui->cryptoContainerPage->clear(); delete cryptoDoc; cryptoDoc = doc; @@ -882,7 +891,7 @@ void MainWindow::removeAddress(int index) if(cryptoDoc) { cryptoDoc->removeKey(index); - ui->cryptoContainerPage->transition(cryptoDoc, qApp->signer()->tokenauth().cert()); + ui->cryptoContainerPage->update(cryptoDoc, qApp->signer()->tokenauth().cert()); } } @@ -1077,7 +1086,7 @@ void MainWindow::updateKeys(const QList &keys) cryptoDoc->removeKey(i); for(const auto &key: keys) cryptoDoc->addKey(key); - ui->cryptoContainerPage->update(cryptoDoc->canDecrypt(qApp->signer()->tokenauth().cert()), cryptoDoc); + ui->cryptoContainerPage->update(cryptoDoc, qApp->signer()->tokenauth().cert()); } void MainWindow::containerSummary() @@ -1094,7 +1103,7 @@ void MainWindow::containerSummary() dialog->printer()->setPageSize( QPageSize( QPageSize::A4 ) ); dialog->printer()->setPageOrientation( QPageLayout::Portrait ); dialog->setMinimumHeight( 700 ); - connect(dialog, &QPrintPreviewDialog::paintRequested, digiDoc, [=](QPrinter *printer){ + connect(dialog, &QPrintPreviewDialog::paintRequested, digiDoc, [this](QPrinter *printer) { PrintSheet(digiDoc, printer); }); dialog->exec(); diff --git a/client/QCNG.cpp b/client/QCNG.cpp index 2e2bb1324..a99d511de 100644 --- a/client/QCNG.cpp +++ b/client/QCNG.cpp @@ -100,7 +100,7 @@ QByteArray QCNG::derive(const QByteArray &publicKey, F &&func) const }); } -QByteArray QCNG::deriveConcatKDF(const QByteArray &publicKey, QCryptographicHash::Algorithm digest, int keySize, +QByteArray QCNG::deriveConcatKDF(const QByteArray &publicKey, QCryptographicHash::Algorithm digest, const QByteArray &algorithmID, const QByteArray &partyUInfo, const QByteArray &partyVInfo) const { return derive(publicKey, [&](NCRYPT_SECRET_HANDLE sharedSecret, QByteArray &derived) { @@ -126,7 +126,7 @@ QByteArray QCNG::deriveConcatKDF(const QByteArray &publicKey, QCryptographicHash return err; derived.resize(int(size)); if(SUCCEEDED(err = NCryptDeriveKey(sharedSecret, BCRYPT_KDF_SP80056A_CONCAT, ¶ms, PBYTE(derived.data()), size, &size, 0))) - derived.resize(keySize); + derived.resize(32); return err; }); } diff --git a/client/QCNG.h b/client/QCNG.h index cf8c86616..279860ab5 100644 --- a/client/QCNG.h +++ b/client/QCNG.h @@ -33,7 +33,7 @@ class QCNG final: public QCryptoBackend QList tokens() const final; QByteArray decrypt(const QByteArray &data, bool oaep) const final; - QByteArray deriveConcatKDF(const QByteArray &publicKey, QCryptographicHash::Algorithm digest, int keySize, + QByteArray deriveConcatKDF(const QByteArray &publicKey, QCryptographicHash::Algorithm digest, const QByteArray &algorithmID, const QByteArray &partyUInfo, const QByteArray &partyVInfo) const final; QByteArray deriveHMACExtract(const QByteArray &publicKey, const QByteArray &salt, int keySize) const final; PinStatus lastError() const final; diff --git a/client/QCryptoBackend.h b/client/QCryptoBackend.h index 9a7035366..210826b96 100644 --- a/client/QCryptoBackend.h +++ b/client/QCryptoBackend.h @@ -28,7 +28,7 @@ class QCryptoBackend: public QObject { Q_OBJECT public: - enum PinStatus + enum PinStatus : quint8 { PinOK, PinCanceled, @@ -43,7 +43,7 @@ class QCryptoBackend: public QObject virtual QList tokens() const = 0; virtual QByteArray decrypt(const QByteArray &data, bool oaep) const = 0; - virtual QByteArray deriveConcatKDF(const QByteArray &publicKey, QCryptographicHash::Algorithm digest, int keySize, + virtual QByteArray deriveConcatKDF(const QByteArray &publicKey, QCryptographicHash::Algorithm digest, const QByteArray &algorithmID, const QByteArray &partyUInfo, const QByteArray &partyVInfo) const = 0; virtual QByteArray deriveHMACExtract(const QByteArray &publicKey, const QByteArray &salt, int keySize) const = 0; virtual PinStatus lastError() const { return PinOK; } diff --git a/client/QPKCS11.cpp b/client/QPKCS11.cpp index 709c13eba..b98c3bad2 100644 --- a/client/QPKCS11.cpp +++ b/client/QPKCS11.cpp @@ -140,9 +140,9 @@ QByteArray QPKCS11::derive(const QByteArray &publicKey) const } QByteArray QPKCS11::deriveConcatKDF(const QByteArray &publicKey, QCryptographicHash::Algorithm digest, - int keySize, const QByteArray &algorithmID, const QByteArray &partyUInfo, const QByteArray &partyVInfo) const + const QByteArray &algorithmID, const QByteArray &partyUInfo, const QByteArray &partyVInfo) const { - return Crypto::concatKDF(digest, quint32(keySize), derive(publicKey), algorithmID + partyUInfo + partyVInfo); + return Crypto::concatKDF(digest, derive(publicKey), algorithmID + partyUInfo + partyVInfo); } QByteArray QPKCS11::deriveHMACExtract(const QByteArray &publicKey, const QByteArray &salt, int keySize) const diff --git a/client/QPKCS11.h b/client/QPKCS11.h index 300e5299c..468e7e23b 100644 --- a/client/QPKCS11.h +++ b/client/QPKCS11.h @@ -30,7 +30,7 @@ class QPKCS11 final: public QCryptoBackend QByteArray decrypt(const QByteArray &data, bool oaep) const final; QByteArray derive(const QByteArray &publicKey) const; - QByteArray deriveConcatKDF(const QByteArray &publicKey, QCryptographicHash::Algorithm digest, int keySize, + QByteArray deriveConcatKDF(const QByteArray &publicKey, QCryptographicHash::Algorithm digest, const QByteArray &algorithmID, const QByteArray &partyUInfo, const QByteArray &partyVInfo) const final; QByteArray deriveHMACExtract(const QByteArray &publicKey, const QByteArray &salt, int keySize) const final; bool isLoaded() const; diff --git a/client/common_enums.h b/client/common_enums.h index 69c1b1764..c9529e7cf 100644 --- a/client/common_enums.h +++ b/client/common_enums.h @@ -54,7 +54,8 @@ enum Actions { SignatureMobile, SignatureSmartID, SignatureToken, - ClearSignatureWarning + ClearSignatureWarning, + ClearCryptoWarning, }; enum ItemType { @@ -88,6 +89,7 @@ enum WarningType { UnsupportedAsicSWarning, UnsupportedAsicCadesWarning, UnsupportedDDocWarning, + UnsupportedCDocWarning, EmptyFileWarning, }; diff --git a/client/dialogs/KeyDialog.cpp b/client/dialogs/KeyDialog.cpp index b9b662ca3..1fdac3556 100644 --- a/client/dialogs/KeyDialog.cpp +++ b/client/dialogs/KeyDialog.cpp @@ -64,15 +64,11 @@ KeyDialog::KeyDialog( const CKey &k, QWidget *parent ) }; addItem(tr("Recipient"), k.recipient); - addItem(tr("Crypto method"), k.method); - addItem(tr("Agreement method"), k.agreement); - addItem(tr("Key derivation method"), k.derive); addItem(tr("ConcatKDF digest method"), k.concatDigest); addItem(tr("Key server ID"), k.keyserver_id); addItem(tr("Transaction ID"), k.transaction_id); addItem(tr("Expiry date"), k.cert.expiryDate().toLocalTime().toString(QStringLiteral("dd.MM.yyyy hh:mm:ss"))); addItem(tr("Issuer"), SslCertificate(k.cert).issuerInfo(QSslCertificate::CommonName)); d->view->resizeColumnToContents( 0 ); - if(!k.agreement.isEmpty()) - adjustSize(); + adjustSize(); } diff --git a/client/translations/en.ts b/client/translations/en.ts index e6dad8b20..f12702b36 100644 --- a/client/translations/en.ts +++ b/client/translations/en.ts @@ -157,6 +157,10 @@ Expired on Expired on + + Unsupported cryptographic algorithm or recipient type + Unsupported cryptographic algorithm or recipient type + Application @@ -1291,18 +1295,6 @@ SHOW CERTIFICATE SHOW CERTIFICATE - - Crypto method - Crypto method - - - Agreement method - Agreement method - - - Key derivation method - Key derivation method - ConcatKDF digest method ConcatKDF digest method @@ -1338,6 +1330,13 @@ Transaction ID + + LabelItem + + The container must be decrypted in order to see the contents of an encrypted container. + The container must be decrypted in order to see the contents of an encrypted container. + + LdapSearch @@ -3162,5 +3161,13 @@ Additional licenses and components This container contains CAdES signature. You are not allowed to add or remove signatures to this container. This container contains CAdES signature. You are not allowed to add or remove signatures to this container. + + The encrypted container contains a cryptographic algorithm or recipient type that is not supported in this DigiDoc4 application version. Please make sure that you are using the latest DigiDoc4 application version. + The encrypted container contains a cryptographic algorithm or recipient type that is not supported in this DigiDoc4 application version. Please make sure that you are using the latest DigiDoc4 application version. + + + https://www.id.ee/en/article/install-id-software/ + https://www.id.ee/en/article/install-id-software/ + diff --git a/client/translations/et.ts b/client/translations/et.ts index c5ff06463..de740eb6a 100644 --- a/client/translations/et.ts +++ b/client/translations/et.ts @@ -157,6 +157,10 @@ Expired on Aegus + + Unsupported cryptographic algorithm or recipient type + Mittetoetatud krüptograafiline algoritm või adressaadi tüüp + Application @@ -1291,18 +1295,6 @@ SHOW CERTIFICATE NÄITA SERTIFIKAATI - - Crypto method - Krüpteerimismeetod - - - Agreement method - Aktsepteeritud meetod - - - Key derivation method - Võtme tuletamise meetod - ConcatKDF digest method ConcatKDF referaatmeetod @@ -1338,6 +1330,13 @@ Transaktsiooni identifikaator + + LabelItem + + The container must be decrypted in order to see the contents of an encrypted container. + Krüpteeritud ümbriku sisu nägemiseks tuleb ümbrik dekrüpteerida. + + LdapSearch @@ -3162,5 +3161,13 @@ Täiendavad litsentsid ja komponendid This container contains CAdES signature. You are not allowed to add or remove signatures to this container. Tegemist on CAdES allkirja sisaldava ümbrikuga. Sellele ümbrikule ei saa allkirja lisada ega eemaldada. + + The encrypted container contains a cryptographic algorithm or recipient type that is not supported in this DigiDoc4 application version. Please make sure that you are using the latest DigiDoc4 application version. + Krüpteeritud ümbrik sisaldab DigiDoc4 rakenduse käesolevas versioonis mittetoetatud krüptograafilist algoritmi või adressaadi tüüpi. Palun veendu, et kasutad uusimat DigiDoc4 rakenduse versiooni. + + + https://www.id.ee/en/article/install-id-software/ + https://www.id.ee/artikkel/paigalda-id-tarkvara/ + diff --git a/client/translations/ru.ts b/client/translations/ru.ts index 4f4d61cda..ea89362cd 100644 --- a/client/translations/ru.ts +++ b/client/translations/ru.ts @@ -157,6 +157,10 @@ Expired on Истекший + + Unsupported cryptographic algorithm or recipient type + Неподдерживаемый криптографический алгоритм или тип получателя + Application @@ -1291,18 +1295,6 @@ SHOW CERTIFICATE ПОКАЗАТЬ СЕРТИФИКАТ - - Crypto method - Метод шифровки - - - Agreement method - Метод подтверждения - - - Key derivation method - Метод деривации ключа - ConcatKDF digest method Метод подсчета ConcatKDF @@ -1338,6 +1330,13 @@ Идентификатор транзакции + + LabelItem + + The container must be decrypted in order to see the contents of an encrypted container. + Контейнер должен быть расшифрован, чтобы увидеть его зашифрованное содержимое. + + LdapSearch @@ -3167,5 +3166,13 @@ Additional licenses and components This container contains CAdES signature. You are not allowed to add or remove signatures to this container. Этот контейнер содержит подпись CAdES. К данному контейнеру нельзя добавить или удалить из него подпись. + + The encrypted container contains a cryptographic algorithm or recipient type that is not supported in this DigiDoc4 application version. Please make sure that you are using the latest DigiDoc4 application version. + Зашифрованный конверт содержит криптографический алгоритм или тип получателя, не поддерживаемый в текущей версии приложения DigiDoc4. Пожалуйста, убедитесь, что вы используете последнюю версию приложения DigiDoc4. + + + https://www.id.ee/en/article/install-id-software/ + https://www.id.ee/ru/artikkel/ustanovite-id-programmu/ + diff --git a/client/widgets/AddressItem.cpp b/client/widgets/AddressItem.cpp index 4cc51efc8..48794f136 100644 --- a/client/widgets/AddressItem.cpp +++ b/client/widgets/AddressItem.cpp @@ -68,6 +68,8 @@ AddressItem::AddressItem(CKey k, QWidget *parent, bool showIcon) ui->label = ui->key.recipient.toHtmlEscaped(); setIdType(); showButton(AddressItem::Remove); + if(ui->key.unsupported) + ui->idType->setText(tr("Unsupported cryptographic algorithm or recipient type")); } AddressItem::~AddressItem() @@ -135,6 +137,8 @@ void AddressItem::setName() { ui->name->setText(QStringLiteral("%1 %2") .arg(ui->label, ui->yourself ? ui->code + tr(" (Yourself)") : ui->code)); + if(ui->name->text().isEmpty()) + ui->name->hide(); } void AddressItem::showButton(ShowToolButton show) diff --git a/client/widgets/ContainerPage.cpp b/client/widgets/ContainerPage.cpp index f20391814..f5a41b8f8 100644 --- a/client/widgets/ContainerPage.cpp +++ b/client/widgets/ContainerPage.cpp @@ -37,7 +37,6 @@ #include #include #include -#include using namespace ria::qdigidoc4; @@ -290,14 +289,20 @@ void ContainerPage::showSigningButton() void ContainerPage::transition(CryptoDoc *container, const QSslCertificate &cert) { clear(); - isSupported = container && (container->state() & UnencryptedContainer || container->canDecrypt(cert)); - if(!container) - return; + emit action(ClearCryptoWarning); + isSupported = container->state() & UnencryptedContainer || container->canDecrypt(cert); setHeader(container->fileName()); + bool hasUnsupported = false; + ui->rightPane->clear(); for(const CKey &key: container->keys()) + { + hasUnsupported = std::max(hasUnsupported, key.unsupported); ui->rightPane->addWidget(new AddressItem(key, ui->rightPane, true)); - ui->leftPane->setModel(container->documentModel()); + } + if(hasUnsupported) + emit warning({UnsupportedCDocWarning}); updatePanes(container->state()); + ui->leftPane->setModel(container->documentModel()); } void ContainerPage::transition(DigiDoc* container) @@ -358,19 +363,21 @@ void ContainerPage::transition(DigiDoc* container) updatePanes(container->state()); } -void ContainerPage::update(bool canDecrypt, CryptoDoc* container) +void ContainerPage::update(CryptoDoc* container, const QSslCertificate &cert) { - isSupported = canDecrypt || container->state() & UnencryptedContainer; - if(container && container->state() & EncryptedContainer) - updateDecryptionButton(); - - if(!container) - return; - + isSupported = container->canDecrypt(cert) || container->state() & UnencryptedContainer; hasEmptyFile = false; + bool hasUnsupported = false; ui->rightPane->clear(); for(const CKey &key: container->keys()) + { + hasUnsupported = std::max(hasUnsupported, key.unsupported); ui->rightPane->addWidget(new AddressItem(key, ui->rightPane, true)); + } + if(hasUnsupported) + emit warning({UnsupportedCDocWarning}); + if(container->state() & EncryptedContainer) + updateDecryptionButton(); if(container->state() & UnencryptedContainer) showMainAction({ EncryptContainer }); } diff --git a/client/widgets/ContainerPage.h b/client/widgets/ContainerPage.h index f035d2b69..c9370fc47 100644 --- a/client/widgets/ContainerPage.h +++ b/client/widgets/ContainerPage.h @@ -52,7 +52,7 @@ class ContainerPage final : public QWidget void togglePrinting(bool enable); void transition(CryptoDoc *container, const QSslCertificate &cert); void transition(DigiDoc* container); - void update(bool canDecrypt, CryptoDoc *container); + void update(CryptoDoc *container, const QSslCertificate &cert); signals: void action(int code, const QString &info1 = {}, const QString &info2 = {}); diff --git a/client/widgets/FileList.cpp b/client/widgets/FileList.cpp index 0fd246a80..d1068ca55 100644 --- a/client/widgets/FileList.cpp +++ b/client/widgets/FileList.cpp @@ -216,6 +216,9 @@ void FileList::setModel(DocumentModel *documentModel) auto count = documentModel->rowCount(); for(int i = 0; i < count; i++) addFile(documentModel->data(i)); + if(state == EncryptedContainer && count == 0) + addWidget(new LabelItem(QT_TRANSLATE_NOOP("LabelItem", + "The container must be decrypted in order to see the contents of an encrypted container."))); } void FileList::stateChange(ria::qdigidoc4::ContainerState state) @@ -226,7 +229,7 @@ void FileList::stateChange(ria::qdigidoc4::ContainerState state) void FileList::updateDownload() { - int c = findChildren().size(); + auto c = findChildren().size(); ui->download->setVisible(state & (UnsignedSavedContainer | SignedContainer | UnencryptedContainer) && c); ui->count->setVisible(state & (UnsignedSavedContainer | SignedContainer | UnencryptedContainer) && c); ui->count->setText(QString::number(c)); diff --git a/client/widgets/Item.cpp b/client/widgets/Item.cpp index d8d2a83f6..ae85f2655 100644 --- a/client/widgets/Item.cpp +++ b/client/widgets/Item.cpp @@ -19,6 +19,48 @@ #include "Item.h" +#include +#include +#include + void Item::idChanged(const SslCertificate & /* cert */) {} void Item::initTabOrder(QWidget * /* item */) {} QWidget* Item::lastTabWidget() { return this; } + +LabelItem::LabelItem(const char *text, QWidget *parent) + : Item(parent) + , _text(text) +{ + setObjectName(QStringLiteral("LabelItem")); + setStyleSheet(QStringLiteral(R"( +QWidget { +font-family: Roboto, Helvetica; +font-size: 14px; +} +#LabelItem { +border-bottom: 1px solid rgba(217, 217, 216, 0.45); +} +#label { +color: #07142A; +} +)")); + setLayout(new QVBoxLayout); + layout()->setContentsMargins(8, 16, 8, 16); + layout()->addWidget(label = new QLabel(tr(text), this)); + label->setObjectName("label"); + label->setFocusPolicy(Qt::TabFocus); + label->setWordWrap(true); +} + +void LabelItem::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::LanguageChange) + label->setText(tr(_text)); + Item::changeEvent(event); +} + +void LabelItem::initTabOrder(QWidget *item) +{ + setTabOrder(item, label); + setTabOrder(label, lastTabWidget()); +} diff --git a/client/widgets/Item.h b/client/widgets/Item.h index a35d4ce03..3c540e381 100644 --- a/client/widgets/Item.h +++ b/client/widgets/Item.h @@ -21,6 +21,7 @@ #include "widgets/StyledWidget.h" +class QLabel; class SslCertificate; class Item : public StyledWidget @@ -38,3 +39,18 @@ class Item : public StyledWidget void add(Item* item); void remove(Item* item); }; + + +class LabelItem : public Item +{ + Q_OBJECT + +public: + LabelItem(const char *text, QWidget *parent = nullptr); + void initTabOrder(QWidget *item) override; + +private: + void changeEvent(QEvent *event) override; + QLabel *label; + const char *_text; +}; diff --git a/client/widgets/WarningItem.cpp b/client/widgets/WarningItem.cpp index 971a4cf12..09795ba3f 100644 --- a/client/widgets/WarningItem.cpp +++ b/client/widgets/WarningItem.cpp @@ -138,6 +138,12 @@ void WarningItem::lookupWarning() url = tr("https://www.id.ee/en/article/digidoc-container-format-life-cycle-2/"); _page = SignDetails; break; + case UnsupportedCDocWarning: + ui->warningText->setText(tr("The encrypted container contains a cryptographic algorithm or recipient type that is not supported in this DigiDoc4 application version. " + "Please make sure that you are using the latest DigiDoc4 application version.")); + url = tr("https://www.id.ee/en/article/install-id-software/"); + _page = CryptoDetails; + break; case EmptyFileWarning: ui->warningText->setText(tr("An empty file is attached to the container. " "Remove the empty file from the container to sign.")); From e1a8ead36c312b33cab957ee2c45e1240fa693cb Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Mon, 25 Nov 2024 11:11:16 +0200 Subject: [PATCH 3/4] Update AddressItem UI Signed-off-by: Raul Metsma --- client/images/icon_download.svg | 13 +- client/images/icon_download_hover.svg | 12 -- client/images/icon_download_pressed.svg | 12 -- client/images/icon_remove.svg | 14 +-- client/images/icon_remove_hover.svg | 13 -- client/images/icon_remove_pressed.svg | 13 -- client/images/images.qrc | 4 - client/translations/en.ts | 10 -- client/translations/et.ts | 10 -- client/translations/ru.ts | 10 -- client/widgets/AddressItem.cpp | 5 +- client/widgets/AddressItem.h | 1 - client/widgets/AddressItem.ui | 158 +++++++++++------------- client/widgets/FileItem.cpp | 8 +- client/widgets/FileItem.ui | 61 +++++---- client/widgets/FileList.cpp | 8 +- client/widgets/ItemList.ui | 28 +++-- client/widgets/LabelButton.cpp | 6 - client/widgets/LabelButton.h | 2 - client/widgets/SignatureItem.cpp | 5 +- client/widgets/SignatureItem.ui | 34 ++--- 21 files changed, 149 insertions(+), 278 deletions(-) delete mode 100644 client/images/icon_download_hover.svg delete mode 100644 client/images/icon_download_pressed.svg delete mode 100644 client/images/icon_remove_hover.svg delete mode 100644 client/images/icon_remove_pressed.svg diff --git a/client/images/icon_download.svg b/client/images/icon_download.svg index 62afabf30..9239dcf42 100644 --- a/client/images/icon_download.svg +++ b/client/images/icon_download.svg @@ -1,12 +1,3 @@ - - - - icon_download - - - - - - - + + \ No newline at end of file diff --git a/client/images/icon_download_hover.svg b/client/images/icon_download_hover.svg deleted file mode 100644 index 48a32280d..000000000 --- a/client/images/icon_download_hover.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - icon_download hover - - - - - - - - \ No newline at end of file diff --git a/client/images/icon_download_pressed.svg b/client/images/icon_download_pressed.svg deleted file mode 100644 index cc7397c60..000000000 --- a/client/images/icon_download_pressed.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - icon_download hover - - - - - - - - \ No newline at end of file diff --git a/client/images/icon_remove.svg b/client/images/icon_remove.svg index b9bf28bcc..818ad53d4 100644 --- a/client/images/icon_remove.svg +++ b/client/images/icon_remove.svg @@ -1,13 +1,3 @@ - - - - icon_remove - - - - - - - - + + \ No newline at end of file diff --git a/client/images/icon_remove_hover.svg b/client/images/icon_remove_hover.svg deleted file mode 100644 index 460c54b8a..000000000 --- a/client/images/icon_remove_hover.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - icon_remove hover - - - - - - - - - \ No newline at end of file diff --git a/client/images/icon_remove_pressed.svg b/client/images/icon_remove_pressed.svg deleted file mode 100644 index 3acabc02a..000000000 --- a/client/images/icon_remove_pressed.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - icon_remove hover - - - - - - - - - \ No newline at end of file diff --git a/client/images/images.qrc b/client/images/images.qrc index 74dbadf06..8355e5942 100644 --- a/client/images/images.qrc +++ b/client/images/images.qrc @@ -29,9 +29,7 @@ icon_checkbox_check_disabled.svg icon_checkbox_check_hover.svg icon_digitempel.svg - icon_download_hover.svg icon_download.svg - icon_download_pressed.svg icon_Edit_hover.svg icon_Edit_pressed.svg icon_Edit.svg @@ -55,9 +53,7 @@ icon_radio_check_active.svg icon_radio_check_disabled.svg icon_radio_check_hover.svg - icon_remove_hover.svg icon_remove.svg - icon_remove_pressed.svg icon_Seaded.svg icon_Seaded_hover.svg intro_crypto-select_en.png diff --git a/client/translations/en.ts b/client/translations/en.ts index f12702b36..27320d2fa 100644 --- a/client/translations/en.ts +++ b/client/translations/en.ts @@ -99,14 +99,6 @@ AddressItem - - ADD - ADD - - - ADDED - ADDED - (Yourself) (Yourself) @@ -129,12 +121,10 @@ Added - accessible Added Add - accessible Add diff --git a/client/translations/et.ts b/client/translations/et.ts index de740eb6a..17228a606 100644 --- a/client/translations/et.ts +++ b/client/translations/et.ts @@ -99,14 +99,6 @@ AddressItem - - ADD - LISA - - - ADDED - LISATUD - (Yourself) (Sina ise) @@ -129,12 +121,10 @@ Added - accessible Lisatud Add - accessible Lisa diff --git a/client/translations/ru.ts b/client/translations/ru.ts index ea89362cd..be84dd2a2 100644 --- a/client/translations/ru.ts +++ b/client/translations/ru.ts @@ -99,14 +99,6 @@ AddressItem - - ADD - ДОБАВИТЬ - - - ADDED - Добавлен - (Yourself) (Вы сами) @@ -129,12 +121,10 @@ Added - accessible Добавлен Add - accessible Добавить diff --git a/client/widgets/AddressItem.cpp b/client/widgets/AddressItem.cpp index 48794f136..2d06df9a0 100644 --- a/client/widgets/AddressItem.cpp +++ b/client/widgets/AddressItem.cpp @@ -51,11 +51,8 @@ AddressItem::AddressItem(CKey k, QWidget *parent, bool showIcon) ui->idType->setFont(Styles::font(Styles::Regular, 11)); ui->idType->installEventFilter(this); - ui->remove->setIcons(QStringLiteral("/images/icon_remove.svg"), QStringLiteral("/images/icon_remove_hover.svg"), - QStringLiteral("/images/icon_remove_pressed.svg"), 17, 17); - ui->remove->init(LabelButton::White); connect(ui->add, &QToolButton::clicked, this, [this]{ emit add(this);}); - connect(ui->remove, &LabelButton::clicked, this, [this]{ emit remove(this);}); + connect(ui->remove, &QToolButton::clicked, this, [this]{ emit remove(this);}); ui->add->setFont(Styles::font(Styles::Condensed, 12)); ui->added->setFont(ui->add->font()); diff --git a/client/widgets/AddressItem.h b/client/widgets/AddressItem.h index 54d3788db..9f04c09f4 100644 --- a/client/widgets/AddressItem.h +++ b/client/widgets/AddressItem.h @@ -30,7 +30,6 @@ class AddressItem final : public Item public: enum ShowToolButton { - None, Remove, Add, Added, diff --git a/client/widgets/AddressItem.ui b/client/widgets/AddressItem.ui index 9f641e565..e32d134a0 100644 --- a/client/widgets/AddressItem.ui +++ b/client/widgets/AddressItem.ui @@ -6,38 +6,41 @@ 0 0 - 633 - 44 + 619 + 52 - - - 0 - 44 - - - - - 14 - false - false - false - - PointingHandCursor - #AddressItem { -border: solid rgba(217, 217, 216, 0.45); -border-width: 0px 0px 1px 0px; + QWidget { +font-family: Roboto, Helvetica; +font-size: 12px; +} +#AddressItem { +border-bottom: 1px solid rgba(217, 217, 216, 0.45); background-color: #FFFFFF; -color: #000000; } #AddressItem:disabled { -background-color: #F0F0F0; +background-color: #F0F0F2; +} +#name { +color: #07142A; +font-size: 14px; +font-weight: 700; +} +#idType { +color: #07142A; +} +#expire { +color: #07142A; +background: #F3F5F7; +padding: 2px 8px; +border-radius: 8px; } QToolButton { +font-weight: 700; border-radius: 2px; border: none; color: #006EB5; @@ -56,22 +59,22 @@ color: #727679; - 0 + 8 - 5 + 8 - 0 + 8 - 7 + 8 8 - 0 + 2 @@ -87,26 +90,12 @@ color: #727679; 32 - - border: none; - - + - - - Roboto - 14 - false - false - - - Qt::TabFocus - - - border: none; + Qt::FocusPolicy::TabFocus MARI MAASIKAS MUSTIKAS 48405050123 (Sina ise) @@ -118,47 +107,42 @@ color: #727679; - - - Roboto - 11 - false - false - - - Qt::TabFocus - - - color: #727679;border: none; + Qt::FocusPolicy::TabFocus ID-card - - - + + + + Expire + + + + + + + Qt::Orientation::Horizontal + + - 19 - 19 + 40 + 20 + + + + - 19 - 19 + 24 + 24 - - - Roboto - 14 - false - false - - PointingHandCursor @@ -166,14 +150,21 @@ color: #727679; Remove - border: none; background-color: none; + border: none; background: none; - - + + + :/images/icon_remove.svg:/images/icon_remove.svg + + + + 20 + 20 + - + false @@ -190,15 +181,12 @@ color: #727679; 25 - - Added - - ADDED + Added - + @@ -215,22 +203,14 @@ color: #727679; PointingHandCursor - - Add - - ADD + Add - - LabelButton - QToolButton -
widgets/LabelButton.h
-
QSvgWidget QWidget @@ -238,6 +218,8 @@ color: #727679; 1
- + + + diff --git a/client/widgets/FileItem.cpp b/client/widgets/FileItem.cpp index 0b1a5473d..8864ab362 100644 --- a/client/widgets/FileItem.cpp +++ b/client/widgets/FileItem.cpp @@ -30,16 +30,12 @@ FileItem::FileItem(QString file, ContainerState state, QWidget *parent) { ui->setupUi(this); ui->fileName->setFont(Styles::font(Styles::Regular, 14)); - ui->download->setIcons(QStringLiteral("/images/icon_download.svg"), QStringLiteral("/images/icon_download_hover.svg"), QStringLiteral("/images/icon_download_pressed.svg"), 17, 17); - ui->download->init(LabelButton::White); - ui->remove->setIcons(QStringLiteral("/images/icon_remove.svg"), QStringLiteral("/images/icon_remove_hover.svg"), QStringLiteral("/images/icon_remove_pressed.svg"), 17, 17); - ui->remove->init(LabelButton::White); stateChange(state); connect(ui->fileName, &QToolButton::clicked, this, [this]{ emit open(this); setUnderline(false); }); - connect(ui->download, &LabelButton::clicked, this, [this]{ emit download(this); setUnderline(false); }); - connect(ui->remove, &LabelButton::clicked, this, [this]{ emit remove(this);}); + connect(ui->download, &QToolButton::clicked, this, [this]{ emit download(this); setUnderline(false); }); + connect(ui->remove, &QToolButton::clicked, this, [this]{ emit remove(this);}); setFileName(); } diff --git a/client/widgets/FileItem.ui b/client/widgets/FileItem.ui index c1bac4d24..a6393d9ac 100644 --- a/client/widgets/FileItem.ui +++ b/client/widgets/FileItem.ui @@ -67,17 +67,11 @@ text-align: left; - - - - 19 - 19 - - + - 19 - 19 + 24 + 24 @@ -86,20 +80,27 @@ text-align: left; Remove file - - - - - + + border: none + + + + :/images/icon_remove.svg:/images/icon_remove.svg + + - 19 - 19 + 20 + 20 + + + + - 19 - 19 + 24 + 24 @@ -108,17 +109,25 @@ text-align: left; Download file + + border: none + + + + :/images/icon_download.svg:/images/icon_download.svg + + + + 20 + 20 + + - - - LabelButton - QToolButton -
widgets/LabelButton.h
-
-
- + + + diff --git a/client/widgets/FileList.cpp b/client/widgets/FileList.cpp index d1068ca55..1d6bc0adf 100644 --- a/client/widgets/FileList.cpp +++ b/client/widgets/FileList.cpp @@ -22,7 +22,6 @@ #include "dialogs/FileDialog.h" #include "dialogs/WarningDialog.h" -#include "effects/ButtonHoverFilter.h" #include "widgets/FileItem.h" #include @@ -39,13 +38,8 @@ using namespace ria::qdigidoc4; FileList::FileList(QWidget *parent) : ItemList(parent) { - ui->download->setIcons(QStringLiteral("/images/icon_download.svg"), QStringLiteral("/images/icon_download_hover.svg"), - QStringLiteral("/images/icon_download_pressed.svg"), 17, 17); - ui->download->init(LabelButton::White); - ui->download->installEventFilter( - new ButtonHoverFilter(QStringLiteral(":/images/icon_download.svg"), QStringLiteral(":/images/icon_download_hover.svg"), this)); connect(ui->add, &LabelButton::clicked, this, &FileList::selectFile); - connect(ui->download, &LabelButton::clicked, this, &FileList::saveAll); + connect(ui->download, &QToolButton::clicked, this, &FileList::saveAll); } void FileList::addFile( const QString& file ) diff --git a/client/widgets/ItemList.ui b/client/widgets/ItemList.ui index 064af4a56..0a1641ee1 100644 --- a/client/widgets/ItemList.ui +++ b/client/widgets/ItemList.ui @@ -62,7 +62,7 @@ border-width: 0px 0px 1px 0px; - 4 + 0 20 @@ -233,17 +233,11 @@ border-width: 0px 0px 1px 0px; - - - - 19 - 19 - - + - 19 - 19 + 24 + 24 @@ -255,6 +249,16 @@ border-width: 0px 0px 1px 0px; border: none; + + + :/images/icon_download.svg:/images/icon_download.svg + + + + 20 + 20 + + @@ -272,13 +276,13 @@ border-width: 0px 0px 1px 0px; 0 - 0 + 8 0 - 0 + 8 diff --git a/client/widgets/LabelButton.cpp b/client/widgets/LabelButton.cpp index 03fc66980..2a72cde7f 100644 --- a/client/widgets/LabelButton.cpp +++ b/client/widgets/LabelButton.cpp @@ -74,12 +74,6 @@ void LabelButton::init(Style style, const QString &label) styleTemplate.arg(DEEP_CERULEAN, WHITE, none, QString()), styleTemplate.arg(CURIOUS_BLUE, WHITE, none, QString())); break; - case White: // Add files - setStyle( - QStringLiteral("border: none; background-color: none;"), - QStringLiteral("border: none; background-color: none;"), - QStringLiteral("border: none; background-color: none;")); - break; default: break; } } diff --git a/client/widgets/LabelButton.h b/client/widgets/LabelButton.h index f89dffde8..ea6ea3068 100644 --- a/client/widgets/LabelButton.h +++ b/client/widgets/LabelButton.h @@ -33,8 +33,6 @@ class LabelButton : public QToolButton BoxedMojo, BoxedDeepCeruleanWithCuriousBlue, // Edit DeepCeruleanWithLochmara, // Add files - White, - None }; explicit LabelButton(QWidget *parent = nullptr); diff --git a/client/widgets/SignatureItem.cpp b/client/widgets/SignatureItem.cpp index d3142d2b7..540c129e6 100644 --- a/client/widgets/SignatureItem.cpp +++ b/client/widgets/SignatureItem.cpp @@ -61,11 +61,8 @@ SignatureItem::SignatureItem(DigiDocSignature s, ContainerState /*state*/, QWidg ui->idSignTime->installEventFilter(this); ui->role->setFont(Styles::font(Styles::Regular, 11)); ui->role->installEventFilter(this); - ui->remove->setIcons(QStringLiteral("/images/icon_remove.svg"), QStringLiteral("/images/icon_remove_hover.svg"), - QStringLiteral("/images/icon_remove_pressed.svg"), 17, 17); - ui->remove->init(LabelButton::White); ui->remove->setVisible(ui->signature.container()->isSupported()); - connect(ui->remove, &LabelButton::clicked, this, [this]{ + connect(ui->remove, &QToolButton::clicked, this, [this]{ const SslCertificate c = ui->signature.cert(); auto *dlg = new WarningDialog(tr("Remove signature %1?") .arg(c.toString(c.showCN() ? QStringLiteral("CN serialNumber") : QStringLiteral("GN SN serialNumber"))), this); diff --git a/client/widgets/SignatureItem.ui b/client/widgets/SignatureItem.ui index 88582b097..c5a381413 100644 --- a/client/widgets/SignatureItem.ui +++ b/client/widgets/SignatureItem.ui @@ -113,17 +113,11 @@ background-color: #ffffff; - - - - 19 - 19 - - + - 19 - 19 + 24 + 24 @@ -132,6 +126,19 @@ background-color: #ffffff; Remove signature + + border: none + + + + :/images/icon_remove.svg:/images/icon_remove.svg + + + + 20 + 20 + + @@ -143,12 +150,9 @@ background-color: #ffffff;
QtSvg/QSvgWidget
1 - - LabelButton - QToolButton -
widgets/LabelButton.h
-
- + + + From 32612883a1100b5c42ce9b85f3e438ed9d3308af Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Mon, 25 Nov 2024 11:12:27 +0200 Subject: [PATCH 4/4] Update to new UI Signed-off-by: Raul Metsma --- client/CDoc2.cpp | 16 +++-- client/CryptoDoc.cpp | 55 +++++++++++++++++ client/CryptoDoc.h | 2 + client/translations/en.ts | 12 ++++ client/translations/et.ts | 12 ++++ client/translations/ru.ts | 12 ++++ client/widgets/AddressItem.cpp | 108 +++++++++++++++++---------------- client/widgets/AddressItem.h | 2 - client/widgets/AddressItem.ui | 47 +++++++++----- 9 files changed, 190 insertions(+), 76 deletions(-) diff --git a/client/CDoc2.cpp b/client/CDoc2.cpp index 853af318d..12a9b6376 100644 --- a/client/CDoc2.cpp +++ b/client/CDoc2.cpp @@ -274,6 +274,8 @@ namespace cdoc20 { io->skip(padding(f.size)); if(!readHeader() || h.isNull() || !h.verify()) return {}; + if(f.name.startsWith(QLatin1String("./PaxHeaders.X"))) + f.name = QString::fromUtf8(h.name.data(), std::min(h.name.size(), int(strlen(h.name.data())))); f.size = fromOctal(h.size); for(const QByteArray &data: paxData.split('\n')) { @@ -495,7 +497,10 @@ CDoc2::CDoc2(const QString &path) CKey CDoc2::canDecrypt(const QSslCertificate &cert) const { - return keys.value(keys.indexOf(CKey(cert))); + auto key = keys.value(keys.indexOf(CKey(cert))); + if(key.unsupported || (!key.transaction_id.isEmpty() && cert.expiryDate() <= QDateTime::currentDateTimeUtc())) + return {}; + return key; } bool CDoc2::decryptPayload(const QByteArray &fmk) @@ -558,6 +563,7 @@ bool CDoc2::save(const QString &path) if(!cdoc20::checkConnection()) return false; QScopedPointer nam(CheckConnection::setupNAM(req, Settings::CDOC2_POST_CERT)); + req.setRawHeader("x-expiry-time", QDateTime::currentDateTimeUtc().addMonths(6).toString(Qt::ISODate).toLatin1()); QEventLoop e; QNetworkReply *reply = nam->post(req, QJsonDocument({ {QLatin1String("recipient_id"), QLatin1String(recipient_id.toBase64())}, @@ -598,7 +604,7 @@ bool CDoc2::save(const QString &path) toVector(key.key), toVector(encrytpedKek)); recipients.push_back(cdoc20::Header::CreateRecipientRecord(builder, cdoc20::Recipients::Capsule::RSAPublicKeyCapsule, rsaPublicKey.Union(), - toString(key.recipient), toVector(xor_key), cdoc20::Header::FMKEncryptionMethod::XOR)); + toString(key.toKeyLabel()), toVector(xor_key), cdoc20::Header::FMKEncryptionMethod::XOR)); continue; } @@ -610,7 +616,7 @@ bool CDoc2::save(const QString &path) rsaKeyServer.Union(), toString(key.keyserver_id), toString(key.transaction_id)); recipients.push_back(cdoc20::Header::CreateRecipientRecord(builder, cdoc20::Recipients::Capsule::KeyServerCapsule, keyServer.Union(), - toString(key.recipient), toVector(xor_key), cdoc20::Header::FMKEncryptionMethod::XOR)); + toString(key.toKeyLabel()), toVector(xor_key), cdoc20::Header::FMKEncryptionMethod::XOR)); continue; } @@ -638,7 +644,7 @@ bool CDoc2::save(const QString &path) cdoc20::Recipients::EllipticCurve::secp384r1, toVector(key.key), toVector(ephPublicKeyDer)); recipients.push_back(cdoc20::Header::CreateRecipientRecord(builder, cdoc20::Recipients::Capsule::ECCPublicKeyCapsule, eccPublicKey.Union(), - toString(key.recipient), toVector(xor_key), cdoc20::Header::FMKEncryptionMethod::XOR)); + toString(key.toKeyLabel()), toVector(xor_key), cdoc20::Header::FMKEncryptionMethod::XOR)); continue; } @@ -651,7 +657,7 @@ bool CDoc2::save(const QString &path) eccKeyServer.Union(), toString(key.keyserver_id), toString(key.transaction_id)); recipients.push_back(cdoc20::Header::CreateRecipientRecord(builder, cdoc20::Recipients::Capsule::KeyServerCapsule, keyServer.Union(), - toString(key.recipient), toVector(xor_key), cdoc20::Header::FMKEncryptionMethod::XOR)); + toString(key.toKeyLabel()), toVector(xor_key), cdoc20::Header::FMKEncryptionMethod::XOR)); } auto offset = cdoc20::Header::CreateHeader(builder, builder.CreateVector(recipients), diff --git a/client/CryptoDoc.cpp b/client/CryptoDoc.cpp index 442ebf6a8..02f407719 100644 --- a/client/CryptoDoc.cpp +++ b/client/CryptoDoc.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -250,6 +251,60 @@ void CKey::setCert(const QSslCertificate &c) isRSA = k.algorithm() == QSsl::Rsa; } +QHash CKey::fromKeyLabel() const +{ + QHash result; + if(!recipient.startsWith(QLatin1String("data:"), Qt::CaseInsensitive)) + return result; + QString payload = recipient.mid(5); + QString mimeType; + QString encoding; + if(auto pos = payload.indexOf(','); pos != -1) + { + mimeType = payload.left(pos); + payload = payload.mid(pos + 1); + if(auto header = mimeType.split(';'); header.size() == 2) + { + mimeType = header.value(0); + encoding = header.value(1); + } + } + if(!mimeType.isEmpty() && mimeType != QLatin1String("application/x-www-form-urlencoded")) + return result; + if(encoding == QLatin1String("base64")) + payload = QByteArray::fromBase64(payload.toLatin1()); + ; + for(const auto &[key,value]: QUrlQuery(payload).queryItems(QUrl::FullyDecoded)) + result[key.toLower()] = value; + if(!result.contains(QStringLiteral("type")) || !result.contains(QStringLiteral("v"))) + result.clear(); + return result; +} + +QString CKey::toKeyLabel() const +{ + if(cert.isNull()) + return recipient; + QDateTime exp = cert.expiryDate(); + if(Settings::CDOC2_USE_KEYSERVER) + exp = std::min(exp, QDateTime::currentDateTimeUtc().addMonths(6)); + auto escape = [](QString data) { return data.replace(',', QLatin1String("%2C")); }; + QString type = QStringLiteral("ID-card"); + if(auto t = SslCertificate(cert).type(); t & SslCertificate::EResidentSubType) + type = QStringLiteral("Digi-ID E-RESIDENT"); + else if(t & SslCertificate::DigiIDType) + type = QStringLiteral("Digi-ID"); + QUrlQuery q; + q.setQueryItems({ + {QStringLiteral("v"), QString::number(1)}, + {QStringLiteral("type"), type}, + {QStringLiteral("serial_number"), escape(cert.subjectInfo("serialNumber").join(','))}, + {QStringLiteral("cn"), escape(cert.subjectInfo("CN").join(','))}, + {QStringLiteral("server_exp"), QString::number(exp.toSecsSinceEpoch())}, + }); + return "data:" + q.query(QUrl::FullyEncoded); +} + CryptoDoc::CryptoDoc( QObject *parent ) diff --git a/client/CryptoDoc.h b/client/CryptoDoc.h index fc490392e..cdf1683cf 100644 --- a/client/CryptoDoc.h +++ b/client/CryptoDoc.h @@ -43,6 +43,8 @@ class CKey bool operator==(const CKey &other) const { return other.key == key; } void setCert(const QSslCertificate &c); + QHash fromKeyLabel() const; + QString toKeyLabel() const; QByteArray key, cipher, publicKey; QSslCertificate cert; diff --git a/client/translations/en.ts b/client/translations/en.ts index 27320d2fa..277107699 100644 --- a/client/translations/en.ts +++ b/client/translations/en.ts @@ -151,6 +151,18 @@ Unsupported cryptographic algorithm or recipient type Unsupported cryptographic algorithm or recipient type
+ + Decryption is possible until: + Decryption is possible until: + + + Decryption has expired + Decryption has expired + + + ID-CARD + ID-CARD +
Application diff --git a/client/translations/et.ts b/client/translations/et.ts index 17228a606..6bdb232f1 100644 --- a/client/translations/et.ts +++ b/client/translations/et.ts @@ -151,6 +151,18 @@ Unsupported cryptographic algorithm or recipient type Mittetoetatud krüptograafiline algoritm või adressaadi tüüp + + Decryption is possible until: + Dekrüpteerimine on võimalik kuni: + + + Decryption has expired + Dekrüpteerimine on aegunud + + + ID-CARD + ID-KAART + Application diff --git a/client/translations/ru.ts b/client/translations/ru.ts index be84dd2a2..8022b67b3 100644 --- a/client/translations/ru.ts +++ b/client/translations/ru.ts @@ -151,6 +151,18 @@ Unsupported cryptographic algorithm or recipient type Неподдерживаемый криптографический алгоритм или тип получателя + + Decryption is possible until: + Расшифровка возможна до: + + + Decryption has expired + Срок расшифровки истек + + + ID-CARD + ID-КАРТА + Application diff --git a/client/widgets/AddressItem.cpp b/client/widgets/AddressItem.cpp index 2d06df9a0..0d9482dda 100644 --- a/client/widgets/AddressItem.cpp +++ b/client/widgets/AddressItem.cpp @@ -21,9 +21,7 @@ #include "ui_AddressItem.h" #include "CryptoDoc.h" -#include "DateTime.h" #include "SslCertificate.h" -#include "Styles.h" #include "dialogs/KeyDialog.h" using namespace ria::qdigidoc4; @@ -46,27 +44,23 @@ AddressItem::AddressItem(CKey k, QWidget *parent, bool showIcon) if(showIcon) ui->icon->load(QStringLiteral(":/images/icon_Krypto_small.svg")); ui->icon->setVisible(showIcon); - ui->name->setFont(Styles::font(Styles::Regular, 14, QFont::DemiBold)); - ui->name->installEventFilter(this); - ui->idType->setFont(Styles::font(Styles::Regular, 11)); - ui->idType->installEventFilter(this); + ui->name->setAttribute(Qt::WA_TransparentForMouseEvents, true); + ui->expire->setAttribute(Qt::WA_TransparentForMouseEvents, true); + ui->idType->setAttribute(Qt::WA_TransparentForMouseEvents, true); + if(!ui->key.unsupported) + setCursor(Qt::PointingHandCursor); connect(ui->add, &QToolButton::clicked, this, [this]{ emit add(this);}); connect(ui->remove, &QToolButton::clicked, this, [this]{ emit remove(this);}); - ui->add->setFont(Styles::font(Styles::Condensed, 12)); - ui->added->setFont(ui->add->font()); - - ui->code = SslCertificate(ui->key.cert).personalCode().toHtmlEscaped(); - ui->label = (!ui->key.cert.subjectInfo("GN").isEmpty() && !ui->key.cert.subjectInfo("SN").isEmpty() ? - ui->key.cert.subjectInfo("GN").join(' ') + " " + ui->key.cert.subjectInfo("SN").join(' ') : - ui->key.cert.subjectInfo("CN").join(' ')).toHtmlEscaped(); + ui->code = SslCertificate(ui->key.cert).personalCode(); + ui->label = !ui->key.cert.subjectInfo("GN").isEmpty() && !ui->key.cert.subjectInfo("SN").isEmpty() ? + ui->key.cert.subjectInfo("GN").join(' ') + ' ' + ui->key.cert.subjectInfo("SN").join(' ') : + ui->key.cert.subjectInfo("CN").join(' '); if(ui->label.isEmpty()) - ui->label = ui->key.recipient.toHtmlEscaped(); + ui->label = ui->key.fromKeyLabel().value(QStringLiteral("cn"), ui->key.recipient); setIdType(); showButton(AddressItem::Remove); - if(ui->key.unsupported) - ui->idType->setText(tr("Unsupported cryptographic algorithm or recipient type")); } AddressItem::~AddressItem() @@ -85,37 +79,24 @@ void AddressItem::changeEvent(QEvent* event) QWidget::changeEvent(event); } -bool AddressItem::eventFilter(QObject *o, QEvent *e) -{ - if((o == ui->name || o == ui->idType) && e->type() == QEvent::MouseButtonRelease) - { - (new KeyDialog(ui->key, this))->open(); - return true; - } - return Item::eventFilter(o, e); -} - const CKey& AddressItem::getKey() const { return ui->key; } -void AddressItem::idChanged(const CKey &key) +void AddressItem::idChanged(const SslCertificate &cert) { + CKey key(cert); ui->yourself = !key.key.isNull() && ui->key == key; setName(); } -void AddressItem::idChanged(const SslCertificate &cert) -{ - idChanged(CKey(cert)); -} - void AddressItem::initTabOrder(QWidget *item) { setTabOrder(item, ui->name); setTabOrder(ui->name, ui->idType); - setTabOrder(ui->idType, ui->remove); + setTabOrder(ui->idType, ui->expire); + setTabOrder(ui->expire, ui->remove); setTabOrder(ui->remove, ui->added); setTabOrder(ui->added, lastTabWidget()); } @@ -127,13 +108,14 @@ QWidget* AddressItem::lastTabWidget() void AddressItem::mouseReleaseEvent(QMouseEvent * /*event*/) { - (new KeyDialog(ui->key, this))->open(); + if(!ui->key.unsupported) + (new KeyDialog(ui->key, this))->open(); } void AddressItem::setName() { ui->name->setText(QStringLiteral("%1
%2") - .arg(ui->label, ui->yourself ? ui->code + tr(" (Yourself)") : ui->code)); + .arg(ui->label.toHtmlEscaped(), (ui->yourself ? ui->code + tr(" (Yourself)") : ui->code).toHtmlEscaped())); if(ui->name->text().isEmpty()) ui->name->hide(); } @@ -152,33 +134,53 @@ void AddressItem::stateChange(ContainerState state) void AddressItem::setIdType() { - ui->idType->setHidden(ui->key.cert.isNull()); - if(ui->key.cert.isNull()) - return; - - QString str; + ui->expire->clear(); SslCertificate cert(ui->key.cert); SslCertificate::CertType type = cert.type(); - if(type & SslCertificate::DigiIDType) - str = tr("digi-ID"); + if(ui->key.unsupported) + { + ui->label = tr("Unsupported cryptographic algorithm or recipient type"); + ui->idType->clear(); + } + else if(type & SslCertificate::DigiIDType) + ui->idType->setText(tr("digi-ID")); else if(type & SslCertificate::EstEidType) - str = tr("ID-card"); + ui->idType->setText(tr("ID-card")); else if(type & SslCertificate::MobileIDType) - str = tr("mobile-ID"); + ui->idType->setText(tr("mobile-ID")); else if(type & SslCertificate::TempelType) { if(cert.keyUsage().contains(SslCertificate::NonRepudiation)) - str = tr("e-Seal"); + ui->idType->setText(tr("e-Seal")); else if(cert.enhancedKeyUsage().contains(SslCertificate::ClientAuth)) - str = tr("Authentication certificate"); + ui->idType->setText(tr("Authentication certificate")); else - str = tr("Certificate for Encryption"); + ui->idType->setText(tr("Certificate for Encryption")); + } + else + { + auto items = ui->key.fromKeyLabel(); + void(QT_TR_NOOP("ID-CARD")); + ui->idType->setText(tr(items[QStringLiteral("type")].toUtf8().data())); + if(QString server_exp = items[QStringLiteral("server_exp")]; !server_exp.isEmpty()) + { + auto date = QDateTime::fromSecsSinceEpoch(server_exp.toLongLong(), Qt::UTC); + bool canDecrypt = QDateTime::currentDateTimeUtc() < date; + ui->expire->setProperty("label", canDecrypt ? QStringLiteral("good") : QStringLiteral("error")); + ui->expire->setText(canDecrypt ? QStringLiteral("%1 %2").arg( + tr("Decryption is possible until:"), date.toLocalTime().toString(QStringLiteral("dd.MM.yyyy"))) : + tr("Decryption has expired")); + } + } + + if(!cert.isNull()) + { + ui->expire->setProperty("label", QStringLiteral("default")); + ui->expire->setText(QStringLiteral("%1 %2").arg( + cert.isValid() ? tr("Expires on") : tr("Expired on"), + cert.expiryDate().toLocalTime().toString(QStringLiteral("dd.MM.yyyy")))); } - if(!str.isEmpty()) - str += QStringLiteral(" - "); - DateTime date(cert.expiryDate().toLocalTime()); - ui->idType->setText(QStringLiteral("%1%2 %3").arg(str, - cert.isValid() ? tr("Expires on") : tr("Expired on"), - date.formatDate(QStringLiteral("dd. MMMM yyyy")))); + ui->idType->setHidden(ui->idType->text().isEmpty()); + ui->expire->setHidden(ui->expire->text().isEmpty()); } diff --git a/client/widgets/AddressItem.h b/client/widgets/AddressItem.h index 9f04c09f4..d6ce8a578 100644 --- a/client/widgets/AddressItem.h +++ b/client/widgets/AddressItem.h @@ -39,7 +39,6 @@ class AddressItem final : public Item ~AddressItem() final; const CKey& getKey() const; - void idChanged(const CKey &cert); void idChanged(const SslCertificate &cert) final; void initTabOrder(QWidget *item) final; QWidget* lastTabWidget() final; @@ -48,7 +47,6 @@ class AddressItem final : public Item private: void changeEvent(QEvent *event) final; - bool eventFilter(QObject *o, QEvent *e) final; void mouseReleaseEvent(QMouseEvent *event) final; void setName(); void setIdType(); diff --git a/client/widgets/AddressItem.ui b/client/widgets/AddressItem.ui index e32d134a0..0c1a1816f 100644 --- a/client/widgets/AddressItem.ui +++ b/client/widgets/AddressItem.ui @@ -10,21 +10,17 @@ 52 - - PointingHandCursor - - QWidget { -font-family: Roboto, Helvetica; -font-size: 12px; -} -#AddressItem { + #AddressItem { border-bottom: 1px solid rgba(217, 217, 216, 0.45); background-color: #FFFFFF; } #AddressItem:disabled { background-color: #F0F0F2; } +#AddressItem > QWidget { +font-family: Roboto, Helvetica; +} #name { color: #07142A; font-size: 14px; @@ -32,14 +28,27 @@ font-weight: 700; } #idType { color: #07142A; +font-size: 12px; } -#expire { -color: #07142A; -background: #F3F5F7; +QLabel[label] { +font-size: 12px; padding: 2px 8px; border-radius: 8px; } +QLabel[label="default"] { +color: #07142A; +background: #F3F5F7; +} +QLabel[label="error"] { +color: #AD2A45; +background: #F5EBED; +} +QLabel[label="good"] { +color: #1A641B; +background: #EAF8EA; +} QToolButton { +font-size: 12px; font-weight: 700; border-radius: 2px; border: none; @@ -95,7 +104,7 @@ color: #727679; - Qt::FocusPolicy::TabFocus + Qt::TabFocus MARI MAASIKAS MUSTIKAS 48405050123 (Sina ise) @@ -108,7 +117,7 @@ color: #727679; - Qt::FocusPolicy::TabFocus + Qt::TabFocus ID-card @@ -117,20 +126,26 @@ color: #727679; + + Qt::TabFocus + Expire + + default + - Qt::Orientation::Horizontal + Qt::Horizontal 40 - 20 + 0 @@ -214,7 +229,7 @@ color: #727679; QSvgWidget QWidget -
QtSvg/QSvgWidget
+
QSvgWidget
1