File indexing completed on 2024-04-28 04:33:06

0001 /*
0002     SPDX-FileCopyrightText: 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "signatureguiutils.h"
0008 
0009 #include <KLocalizedString>
0010 
0011 #include "core/document.h"
0012 #include "core/form.h"
0013 #include "core/page.h"
0014 
0015 namespace SignatureGuiUtils
0016 {
0017 QVector<const Okular::FormFieldSignature *> getSignatureFormFields(const Okular::Document *doc)
0018 {
0019     uint curPage = 0;
0020     const uint endPage = doc->pages() - 1;
0021     QVector<const Okular::FormFieldSignature *> signatureFormFields;
0022     while (curPage <= endPage) {
0023         const QList<Okular::FormField *> formFields = doc->page(curPage++)->formFields();
0024         for (Okular::FormField *f : formFields) {
0025             if (f->type() == Okular::FormField::FormSignature) {
0026                 signatureFormFields.append(static_cast<Okular::FormFieldSignature *>(f));
0027             }
0028         }
0029     }
0030     std::sort(signatureFormFields.begin(), signatureFormFields.end(), [](const Okular::FormFieldSignature *a, const Okular::FormFieldSignature *b) {
0031         const Okular::SignatureInfo &infoA = a->signatureInfo();
0032         const Okular::SignatureInfo &infoB = b->signatureInfo();
0033         return infoA.signingTime() < infoB.signingTime();
0034     });
0035     return signatureFormFields;
0036 }
0037 
0038 QString getReadableSignatureStatus(Okular::SignatureInfo::SignatureStatus sigStatus)
0039 {
0040     switch (sigStatus) {
0041     case Okular::SignatureInfo::SignatureValid:
0042         return i18n("The signature is cryptographically valid.");
0043     case Okular::SignatureInfo::SignatureInvalid:
0044         return i18n("The signature is cryptographically invalid.");
0045     case Okular::SignatureInfo::SignatureDigestMismatch:
0046         return i18n("Digest Mismatch occurred.");
0047     case Okular::SignatureInfo::SignatureDecodingError:
0048         return i18n("The signature CMS/PKCS7 structure is malformed.");
0049     case Okular::SignatureInfo::SignatureNotFound:
0050         return i18n("The requested signature is not present in the document.");
0051     default:
0052         return i18n("The signature could not be verified.");
0053     }
0054 }
0055 
0056 QString getReadableCertStatus(Okular::SignatureInfo::CertificateStatus certStatus)
0057 {
0058     switch (certStatus) {
0059     case Okular::SignatureInfo::CertificateTrusted:
0060         return i18n("Certificate is Trusted.");
0061     case Okular::SignatureInfo::CertificateUntrustedIssuer:
0062         return i18n("Certificate issuer isn't Trusted.");
0063     case Okular::SignatureInfo::CertificateUnknownIssuer:
0064         return i18n("Certificate issuer is unknown.");
0065     case Okular::SignatureInfo::CertificateRevoked:
0066         return i18n("Certificate has been Revoked.");
0067     case Okular::SignatureInfo::CertificateExpired:
0068         return i18n("Certificate has Expired.");
0069     case Okular::SignatureInfo::CertificateNotVerified:
0070         return i18n("Certificate has not yet been verified.");
0071     default:
0072         return i18n("Unknown issue with Certificate or corrupted data.");
0073     }
0074 }
0075 
0076 QString getReadableHashAlgorithm(Okular::SignatureInfo::HashAlgorithm hashAlg)
0077 {
0078     switch (hashAlg) {
0079     case Okular::SignatureInfo::HashAlgorithmMd2:
0080         return i18n("MD2");
0081     case Okular::SignatureInfo::HashAlgorithmMd5:
0082         return i18n("MD5");
0083     case Okular::SignatureInfo::HashAlgorithmSha1:
0084         return i18n("SHA1");
0085     case Okular::SignatureInfo::HashAlgorithmSha256:
0086         return i18n("SHA256");
0087     case Okular::SignatureInfo::HashAlgorithmSha384:
0088         return i18n("SHA384");
0089     case Okular::SignatureInfo::HashAlgorithmSha512:
0090         return i18n("SHA512");
0091     case Okular::SignatureInfo::HashAlgorithmSha224:
0092         return i18n("SHA224");
0093     default:
0094         return i18n("Unknown Algorithm");
0095     }
0096 }
0097 
0098 QString getReadablePublicKeyType(Okular::CertificateInfo::PublicKeyType type)
0099 {
0100     switch (type) {
0101     case Okular::CertificateInfo::RsaKey:
0102         return i18n("RSA");
0103     case Okular::CertificateInfo::DsaKey:
0104         return i18n("DSA");
0105     case Okular::CertificateInfo::EcKey:
0106         return i18n("EC");
0107     case Okular::CertificateInfo::OtherKey:
0108         return i18n("Unknown Type");
0109     }
0110 
0111     return i18n("Unknown Type");
0112 }
0113 
0114 QString getReadableKeyUsage(Okular::CertificateInfo::KeyUsageExtensions kuExtensions, const QString &separator)
0115 {
0116     QStringList ku;
0117     if (kuExtensions.testFlag(Okular::CertificateInfo::KuDigitalSignature)) {
0118         ku << i18n("Digital Signature");
0119     }
0120     if (kuExtensions.testFlag(Okular::CertificateInfo::KuNonRepudiation)) {
0121         ku << i18n("Non-Repudiation");
0122     }
0123     if (kuExtensions.testFlag(Okular::CertificateInfo::KuKeyEncipherment)) {
0124         ku << i18n("Encrypt Keys");
0125     }
0126     if (kuExtensions.testFlag(Okular::CertificateInfo::KuDataEncipherment)) {
0127         ku << i18n("Decrypt Keys");
0128     }
0129     if (kuExtensions.testFlag(Okular::CertificateInfo::KuKeyAgreement)) {
0130         ku << i18n("Key Agreement");
0131     }
0132     if (kuExtensions.testFlag(Okular::CertificateInfo::KuKeyCertSign)) {
0133         ku << i18n("Sign Certificate");
0134     }
0135     if (kuExtensions.testFlag(Okular::CertificateInfo::KuClrSign)) {
0136         ku << i18n("Sign CRL");
0137     }
0138     if (kuExtensions.testFlag(Okular::CertificateInfo::KuEncipherOnly)) {
0139         ku << i18n("Encrypt Only");
0140     }
0141     if (ku.isEmpty()) {
0142         ku << i18n("No Usage Specified");
0143     }
0144     return ku.join(separator);
0145 }
0146 
0147 QString getReadableKeyUsageCommaSeparated(Okular::CertificateInfo::KeyUsageExtensions kuExtensions)
0148 {
0149     return getReadableKeyUsage(kuExtensions, i18nc("Joins the various ways a signature key can be used in a longer string", ", "));
0150 }
0151 
0152 QString getReadableKeyUsageNewLineSeparated(Okular::CertificateInfo::KeyUsageExtensions kuExtensions)
0153 {
0154     return getReadableKeyUsage(kuExtensions, QStringLiteral("\n"));
0155 }
0156 
0157 QString getReadableModificationSummary(const Okular::SignatureInfo &signatureInfo)
0158 {
0159     const Okular::SignatureInfo::SignatureStatus signatureStatus = signatureInfo.signatureStatus();
0160     // signature validation status
0161     if (signatureStatus == Okular::SignatureInfo::SignatureValid) {
0162         if (signatureInfo.signsTotalDocument()) {
0163             return i18n("The document has not been modified since it was signed.");
0164         } else {
0165             return i18n(
0166                 "The revision of the document that was covered by this signature has not been modified;\n"
0167                 "however there have been subsequent changes to the document.");
0168         }
0169     } else if (signatureStatus == Okular::SignatureInfo::SignatureDigestMismatch) {
0170         return i18n("The document has been modified in a way not permitted by a previous signer.");
0171     } else {
0172         return i18n("The document integrity verification could not be completed.");
0173     }
0174 }
0175 
0176 std::pair<KMessageWidget::MessageType, QString> documentSignatureMessageWidgetText(const Okular::Document *doc)
0177 {
0178     const uint numPages = doc->pages();
0179     bool isDigitallySigned = false;
0180     for (uint i = 0; i < numPages; i++) {
0181         const QList<Okular::FormField *> formFields = doc->page(i)->formFields();
0182         for (const Okular::FormField *f : formFields) {
0183             if (f->type() == Okular::FormField::FormSignature) {
0184                 isDigitallySigned = true;
0185             }
0186         }
0187     }
0188 
0189     if (isDigitallySigned) {
0190         const QVector<const Okular::FormFieldSignature *> signatureFormFields = SignatureGuiUtils::getSignatureFormFields(doc);
0191         bool allSignaturesValid = true;
0192         bool anySignatureUnsigned = false;
0193         for (const Okular::FormFieldSignature *signature : signatureFormFields) {
0194             if (signature->signatureType() == Okular::FormFieldSignature::UnsignedSignature) {
0195                 anySignatureUnsigned = true;
0196             } else {
0197                 const Okular::SignatureInfo &info = signature->signatureInfo();
0198                 if (info.signatureStatus() != Okular::SignatureInfo::SignatureValid) {
0199                     allSignaturesValid = false;
0200                 }
0201             }
0202         }
0203 
0204         if (anySignatureUnsigned) {
0205             return {KMessageWidget::Information, i18n("This document has unsigned signature fields.")};
0206         } else if (allSignaturesValid) {
0207             if (signatureFormFields.last()->signatureInfo().signsTotalDocument()) {
0208                 return {KMessageWidget::Information, i18n("This document is digitally signed.")};
0209             } else {
0210                 return {KMessageWidget::Warning, i18n("This document is digitally signed. There have been changes since last signed.")};
0211             }
0212         } else {
0213             return {KMessageWidget::Warning, i18n("This document is digitally signed. Some of the signatures could not be validated properly.")};
0214         }
0215     }
0216 
0217     return {KMessageWidget::Information, QString()};
0218 }
0219 }