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