Fix unsuccessful signing

This commit is contained in:
Svetlana Kulikova
2026-02-06 14:26:54 +03:00
parent 9a91e8192c
commit 981b8b16a3
4 changed files with 57 additions and 4 deletions

View File

@ -232,7 +232,7 @@ namespace PdfWriter
SaveToStream((CStream*)pStream);
delete pStream;
Sign(wsPath, m_pXref->GetSizeXRef());
Sign(wsPath, m_pXref->GetSizeXRef() + 1, true);
return true;
}
@ -1988,7 +1988,9 @@ namespace PdfWriter
m_pXref = pXrefBefore;
return false;
}
m_pXref->SetPrevAddr(pSI->nPrevAddr ? pSI->nPrevAddr : pXrefBefore->GetPrevAddr());
if (!pSI->nPrevAddr)
pSI->nPrevAddr = pXrefBefore->GetPrevAddr();
m_pXref->SetPrevAddr(pSI->nPrevAddr);
// Создаем поле подписи
CSignatureField* pField = CreateSignatureField();
@ -2017,6 +2019,7 @@ namespace PdfWriter
m_pXref = pXrefBefore;
return false;
}
pSI->nFileSizeBefore = pStream->Size();
// Вычисляем размер для Contents
unsigned int nContentsSize = 7000 + pStream->Size() / 1000 + 1000;
@ -2076,6 +2079,50 @@ namespace PdfWriter
if (wsPath.empty() || !pSI->pField)
return false;
// Если подписание не удалось
if (!pSignedData || dwDataLength == 0)
{
unsigned int nFileSizeBefore = pSI->nFileSizeBefore;
// Обрезаем файл
NSFile::CFileBinary::Truncate(wsPath, nFileSizeBefore);
CXref* pXref = pSI->pXref;
m_vSignatures.pop_front();
pSI->pPage->DeleteAnnotation(pSI->pField->GetObjId());
if (m_pAcroForm)
{
CArrayObject* ppFields = (CArrayObject*)m_pAcroForm->Get("Fields");
for (int i = 0; i < ppFields->GetCount(); ++i)
{
CObjectBase* pObj = ppFields->Get(i);
if (pObj->GetObjId() == pSI->pField->GetObjId())
{
CObjectBase* pDelete = ppFields->Remove(i);
if (pDelete->GetType() == object_type_UNKNOWN)
RELEASEOBJECT(pDelete);
break;
}
}
}
// Продолжаем со следующей подписью
if (!m_vSignatures.empty())
{
CXref* pPrev = pXref;
while (pPrev->GetPrev())
pPrev = pPrev->GetPrev();
Sign(wsPath, pSI->nSizeXRef, bNeedStreamXRef, pSI->nPrevAddr);
}
delete pSI;
delete pXref;
return true; // Успешно откатили
}
CFileStream* pStream = new CFileStream();
if (!pStream || !pStream->OpenFile(wsPath, false))
{

View File

@ -267,6 +267,7 @@ namespace PdfWriter
nSizeXRef = 0;
nPrevAddr = 0;
nFileSizeBefore = 0;
bNeedStreamXRef = false;
pField = NULL;
pXref = NULL;
@ -279,6 +280,7 @@ namespace PdfWriter
std::wstring wsPath;
unsigned int nSizeXRef;
unsigned int nPrevAddr;
unsigned int nFileSizeBefore;
bool bNeedStreamXRef;
CSignatureField* pField;
CXref* pXref;

View File

@ -1232,7 +1232,8 @@ namespace PdfWriter
if (pObj->GetObjId() == nID)
{
CObjectBase* pDelete = pArray->Remove(i);
RELEASEOBJECT(pDelete);
if (pDelete->GetType() == object_type_UNKNOWN)
RELEASEOBJECT(pDelete);
return true;
}
}

View File

@ -633,11 +633,14 @@ TEST_F(CPdfFileTest, EditPdfSign)
BYTE* pDatatoWrite = NULL;
unsigned int dwLenDatatoWrite = 0;
// Предположим, что для подписи 1 произошло не успешное подписание, и данные остались пустыми
pCertificate->SignPKCS7(pDataToSign, dwDataLength, pDatatoWrite, dwLenDatatoWrite);
if (i % 2 == 0)
pCertificate->SignPKCS7(pDataToSign, dwDataLength, pDatatoWrite, dwLenDatatoWrite);
RELEASEARRAYOBJECTS(pDataToSign);
// Обязательно FinalizeSignature - он либо заполнит данные, либо сделает подпись пустой
pdfFile->FinalizeSignature(pDatatoWrite, dwLenDatatoWrite);
RELEASEARRAYOBJECTS(pDatatoWrite);
RELEASEOBJECT(pCertificate);
}