[pim/libkleo] /: Show issuer serial number and issuer name for unknown S/MIME certs

Ingo Klöcker <[email protected]> Tue, 4 Aug 2026 14:33:46 +0000 (UTC)
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 2e714e6ef53f7eedbdd776b798454c02a79aab86 by Ingo Klöcker, on behalf of Ingo Klöcker.
Committed on 04/08/2026 at 14:33.
Pushed by kloecker into branch 'master'.

Show issuer serial number and issuer name for unknown S/MIME certs

This allows the user to search for the S/MIME certificate that was used
for signing something but that is not included with the signature.

GnuPG-bug-id: 7786

M  +9    -1    autotests/formattingtest.cpp
M  +20   -0    src/utils/formatting.cpp

https://invent.kde.org/pim/libkleo/-/commit/2e714e6ef53f7eedbdd776b798454c02a79aab86

diff --git a/autotests/formattingtest.cpp b/autotests/formattingtest.cpp
index 6587f301..014c6a97 100644
--- a/autotests/formattingtest.cpp
+++ b/autotests/formattingtest.cpp
@@ -24,6 +24,7 @@
 #include <QTest>
 
 #include <gpgme++/engineinfo.h>
+#include <gpgme++/gpgmepp_version.h>
 #include <gpgme++/importresult.h>
 #include <gpgme++/signingresult.h>
 #include <gpgme++/verificationresult.h>
@@ -529,7 +530,14 @@ private Q_SLOTS:
         QCOMPARE(verificationResult.numSignatures(), 1);
 
         const QString result = Formatting::prettyDataSignature(verificationResult.signature(0), {});
-        const auto expected = u"The data cannot be trusted. Reason: The signature cannot be verified because the corresponding certificate is not available."_s;
+        const auto expected = u"The data cannot be trusted. Reason: The signature cannot be verified because the corresponding certificate is not available."_s
+#if GPGMEPP_VERSION >= QT_VERSION_CHECK(2, 1, 1)
+            + ((GpgME::engineInfo(GpgME::GpgEngine).engineVersion() >= "2.5.22")
+                   ? u" The signing certificate’s serial number and issuer are "
+                     "#1A03/1.2.840.113549.1.9.1=#696E666F40673130636F64652E636F6D,CN=g10 Code TEST CA 2019,OU=Testlab,O=g10 Code GmbH,C=DE."_s
+                   : QString{})
+#endif
+            ;
         QCOMPARE(result, expected);
     }
 
diff --git a/src/utils/formatting.cpp b/src/utils/formatting.cpp
index 84e84686..b211ce2f 100644
--- a/src/utils/formatting.cpp
+++ b/src/utils/formatting.cpp
@@ -38,6 +38,7 @@
 #include <QRegularExpression>
 #include <QString>
 
+#include <gpgme++/gpgmepp_version.h>
 #include <gpgme++/importresult.h>
 #include <gpgme++/key.h>
 
@@ -1539,6 +1540,18 @@ static QString renderFingerprintLinkV2(const char *fpr)
     return u"<a href=\"certificate:%1\">%2</a>"_s.arg(QString::fromLatin1(fpr), Formatting::prettyID(fpr));
 }
 
+#if GPGMEPP_VERSION >= QT_VERSION_CHECK(2, 1, 1)
+// assumes that issuerSerial is hex-encoded serial number and that issuerName is RFC 2253-encoded DN of issuer
+static QString renderSMIMECertificateReference(const char *issuerSerial, const char *issuerName)
+{
+    Q_ASSERT(issuerSerial && issuerName);
+    if (!(issuerSerial && issuerName)) {
+        return {};
+    }
+    return QString::fromLatin1('#' + QByteArrayView{issuerSerial} + '/' + QByteArrayView{issuerName});
+}
+#endif
+
 static QDateTime signatureCreationTime(const GpgME::Signature &sig)
 {
     return sig.creationTime() != 0 ? QDateTime::fromSecsSinceEpoch(quint32(sig.creationTime())) : QDateTime();
@@ -1823,6 +1836,13 @@ QString Kleo::Formatting::prettyDataSignature(const GpgME::Signature &sig, const
         if (sig.fingerprint()) {
             text += u' ';
             text += i18nc("@info", "The signing certificate’s fingerprint is %1.", renderFingerprintLinkV2(sig.fingerprint()));
+#if GPGMEPP_VERSION >= QT_VERSION_CHECK(2, 1, 1)
+        } else if (sig.issuerSerial() && sig.issuerName()) {
+            text += u' ';
+            text += i18nc("@info",
+                          "The signing certificate’s serial number and issuer are %1.",
+                          renderSMIMECertificateReference(sig.issuerSerial(), sig.issuerName()));
+#endif
         }
         return text;
     }