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
|
PDFSignature::Type PDFSignatureVerificationResult::getType() const
|
||||||
{
|
{
|
||||||
return m_type;
|
return m_type;
|
||||||
|
@ -386,6 +416,7 @@ void PDFPublicKeySignatureHandler::initializeResult(PDFSignatureVerificationResu
|
||||||
result.setType(m_signatureField->getSignature().getType());
|
result.setType(m_signatureField->getSignature().getType());
|
||||||
result.setSignatureFieldReference(signatureFieldReference);
|
result.setSignatureFieldReference(signatureFieldReference);
|
||||||
result.setSignatureFieldQualifiedName(signatureFieldQualifiedName);
|
result.setSignatureFieldQualifiedName(signatureFieldQualifiedName);
|
||||||
|
result.setSignatureFilter(m_signatureField->getSignature().getFilter());
|
||||||
}
|
}
|
||||||
|
|
||||||
STACK_OF(X509)* PDFPublicKeySignatureHandler::getCertificates(PKCS7* pkcs7)
|
STACK_OF(X509)* PDFPublicKeySignatureHandler::getCertificates(PKCS7* pkcs7)
|
||||||
|
@ -652,6 +683,8 @@ void PDFPublicKeySignatureHandler::verifySignature(PDFSignatureVerificationResul
|
||||||
} while (bytesRead > 0);
|
} while (bytesRead > 0);
|
||||||
|
|
||||||
STACK_OF(PKCS7_SIGNER_INFO)* signerInfo = PKCS7_get_signer_info(pkcs7);
|
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);
|
const int signerInfoCount = sk_PKCS7_SIGNER_INFO_num(signerInfo);
|
||||||
STACK_OF(X509)* certificates = getCertificates(pkcs7);
|
STACK_OF(X509)* certificates = getCertificates(pkcs7);
|
||||||
if (signerInfo && signerInfoCount > 0 && certificates)
|
if (signerInfo && signerInfoCount > 0 && certificates)
|
||||||
|
@ -668,13 +701,6 @@ void PDFPublicKeySignatureHandler::verifySignature(PDFSignatureVerificationResul
|
||||||
break;
|
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);
|
const int verification = PKCS7_signatureVerify(dataBio, pkcs7, signerInfoValue, signer);
|
||||||
if (verification <= 0)
|
if (verification <= 0)
|
||||||
{
|
{
|
||||||
|
@ -815,6 +841,18 @@ void PDFSignatureHandler_ETSI_RFC3161::verifySignatureTimestamp(PDFSignatureVeri
|
||||||
TS_VERIFY_CTX_set_store(ts_context, store);
|
TS_VERIFY_CTX_set_store(ts_context, store);
|
||||||
TS_VERIFY_CTS_set_certs(ts_context, usedCertificates);
|
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);
|
const int verifyValue = TS_RESP_verify_token(ts_context, pkcs7);
|
||||||
if (verifyValue <= 0)
|
if (verifyValue <= 0)
|
||||||
{
|
{
|
||||||
|
@ -1740,6 +1778,71 @@ QDateTime PDFPublicKeySignatureHandler::getDateTimeFromASN(const ASN1_TIME* time
|
||||||
return result;
|
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
|
void PDFCertificateStore::serialize(QDataStream& stream) const
|
||||||
{
|
{
|
||||||
stream << persist_version;
|
stream << persist_version;
|
||||||
|
|
|
@ -377,14 +377,26 @@ public:
|
||||||
/// Adds OK flag, if both certificate and signature are valid
|
/// Adds OK flag, if both certificate and signature are valid
|
||||||
void validate();
|
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:
|
private:
|
||||||
PDFSignature::Type m_type = PDFSignature::Type::Invalid;
|
PDFSignature::Type m_type = PDFSignature::Type::Invalid;
|
||||||
VerificationFlags m_flags = None;
|
VerificationFlags m_flags = None;
|
||||||
PDFObjectReference m_signatureFieldReference;
|
PDFObjectReference m_signatureFieldReference;
|
||||||
QString m_signatureFieldQualifiedName;
|
QString m_signatureFieldQualifiedName;
|
||||||
|
QDateTime m_signatureDate;
|
||||||
|
QDateTime m_timestampDate;
|
||||||
QStringList m_errors;
|
QStringList m_errors;
|
||||||
QStringList m_warnings;
|
QStringList m_warnings;
|
||||||
QStringList m_hashAlgorithms;
|
QStringList m_hashAlgorithms;
|
||||||
|
QByteArray m_signatureFilter;
|
||||||
PDFCertificateInfos m_certificateInfos;
|
PDFCertificateInfos m_certificateInfos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,20 @@ public:
|
||||||
/// datetime is returned.
|
/// datetime is returned.
|
||||||
static QDateTime getDateTimeFromASN(const ASN1_TIME* time);
|
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:
|
protected:
|
||||||
const PDFFormFieldSignature* m_signatureField;
|
const PDFFormFieldSignature* m_signatureField;
|
||||||
QByteArray m_sourceData;
|
QByteArray m_sourceData;
|
||||||
|
|
|
@ -375,11 +375,11 @@ void PDFSidebarWidget::updateSignatures(const std::vector<pdf::PDFSignatureVerif
|
||||||
switch (signature.getType())
|
switch (signature.getType())
|
||||||
{
|
{
|
||||||
case pdf::PDFSignature::Type::Sig:
|
case pdf::PDFSignature::Type::Sig:
|
||||||
templateString = tr("Signed by - %1");
|
templateString = tr("Signature - %1");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case pdf::PDFSignature::Type::DocTimeStamp:
|
case pdf::PDFSignature::Type::DocTimeStamp:
|
||||||
templateString = tr("Timestamped by - %1");
|
templateString = tr("Timestamp - %1");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case pdf::PDFSignature::Type::Invalid:
|
case pdf::PDFSignature::Type::Invalid:
|
||||||
|
@ -433,7 +433,22 @@ void PDFSidebarWidget::updateSignatures(const std::vector<pdf::PDFSignatureVerif
|
||||||
QString hashAlgorithms = signature.getHashAlgorithms().join(", ");
|
QString hashAlgorithms = signature.getHashAlgorithms().join(", ");
|
||||||
if (!hashAlgorithms.isEmpty())
|
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);
|
item->setIcon(0, infoIcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue