#Issue 17: Public key security handler

This commit is contained in:
Jakub Melka 2022-06-29 17:45:54 +02:00
commit 59d1ab2b7a
30 changed files with 1754 additions and 914 deletions

View File

@ -10,7 +10,6 @@ Section 6: OK
Section 7: Issues
- 7.4.7 JBIG2 decoder ammendments 1 and 2 not implemented
- 7.6.5 Public-key security handlers not implemented
- 7.6.7 Unencrypted wrapper document not implemented
- 7.10.2 Only linear interpolation for sampled function is performed
@ -71,7 +70,7 @@ Section 12: Issues
to PDF specification, but all unicode characters can be used.
- 12.7.5.5 Signature field locking not implemented and signature
seed dictionary is ignored
- 12.7.6.2 Sumbit form action not implemented in viewer
- 12.7.6.2 Submit form action not implemented in viewer
- 12.7.6.4 Import data action not implemented in viewer
- 12.7.8 Form data format not implemented
- 12.8 Modification detection using UR3/DocMDP method is not

View File

@ -47,8 +47,11 @@ SOURCES += \
sources/pdfannotation.cpp \
sources/pdfblendfunction.cpp \
sources/pdfccittfaxdecoder.cpp \
sources/pdfcertificatemanager.cpp \
sources/pdfcertificatemanagerdialog.cpp \
sources/pdfcms.cpp \
sources/pdfcompiler.cpp \
sources/pdfcreatecertificatedialog.cpp \
sources/pdfdiff.cpp \
sources/pdfdocumentbuilder.cpp \
sources/pdfdocumentmanipulator.cpp \
@ -121,8 +124,11 @@ HEADERS += \
sources/pdfannotation.h \
sources/pdfblendfunction.h \
sources/pdfccittfaxdecoder.h \
sources/pdfcertificatemanager.h \
sources/pdfcertificatemanagerdialog.h \
sources/pdfcms.h \
sources/pdfcompiler.h \
sources/pdfcreatecertificatedialog.h \
sources/pdfdbgheap.h \
sources/pdfdiff.h \
sources/pdfdocumentbuilder.h \
@ -202,6 +208,8 @@ HEADERS += \
sources/pdfimage.h
FORMS += \
sources/pdfcertificatemanagerdialog.ui \
sources/pdfcreatecertificatedialog.ui \
sources/pdfpagecontenteditorstylesettings.ui \
sources/pdfpagecontenteditorwidget.ui \
sources/pdfrenderingerrorswidget.ui \

View File

@ -15,7 +15,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
#include "certificatemanager.h"
#include "pdfcertificatemanager.h"
#include <QDir>
#include <QFile>
@ -32,10 +32,10 @@
#include <memory>
namespace pdfplugin
namespace pdf
{
CertificateManager::CertificateManager()
PDFCertificateManager::PDFCertificateManager()
{
}
@ -43,7 +43,7 @@ CertificateManager::CertificateManager()
template<typename T>
using openssl_ptr = std::unique_ptr<T, void(*)(T*)>;
void CertificateManager::createCertificate(const NewCertificateInfo& info)
void PDFCertificateManager::createCertificate(const NewCertificateInfo& info)
{
openssl_ptr<BIO> pksBuffer(BIO_new(BIO_s_mem()), &BIO_free_all);
@ -132,19 +132,20 @@ void CertificateManager::createCertificate(const NewCertificateInfo& info)
}
}
QFileInfoList CertificateManager::getCertificates()
QFileInfoList PDFCertificateManager::getCertificates()
{
QDir directory(getCertificateDirectory());
return directory.entryInfoList(QStringList() << "*.pfx", QDir::Files | QDir::NoDotAndDotDot | QDir::Readable, QDir::Name);
}
QString CertificateManager::getCertificateDirectory()
QString PDFCertificateManager::getCertificateDirectory()
{
QDir directory(QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).front() + "/certificates/");
QString standardDataLocation = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).front();
QDir directory(standardDataLocation + "/certificates/");
return directory.absolutePath();
}
QString CertificateManager::generateCertificateFileName()
QString PDFCertificateManager::generateCertificateFileName()
{
QString directoryString = getCertificateDirectory();
QDir directory(directoryString);
@ -162,7 +163,7 @@ QString CertificateManager::generateCertificateFileName()
return QString();
}
bool CertificateManager::isCertificateValid(QString fileName, QString password)
bool PDFCertificateManager::isCertificateValid(QString fileName, QString password)
{
QFile file(fileName);
if (file.open(QFile::ReadOnly))
@ -190,7 +191,7 @@ bool CertificateManager::isCertificateValid(QString fileName, QString password)
return false;
}
bool SignatureFactory::sign(QString certificateName, QString password, QByteArray data, QByteArray& result)
bool PDFSignatureFactory::sign(QString certificateName, QString password, QByteArray data, QByteArray& result)
{
QFile file(certificateName);
if (file.open(QFile::ReadOnly))
@ -247,4 +248,4 @@ bool SignatureFactory::sign(QString certificateName, QString password, QByteArra
return false;
}
} // namespace pdfplugin
} // namespace pdf

View File

@ -15,19 +15,21 @@
// You should have received a copy of the GNU Lesser General Public License
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
#ifndef CERTIFICATEMANAGER_H
#define CERTIFICATEMANAGER_H
#ifndef PDFCERTIFICATEMANAGER_H
#define PDFCERTIFICATEMANAGER_H
#include "pdfglobal.h"
#include <QString>
#include <QFileInfoList>
namespace pdfplugin
namespace pdf
{
class CertificateManager
class PDF4QTLIBSHARED_EXPORT PDFCertificateManager
{
public:
CertificateManager();
PDFCertificateManager();
struct NewCertificateInfo
{
@ -53,12 +55,12 @@ public:
static bool isCertificateValid(QString fileName, QString password);
};
class SignatureFactory
class PDF4QTLIBSHARED_EXPORT PDFSignatureFactory
{
public:
static bool sign(QString certificateName, QString password, QByteArray data, QByteArray& result);
};
} // namespace pdfplugin
} // namespace pdf
#endif // CERTIFICATEMANAGER_H
#endif // PDFCERTIFICATEMANAGER_H

View File

@ -15,9 +15,9 @@
// You should have received a copy of the GNU Lesser General Public License
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
#include "certificatemanagerdialog.h"
#include "ui_certificatemanagerdialog.h"
#include "createcertificatedialog.h"
#include "pdfcertificatemanagerdialog.h"
#include "ui_pdfcertificatemanagerdialog.h"
#include "pdfcreatecertificatedialog.h"
#include "pdfwidgetutils.h"
@ -28,12 +28,12 @@
#include <QMessageBox>
#include <QFileDialog>
namespace pdfplugin
namespace pdf
{
CertificateManagerDialog::CertificateManagerDialog(QWidget *parent) :
PDFCertificateManagerDialog::PDFCertificateManagerDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::CertificateManagerDialog),
ui(new Ui::PDFCertificateManagerDialog),
m_newCertificateButton(nullptr),
m_openCertificateDirectoryButton(nullptr),
m_deleteCertificateButton(nullptr),
@ -42,10 +42,10 @@ CertificateManagerDialog::CertificateManagerDialog(QWidget *parent) :
{
ui->setupUi(this);
QDir::root().mkpath(CertificateManager::getCertificateDirectory());
QDir::root().mkpath(PDFCertificateManager::getCertificateDirectory());
m_certificateFileModel = new QFileSystemModel(this);
QModelIndex rootIndex = m_certificateFileModel->setRootPath(CertificateManager::getCertificateDirectory());
QModelIndex rootIndex = m_certificateFileModel->setRootPath(PDFCertificateManager::getCertificateDirectory());
ui->fileView->setModel(m_certificateFileModel);
ui->fileView->setRootIndex(rootIndex);
@ -54,35 +54,35 @@ CertificateManagerDialog::CertificateManagerDialog(QWidget *parent) :
m_deleteCertificateButton = ui->buttonBox->addButton(tr("Delete"), QDialogButtonBox::ActionRole);
m_importCertificateButton = ui->buttonBox->addButton(tr("Import"), QDialogButtonBox::ActionRole);
connect(m_newCertificateButton, &QPushButton::clicked, this, &CertificateManagerDialog::onNewCertificateClicked);
connect(m_openCertificateDirectoryButton, &QPushButton::clicked, this, &CertificateManagerDialog::onOpenCertificateDirectoryClicked);
connect(m_deleteCertificateButton, &QPushButton::clicked, this, &CertificateManagerDialog::onDeleteCertificateClicked);
connect(m_importCertificateButton, &QPushButton::clicked, this, &CertificateManagerDialog::onImportCertificateClicked);
connect(m_newCertificateButton, &QPushButton::clicked, this, &PDFCertificateManagerDialog::onNewCertificateClicked);
connect(m_openCertificateDirectoryButton, &QPushButton::clicked, this, &PDFCertificateManagerDialog::onOpenCertificateDirectoryClicked);
connect(m_deleteCertificateButton, &QPushButton::clicked, this, &PDFCertificateManagerDialog::onDeleteCertificateClicked);
connect(m_importCertificateButton, &QPushButton::clicked, this, &PDFCertificateManagerDialog::onImportCertificateClicked);
setMinimumSize(pdf::PDFWidgetUtils::scaleDPI(this, QSize(640, 480)));
}
CertificateManagerDialog::~CertificateManagerDialog()
PDFCertificateManagerDialog::~PDFCertificateManagerDialog()
{
delete ui;
}
void CertificateManagerDialog::onNewCertificateClicked()
void PDFCertificateManagerDialog::onNewCertificateClicked()
{
CreateCertificateDialog dialog(this);
if (dialog.exec() == CreateCertificateDialog::Accepted)
PDFCreateCertificateDialog dialog(this);
if (dialog.exec() == PDFCreateCertificateDialog::Accepted)
{
const CertificateManager::NewCertificateInfo info = dialog.getNewCertificateInfo();
const PDFCertificateManager::NewCertificateInfo info = dialog.getNewCertificateInfo();
m_certificateManager.createCertificate(info);
}
}
void CertificateManagerDialog::onOpenCertificateDirectoryClicked()
void PDFCertificateManagerDialog::onOpenCertificateDirectoryClicked()
{
QDesktopServices::openUrl(QString("file:///%1").arg(CertificateManager::getCertificateDirectory(), QUrl::TolerantMode));
QDesktopServices::openUrl(QString("file:///%1").arg(PDFCertificateManager::getCertificateDirectory(), QUrl::TolerantMode));
}
void CertificateManagerDialog::onDeleteCertificateClicked()
void PDFCertificateManagerDialog::onDeleteCertificateClicked()
{
QFileInfo fileInfo = m_certificateFileModel->fileInfo(ui->fileView->currentIndex());
if (fileInfo.exists())
@ -98,7 +98,7 @@ void CertificateManagerDialog::onDeleteCertificateClicked()
}
}
void CertificateManagerDialog::onImportCertificateClicked()
void PDFCertificateManagerDialog::onImportCertificateClicked()
{
QString selectedFile = QFileDialog::getOpenFileName(this, tr("Import Certificate"), QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), tr("Certificate file (*.pfx);;All files (*.*)"));
@ -110,7 +110,7 @@ void CertificateManagerDialog::onImportCertificateClicked()
QFile file(selectedFile);
if (file.exists())
{
QString path = CertificateManager::getCertificateDirectory();
QString path = PDFCertificateManager::getCertificateDirectory();
QString targetFile = QString("%1/%2").arg(path, QFileInfo(file).fileName());
if (QFile::exists(targetFile))
{
@ -130,4 +130,4 @@ void CertificateManagerDialog::onImportCertificateClicked()
}
}
} // namespace pdfplugin
} // namespace pdf

View File

@ -15,10 +15,10 @@
// You should have received a copy of the GNU Lesser General Public License
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
#ifndef CERTIFICATEMANAGERDIALOG_H
#define CERTIFICATEMANAGERDIALOG_H
#ifndef PDFCERTIFICATEMANAGERDIALOG_H
#define PDFCERTIFICATEMANAGERDIALOG_H
#include "certificatemanager.h"
#include "pdfcertificatemanager.h"
#include <QDialog>
@ -27,19 +27,19 @@ class QFileSystemModel;
namespace Ui
{
class CertificateManagerDialog;
class PDFCertificateManagerDialog;
}
namespace pdfplugin
namespace pdf
{
class CertificateManagerDialog : public QDialog
class PDF4QTLIBSHARED_EXPORT PDFCertificateManagerDialog : public QDialog
{
Q_OBJECT
public:
explicit CertificateManagerDialog(QWidget* parent);
virtual ~CertificateManagerDialog() override;
explicit PDFCertificateManagerDialog(QWidget* parent);
virtual ~PDFCertificateManagerDialog() override;
private:
void onNewCertificateClicked();
@ -47,8 +47,8 @@ private:
void onDeleteCertificateClicked();
void onImportCertificateClicked();
Ui::CertificateManagerDialog* ui;
CertificateManager m_certificateManager;
Ui::PDFCertificateManagerDialog* ui;
PDFCertificateManager m_certificateManager;
QPushButton* m_newCertificateButton;
QPushButton* m_openCertificateDirectoryButton;
QPushButton* m_deleteCertificateButton;
@ -56,6 +56,6 @@ private:
QFileSystemModel* m_certificateFileModel;
};
} // namespace pdfplugin
} // namespace pdf
#endif // CERTIFICATEMANAGERDIALOG_H
#endif // PDFCERTIFICATEMANAGERDIALOG_H

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CertificateManagerDialog</class>
<widget class="QDialog" name="CertificateManagerDialog">
<class>PDFCertificateManagerDialog</class>
<widget class="QDialog" name="PDFCertificateManagerDialog">
<property name="geometry">
<rect>
<x>0</x>
@ -43,7 +43,7 @@
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>CertificateManagerDialog</receiver>
<receiver>PDFCertificateManagerDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
@ -59,7 +59,7 @@
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>CertificateManagerDialog</receiver>
<receiver>PDFCertificateManagerDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">

View File

@ -15,27 +15,27 @@
// You should have received a copy of the GNU Lesser General Public License
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
#include "createcertificatedialog.h"
#include "ui_createcertificatedialog.h"
#include "pdfcreatecertificatedialog.h"
#include "ui_pdfcreatecertificatedialog.h"
#include "certificatemanager.h"
#include "pdfcertificatemanager.h"
#include <QMessageBox>
#include <QInputDialog>
#include <QDate>
#include <QCalendar>
namespace pdfplugin
namespace pdf
{
CreateCertificateDialog::CreateCertificateDialog(QWidget *parent) :
PDFCreateCertificateDialog::PDFCreateCertificateDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::CreateCertificateDialog)
ui(new Ui::PDFCreateCertificateDialog)
{
ui->setupUi(this);
ui->fileNameEdit->setReadOnly(true);
ui->fileNameEdit->setText(CertificateManager::generateCertificateFileName());
ui->fileNameEdit->setText(PDFCertificateManager::generateCertificateFileName());
ui->keyLengthCombo->addItem(tr("1024 bits"), 1024);
ui->keyLengthCombo->addItem(tr("2048 bits"), 2048);
@ -88,12 +88,12 @@ CreateCertificateDialog::CreateCertificateDialog(QWidget *parent) :
ui->validTillEdit->setSelectedDate(selectedDate);
}
CreateCertificateDialog::~CreateCertificateDialog()
PDFCreateCertificateDialog::~PDFCreateCertificateDialog()
{
delete ui;
}
void CreateCertificateDialog::accept()
void PDFCreateCertificateDialog::accept()
{
if (validate())
{
@ -132,7 +132,7 @@ void CreateCertificateDialog::accept()
}
}
bool CreateCertificateDialog::validate()
bool PDFCreateCertificateDialog::validate()
{
// validate empty text fields
if (ui->commonNameEdit->text().isEmpty())
@ -159,4 +159,4 @@ bool CreateCertificateDialog::validate()
return true;
}
} // namespace plugin
} // namespace pdf

View File

@ -15,22 +15,22 @@
// You should have received a copy of the GNU Lesser General Public License
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
#ifndef CREATECERTIFICATEDIALOG_H
#define CREATECERTIFICATEDIALOG_H
#ifndef PDFCREATECERTIFICATEDIALOG_H
#define PDFCREATECERTIFICATEDIALOG_H
#include "certificatemanager.h"
#include "pdfcertificatemanager.h"
#include <QDialog>
namespace Ui
{
class CreateCertificateDialog;
class PDFCreateCertificateDialog;
}
namespace pdfplugin
namespace pdf
{
class CreateCertificateDialog : public QDialog
class PDF4QTLIBSHARED_EXPORT PDFCreateCertificateDialog : public QDialog
{
Q_OBJECT
@ -38,10 +38,10 @@ private:
using BaseClass = QDialog;
public:
explicit CreateCertificateDialog(QWidget* parent);
virtual ~CreateCertificateDialog() override;
explicit PDFCreateCertificateDialog(QWidget* parent);
virtual ~PDFCreateCertificateDialog() override;
const CertificateManager::NewCertificateInfo& getNewCertificateInfo() const { return m_newCertificateInfo; }
const PDFCertificateManager::NewCertificateInfo& getNewCertificateInfo() const { return m_newCertificateInfo; }
public slots:
virtual void accept() override;
@ -49,11 +49,11 @@ public slots:
private:
bool validate();
CertificateManager::NewCertificateInfo m_newCertificateInfo;
PDFCertificateManager::NewCertificateInfo m_newCertificateInfo;
Ui::CreateCertificateDialog* ui;
Ui::PDFCreateCertificateDialog* ui;
};
} // namespace plugin
} // namespace pdf
#endif // CREATECERTIFICATEDIALOG_H
#endif // PDFCREATECERTIFICATEDIALOG_H

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CreateCertificateDialog</class>
<widget class="QDialog" name="CreateCertificateDialog">
<class>PDFCreateCertificateDialog</class>
<widget class="QDialog" name="PDFCreateCertificateDialog">
<property name="geometry">
<rect>
<x>0</x>
@ -149,7 +149,7 @@
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>CreateCertificateDialog</receiver>
<receiver>PDFCreateCertificateDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
@ -165,7 +165,7 @@
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>CreateCertificateDialog</receiver>
<receiver>PDFCreateCertificateDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,7 @@ enum class EncryptionMode
{
None, ///< Document is not encrypted
Standard, ///< Document is encrypted and using standard security handler
PublicKey, ///< Document is encrypted and using public key security handler
Custom ///< Document is encrypted and using custom security handler. Custom handlers must return this value.
};
@ -68,11 +69,15 @@ struct CryptFilter
CryptFilterType type = CryptFilterType::None;
AuthEvent authEvent = AuthEvent::DocOpen;
int keyLength = 0; ///< Key length in bytes
QByteArrayList recipients; ///< Recipients for public key security handler
bool encryptMetadata = true; ///< Encrypt metadata (for public key encryption)
};
class PDFSecurityHandler;
using PDFSecurityHandlerPointer = QSharedPointer<PDFSecurityHandler>;
class PDFStandardSecurityHandler;
class PDFSecurityHandler
{
public:
@ -196,10 +201,21 @@ public:
static PDFSecurityHandlerPointer createSecurityHandler(const PDFObject& encryptionDictionaryObject, const QByteArray& id);
protected:
friend class PDFSecurityHandlerFactory;
static bool parseBool(const PDFDictionary* dictionary, const char* key, bool required, bool defaultValue = true);
static QByteArray parseName(const PDFDictionary* dictionary, const char* key, bool required, const char* defaultValue = nullptr);
static PDFInteger parseInt(const PDFDictionary* dictionary, const char* key, bool required, PDFInteger defaultValue = -1);
static CryptFilter parseCryptFilter(PDFInteger length, const PDFObject& object, bool publicKey);
static PDFSecurityHandlerPointer createSecurityHandlerInstance(const PDFDictionary* dictionary);
static QByteArrayList parseRecipients(const PDFDictionary* dictionary);
static void parseCryptFilters(const PDFDictionary* dictionary, PDFSecurityHandler& handler, int Length, bool publicKey);
static void parseDataStandardSecurityHandler(const PDFDictionary* dictionary, const QByteArray& id, int Length, PDFStandardSecurityHandler& handler);
/// Fills encryption dictionary with basic data
/// \param factory Factory
void fillEncryptionDictionary(PDFObjectFactory& factory) const;
void fillEncryptionDictionary(PDFObjectFactory& factory, bool publicKeyHandler) const;
/// Version of the encryption, shall be a number from 1 to 5, according the
/// PDF specification. Other values are invalid.
@ -242,23 +258,18 @@ public:
virtual PDFObject createEncryptionDictionaryObject() const override { return PDFObject(); }
};
/// Specifies the security using standard security handler (see PDF specification
/// for details).
class PDFStandardSecurityHandler : public PDFSecurityHandler
class PDFStandardOrPublicSecurityHandler : public PDFSecurityHandler
{
public:
virtual EncryptionMode getMode() const override { return EncryptionMode::Standard; }
virtual PDFSecurityHandler* clone() const override;
virtual AuthorizationResult authenticate(const std::function<QString(bool*)>& getPasswordCallback, bool authorizeOwnerOnly) override;
virtual QByteArray decrypt(const QByteArray& data, PDFObjectReference reference, EncryptionScope encryptionScope) const override;
virtual QByteArray decryptByFilter(const QByteArray& data, const QByteArray& filterName, PDFObjectReference reference) const override;
virtual QByteArray encrypt(const QByteArray& data, PDFObjectReference reference, EncryptionScope encryptionScope) const override;
virtual QByteArray encryptByFilter(const QByteArray& data, const QByteArray& filterName, PDFObjectReference reference) const override;
virtual bool isMetadataEncrypted() const override { return m_encryptMetadata; }
virtual bool isAllowed(Permission permission) const override { return m_authorizationData.authorizationResult == AuthorizationResult::OwnerAuthorized || (m_permissions & static_cast<uint32_t>(permission)); }
virtual bool isEncryptionAllowed() const override { return m_authorizationData.isAuthorized(); }
virtual AuthorizationResult getAuthorizationResult() const override { return m_authorizationData.authorizationResult; }
virtual PDFObject createEncryptionDictionaryObject() const override;
virtual bool isEncryptionAllowed() const override { return m_authorizationData.isAuthorized(); }
/// Adjusts the password according to the PDF specification
static QByteArray adjustPassword(const QString& password, int revision);
struct AuthorizationData
{
@ -268,10 +279,55 @@ public:
QByteArray fileEncryptionKey;
};
/// Adjusts the password according to the PDF specification
static QByteArray adjustPassword(const QString& password, int revision);
protected:
friend class PDFSecurityHandlerFactory;
/// Decrypts data using specified filter. This function can be called only, if authorization was successfull.
/// \param data Data to be decrypted
/// \param filter Filter to be used for decryption
/// \param reference Object reference for key generation
/// \returns Decrypted data
QByteArray decryptUsingFilter(const QByteArray& data, CryptFilter filter, PDFObjectReference reference) const;
/// Encrypts data using specified filter. This function can be called only, if authorization was successfull.
/// \param data Data to be encrypted
/// \param filter Filter to be used for encryption
/// \param reference Object reference for key generation
/// \returns Encrypted data
QByteArray encryptUsingFilter(const QByteArray& data, CryptFilter filter, PDFObjectReference reference) const;
/// Returns true, if character with unicode code is non-ascii space character
/// according the RFC 3454, section C.1.2
/// \param unicode Unicode code to be tested
static bool isUnicodeNonAsciiSpaceCharacter(ushort unicode);
/// Returns true, if character with unicode code is mapped to nothing,
/// according the RFC 3454, section B.1
/// \param unicode Unicode code to be tested
static bool isUnicodeMappedToNothing(ushort unicode);
std::vector<uint8_t> createV2_ObjectEncryptionKey(PDFObjectReference reference, CryptFilter filter) const;
std::vector<uint8_t> createAESV2_ObjectEncryptionKey(PDFObjectReference reference) const;
CryptFilter getCryptFilter(EncryptionScope encryptionScope) const;
/// Authorization data
AuthorizationData m_authorizationData;
};
/// Specifies the security using standard security handler (see PDF specification
/// for details).
class PDFStandardSecurityHandler : public PDFStandardOrPublicSecurityHandler
{
public:
virtual EncryptionMode getMode() const override { return EncryptionMode::Standard; }
virtual PDFSecurityHandler* clone() const override;
virtual AuthorizationResult authenticate(const std::function<QString(bool*)>& getPasswordCallback, bool authorizeOwnerOnly) override;
virtual bool isMetadataEncrypted() const override { return m_encryptMetadata; }
virtual bool isAllowed(Permission permission) const override { return m_authorizationData.authorizationResult == AuthorizationResult::OwnerAuthorized || (m_permissions & static_cast<uint32_t>(permission)); }
virtual PDFObject createEncryptionDictionaryObject() const override;
private:
friend class PDFSecurityHandler;
friend class PDFSecurityHandlerFactory;
friend PDFSecurityHandlerPointer PDFSecurityHandler::createSecurityHandler(const PDFObject& encryptionDictionaryObject, const QByteArray& id);
@ -311,35 +367,6 @@ private:
/// Parses parts of the user/owner data (U/O values of the encryption dictionary)
UserOwnerData_r6 parseParts(const QByteArray& data) const;
/// Decrypts data using specified filter. This function can be called only, if authorization was successfull.
/// \param data Data to be decrypted
/// \param filter Filter to be used for decryption
/// \param reference Object reference for key generation
/// \returns Decrypted data
QByteArray decryptUsingFilter(const QByteArray& data, CryptFilter filter, PDFObjectReference reference) const;
/// Encrypts data using specified filter. This function can be called only, if authorization was successfull.
/// \param data Data to be encrypted
/// \param filter Filter to be used for encryption
/// \param reference Object reference for key generation
/// \returns Encrypted data
QByteArray encryptUsingFilter(const QByteArray& data, CryptFilter filter, PDFObjectReference reference) const;
std::vector<uint8_t> createV2_ObjectEncryptionKey(PDFObjectReference reference, CryptFilter filter) const;
std::vector<uint8_t> createAESV2_ObjectEncryptionKey(PDFObjectReference reference) const;
CryptFilter getCryptFilter(EncryptionScope encryptionScope) const;
/// Returns true, if character with unicode code is non-ascii space character
/// according the RFC 3454, section C.1.2
/// \param unicode Unicode code to be tested
static bool isUnicodeNonAsciiSpaceCharacter(ushort unicode);
/// Returns true, if character with unicode code is mapped to nothing,
/// according the RFC 3454, section B.1
/// \param unicode Unicode code to be tested
static bool isUnicodeMappedToNothing(ushort unicode);
/// Revision number of standard security number
int m_R = 0;
@ -372,9 +399,49 @@ private:
/// First part of the id of the document
QByteArray m_ID;
};
/// Authorization data
AuthorizationData m_authorizationData;
/// Specifies the security using public key security handler (see PDF specification
/// for details).
class PDFPublicKeySecurityHandler : public PDFStandardOrPublicSecurityHandler
{
public:
virtual EncryptionMode getMode() const override { return EncryptionMode::PublicKey; }
virtual PDFSecurityHandler* clone() const override;
virtual AuthorizationResult authenticate(const std::function<QString(bool*)>& getPasswordCallback, bool authorizeOwnerOnly) override;
virtual bool isMetadataEncrypted() const override;
virtual bool isAllowed(Permission permission) const override;
virtual PDFObject createEncryptionDictionaryObject() const override;
private:
friend class PDFSecurityHandler;
friend class PDFSecurityHandlerFactory;
enum class PKCS7_Type
{
Unknown,
PKCS7_S3,
PKCS7_S4,
PKCS7_S5
};
enum PermissionFlag : uint32_t
{
PKSH_Owner = 1 << 1,
PKSH_PrintLowResolution = 1 << 2,
PKSH_Modify = 1 << 3,
PKSH_CopyContent = 1 << 4,
PKSH_ModifyAnnotationsFillFormFields = 1 << 5,
PKSH_FillFormFields = 1 << 8,
PKSH_Assemble = 1 << 10,
PKSH_PrintHighResolution = 1 << 11
};
/// What operations shall be permitted, when document is opened with user access.
uint32_t m_permissions = 0;
/// Type of the PKCS7 subfilter
PKCS7_Type m_pkcs7Type = PKCS7_Type::Unknown;
};
/// Factory, which creates security handler based on settings.
@ -389,7 +456,8 @@ public:
None,
RC4,
AES_128,
AES_256
AES_256,
Certificate
};
enum EncryptContents
@ -407,6 +475,7 @@ public:
QString ownerPassword;
uint32_t permissions = 0;
QByteArray id;
QString certificateFileName;
};
/// Creates security handler based on given settings. If security handler cannot

View File

@ -90,5 +90,6 @@
<file>resources/pce-same-height.svg</file>
<file>resources/pce-same-size.svg</file>
<file>resources/pce-same-width.svg</file>
<file>resources/certificate-manager.svg</file>
</qresource>
</RCC>

View File

@ -189,6 +189,10 @@ void PDFDocumentPropertiesDialog::initializeSecurity(const pdf::PDFDocument* doc
modeString = tr("Standard");
break;
case pdf::EncryptionMode::PublicKey:
modeString = tr("Public Key");
break;
case pdf::EncryptionMode::Custom:
modeString = tr("Custom");
break;

View File

@ -21,6 +21,7 @@
#include "pdfutils.h"
#include "pdfwidgetutils.h"
#include "pdfsecurityhandler.h"
#include "pdfcertificatemanager.h"
#include "pdfdbgheap.h"
#include <QMessageBox>
@ -40,6 +41,7 @@ PDFEncryptionSettingsDialog::PDFEncryptionSettingsDialog(QByteArray documentId,
ui->algorithmComboBox->addItem(tr("RC4 128-bit | R4"), int(pdf::PDFSecurityHandlerFactory::RC4));
ui->algorithmComboBox->addItem(tr("AES 128-bit | R4"), int(pdf::PDFSecurityHandlerFactory::AES_128));
ui->algorithmComboBox->addItem(tr("AES 256-bit | R6"), int(pdf::PDFSecurityHandlerFactory::AES_256));
ui->algorithmComboBox->addItem(tr("Certificate Encryption"), int(pdf::PDFSecurityHandlerFactory::Certificate));
ui->algorithmComboBox->setCurrentIndex(0);
@ -73,6 +75,7 @@ PDFEncryptionSettingsDialog::PDFEncryptionSettingsDialog(QByteArray documentId,
m_checkBoxToPermission[ui->permAssembleCheckBox] = pdf::PDFSecurityHandler::Permission::Assemble;
m_checkBoxToPermission[ui->permPrintHighResolutionCheckBox] = pdf::PDFSecurityHandler::Permission::PrintHighResolution;
updateCertificates();
updateUi();
updatePasswordScore();
@ -95,6 +98,7 @@ void PDFEncryptionSettingsDialog::updateUi()
const pdf::PDFSecurityHandlerFactory::Algorithm algorithm = static_cast<const pdf::PDFSecurityHandlerFactory::Algorithm>(ui->algorithmComboBox->currentData().toInt());
const bool encrypted = algorithm != pdf::PDFSecurityHandlerFactory::None;
const bool isEncryptedUsingCertificate = algorithm == pdf::PDFSecurityHandlerFactory::Certificate;
switch (algorithm)
{
@ -108,6 +112,7 @@ void PDFEncryptionSettingsDialog::updateUi()
ui->algorithmHintWidget->setCurrentValue(4);
break;
case pdf::PDFSecurityHandlerFactory::AES_256:
case pdf::PDFSecurityHandlerFactory::Certificate:
ui->algorithmHintWidget->setCurrentValue(5);
break;
@ -116,20 +121,40 @@ void PDFEncryptionSettingsDialog::updateUi()
break;
}
ui->userPasswordEnableCheckBox->setEnabled(encrypted);
ui->ownerPasswordEnableCheckBox->setEnabled(false);
ui->certificateComboBox->setEnabled(isEncryptedUsingCertificate);
if (!encrypted)
if (!isEncryptedUsingCertificate)
{
ui->userPasswordEnableCheckBox->setChecked(false);
ui->ownerPasswordEnableCheckBox->setChecked(false);
ui->userPasswordEnableCheckBox->setEnabled(encrypted);
ui->ownerPasswordEnableCheckBox->setEnabled(false);
ui->userPasswordEdit->clear();
ui->ownerPasswordEdit->clear();
if (!encrypted)
{
ui->userPasswordEnableCheckBox->setChecked(false);
ui->ownerPasswordEnableCheckBox->setChecked(false);
ui->userPasswordEdit->clear();
ui->ownerPasswordEdit->clear();
}
else
{
ui->ownerPasswordEnableCheckBox->setChecked(true);
}
ui->certificateComboBox->setCurrentIndex(-1);
}
else
{
ui->ownerPasswordEnableCheckBox->setChecked(true);
ui->userPasswordEnableCheckBox->setEnabled(false);
ui->ownerPasswordEnableCheckBox->setEnabled(false);
ui->userPasswordEnableCheckBox->setChecked(true);
ui->ownerPasswordEnableCheckBox->setChecked(false);
if (ui->certificateComboBox->currentIndex() == -1 && ui->certificateComboBox->count() > 0)
{
ui->certificateComboBox->setCurrentIndex(0);
}
}
ui->userPasswordEdit->setEnabled(ui->userPasswordEnableCheckBox->isChecked());
@ -158,6 +183,21 @@ void PDFEncryptionSettingsDialog::updateUi()
}
}
void PDFEncryptionSettingsDialog::updateCertificates()
{
QFileInfoList certificates = pdf::PDFCertificateManager::getCertificates();
QVariant currentCertificate = ui->certificateComboBox->currentData();
ui->certificateComboBox->clear();
for (const QFileInfo& certificateItem : certificates)
{
ui->certificateComboBox->addItem(certificateItem.fileName(), certificateItem.absoluteFilePath());
}
ui->certificateComboBox->setCurrentIndex(ui->certificateComboBox->findData(currentCertificate));
}
void PDFEncryptionSettingsDialog::updatePasswordScore()
{
const pdf::PDFSecurityHandlerFactory::Algorithm algorithm = static_cast<const pdf::PDFSecurityHandlerFactory::Algorithm>(ui->algorithmComboBox->currentData().toInt());
@ -188,6 +228,7 @@ void PDFEncryptionSettingsDialog::accept()
settings.userPassword = ui->userPasswordEdit->text();
settings.ownerPassword = ui->ownerPasswordEdit->text();
settings.permissions = 0;
settings.certificateFileName = ui->certificateComboBox->currentData().toString();
for (auto item : m_checkBoxToPermission)
{

View File

@ -50,6 +50,7 @@ private:
Ui::PDFEncryptionSettingsDialog* ui;
void updateUi();
void updateCertificates();
void updatePasswordScore();
bool m_isUpdatingUi;

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>705</width>
<height>609</height>
<width>843</width>
<height>620</height>
</rect>
</property>
<property name="windowTitle">
@ -20,8 +20,8 @@
<string>Encryption Method</string>
</property>
<layout class="QGridLayout" name="methodGroupBoxLayout">
<item row="0" column="1">
<widget class="QComboBox" name="algorithmComboBox"/>
<item row="0" column="2">
<widget class="pdfviewer::PDFEncryptionStrengthHintWidget" name="algorithmHintWidget" native="true"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="encryptionAlgorithm">
@ -30,19 +30,29 @@
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="pdfviewer::PDFEncryptionStrengthHintWidget" name="algorithmHintWidget" native="true"/>
<item row="0" column="1">
<widget class="QComboBox" name="algorithmComboBox"/>
</item>
<item row="1" column="0" colspan="3">
<item row="2" column="0" colspan="3">
<widget class="QLabel" name="encryptionMethodHintLabel">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select encryption algorithm. AES-256 is strongly recommended, because older encryption algorithm can be potentially broken. Select older algorithms (as AES-128 or RC4) only, if you need backward compatibility. Also, choose a strong password to ensure strong encryption.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select encryption algorithm. AES-256 is strongly recommended, because older encryption algorithm can be potentially broken. Select older algorithms (as AES-128 or RC4) only, if you need backward compatibility. Also, choose a strong password to ensure strong encryption.&lt;/p&gt;&lt;p&gt;Public key security using certificate is also supported. In that case, you must select a certificate with private key, and this certificate is then used to encrypt data. User, which wants to open document encrypted with certificate, must have a private key to the certificae.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="certificateLabel">
<property name="text">
<string>Certificate</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="certificateComboBox"/>
</item>
</layout>
</widget>
</item>

View File

@ -26,6 +26,7 @@
#include "pdfconstants.h"
#include "pdfdocumentbuilder.h"
#include "pdfdbgheap.h"
#include "pdfcertificatemanagerdialog.h"
#include "pdfviewersettings.h"
#include "pdfundoredomanager.h"
@ -494,6 +495,10 @@ void PDFProgramController::initialize(Features features,
{
connect(action, &QAction::triggered, this, &PDFProgramController::onActionOptionsTriggered);
}
if (QAction* action = m_actionManager->getAction(PDFActionManager::CertificateManager))
{
connect(action, &QAction::triggered, this, &PDFProgramController::onActionCertificateManagerTriggered);
}
if (QAction* action = m_actionManager->getAction(PDFActionManager::Open))
{
connect(action, &QAction::triggered, this, &PDFProgramController::onActionOpenTriggered);
@ -1197,16 +1202,45 @@ void PDFProgramController::onActionEncryptionTriggered()
{
pdf::PDFSecurityHandlerPointer updatedSecurityHandler = dialog.getUpdatedSecurityHandler();
if (!updatedSecurityHandler)
{
QMessageBox::critical(m_mainWindow, QApplication::applicationDisplayName(), tr("Failed to create security handler."));
return;
}
// Jakub Melka: If we changed encryption (password), recheck, that user doesn't
// forgot (or accidentally entered wrong) password. So, we require owner authentization
// to continue.
if (updatedSecurityHandler->getMode() != pdf::EncryptionMode::None)
switch (updatedSecurityHandler->getMode())
{
if (updatedSecurityHandler->authenticate(queryPassword, true) != pdf::PDFSecurityHandler::AuthorizationResult::OwnerAuthorized)
case pdf::EncryptionMode::Standard:
{
QMessageBox::critical(m_mainWindow, QApplication::applicationDisplayName(), tr("Reauthorization is required to change document encryption."));
return;
if (updatedSecurityHandler->authenticate(queryPassword, true) != pdf::PDFSecurityHandler::AuthorizationResult::OwnerAuthorized)
{
QMessageBox::critical(m_mainWindow, QApplication::applicationDisplayName(), tr("Reauthorization is required to change document encryption."));
return;
}
break;
}
case pdf::EncryptionMode::PublicKey:
{
if (updatedSecurityHandler->authenticate(queryPassword, false) != pdf::PDFSecurityHandler::AuthorizationResult::UserAuthorized)
{
QMessageBox::critical(m_mainWindow, QApplication::applicationDisplayName(), tr("Reauthorization is required to change document encryption."));
return;
}
break;
}
case pdf::EncryptionMode::None:
break;
default:
Q_ASSERT(false);
break;
}
pdf::PDFDocumentBuilder builder(m_pdfDocument.data());
@ -1921,6 +1955,12 @@ void PDFProgramController::onActionOptionsTriggered()
}
}
void PDFProgramController::onActionCertificateManagerTriggered()
{
pdf::PDFCertificateManagerDialog dialog(getMainWindow());
dialog.exec();
}
void PDFProgramController::onDrawSpaceChanged()
{
m_mainWindowInterface->updateUI(false);

View File

@ -98,6 +98,7 @@ public:
SaveAs,
Properties,
Options,
CertificateManager,
GetSource,
About,
SendByMail,
@ -333,6 +334,7 @@ private:
void onActionFirstPageOnRightSideTriggered();
void onActionFindTriggered();
void onActionOptionsTriggered();
void onActionCertificateManagerTriggered();
void onActionOpenTriggered();
void onActionCloseTriggered();
void onActionDeveloperCreateInstaller();

View File

@ -164,6 +164,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
m_actionManager->setAction(PDFActionManager::RenderOptionShowTextLines, ui->actionShow_Text_Lines);
m_actionManager->setAction(PDFActionManager::Properties, ui->actionProperties);
m_actionManager->setAction(PDFActionManager::Options, ui->actionOptions);
m_actionManager->setAction(PDFActionManager::CertificateManager, ui->actionCertificateManager);
m_actionManager->setAction(PDFActionManager::GetSource, ui->actionGetSource);
m_actionManager->setAction(PDFActionManager::About, ui->actionAbout);
m_actionManager->setAction(PDFActionManager::SendByMail, ui->actionSend_by_E_Mail);

View File

@ -103,6 +103,7 @@
<addaction name="actionRendering_Errors"/>
<addaction name="separator"/>
<addaction name="actionOptions"/>
<addaction name="actionCertificateManager"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
@ -893,6 +894,15 @@
<string>Encryption...</string>
</property>
</action>
<action name="actionCertificateManager">
<property name="icon">
<iconset resource="pdf4qtviewer.qrc">
<normaloff>:/resources/certificate-manager.svg</normaloff>:/resources/certificate-manager.svg</iconset>
</property>
<property name="text">
<string>Certificates...</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>

View File

@ -132,6 +132,7 @@ PDFViewerMainWindowLite::PDFViewerMainWindowLite(QWidget* parent) :
m_actionManager->setAction(PDFActionManager::RenderOptionInvertColors, ui->actionInvertColors);
m_actionManager->setAction(PDFActionManager::Properties, ui->actionProperties);
m_actionManager->setAction(PDFActionManager::Options, ui->actionOptions);
m_actionManager->setAction(PDFActionManager::CertificateManager, ui->actionCertificateManager);
m_actionManager->setAction(PDFActionManager::GetSource, ui->actionGetSource);
m_actionManager->setAction(PDFActionManager::About, ui->actionAbout);
m_actionManager->setAction(PDFActionManager::SendByMail, ui->actionSend_by_E_Mail);

View File

@ -97,6 +97,7 @@
<addaction name="actionRendering_Errors"/>
<addaction name="separator"/>
<addaction name="actionOptions"/>
<addaction name="actionCertificateManager"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
@ -442,6 +443,15 @@
<string>Get Source</string>
</property>
</action>
<action name="actionCertificateManager">
<property name="icon">
<iconset resource="pdf4qtviewer.qrc">
<normaloff>:/resources/certificate-manager.svg</normaloff>:/resources/certificate-manager.svg</iconset>
</property>
<property name="text">
<string>Certificates...</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 KiB

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Vrstva_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<g>
<path fill="#292D32" stroke="#292D32" stroke-width="0.2" stroke-miterlimit="10" d="M11.987,14.505
c-2.647,0.009-4.82-2.152-4.828-4.801c-0.01-2.663,2.153-4.833,4.818-4.837c2.656-0.003,4.824,2.144,4.828,4.8
C16.82,12.329,14.656,14.501,11.987,14.505z M11.958,13.266c1.961,0.02,3.586-1.575,3.61-3.538
c0.023-1.964-1.566-3.599-3.525-3.622C10.048,6.084,8.42,7.665,8.396,9.641C8.374,11.625,9.969,13.245,11.958,13.266z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#292D32" stroke="#292D32" stroke-width="0.3" stroke-miterlimit="10" d="
M11.287,10.553c0.721-0.681,1.413-1.333,2.104-1.987c0.166-0.156,0.33-0.314,0.498-0.468c0.189-0.174,0.41-0.183,0.561-0.027
c0.154,0.158,0.137,0.374-0.057,0.556c-0.932,0.881-1.865,1.761-2.798,2.638c-0.21,0.198-0.409,0.193-0.612-0.013
c-0.476-0.483-0.947-0.97-1.42-1.456c-0.114-0.118-0.2-0.259-0.12-0.413c0.052-0.1,0.161-0.193,0.266-0.234
c0.155-0.061,0.281,0.042,0.389,0.153c0.357,0.368,0.715,0.735,1.071,1.104C11.208,10.446,11.24,10.494,11.287,10.553z"/>
<g>
<path fill="#292D32" d="M19.605,9.754c-0.025-0.07-0.025-0.168,0-0.247c0.203-0.596,0.377-1.082,0.547-1.53
c0.059-0.156,0.033-0.271-0.094-0.396c-0.373-0.355-0.76-0.74-1.154-1.142c-0.055-0.055-0.098-0.137-0.105-0.201
c-0.061-0.479-0.125-1.045-0.172-1.618c-0.014-0.186-0.094-0.285-0.275-0.341c-0.48-0.159-0.99-0.329-1.498-0.511
c-0.084-0.031-0.174-0.104-0.223-0.179c-0.316-0.489-0.615-0.986-0.84-1.365C15.703,2.08,15.607,2.03,15.426,2.05
c-0.547,0.076-1.096,0.138-1.66,0.202c-0.047,0.006-0.107-0.002-0.107-0.002c-0.52-0.337-1.043-0.679-1.563-1.02L12.07,1.213
h-0.144L11.9,1.23c-0.095,0.063-0.192,0.125-0.289,0.187c-0.218,0.139-0.444,0.283-0.65,0.449
c-0.426,0.35-0.866,0.451-1.398,0.315c-0.216-0.054-0.44-0.074-0.657-0.093C8.787,2.077,8.668,2.066,8.551,2.05
c-0.189-0.027-0.276,0.073-0.33,0.161C7.979,2.619,7.688,3.1,7.379,3.575C7.321,3.662,7.218,3.743,7.123,3.778
C6.622,3.967,6.108,4.138,5.627,4.294C5.459,4.349,5.388,4.442,5.371,4.625c-0.047,0.58-0.112,1.143-0.169,1.616
C5.193,6.31,5.15,6.393,5.098,6.445c-0.34,0.347-0.719,0.722-1.158,1.148c-0.091,0.089-0.165,0.198-0.092,0.39
c0.201,0.532,0.384,1.046,0.545,1.528c0.025,0.075,0.026,0.177,0,0.247c-0.167,0.499-0.349,1.007-0.541,1.511
c-0.065,0.172-0.039,0.297,0.095,0.432c0.348,0.325,0.712,0.683,1.146,1.126c0.057,0.058,0.102,0.147,0.108,0.224
c0.067,0.547,0.126,1.098,0.174,1.636c0.015,0.151,0.08,0.234,0.229,0.289c0.175,0.056,0.349,0.114,0.527,0.175
c0.088,0.03,0.177,0.061,0.268,0.091l0.872,0.238l0.547,0.922l0.003,0.011c0.13,0.209,0.26,0.416,0.376,0.622
c0.078,0.132,0.174,0.191,0.313,0.191c0.021,0,0.043-0.002,0.069-0.005c0.497-0.066,0.995-0.128,1.493-0.188l0.045-0.007
c0.063-0.008,0.134-0.011,0.196-0.004l0.005-0.002l0.016,0.009c0.036,0.006,0.076,0.011,0.09,0.03c0.003,0.004-0.002-0.004,0,0
l1.556,0.89c0,0-0.005,0.023-0.012,0.052c0.083,0.009,0.164-0.012,0.241-0.052l1.364-0.884c0.002-0.002,0-0.008,0.002-0.01
c0.014-0.017,0.037-0.026,0.064-0.032v-0.001l0,0c0.027-0.006,0.057-0.007,0.076-0.007c0.025,0,0.053,0.001,0.082,0.005
c0.24,0.022,0.482,0.054,0.725,0.084c0.141,0.017,0.279,0.034,0.418,0.051c0.061,0.006,0.125,0.019,0.188,0.031
c0.178,0.034,0.367,0.054,0.494,0.003l1.182-2.006h0.961c0.188-0.069,0.363-0.135,0.547-0.182c0.254-0.065,0.305-0.23,0.32-0.402
c0.039-0.53,0.102-1.061,0.166-1.557c0.006-0.073,0.051-0.161,0.107-0.22c0.355-0.366,0.725-0.73,1.131-1.111
c0.146-0.138,0.178-0.273,0.104-0.468C19.967,10.791,19.793,10.304,19.605,9.754z M18.111,9.891
c0.086,0.221,0.166,0.447,0.248,0.672c0.059,0.162,0.115,0.324,0.176,0.484c0.031,0.078,0.025,0.107-0.033,0.16
c-0.281,0.266-0.58,0.56-0.914,0.9c-0.092,0.098-0.154,0.23-0.17,0.354c-0.059,0.406-0.105,0.836-0.139,1.277
c-0.006,0.084-0.027,0.106-0.117,0.138c-0.396,0.13-0.807,0.265-1.211,0.418c-0.117,0.043-0.229,0.132-0.293,0.231
c-0.258,0.392-0.475,0.743-0.664,1.073c-0.063,0.112-0.129,0.104-0.215,0.096c-0.443-0.064-0.846-0.114-1.232-0.152l-0.033-0.001
c-0.109,0-0.236,0.033-0.352,0.095c-0.316,0.191-0.658,0.409-1.049,0.668c-0.049,0.032-0.083,0.047-0.112,0.047
c-0.018,0-0.048-0.004-0.105-0.043c-0.328-0.222-0.682-0.446-1.076-0.685c-0.065-0.044-0.138-0.065-0.186-0.079
c-0.013-0.004-0.023-0.007-0.031-0.011l-0.023-0.009l-0.438,0.054c-0.315,0.038-0.613,0.074-0.915,0.116
c-0.097,0.016-0.161,0.021-0.231-0.098c-0.192-0.34-0.408-0.693-0.661-1.081c-0.059-0.091-0.159-0.17-0.278-0.22
c-0.426-0.157-0.822-0.292-1.208-0.414c-0.096-0.033-0.122-0.054-0.128-0.153c-0.035-0.444-0.08-0.854-0.136-1.251
c-0.017-0.132-0.088-0.272-0.195-0.386c-0.271-0.289-0.559-0.563-0.836-0.828l-0.061-0.058c-0.057-0.058-0.059-0.083-0.033-0.146
l0.029-0.077c0.135-0.362,0.274-0.736,0.393-1.112C5.929,9.734,5.928,9.549,5.88,9.4C5.751,8.992,5.597,8.581,5.464,8.235
C5.436,8.155,5.441,8.13,5.499,8.075C5.86,7.731,6.151,7.445,6.411,7.176c0.087-0.086,0.156-0.218,0.173-0.338
c0.053-0.401,0.1-0.831,0.143-1.314C6.733,5.455,6.748,5.438,6.82,5.415C7.19,5.293,7.619,5.15,8.033,4.998
c0.125-0.046,0.251-0.147,0.322-0.256c0.249-0.377,0.48-0.763,0.673-1.089c0.054-0.09,0.088-0.08,0.149-0.072
c0.479,0.066,0.916,0.118,1.334,0.158c0.095,0.008,0.21-0.021,0.309-0.079c0.356-0.22,0.724-0.447,1.079-0.691
c0.054-0.036,0.084-0.04,0.102-0.04c0.03,0,0.065,0.014,0.113,0.046c0.354,0.236,0.717,0.467,1.08,0.688
c0.074,0.048,0.184,0.076,0.291,0.076l0.041-0.001c0.486-0.051,0.916-0.102,1.309-0.156c0.055-0.007,0.086-0.021,0.133,0.061
c0.207,0.353,0.434,0.729,0.68,1.09c0.074,0.113,0.203,0.215,0.336,0.267c0.211,0.079,0.422,0.15,0.631,0.221
c0.191,0.065,0.383,0.13,0.572,0.2c0.031,0.011,0.078,0.069,0.08,0.099c0.033,0.233,0.057,0.466,0.082,0.698
c0.023,0.211,0.045,0.421,0.072,0.628c0.012,0.11,0.076,0.236,0.162,0.321c0.311,0.32,0.623,0.628,0.928,0.915
c0.055,0.053,0.059,0.073,0.031,0.141C18.475,8.4,18.41,8.58,18.346,8.759c-0.078,0.216-0.156,0.432-0.236,0.643
C18.045,9.564,18.047,9.719,18.111,9.891z"/>
</g>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#292D32" d="M14.105,22.69c0.283,0,0.5-0.146,0.641-0.435
c0.209-0.434,0.42-0.868,0.629-1.303l0.426-0.881c0.031-0.064,0.064-0.127,0.1-0.196l0.084-0.159l0.078,0.021
c0.701,0.196,1.398,0.388,2.094,0.579l0.17,0.047c0.051,0.015,0.104,0.029,0.156,0.045c0.074,0.022,0.15,0.045,0.225,0.063
c0.084,0.021,0.164,0.03,0.238,0.03c0.205,0,0.369-0.077,0.504-0.235c0.191-0.222,0.223-0.478,0.098-0.76
c-0.275-0.615-0.553-1.229-0.832-1.844c-0.133-0.296-0.285-0.62-0.441-0.955c-0.301-0.65-0.613-1.322-0.859-1.908l-1.152,0.738
l0.547,1.245c0.264,0.584,0.527,1.17,0.799,1.773l0.084,0.187l-0.199-0.049c-0.041-0.01-0.074-0.017-0.102-0.022
c-0.033-0.008-0.061-0.014-0.086-0.021l-1.369-0.376c-0.527-0.146-0.777-0.032-1.018,0.466l-0.49,1.01
c-0.063,0.13-0.125,0.26-0.213,0.438l-0.094,0.19l-1.525-3.376l-0.826,0.324l-0.825-0.324l-1.527,3.376l-0.093-0.19
c-0.087-0.178-0.15-0.308-0.213-0.438l-0.49-1.009c-0.24-0.498-0.492-0.61-1.017-0.466l-1.371,0.377
c-0.024,0.007-0.05,0.013-0.085,0.021c-0.027,0.006-0.06,0.013-0.101,0.022l-0.199,0.049l0.084-0.187
c0.271-0.604,0.535-1.189,0.8-1.774l0.655-1.438l-1.362-0.281c-0.224,0.534-0.477,1.064-0.722,1.578
c-0.162,0.34-0.324,0.68-0.479,1.021c-0.278,0.615-0.556,1.229-0.831,1.844c-0.126,0.282-0.094,0.538,0.096,0.759
c0.185,0.217,0.429,0.285,0.742,0.206c0.076-0.019,0.151-0.041,0.227-0.063c0.052-0.016,0.104-0.03,0.156-0.045l0.17-0.047
c0.695-0.191,1.392-0.383,2.093-0.579l0.078-0.021l0.083,0.159c0.036,0.069,0.069,0.133,0.1,0.197l0.425,0.88
c0.21,0.435,0.419,0.869,0.63,1.303c0.141,0.288,0.356,0.435,0.641,0.435c0.299-0.006,0.511-0.154,0.647-0.441
c0.023-0.048,0.044-0.094,0.065-0.14l1.623-3.59l1.623,3.59c0.021,0.046,0.043,0.092,0.064,0.139
c0.137,0.288,0.35,0.437,0.631,0.442l0.018,0.098l0,0V22.69z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@ -40,16 +40,10 @@ INCLUDEPATH += $$Pdf4Qt_OPENSSL_PATH/OpenSSL/Win_x64/include
DEPENDPATH += $$Pdf4Qt_OPENSSL_PATH/OpenSSL/Win_x64/include
SOURCES += \
certificatemanager.cpp \
certificatemanagerdialog.cpp \
createcertificatedialog.cpp \
signatureplugin.cpp \
signdialog.cpp
HEADERS += \
certificatemanager.h \
certificatemanagerdialog.h \
createcertificatedialog.h \
signatureplugin.h \
signdialog.h
@ -62,7 +56,5 @@ RESOURCES += \
icons.qrc
FORMS += \
certificatemanagerdialog.ui \
createcertificatedialog.ui \
signdialog.ui

View File

@ -21,7 +21,7 @@
#include "pdfpagecontenteditorwidget.h"
#include "pdfpagecontenteditorstylesettings.h"
#include "pdfdocumentbuilder.h"
#include "certificatemanagerdialog.h"
#include "pdfcertificatemanagerdialog.h"
#include "signdialog.h"
#include "pdfdocumentwriter.h"
@ -314,11 +314,11 @@ void SignaturePlugin::onSignDigitally()
// Jakub Melka: do we have certificates? If not,
// open certificate dialog, so the user can create
// a new one.
if (CertificateManager::getCertificates().isEmpty())
if (pdf::PDFCertificateManager::getCertificates().isEmpty())
{
onOpenCertificatesManager();
if (CertificateManager::getCertificates().isEmpty())
if (pdf::PDFCertificateManager::getCertificates().isEmpty())
{
return;
}
@ -329,7 +329,7 @@ void SignaturePlugin::onSignDigitally()
{
QByteArray data = "SampleDataToBeSigned" + QByteArray::number(QDateTime::currentMSecsSinceEpoch());
QByteArray signature;
if (!SignatureFactory::sign(dialog.getCertificatePath(), dialog.getPassword(), data, signature))
if (!pdf::PDFSignatureFactory::sign(dialog.getCertificatePath(), dialog.getPassword(), data, signature))
{
QMessageBox::critical(m_widget, tr("Error"), tr("Failed to create digital signature."));
return;
@ -458,7 +458,7 @@ void SignaturePlugin::onSignDigitally()
buffer.seek(i3);
dataToBeSigned.append(buffer.read(i4));
if (!SignatureFactory::sign(dialog.getCertificatePath(), dialog.getPassword(), dataToBeSigned, signature))
if (!pdf::PDFSignatureFactory::sign(dialog.getCertificatePath(), dialog.getPassword(), dataToBeSigned, signature))
{
QMessageBox::critical(m_widget, tr("Error"), tr("Failed to create digital signature."));
buffer.close();
@ -492,7 +492,7 @@ QString SignaturePlugin::getSignedFileName() const
void SignaturePlugin::onOpenCertificatesManager()
{
CertificateManagerDialog dialog(m_dataExchangeInterface->getMainWindow());
pdf::PDFCertificateManagerDialog dialog(m_dataExchangeInterface->getMainWindow());
dialog.exec();
}

View File

@ -18,7 +18,7 @@
#include "signdialog.h"
#include "ui_signdialog.h"
#include "certificatemanager.h"
#include "pdfcertificatemanager.h"
#include <openssl/pkcs7.h>
@ -41,7 +41,7 @@ SignDialog::SignDialog(QWidget* parent, bool isSceneEmpty) :
ui->methodCombo->addItem(tr("Sign digitally (invisible signature)"), SignDigitallyInvisible);
ui->methodCombo->setCurrentIndex(0);
QFileInfoList certificates = CertificateManager::getCertificates();
QFileInfoList certificates = pdf::PDFCertificateManager::getCertificates();
for (const QFileInfo& certificateFileInfo : certificates)
{
ui->certificateCombo->addItem(certificateFileInfo.fileName(), certificateFileInfo.absoluteFilePath());
@ -89,7 +89,7 @@ void SignDialog::accept()
}
// Check we can access the certificate
if (!CertificateManager::isCertificateValid(getCertificatePath(), ui->certificatePasswordEdit->text()))
if (!pdf::PDFCertificateManager::isCertificateValid(getCertificatePath(), ui->certificatePasswordEdit->text()))
{
QMessageBox::critical(this, tr("Error"), tr("Password to open certificate is invalid."));
ui->certificatePasswordEdit->setFocus();

View File

@ -179,6 +179,10 @@ int PDFToolInfoApplication::execute(const PDFToolOptions& options)
modeString = PDFToolTranslationContext::tr("Standard");
break;
case pdf::EncryptionMode::PublicKey:
modeString = PDFToolTranslationContext::tr("Public Key");
break;
case pdf::EncryptionMode::Custom:
modeString = PDFToolTranslationContext::tr("Custom");
break;

View File

@ -1,6 +1,6 @@
CURRENT:
V: 1.2.0
V: 1.2.0 5.6.2022
- Issue #10: Performance optimization
- Issue #14: Incorrect text drawing for vertical writing systems
- Issue #15: .msi installer