mirror of https://github.com/JakubMelka/PDF4QT.git
Signature hash/signing time update
This commit is contained in:
parent
ddf852d34e
commit
5eb7472473
|
@ -369,6 +369,36 @@ void PDFSignatureVerificationResult::validate()
|
|||
}
|
||||
}
|
||||
|
||||
QDateTime PDFSignatureVerificationResult::getSignatureDate() const
|
||||
{
|
||||
return m_signatureDate;
|
||||
}
|
||||
|
||||
void PDFSignatureVerificationResult::setSignatureDate(const QDateTime& signatureDate)
|
||||
{
|
||||
m_signatureDate = signatureDate;
|
||||
}
|
||||
|
||||
QDateTime PDFSignatureVerificationResult::getTimestampDate() const
|
||||
{
|
||||
return m_timestampDate;
|
||||
}
|
||||
|
||||
void PDFSignatureVerificationResult::setTimestampDate(const QDateTime& timestampDate)
|
||||
{
|
||||
m_timestampDate = timestampDate;
|
||||
}
|
||||
|
||||
QByteArray PDFSignatureVerificationResult::getSignatureFilter() const
|
||||
{
|
||||
return m_signatureFilter;
|
||||
}
|
||||
|
||||
void PDFSignatureVerificationResult::setSignatureFilter(const QByteArray& signatureFilter)
|
||||
{
|
||||
m_signatureFilter = signatureFilter;
|
||||
}
|
||||
|
||||
PDFSignature::Type PDFSignatureVerificationResult::getType() const
|
||||
{
|
||||
return m_type;
|
||||
|
@ -386,6 +416,7 @@ void PDFPublicKeySignatureHandler::initializeResult(PDFSignatureVerificationResu
|
|||
result.setType(m_signatureField->getSignature().getType());
|
||||
result.setSignatureFieldReference(signatureFieldReference);
|
||||
result.setSignatureFieldQualifiedName(signatureFieldQualifiedName);
|
||||
result.setSignatureFilter(m_signatureField->getSignature().getFilter());
|
||||
}
|
||||
|
||||
STACK_OF(X509)* PDFPublicKeySignatureHandler::getCertificates(PKCS7* pkcs7)
|
||||
|
@ -652,6 +683,8 @@ void PDFPublicKeySignatureHandler::verifySignature(PDFSignatureVerificationResul
|
|||
} while (bytesRead > 0);
|
||||
|
||||
STACK_OF(PKCS7_SIGNER_INFO)* signerInfo = PKCS7_get_signer_info(pkcs7);
|
||||
addHashAlgorithmFromSignerInfoStack(signerInfo, result);
|
||||
addSignatureDateFromSignerInfoStack(signerInfo, result);
|
||||
const int signerInfoCount = sk_PKCS7_SIGNER_INFO_num(signerInfo);
|
||||
STACK_OF(X509)* certificates = getCertificates(pkcs7);
|
||||
if (signerInfo && signerInfoCount > 0 && certificates)
|
||||
|
@ -668,13 +701,6 @@ void PDFPublicKeySignatureHandler::verifySignature(PDFSignatureVerificationResul
|
|||
break;
|
||||
}
|
||||
|
||||
if (signerInfoValue->digest_alg && signerInfoValue->digest_alg->algorithm)
|
||||
{
|
||||
std::array<char, 64> buffer = { };
|
||||
OBJ_obj2txt(buffer.data(), int(buffer.size() - 1), signerInfoValue->digest_alg->algorithm, 0);
|
||||
result.addHashAlgorithm(QString::fromLatin1(buffer.data()));
|
||||
}
|
||||
|
||||
const int verification = PKCS7_signatureVerify(dataBio, pkcs7, signerInfoValue, signer);
|
||||
if (verification <= 0)
|
||||
{
|
||||
|
@ -815,6 +841,18 @@ void PDFSignatureHandler_ETSI_RFC3161::verifySignatureTimestamp(PDFSignatureVeri
|
|||
TS_VERIFY_CTX_set_store(ts_context, store);
|
||||
TS_VERIFY_CTS_set_certs(ts_context, usedCertificates);
|
||||
|
||||
// Get timestamp and hash algorithm
|
||||
if (TS_TST_INFO* info = PKCS7_to_TS_TST_INFO(pkcs7))
|
||||
{
|
||||
// Date/time of timestamp
|
||||
const ASN1_GENERALIZEDTIME* time = TS_TST_INFO_get_time(info);
|
||||
result.setTimestampDate(getDateTimeFromASN(time));
|
||||
}
|
||||
|
||||
STACK_OF(PKCS7_SIGNER_INFO)* signerInfos = PKCS7_get_signer_info(pkcs7);
|
||||
addHashAlgorithmFromSignerInfoStack(signerInfos, result);
|
||||
addSignatureDateFromSignerInfoStack(signerInfos, result);
|
||||
|
||||
const int verifyValue = TS_RESP_verify_token(ts_context, pkcs7);
|
||||
if (verifyValue <= 0)
|
||||
{
|
||||
|
@ -1740,6 +1778,71 @@ QDateTime PDFPublicKeySignatureHandler::getDateTimeFromASN(const ASN1_TIME* time
|
|||
return result;
|
||||
}
|
||||
|
||||
void PDFPublicKeySignatureHandler::addHashAlgorithmFromSignerInfoStack(STACK_OF(PKCS7_SIGNER_INFO)* signerInfoStack, PDFSignatureVerificationResult& result)
|
||||
{
|
||||
if (!signerInfoStack)
|
||||
{
|
||||
// No signature info provided
|
||||
return;
|
||||
}
|
||||
|
||||
const int count = sk_PKCS7_SIGNER_INFO_num(signerInfoStack);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
PKCS7_SIGNER_INFO* signerInfoValue = sk_PKCS7_SIGNER_INFO_value(signerInfoStack, i);
|
||||
if (signerInfoValue && signerInfoValue->digest_alg && signerInfoValue->digest_alg->algorithm)
|
||||
{
|
||||
std::array<char, 64> buffer = { };
|
||||
OBJ_obj2txt(buffer.data(), int(buffer.size() - 1), signerInfoValue->digest_alg->algorithm, 0);
|
||||
result.addHashAlgorithm(QString::fromLatin1(buffer.data()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PDFPublicKeySignatureHandler::addSignatureDateFromSignerInfoStack(STACK_OF(PKCS7_SIGNER_INFO)* signerInfoStack, PDFSignatureVerificationResult& result)
|
||||
{
|
||||
if (!signerInfoStack)
|
||||
{
|
||||
// No signature info provided
|
||||
return;
|
||||
}
|
||||
|
||||
if (sk_PKCS7_SIGNER_INFO_num(signerInfoStack) != 1)
|
||||
{
|
||||
// Multiple signature infos, or no signature info
|
||||
return;
|
||||
}
|
||||
|
||||
// Jakub Melka: We will get signed attribute from signer info. If it fails,
|
||||
// then try to get unsigned attribute.
|
||||
PKCS7_SIGNER_INFO* signerInfo = sk_PKCS7_SIGNER_INFO_value(signerInfoStack, 0);
|
||||
ASN1_TYPE* attribute = PKCS7_get_signed_attribute(signerInfo, NID_pkcs9_signingTime);
|
||||
|
||||
if (!attribute)
|
||||
{
|
||||
attribute = PKCS7_get_attribute(signerInfo, NID_pkcs9_signingTime);
|
||||
}
|
||||
|
||||
if (!attribute)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (attribute->type)
|
||||
{
|
||||
case V_ASN1_UTCTIME:
|
||||
result.setSignatureDate(getDateTimeFromASN(attribute->value.utctime));
|
||||
break;
|
||||
|
||||
case V_ASN1_GENERALIZEDTIME:
|
||||
result.setSignatureDate(getDateTimeFromASN(attribute->value.generalizedtime));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PDFCertificateStore::serialize(QDataStream& stream) const
|
||||
{
|
||||
stream << persist_version;
|
||||
|
|
|
@ -377,14 +377,26 @@ public:
|
|||
/// Adds OK flag, if both certificate and signature are valid
|
||||
void validate();
|
||||
|
||||
QDateTime getSignatureDate() const;
|
||||
void setSignatureDate(const QDateTime& signatureDate);
|
||||
|
||||
QDateTime getTimestampDate() const;
|
||||
void setTimestampDate(const QDateTime& timestampDate);
|
||||
|
||||
QByteArray getSignatureFilter() const;
|
||||
void setSignatureFilter(const QByteArray& signatureFilter);
|
||||
|
||||
private:
|
||||
PDFSignature::Type m_type = PDFSignature::Type::Invalid;
|
||||
VerificationFlags m_flags = None;
|
||||
PDFObjectReference m_signatureFieldReference;
|
||||
QString m_signatureFieldQualifiedName;
|
||||
QDateTime m_signatureDate;
|
||||
QDateTime m_timestampDate;
|
||||
QStringList m_errors;
|
||||
QStringList m_warnings;
|
||||
QStringList m_hashAlgorithms;
|
||||
QByteArray m_signatureFilter;
|
||||
PDFCertificateInfos m_certificateInfos;
|
||||
};
|
||||
|
||||
|
|
|
@ -63,6 +63,20 @@ public:
|
|||
/// datetime is returned.
|
||||
static QDateTime getDateTimeFromASN(const ASN1_TIME* time);
|
||||
|
||||
protected:
|
||||
/// Add hash algorithm from signer info stack. If \p signerInfoStack is nullptr,
|
||||
/// then nothing happens. If multiple signer hash algorithms are present,
|
||||
/// then they are all added.
|
||||
/// \param signerInfoStack Signer stack
|
||||
/// \param result Result, to which algorithm is added
|
||||
static void addHashAlgorithmFromSignerInfoStack(STACK_OF(PKCS7_SIGNER_INFO)* signerInfoStack, PDFSignatureVerificationResult& result);
|
||||
|
||||
/// Add signing date/time from signer info stack. If there are multiple signature
|
||||
/// infos, nothing is added (because we can't decide, which one is right).
|
||||
/// \param signerInfoStack Signer info stack
|
||||
/// \param result Verification, to which signature date is being set
|
||||
static void addSignatureDateFromSignerInfoStack(STACK_OF(PKCS7_SIGNER_INFO)* signerInfoStack, PDFSignatureVerificationResult& result);
|
||||
|
||||
protected:
|
||||
const PDFFormFieldSignature* m_signatureField;
|
||||
QByteArray m_sourceData;
|
||||
|
|
|
@ -375,11 +375,11 @@ void PDFSidebarWidget::updateSignatures(const std::vector<pdf::PDFSignatureVerif
|
|||
switch (signature.getType())
|
||||
{
|
||||
case pdf::PDFSignature::Type::Sig:
|
||||
templateString = tr("Signed by - %1");
|
||||
templateString = tr("Signature - %1");
|
||||
break;
|
||||
|
||||
case pdf::PDFSignature::Type::DocTimeStamp:
|
||||
templateString = tr("Timestamped by - %1");
|
||||
templateString = tr("Timestamp - %1");
|
||||
break;
|
||||
|
||||
case pdf::PDFSignature::Type::Invalid:
|
||||
|
@ -433,7 +433,22 @@ void PDFSidebarWidget::updateSignatures(const std::vector<pdf::PDFSignatureVerif
|
|||
QString hashAlgorithms = signature.getHashAlgorithms().join(", ");
|
||||
if (!hashAlgorithms.isEmpty())
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(rootItem, QStringList(tr("Hash algorithms: %1").arg(hashAlgorithms)));
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(rootItem, QStringList(tr("Hash algorithm: %1").arg(hashAlgorithms.toUpper())));
|
||||
item->setIcon(0, infoIcon);
|
||||
}
|
||||
|
||||
|
||||
QDateTime signingDate = signature.getSignatureDate();
|
||||
if (signingDate.isValid())
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(rootItem, QStringList(QString("Signing date/time: %2").arg(signingDate.toString(Qt::DefaultLocaleShortDate))));
|
||||
item->setIcon(0, infoIcon);
|
||||
}
|
||||
|
||||
QDateTime timestampDate = signature.getTimestampDate();
|
||||
if (timestampDate.isValid())
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(rootItem, QStringList(QString("Timestamp: %2").arg(timestampDate.toString(Qt::DefaultLocaleShortDate))));
|
||||
item->setIcon(0, infoIcon);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue