xmlsecurity PDF sign: handle AdES when writing SubFilter
Page 21 of "PAdES baseline signatures" specification from <http://www.etsi.org/deliver/etsi_en/319100_319199/31914201/01.01.01_60/en_31914201v010101p.pdf> says: "The Signature Dictionary shall contain a value of ETSI.CAdES.detached for the key SubFilter." So in case the UI has the adescompliant checkbox enabled, write that value instead of the Adobe default. Change-Id: I69e606a32fb09bebd5e9b25b32150d1b8672f544
This commit is contained in:
@@ -59,7 +59,7 @@ public:
|
|||||||
bool isXML(const OUString& rURI);
|
bool isXML(const OUString& rURI);
|
||||||
SignatureStreamHelper ImplOpenSignatureStream(sal_Int32 eStreamMode, bool bTempStream);
|
SignatureStreamHelper ImplOpenSignatureStream(sal_Int32 eStreamMode, bool bTempStream);
|
||||||
/// Add a new signature, using xCert as a signing certificate, and rDescription as description.
|
/// Add a new signature, using xCert as a signing certificate, and rDescription as description.
|
||||||
bool add(const css::uno::Reference<css::security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId, bool bXAdESCompliantIfODF);
|
bool add(const css::uno::Reference<css::security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant);
|
||||||
/// Remove signature at nPosition.
|
/// Remove signature at nPosition.
|
||||||
void remove(sal_uInt16 nPosition);
|
void remove(sal_uInt16 nPosition);
|
||||||
/// Read signatures from either a temp stream or the real storage.
|
/// Read signatures from either a temp stream or the real storage.
|
||||||
|
@@ -117,7 +117,7 @@ class XMLSECURITY_DLLPUBLIC PDFDocument
|
|||||||
/// Suggest a minimal, yet free signature ID to use for the next signature.
|
/// Suggest a minimal, yet free signature ID to use for the next signature.
|
||||||
sal_uInt32 GetNextSignature();
|
sal_uInt32 GetNextSignature();
|
||||||
/// Write the signature object as part of signing.
|
/// Write the signature object as part of signing.
|
||||||
sal_Int32 WriteSignatureObject(const OUString& rDescription, sal_uInt64& rLastByteRangeOffset, sal_Int64& rSignatureContentOffset);
|
sal_Int32 WriteSignatureObject(const OUString& rDescription, bool bAdES, sal_uInt64& rLastByteRangeOffset, sal_Int64& rSignatureContentOffset);
|
||||||
/// Write the appearance object as part of signing.
|
/// Write the appearance object as part of signing.
|
||||||
sal_Int32 WriteAppearanceObject();
|
sal_Int32 WriteAppearanceObject();
|
||||||
/// Write the annot object as part of signing.
|
/// Write the annot object as part of signing.
|
||||||
@@ -162,7 +162,7 @@ public:
|
|||||||
/// Read elements from the start of the stream till its end.
|
/// Read elements from the start of the stream till its end.
|
||||||
bool Read(SvStream& rStream);
|
bool Read(SvStream& rStream);
|
||||||
/// Sign the read document with xCertificate in the edit buffer.
|
/// Sign the read document with xCertificate in the edit buffer.
|
||||||
bool Sign(const css::uno::Reference<css::security::XCertificate>& xCertificate, const OUString& rDescription);
|
bool Sign(const css::uno::Reference<css::security::XCertificate>& xCertificate, const OUString& rDescription, bool bAdES);
|
||||||
/// Serializes the contents of the edit buffer.
|
/// Serializes the contents of the edit buffer.
|
||||||
bool Write(SvStream& rStream);
|
bool Write(SvStream& rStream);
|
||||||
/// Get a list of signatures embedded into this document.
|
/// Get a list of signatures embedded into this document.
|
||||||
|
@@ -43,7 +43,7 @@ public:
|
|||||||
/// Comment / reason to be used next time signing is performed.
|
/// Comment / reason to be used next time signing is performed.
|
||||||
void SetDescription(const OUString& rDescription);
|
void SetDescription(const OUString& rDescription);
|
||||||
/// Append a new signature at the end of xInputStream.
|
/// Append a new signature at the end of xInputStream.
|
||||||
bool Sign(const css::uno::Reference<css::io::XInputStream>& xInputStream);
|
bool Sign(const css::uno::Reference<css::io::XInputStream>& xInputStream, bool bAdES);
|
||||||
/// Remove the signature at nPosition (and all dependent signatures) from xInputStream.
|
/// Remove the signature at nPosition (and all dependent signatures) from xInputStream.
|
||||||
static bool RemoveSignature(const css::uno::Reference<css::io::XInputStream>& xInputStream, sal_uInt16 nPosition);
|
static bool RemoveSignature(const css::uno::Reference<css::io::XInputStream>& xInputStream, sal_uInt16 nPosition);
|
||||||
};
|
};
|
||||||
|
@@ -142,7 +142,7 @@ bool PDFSigningTest::sign(const OUString& rInURL, const OUString& rOutURL, size_
|
|||||||
// NSS failed to parse it's own profile or Windows has no certificates installed.
|
// NSS failed to parse it's own profile or Windows has no certificates installed.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
CPPUNIT_ASSERT(aDocument.Sign(aCertificates[0], "test"));
|
CPPUNIT_ASSERT(aDocument.Sign(aCertificates[0], "test", /*bAdES=*/true));
|
||||||
SvFileStream aOutStream(rOutURL, StreamMode::WRITE | StreamMode::TRUNC);
|
SvFileStream aOutStream(rOutURL, StreamMode::WRITE | StreamMode::TRUNC);
|
||||||
CPPUNIT_ASSERT(aDocument.Write(aOutStream));
|
CPPUNIT_ASSERT(aDocument.Write(aOutStream));
|
||||||
}
|
}
|
||||||
|
@@ -232,7 +232,7 @@ SignatureStreamHelper DocumentSignatureManager::ImplOpenSignatureStream(sal_Int3
|
|||||||
return aHelper;
|
return aHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId, bool bXAdESCompliantIfODF)
|
bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant)
|
||||||
{
|
{
|
||||||
if (!xCert.is())
|
if (!xCert.is())
|
||||||
{
|
{
|
||||||
@@ -255,7 +255,7 @@ bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>&
|
|||||||
getPDFSignatureHelper().SetX509Certificate(xCert);
|
getPDFSignatureHelper().SetX509Certificate(xCert);
|
||||||
getPDFSignatureHelper().SetDescription(rDescription);
|
getPDFSignatureHelper().SetDescription(rDescription);
|
||||||
uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY);
|
uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY);
|
||||||
if (!getPDFSignatureHelper().Sign(xInputStream))
|
if (!getPDFSignatureHelper().Sign(xInputStream, bAdESCompliant))
|
||||||
{
|
{
|
||||||
SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::Sign() failed");
|
SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::Sign() failed");
|
||||||
return false;
|
return false;
|
||||||
@@ -299,7 +299,7 @@ bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>&
|
|||||||
for (sal_Int32 n = 0; n < nElements; n++)
|
for (sal_Int32 n = 0; n < nElements; n++)
|
||||||
{
|
{
|
||||||
bool bBinaryMode = !isXML(aElements[n]);
|
bool bBinaryMode = !isXML(aElements[n]);
|
||||||
maSignatureHelper.AddForSigning(nSecurityId, aElements[n], aElements[n], bBinaryMode, bXAdESCompliantIfODF);
|
maSignatureHelper.AddForSigning(nSecurityId, aElements[n], aElements[n], bBinaryMode, bAdESCompliant);
|
||||||
}
|
}
|
||||||
|
|
||||||
maSignatureHelper.SetDateTime(nSecurityId, Date(Date::SYSTEM), tools::Time(tools::Time::SYSTEM));
|
maSignatureHelper.SetDateTime(nSecurityId, Date(Date::SYSTEM), tools::Time(tools::Time::SYSTEM));
|
||||||
@@ -321,10 +321,10 @@ bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>&
|
|||||||
uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, uno::UNO_QUERY_THROW);
|
uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, uno::UNO_QUERY_THROW);
|
||||||
std::size_t nInfos = maCurrentSignatureInformations.size();
|
std::size_t nInfos = maCurrentSignatureInformations.size();
|
||||||
for (std::size_t n = 0; n < nInfos; n++)
|
for (std::size_t n = 0; n < nInfos; n++)
|
||||||
XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n], bXAdESCompliantIfODF);
|
XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n], bAdESCompliant);
|
||||||
|
|
||||||
// Create a new one...
|
// Create a new one...
|
||||||
maSignatureHelper.CreateAndWriteSignature(xDocumentHandler, bXAdESCompliantIfODF);
|
maSignatureHelper.CreateAndWriteSignature(xDocumentHandler, bAdESCompliant);
|
||||||
|
|
||||||
// That's it...
|
// That's it...
|
||||||
XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler);
|
XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler);
|
||||||
|
@@ -118,7 +118,7 @@ void PDFSignatureHelper::SetDescription(const OUString& rDescription)
|
|||||||
m_aDescription = rDescription;
|
m_aDescription = rDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PDFSignatureHelper::Sign(const uno::Reference<io::XInputStream>& xInputStream)
|
bool PDFSignatureHelper::Sign(const uno::Reference<io::XInputStream>& xInputStream, bool bAdES)
|
||||||
{
|
{
|
||||||
std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
|
std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
|
||||||
xmlsecurity::pdfio::PDFDocument aDocument;
|
xmlsecurity::pdfio::PDFDocument aDocument;
|
||||||
@@ -128,7 +128,7 @@ bool PDFSignatureHelper::Sign(const uno::Reference<io::XInputStream>& xInputStre
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aDocument.Sign(m_xCertificate, m_aDescription))
|
if (!aDocument.Sign(m_xCertificate, m_aDescription, bAdES))
|
||||||
{
|
{
|
||||||
SAL_WARN("xmlsecurity.helper", "failed to sign");
|
SAL_WARN("xmlsecurity.helper", "failed to sign");
|
||||||
return false;
|
return false;
|
||||||
|
@@ -357,7 +357,7 @@ sal_uInt32 PDFDocument::GetNextSignature()
|
|||||||
return nRet + 1;
|
return nRet + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sal_Int32 PDFDocument::WriteSignatureObject(const OUString& rDescription, sal_uInt64& rLastByteRangeOffset, sal_Int64& rContentOffset)
|
sal_Int32 PDFDocument::WriteSignatureObject(const OUString& rDescription, bool bAdES, sal_uInt64& rLastByteRangeOffset, sal_Int64& rContentOffset)
|
||||||
{
|
{
|
||||||
// Write signature object.
|
// Write signature object.
|
||||||
sal_Int32 nSignatureId = m_aXRef.size();
|
sal_Int32 nSignatureId = m_aXRef.size();
|
||||||
@@ -374,7 +374,11 @@ sal_Int32 PDFDocument::WriteSignatureObject(const OUString& rDescription, sal_uI
|
|||||||
OStringBuffer aContentFiller(MAX_SIGNATURE_CONTENT_LENGTH);
|
OStringBuffer aContentFiller(MAX_SIGNATURE_CONTENT_LENGTH);
|
||||||
comphelper::string::padToLength(aContentFiller, MAX_SIGNATURE_CONTENT_LENGTH, '0');
|
comphelper::string::padToLength(aContentFiller, MAX_SIGNATURE_CONTENT_LENGTH, '0');
|
||||||
aSigBuffer.append(aContentFiller.makeStringAndClear());
|
aSigBuffer.append(aContentFiller.makeStringAndClear());
|
||||||
aSigBuffer.append(">\n/Type/Sig/SubFilter/adbe.pkcs7.detached");
|
aSigBuffer.append(">\n/Type/Sig/SubFilter");
|
||||||
|
if (bAdES)
|
||||||
|
aSigBuffer.append("/ETSI.CAdES.detached");
|
||||||
|
else
|
||||||
|
aSigBuffer.append("/adbe.pkcs7.detached");
|
||||||
|
|
||||||
// Time of signing.
|
// Time of signing.
|
||||||
aSigBuffer.append(" /M (");
|
aSigBuffer.append(" /M (");
|
||||||
@@ -941,14 +945,14 @@ void PDFDocument::WriteXRef(sal_uInt64 nXRefOffset, PDFReferenceElement* pRoot)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PDFDocument::Sign(const uno::Reference<security::XCertificate>& xCertificate, const OUString& rDescription)
|
bool PDFDocument::Sign(const uno::Reference<security::XCertificate>& xCertificate, const OUString& rDescription, bool bAdES)
|
||||||
{
|
{
|
||||||
m_aEditBuffer.Seek(STREAM_SEEK_TO_END);
|
m_aEditBuffer.Seek(STREAM_SEEK_TO_END);
|
||||||
m_aEditBuffer.WriteCharPtr("\n");
|
m_aEditBuffer.WriteCharPtr("\n");
|
||||||
|
|
||||||
sal_uInt64 nSignatureLastByteRangeOffset = 0;
|
sal_uInt64 nSignatureLastByteRangeOffset = 0;
|
||||||
sal_Int64 nSignatureContentOffset = 0;
|
sal_Int64 nSignatureContentOffset = 0;
|
||||||
sal_Int32 nSignatureId = WriteSignatureObject(rDescription, nSignatureLastByteRangeOffset, nSignatureContentOffset);
|
sal_Int32 nSignatureId = WriteSignatureObject(rDescription, bAdES, nSignatureLastByteRangeOffset, nSignatureContentOffset);
|
||||||
|
|
||||||
sal_Int32 nAppearanceId = WriteAppearanceObject();
|
sal_Int32 nAppearanceId = WriteAppearanceObject();
|
||||||
|
|
||||||
@@ -2021,7 +2025,7 @@ bool PDFDocument::ValidateSignature(SvStream& rStream, PDFObjectElement* pSignat
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto pSubFilter = dynamic_cast<PDFNameElement*>(pValue->Lookup("SubFilter"));
|
auto pSubFilter = dynamic_cast<PDFNameElement*>(pValue->Lookup("SubFilter"));
|
||||||
if (!pSubFilter || pSubFilter->GetValue() != "adbe.pkcs7.detached")
|
if (!pSubFilter || (pSubFilter->GetValue() != "adbe.pkcs7.detached" && pSubFilter->GetValue() != "ETSI.CAdES.detached"))
|
||||||
{
|
{
|
||||||
SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature: no or unsupported sub-filter");
|
SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature: no or unsupported sub-filter");
|
||||||
return false;
|
return false;
|
||||||
|
@@ -136,7 +136,7 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(nArgc, pArgv)
|
|||||||
SAL_WARN("xmlsecurity.pdfio", "no signing certificates found");
|
SAL_WARN("xmlsecurity.pdfio", "no signing certificates found");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (!aDocument.Sign(aCertificates[0], "pdfverify"))
|
if (!aDocument.Sign(aCertificates[0], "pdfverify", /*bAdES=*/true))
|
||||||
{
|
{
|
||||||
SAL_WARN("xmlsecurity.pdfio", "failed to sign");
|
SAL_WARN("xmlsecurity.pdfio", "failed to sign");
|
||||||
return 1;
|
return 1;
|
||||||
|
Reference in New Issue
Block a user