Create PrepareSignature and FinalizeSignature

This commit is contained in:
Svetlana Kulikova
2026-02-05 18:55:26 +03:00
parent 63510a1fe9
commit 6b58358186
9 changed files with 357 additions and 183 deletions

View File

@ -102,11 +102,23 @@ void CPdfFile::Close()
else if (m_pInternal->pReader)
m_pInternal->pReader->Close();
}
void CPdfFile::Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath, ICertificate* pCertificate)
void CPdfFile::Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath)
{
if (!m_pInternal->pWriter)
return;
m_pInternal->pWriter->Sign(dX, dY, dW, dH, wsPicturePath, pCertificate);
m_pInternal->pWriter->Sign(dX, dY, dW, dH, wsPicturePath);
}
bool CPdfFile::PrepareSignature(BYTE** pDataToSign, DWORD& dwDataLength)
{
if (!m_pInternal->pWriter)
return false;
return m_pInternal->pWriter->PrepareSignature(pDataToSign, dwDataLength);
}
bool CPdfFile::FinalizeSignature(BYTE* pSignedData, DWORD dwDataLength)
{
if (!m_pInternal->pWriter)
return false;
return m_pInternal->pWriter->FinalizeSignature(pSignedData, dwDataLength);
}
void CPdfFile::SetDocumentInfo(const std::wstring& wsTitle, const std::wstring& wsCreator, const std::wstring& wsSubject, const std::wstring& wsKeywords)
{
@ -134,6 +146,12 @@ bool CPdfFile::EditPdf(const std::wstring& wsDstFile)
m_pInternal->pEditor = new CPdfEditor(m_pInternal->wsSrcFile, m_pInternal->wsPassword, wsDstFile, m_pInternal->pReader, m_pInternal->pWriter);
return m_pInternal->pEditor->GetError() == 0;
}
void CPdfFile::EditClose()
{
if (m_pInternal->pEditor)
m_pInternal->pEditor->Close();
RELEASEOBJECT(m_pInternal->pEditor);
}
void CPdfFile::SetEditType(int nType)
{
if (!m_pInternal->pEditor)

View File

@ -92,6 +92,7 @@ public:
// --- EDIT ---
// Переходит в режим редактирования. Pdf уже должен быть открыт на чтение - LoadFromFile/LoadFromMemory
bool EditPdf(const std::wstring& wsDstFile = L"");
void EditClose();
void SetEditType(int nType);
// Манипуляции со страницами возможны в режиме редактирования
bool EditPage (int nPageIndex);
@ -159,7 +160,9 @@ public:
void RotatePage (int nRotate);
void SetPassword (const std::wstring& wsPassword);
void SetDocumentID(const std::wstring& wsDocumentID);
void Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath, ICertificate* pCertificate);
void Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath);
bool PrepareSignature(BYTE** pDataToSign, DWORD& dwDataLength);
bool FinalizeSignature(BYTE* pSignedData, DWORD dwDataLength);
void SetDocumentInfo(const std::wstring& wsTitle, const std::wstring& wsCreator, const std::wstring& wsSubject, const std::wstring& wsKeywords);
void AddMetaData(const std::wstring& sMetaName, BYTE* pMetaData, DWORD nMetaLength);

View File

@ -3256,7 +3256,7 @@ void CPdfWriter::PageRotate(int nRotate)
if (m_pPage)
m_pPage->SetRotate(nRotate);
}
void CPdfWriter::Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath, ICertificate* pCertificate)
void CPdfWriter::Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath)
{
PdfWriter::CImageDict* pImage = NULL;
if (!wsPicturePath.empty())
@ -3265,9 +3265,21 @@ void CPdfWriter::Sign(const double& dX, const double& dY, const double& dW, cons
pImage = LoadImage(&oImage, 255);
}
m_pDocument->Sign(PdfWriter::TRect(MM_2_PT(dX), m_pPage->GetHeight() - MM_2_PT(dY), MM_2_PT(dX + dW), m_pPage->GetHeight() - MM_2_PT(dY + dH)),
pImage, pCertificate);
m_pDocument->Sign(PdfWriter::TRect(MM_2_PT(dX), m_pPage->GetHeight() - MM_2_PT(dY), MM_2_PT(dX + dW), m_pPage->GetHeight() - MM_2_PT(dY + dH)), pImage);
}
bool CPdfWriter::PrepareSignature(BYTE** pDataToSign, DWORD& dwDataLength)
{
if (!m_pDocument)
return false;
return m_pDocument->PrepareSignature(pDataToSign, dwDataLength);
}
bool CPdfWriter::FinalizeSignature(BYTE* pSignedData, DWORD dwDataLength)
{
if (!m_pDocument)
return false;
return m_pDocument->FinalizeSignature(pSignedData, dwDataLength);
}
//----------------------------------------------------------------------------------------
// Внутренние функции
//----------------------------------------------------------------------------------------

View File

@ -225,7 +225,9 @@ public:
bool AddPage(int nPageIndex);
bool EditClose();
void PageRotate(int nRotate);
void Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath, ICertificate* pCertificate);
void Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath);
bool PrepareSignature(BYTE** pDataToSign, DWORD& dwDataLength);
bool FinalizeSignature(BYTE* pSignedData, DWORD dwDataLength);
PdfWriter::CDocument* GetDocument();
PdfWriter::CPage* GetPage();
IRenderer* GetRenderer();

View File

@ -1950,96 +1950,157 @@ namespace PdfWriter
unsigned int nSizeXRef = m_pXref->GetSizeXRef() + (bNeedStreamXRef ? 1 : 0);
m_pXref = m_pLastXref;
Sign(wsPath, nSizeXRef, bNeedStreamXRef);
RELEASEOBJECT(m_pEncryptDict);
// TODO проверить RELEASEOBJECT(m_pEncryptDict);
return true;
}
void CDocument::Sign(const TRect& oRect, CImageDict* pImage, ICertificate* pCertificate)
void CDocument::Sign(const TRect& oRect, CImageDict* pImage)
{
m_vSignatures.push_back({ oRect, m_pCurPage ? m_pCurPage : m_pPageTree->GetPage(0), pImage, pCertificate });
m_vSignatures.push_back(new TSignatureInfo(oRect, m_pCurPage ? m_pCurPage : m_pPageTree->GetPage(0), pImage));
}
bool CDocument::PrepareSignature(BYTE** pDataToSign, DWORD& dwDataLength)
{
// Сначала нужно сохранить основной файл
// Это должно быть сделано в AddToFile или SaveToFile ПЕРЕД вызовом этого метода
if (m_vSignatures.empty())
return false;
TSignatureInfo* pSI = m_vSignatures[0];
std::wstring wsPath = pSI->wsPath;
if (wsPath.empty())
return false;
unsigned int nSizeXRef = pSI->nSizeXRef;
bool bNeedStreamXRef = pSI->bNeedStreamXRef;
// Создаем новый XRef для этой подписи
CXref* pXrefBefore = m_pXref;
m_pXref = new CXref(this, nSizeXRef);
if (!m_pXref)
{
m_pXref = pXrefBefore;
return false;
}
// Создаем поле подписи
CSignatureField* pField = CreateSignatureField();
if (!pField)
{
delete m_pXref;
m_pXref = pXrefBefore;
return false;
}
// Настраиваем поле
pSI->pField = pField;
m_pAcroForm->Add("SigFlags", 3);
pField->GetSignatureDict()->SetDate();
pField->AddPageRect(pSI->pPage, pSI->oRect);
pField->Add("F", 132);
pField->SetFieldName("Sig" + std::to_string(++m_unFormFields));
if (pSI->pImage)
pField->SetAppearance(pSI->pImage);
// Открываем файл для дозаписи
CFileStream* pStream = new CFileStream();
if (!pStream || !pStream->OpenFile(wsPath, false))
{
delete m_pXref;
m_pXref = pXrefBefore;
return false;
}
// Вычисляем размер для Contents
unsigned int nContentsSize = 7000 + pStream->Size() / 1000 + 1000;
if (nContentsSize < 5000)
nContentsSize = 5000;
if (nContentsSize > 20000)
nContentsSize = 20000;
pField->GetSignatureDict()->SetContentsSize(nContentsSize);
// Записываем XRef и получаем информацию о расположении
CXref* pXrefCatalog = new CXref(this, m_pCatalog->GetObjId());
if (pXrefCatalog)
{
pXrefCatalog->Add(m_pCatalog->Copy(), m_pCatalog->GetGenNo());
pXrefCatalog->SetPrev(m_pXref);
}
CXref* pXrefPage = new CXref(this, pSI->pPage->GetObjId());
if (pXrefPage)
{
pXrefPage->Add(pSI->pPage->Copy(), pSI->pPage->GetGenNo());
pXrefPage->SetPrev(pXrefCatalog);
}
CXref* pXref = new CXref(this, 0, 65535);
if (pXref)
{
pXref->SetPrev(pXrefPage);
CDictObject* pTrailer = pXref->GetTrailer();
m_pTrailer->Copy(pTrailer);
CEncrypt* pEncrypt = NULL;
if (m_pEncryptDict)
pEncrypt = m_pEncryptDict->GetEncrypt();
pXref->WriteToStream(pStream, pEncrypt, bNeedStreamXRef);
pSI->pXref = pXref;
}
pField->GetSignatureDict()->WriteToStream(pStream, pStream->Size(), pDataToSign, dwDataLength);
// Восстанавливаем XRef
m_pXref = pXrefBefore;
delete pStream;
return true;
}
bool CDocument::FinalizeSignature(BYTE* pSignedData, DWORD dwDataLength)
{
if (m_vSignatures.empty())
return false;
TSignatureInfo* pSI = m_vSignatures[0];
bool bNeedStreamXRef = pSI->bNeedStreamXRef;
std::wstring wsPath = pSI->wsPath;
if (wsPath.empty() || !pSI->pField)
return false;
CFileStream* pStream = new CFileStream();
if (!pStream || !pStream->OpenFile(wsPath, false))
{
delete pStream;
return false;
}
if (!pSI->pField->GetSignatureDict() || !pSI->pField->GetSignatureDict()->FinalizeSignature(pStream, pSignedData, dwDataLength))
{
delete pStream;
return false;
}
CXref* pXref = pSI->pXref;
delete pStream;
delete pSI;
m_vSignatures.pop_front();
Sign(wsPath, pXref->GetSizeXRef() + (bNeedStreamXRef ? 1 : 0), bNeedStreamXRef);
delete pXref;
return true;
}
void CDocument::Sign(const std::wstring& wsPath, unsigned int nSizeXRef, bool bNeedStreamXRef)
{
unsigned int nPrevAddr = m_pXref->GetPrevAddr();
std::vector<CXref*> vXRefForWrite;
for (unsigned int i = 0; i < m_vSignatures.size(); i++)
if (!m_vSignatures.empty())
{
CXref* pXrefBefore = m_pXref;
m_pXref = new CXref(this, nSizeXRef);
if (!m_pXref)
{
m_pXref = pXrefBefore;
continue;
}
m_pXref->SetPrevAddr(nPrevAddr);
CSignatureField* pField = CreateSignatureField();
if (!pField)
{
RELEASEOBJECT(m_pXref);
m_pXref = pXrefBefore;
continue;
}
m_pAcroForm->Add("SigFlags", 3);
pField->GetSignatureDict()->SetCert(m_vSignatures[i].pCertificate);
pField->GetSignatureDict()->SetDate();
pField->AddPageRect(m_vSignatures[i].pPage, m_vSignatures[i].oRect);
pField->Add("F", 132);
pField->SetFieldName("Sig" + std::to_string(i + m_unFormFields + 1));
if (m_vSignatures[i].pImage)
pField->SetAppearance(m_vSignatures[i].pImage);
CFileStream* pStream = new CFileStream();
if (!pStream || !pStream->OpenFile(wsPath, false))
{
RELEASEOBJECT(m_pXref);
m_pXref = pXrefBefore;
continue;
}
CXref* pXrefCatalog = new CXref(this, m_pCatalog->GetObjId());
if (pXrefCatalog)
{
pXrefCatalog->Add(m_pCatalog->Copy(), m_pCatalog->GetGenNo());
pXrefCatalog->SetPrev(m_pXref);
}
CXref* pXrefPage = new CXref(this, m_vSignatures[i].pPage->GetObjId());
if (pXrefPage)
{
pXrefPage->Add(m_vSignatures[i].pPage->Copy(), m_vSignatures[i].pPage->GetGenNo());
pXrefPage->SetPrev(pXrefCatalog);
}
CXref* pXref = new CXref(this, 0, 65535);
if (pXref)
{
pXref->SetPrev(pXrefPage);
CDictObject* pTrailer = pXref->GetTrailer();
m_pTrailer->Copy(pTrailer);
CEncrypt* pEncrypt = NULL;
if (m_pEncryptDict)
pEncrypt = m_pEncryptDict->GetEncrypt();
pXref->WriteToStream(pStream, pEncrypt, bNeedStreamXRef);
nPrevAddr = pXref->GetPrevAddr();
nSizeXRef = m_pXref->GetSizeXRef();
vXRefForWrite.push_back(pXref);
}
RELEASEOBJECT(pStream);
pStream = new CFileStream();
if (pStream && pStream->OpenFile(wsPath, false))
pField->GetSignatureDict()->WriteToStream(pStream, pStream->Size());
m_pXref = pXrefBefore;
RELEASEOBJECT(pStream);
m_vSignatures[0]->wsPath = wsPath;
m_vSignatures[0]->nSizeXRef = nSizeXRef;
m_vSignatures[0]->bNeedStreamXRef = bNeedStreamXRef;
}
for (CXref* XRef : vXRefForWrite)
RELEASEOBJECT(XRef);
vXRefForWrite.clear();
}
void CDocument::AddShapeXML(const std::string& sXML)
{

View File

@ -33,6 +33,7 @@
#define _PDF_WRITER_SRC_DOCUMENT_H
#include <vector>
#include <deque>
#include <string>
#include "Types.h"
@ -195,7 +196,9 @@ namespace PdfWriter
bool AddToFile(const std::wstring& wsPath, CXref* pXref, CDictObject* pTrailer, CXref* pInfoXref, CInfoDict* pInfo);
void AddObject(CObjectBase* pObj);
bool MovePage(int nPageIndex, int nPos);
void Sign(const TRect& oRect, CImageDict* pImage, ICertificate* pCert);
void Sign(const TRect& oRect, CImageDict* pImage);
bool PrepareSignature(BYTE** pDataToSign, DWORD& dwDataLength);
bool FinalizeSignature(BYTE* pSignedData, DWORD dwDataLength);
bool EditAnnot (CXref* pXref, CAnnotation* pAnnot, int nID);
void AddParent(int nID, CDictObject* pParent);
CDictObject* CreateParent(int nID);
@ -255,18 +258,27 @@ namespace PdfWriter
};
struct TSignatureInfo
{
TSignatureInfo(const TRect& _oRect, CPage* _pPage, CImageDict* _pImage, ICertificate* _pCertificate)
TSignatureInfo(const TRect& _oRect, CPage* _pPage, CImageDict* _pImage)
{
oRect = _oRect;
pPage = _pPage;
pImage = _pImage;
pCertificate = _pCertificate;
nSizeXRef = 0;
bNeedStreamXRef = false;
pField = NULL;
pXref = NULL;
}
TRect oRect;
CPage* pPage;
CImageDict* pImage;
ICertificate* pCertificate;
std::wstring wsPath;
unsigned int nSizeXRef;
bool bNeedStreamXRef;
CSignatureField* pField;
CXref* pXref;
};
struct TImageInfo
{
@ -296,7 +308,7 @@ namespace PdfWriter
CStreamData* m_pMetaData;
bool m_bEncrypt;
CEncryptDict* m_pEncryptDict;
std::vector<TSignatureInfo> m_vSignatures;
std::deque<TSignatureInfo*> m_vSignatures;
std::vector<TImageInfo> m_vImages;
unsigned int m_unFormFields;
unsigned int m_unCompressMode;

View File

@ -223,32 +223,6 @@ namespace PdfWriter
Add("Filter", "Adobe.PPKLite");
Add("SubFilter", "adbe.pkcs7.detached");
unsigned int unDigestLength = 15000;
BYTE* pDigest = new BYTE[unDigestLength];
memset(pDigest, 0, unDigestLength);
Add("Contents", new CBinaryObject(pDigest, unDigestLength));
RELEASEARRAYOBJECTS(pDigest);
CArrayObject* pByteRange = new CArrayObject();
if (!pByteRange)
return;
Add("ByteRange", pByteRange);
pByteRange->Add(0);
pByteRange->Add(1234567890);
pByteRange->Add(1234567890);
pByteRange->Add(1234567890);
// Reference - Массив справочных словарей сигнатур
// Changes - Массив из трех чисел, который указывает изменения в документе в порядке: количество измененных страниц,
// количество измененных полей и количество заполненных полей
// Порядок подписей определяется значением ByteRange. Поскольку каждая подпись приводит к добавочному сохранению,
// более поздние подписи имеют большее значение длины
// Prop_Build - Словарь, который может использоваться обработчиком подписи для записи информации о состоянии компьютерной среды,
// используемой для подписи, такой как имя обработчика, используемого для создания подписи, дата сборки программного обеспечения,
// версия, и операционная система. Спецификация словаря PDF Signature Build содержит рекомендации по использованию этого словаря
m_nLen1 = 0;
m_nOffset2 = 0;
m_nByteRangeBegin = 0;
@ -259,40 +233,33 @@ namespace PdfWriter
}
void CSignatureDict::WriteToStream(CStream* pStream, CEncrypt* pEncrypt)
{
for (auto const &oIter : m_mList)
for (std::map<std::string, CObjectBase*>::const_iterator oIter = m_mList.begin(); oIter != m_mList.end(); ++oIter)
{
CObjectBase* pObject = oIter.second;
if (!pObject)
CObjectBase* pObject = oIter->second;
if (!pObject || pObject->IsHidden())
continue;
if (pObject->IsHidden())
int nBegin, nEnd;
pStream->WriteEscapeName(oIter->first.c_str());
pStream->WriteChar(' ');
nBegin = pStream->Tell();
// Цифровая подпись не шифруется
pStream->Write(pObject, oIter->first == "Contents" ? NULL : pEncrypt);
nEnd = pStream->Tell();
pStream->WriteStr("\012");
if (oIter->first == "Contents")
{
// ничего не делаем
m_nLen1 = nBegin;
m_nOffset2 = nEnd;
}
else
if (oIter->first == "ByteRange")
{
int nBegin, nEnd;
pStream->WriteEscapeName(oIter.first.c_str());
pStream->WriteChar(' ');
nBegin = pStream->Tell();
// Цифровая подпись не шифруется
pStream->Write(pObject, oIter.first == "Contents" ? NULL : pEncrypt);
nEnd = pStream->Tell();
pStream->WriteStr("\012");
if (oIter.first == "Contents")
{
m_nLen1 = nBegin;
m_nOffset2 = nEnd;
}
if (oIter.first == "ByteRange")
{
m_nByteRangeBegin = nBegin;
m_nByteRangeEnd = nEnd;
}
m_nByteRangeBegin = nBegin;
m_nByteRangeEnd = nEnd;
}
}
}
void CSignatureDict::WriteToStream(CStream* pStream, int nFileEnd)
void CSignatureDict::WriteToStream(CStream* pStream, int nFileEnd, BYTE** pDataForSignature, DWORD& dwLenDataForSignature)
{
// Запись ByteRange
if (m_nByteRangeBegin > 0 && m_nByteRangeEnd > 0 && m_nByteRangeBegin < m_nByteRangeEnd && m_nByteRangeEnd < nFileEnd)
@ -325,16 +292,16 @@ namespace PdfWriter
RELEASEOBJECT(pByteRange);
}
// Запись Contents
if (m_pCertificate && m_nLen1 > 0 && m_nOffset2 > 0 && m_nLen1 < m_nOffset2 && m_nOffset2 < nFileEnd)
if (m_nLen1 > 0 && m_nOffset2 > 0 && m_nLen1 < m_nOffset2 && m_nOffset2 < nFileEnd)
{
DWORD dwLenDataForSignature = m_nLen1 + nFileEnd - m_nOffset2;
BYTE* pDataForSignature = new BYTE[dwLenDataForSignature];
if (!pDataForSignature)
dwLenDataForSignature = m_nLen1 + nFileEnd - m_nOffset2;
*pDataForSignature = new BYTE[dwLenDataForSignature];
if (!*pDataForSignature)
return;
pStream->Seek(0, EWhenceMode::SeekSet);
unsigned int dwLenReadData = m_nLen1;
pStream->Read(pDataForSignature, &dwLenReadData);
pStream->Read(*pDataForSignature, &dwLenReadData);
if ((int)dwLenReadData != m_nLen1)
{
RELEASEARRAYOBJECTS(pDataForSignature);
@ -343,40 +310,69 @@ namespace PdfWriter
pStream->Seek(m_nOffset2, EWhenceMode::SeekSet);
dwLenReadData = nFileEnd - m_nOffset2;
pStream->Read(pDataForSignature + m_nLen1, &dwLenReadData);
pStream->Read(*pDataForSignature + m_nLen1, &dwLenReadData);
if ((int)dwLenReadData != nFileEnd - m_nOffset2)
{
RELEASEARRAYOBJECTS(pDataForSignature);
return;
}
/*
BYTE* pDatatoWrite = NULL;
unsigned int dwLenDatatoWrite;
m_pCertificate->SignPKCS7(pDataForSignature, dwLenDataForSignature, pDatatoWrite, dwLenDatatoWrite);
RELEASEARRAYOBJECTS(pDataForSignature);
if (!pDatatoWrite)
return;
pStream->Seek(m_nLen1, EWhenceMode::SeekSet);
CBinaryObject* pContents = new CBinaryObject(pDatatoWrite, dwLenDatatoWrite);
RELEASEARRAYOBJECTS(pDatatoWrite);
if (!pContents)
return;
// Цифровая подпись не шифруется
pStream->Write(pContents, NULL);
RELEASEOBJECT(pContents);
// Стереть лишний >
BYTE cChar = '0';
pStream->Seek(pStream->Tell() - 1, EWhenceMode::SeekSet);
pStream->Write(&cChar, 1);
*/
}
}
void CSignatureDict::SetCert(ICertificate* pCert)
{
m_pCertificate = pCert;
}
void CSignatureDict::SetName(const std::string& sName)
bool CSignatureDict::FinalizeSignature(CStream* pStream, BYTE* pSignedData, DWORD dwDataLength)
{
if (!pSignedData)
return false;
// Записываем подписанные данные в Contents
if (dwDataLength > m_nContentsSize)
{
// Подпись не влезает! Ошибка расчета размера
return false;
}
pStream->Seek(m_nLen1, EWhenceMode::SeekSet);
CBinaryObject* pContents = new CBinaryObject(pSignedData, dwDataLength);
if (!pContents)
return false;
// Цифровая подпись не шифруется
pStream->Write(pContents, NULL);
delete pContents;
// Стираем лишний '>' если нужно
BYTE cChar = '0';
pStream->Seek(pStream->Tell() - 1, EWhenceMode::SeekSet);
pStream->Write(&cChar, 1);
return true;
}
void CSignatureDict::SetContentsSize(unsigned int nSize)
{
m_nContentsSize = nSize;
BYTE* pDigest = new BYTE[m_nContentsSize];
memset(pDigest, 0, m_nContentsSize);
Add("Contents", new CBinaryObject(pDigest, m_nContentsSize, false));
CArrayObject* pByteRange = new CArrayObject();
if (!pByteRange)
return;
Add("ByteRange", pByteRange);
pByteRange->Add(0);
pByteRange->Add(1234567890);
pByteRange->Add(1234567890);
pByteRange->Add(1234567890);
}
void CSignatureDict::SetName(const std::string& sName)
{
// Name - Cтрока, Имя лица или органа, подписавшего документ.
// Значение следует использовать когда невозможно извлечь имя из подписи или сертификата подписавшего.

View File

@ -34,8 +34,6 @@
#include "Objects.h"
#include "../../DesktopEditor/xmlsec/src/include/Certificate.h"
namespace PdfWriter
{
class CEncrypt;
@ -78,18 +76,19 @@ namespace PdfWriter
}
void WriteToStream(CStream* pStream, CEncrypt* pEncrypt) override;
void WriteToStream(CStream* pStream, int nFileEnd);
void SetCert(ICertificate* pCert);
void WriteToStream(CStream* pStream, int nFileEnd, BYTE** pDataToSign, DWORD& dwDataLength);
bool FinalizeSignature(CStream* pStream, BYTE* pSignedData, DWORD dwDataLength);
void SetContentsSize(unsigned int nSize);
void SetName(const std::string& sName);
void SetReason(const std::string& sReason);
void SetContact(const std::string& sContacts);
void SetDate();
private:
ICertificate* m_pCertificate;
unsigned int m_nContentsSize; // Размер Contents
int m_nLen1; // Длина первого интервала сигнатуры
int m_nOffset2; // Начало второго интервала сигнатуры
int m_nLen1; // Длина первого интервала
int m_nOffset2; // Начало второго интервала
int m_nByteRangeBegin; // Смещение начала массива ByteRange
int m_nByteRangeEnd; // Смещение конца массива ByteRange

View File

@ -524,7 +524,7 @@ TEST_F(CPdfFileTest, EditPdf)
TEST_F(CPdfFileTest, EditPdfFromBase64)
{
//GTEST_SKIP();
GTEST_SKIP();
NSFonts::NSApplicationFontStream::SetGlobalMemoryStorage(NSFonts::NSApplicationFontStream::CreateDefaultGlobalMemoryStorage());
@ -602,22 +602,93 @@ TEST_F(CPdfFileTest, EditPdfFromBin)
TEST_F(CPdfFileTest, EditPdfSign)
{
GTEST_SKIP();
//GTEST_SKIP();
LoadFromFile();
ASSERT_TRUE(pdfFile->EditPdf(wsDstFile));
ICertificate* pCertificate = GetCertificate();
ASSERT_TRUE(pCertificate);
EXPECT_TRUE(pdfFile->EditPage(0));
{
pdfFile->Sign(10, 10, 100, 100, NSFile::GetProcessDirectory() + L"/test.jpeg", pCertificate);
pdfFile->Sign(10, 10, 100, 100, NSFile::GetProcessDirectory() + L"/test.jpeg");
pdfFile->Sign(10, 150, 100, 100, NSFile::GetProcessDirectory() + L"/test.jpeg");
pdfFile->Sign(10, 300, 100, 100, NSFile::GetProcessDirectory() + L"/test.jpeg");
}
// Для цифровой подписи важно предварительно pdfFile->EditClose, в остальных случаях pdfFile->Close() сделает тоже самое
pdfFile->EditClose();
// EditPdf & EditClose || CreatePdf & SaveToFile
// И только после подготовка данных для подписания, подписываем, запись подписи
for (int i = 0; i < 3; ++i)
{
BYTE* pDataToSign = NULL;
DWORD dwDataLength = 0;
// Получили данные для подписания
pdfFile->PrepareSignature(&pDataToSign, dwDataLength);
ICertificate* pCertificate = GetCertificate();
ASSERT_TRUE(pCertificate);
BYTE* pDatatoWrite = NULL;
unsigned int dwLenDatatoWrite = 0;
// Предположим, что для подписи 1 произошло не успешное подписание, и данные остались пустыми
pCertificate->SignPKCS7(pDataToSign, dwDataLength, pDatatoWrite, dwLenDatatoWrite);
// Обязательно FinalizeSignature - он либо заполнит данные, либо сделает подпись пустой
pdfFile->FinalizeSignature(pDatatoWrite, dwLenDatatoWrite);
RELEASEOBJECT(pCertificate);
}
pdfFile->Close();
}
RELEASEOBJECT(pCertificate);
TEST_F(CPdfFileTest, PdfToPdfSign)
{
GTEST_SKIP();
LoadFromFile();
pdfFile->CreatePdf();
double dPageDpiX, dPageDpiY, dW, dH;
int nPages = pdfFile->GetPagesCount();
for (int i = 0; i < nPages; i++)
{
pdfFile->NewPage();
pdfFile->GetPageInfo(i, &dW, &dH, &dPageDpiX, &dPageDpiY);
pdfFile->put_Width( dW / dPageDpiX * 25.4);
pdfFile->put_Height(dH / dPageDpiY * 25.4);
pdfFile->DrawPageOnRenderer(pdfFile, i, NULL);
pdfFile->Sign(10, 10, 100, 100, NSFile::GetProcessDirectory() + L"/test.jpeg");
}
pdfFile->SaveToFile(wsDstFile);
for (int i = 0; i < nPages; ++i)
{
BYTE* pDataToSign = NULL;
DWORD dwDataLength = 0;
pdfFile->PrepareSignature(&pDataToSign, dwDataLength);
ICertificate* pCertificate = GetCertificate();
ASSERT_TRUE(pCertificate);
BYTE* pDatatoWrite = NULL;
unsigned int dwLenDatatoWrite = 0;
if (i % 2 == 0)
pCertificate->SignPKCS7(pDataToSign, dwDataLength, pDatatoWrite, dwLenDatatoWrite);
pdfFile->FinalizeSignature(pDatatoWrite, dwLenDatatoWrite);
RELEASEOBJECT(pCertificate);
}
pdfFile->Close();
}
TEST_F(CPdfFileTest, PrintPdf)