mirror of
				https://github.com/JakubMelka/PDF4QT.git
				synced 2025-06-05 21:59:17 +02:00 
			
		
		
		
	Signature plugin: invisible digital signature
This commit is contained in:
		@@ -29,6 +29,7 @@
 | 
			
		||||
#include <QToolButton>
 | 
			
		||||
#include <QMainWindow>
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
#include <QFileDialog>
 | 
			
		||||
 | 
			
		||||
namespace pdfplugin
 | 
			
		||||
{
 | 
			
		||||
@@ -334,15 +335,39 @@ void SignaturePlugin::onSignDigitally()
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        QString signatureName = QString("pdf4qt_signature_%1").arg(QString::number(QDateTime::currentMSecsSinceEpoch()));
 | 
			
		||||
 | 
			
		||||
        pdf::PDFInteger offsetMark = 123456789123;
 | 
			
		||||
        constexpr const char* offsetMarkString = "123456789123";
 | 
			
		||||
        const auto offsetMarkStringLength = std::strlen(offsetMarkString);
 | 
			
		||||
 | 
			
		||||
        pdf::PDFDocumentBuilder builder(m_document);
 | 
			
		||||
        pdf::PDFObjectReference signatureDictionary = builder.createSignatureDictionary("Adobe.PPKLite", "adbe.pkcs7.detached", signature, QDateTime::currentDateTime(), offsetMark);
 | 
			
		||||
        pdf::PDFObjectReference formField = builder.createFormFieldSignature("signature", { }, signatureDictionary);
 | 
			
		||||
        pdf::PDFObjectReference formField = builder.createFormFieldSignature(signatureName, { }, signatureDictionary);
 | 
			
		||||
        builder.createAcroForm({ formField });
 | 
			
		||||
 | 
			
		||||
        if (dialog.getSignMethod() == SignDialog::SignDigitallyInvisible)
 | 
			
		||||
        {
 | 
			
		||||
            const pdf::PDFCatalog* catalog = m_document->getCatalog();
 | 
			
		||||
            if (catalog->getPageCount() > 0)
 | 
			
		||||
            {
 | 
			
		||||
                const pdf::PDFObjectReference pageReference = catalog->getPage(0)->getPageReference();
 | 
			
		||||
                builder.createInvisibleFormFieldWidget(formField, pageReference);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        QString reasonText = dialog.getReasonText();
 | 
			
		||||
        if (!reasonText.isEmpty())
 | 
			
		||||
        {
 | 
			
		||||
            builder.setSignatureReason(signatureDictionary, reasonText);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        QString contactInfoText = dialog.getContactInfoText();
 | 
			
		||||
        if (!contactInfoText.isEmpty())
 | 
			
		||||
        {
 | 
			
		||||
            builder.setSignatureContactInfo(signatureDictionary, contactInfoText);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        pdf::PDFDocument signedDocument = builder.build();
 | 
			
		||||
 | 
			
		||||
        // 1) Save the document with incorrect signature
 | 
			
		||||
@@ -361,8 +386,8 @@ void SignaturePlugin::onSignDigitally()
 | 
			
		||||
 | 
			
		||||
        // 2) Write ranges to be checked
 | 
			
		||||
        const pdf::PDFInteger i1 = 0;
 | 
			
		||||
        const pdf::PDFInteger i2 = indexOfSignature;
 | 
			
		||||
        const pdf::PDFInteger i3 = i2 + signature.size() * 2;
 | 
			
		||||
        const pdf::PDFInteger i2 = indexOfSignature - 1;
 | 
			
		||||
        const pdf::PDFInteger i3 = i2 + signature.size() * 2 + 2;
 | 
			
		||||
        const pdf::PDFInteger i4 = buffer.data().size() - i3;
 | 
			
		||||
 | 
			
		||||
        auto writeInt = [&](pdf::PDFInteger offset)
 | 
			
		||||
@@ -393,13 +418,31 @@ void SignaturePlugin::onSignDigitally()
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        buffer.seek(i2);
 | 
			
		||||
        buffer.seek(i2 + 1);
 | 
			
		||||
        buffer.write(signature.toHex());
 | 
			
		||||
 | 
			
		||||
        buffer.close();
 | 
			
		||||
 | 
			
		||||
        QString fileName = QFileDialog::getSaveFileName(m_dataExchangeInterface->getMainWindow(), tr("Save Signed Document"), getSignedFileName(), tr("Portable Document (*.pdf);;All files (*.*)"));
 | 
			
		||||
        if (!fileName.isEmpty())
 | 
			
		||||
        {
 | 
			
		||||
            QFile signedFile(fileName);
 | 
			
		||||
            if (signedFile.open(QFile::WriteOnly | QFile::Truncate))
 | 
			
		||||
            {
 | 
			
		||||
                signedFile.write(buffer.data());
 | 
			
		||||
                signedFile.close();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString SignaturePlugin::getSignedFileName() const
 | 
			
		||||
{
 | 
			
		||||
    QFileInfo fileInfo(m_dataExchangeInterface->getOriginalFileName());
 | 
			
		||||
 | 
			
		||||
    return fileInfo.path() + "/" + fileInfo.baseName() + "_SIGNED.pdf";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SignaturePlugin::onOpenCertificatesManager()
 | 
			
		||||
{
 | 
			
		||||
    CertificateManagerDialog dialog(m_dataExchangeInterface->getMainWindow());
 | 
			
		||||
 
 | 
			
		||||
@@ -112,6 +112,8 @@ private:
 | 
			
		||||
    void updateGraphics();
 | 
			
		||||
    void updateDockWidget();
 | 
			
		||||
 | 
			
		||||
    QString getSignedFileName() const;
 | 
			
		||||
 | 
			
		||||
    std::array<QAction*, LastAction> m_actions;
 | 
			
		||||
    std::array<pdf::PDFWidgetTool*, LastTool> m_tools;
 | 
			
		||||
    pdf::PDFPageContentEditorWidget* m_editorWidget;
 | 
			
		||||
 
 | 
			
		||||
@@ -68,6 +68,16 @@ QString SignDialog::getPassword() const
 | 
			
		||||
    return ui->certificatePasswordEdit->text();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString SignDialog::getReasonText() const
 | 
			
		||||
{
 | 
			
		||||
    return ui->reasonEdit->text();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString SignDialog::getContactInfoText() const
 | 
			
		||||
{
 | 
			
		||||
    return ui->contactInfoEdit->text();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SignDialog::accept()
 | 
			
		||||
{
 | 
			
		||||
    // Check certificate
 | 
			
		||||
 
 | 
			
		||||
@@ -47,6 +47,8 @@ public:
 | 
			
		||||
    SignMethod getSignMethod() const;
 | 
			
		||||
    QString getCertificatePath() const;
 | 
			
		||||
    QString getPassword() const;
 | 
			
		||||
    QString getReasonText() const;
 | 
			
		||||
    QString getContactInfoText() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Ui::SignDialog* ui;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user