iText7 converting signature as an invisible signature after using append mode property

旧街凉风 提交于 2019-12-24 19:49:17

问题


I am getting issue that if I use UseAppendMode property while creating signature field in the document, upon signing it creates invisible signature. Otherwise it displays the content of my custom signature appearance and creates a visible signature into PDF. Following is my code snippet:

SigningResponse signingResponse = new SigningResponse();
Stream outputStream = new MemoryStream();
Org.BouncyCastle.X509.X509Certificate x509Certificate = null;
int estimatedSize = SigningProfile.ContainsKey(ProfileCommon.DICTIONARY_SIZE.ToString()) ? 
    int.Parse(SigningProfile[ProfileCommon.DICTIONARY_SIZE.ToString()]) * 1024 : 600 * 1024;
Stream readerStream = new MemoryStream(documentBytes);
PdfReader pdfReader = new PdfReader(readerStream);
PdfSigner pdfSigner = new PdfSigner(pdfReader, outputStream, new StampingProperties().UseAppendMode());
pdfSigner.SetFieldName("Signature1");
pdfSigner.GetDocument().GetCatalog().SetModified();
if (signingRequest.CertifyPolicy != (int)CertifyPolicy.NOT_CERTIFIED)
    pdfSigner.SetCertificationLevel(signingRequest.CertifyPolicy);

PdfSignatureAppearance signatureAppearance = pdfSigner.GetSignatureAppearance();
signatureAppearance.SetContact("Contact Info");
signatureAppearance.SetLocation("Location");
signatureAppearance.SetPageNumber(1);
signatureAppearance.SetReason("Signing Reason");
PdfFormXObject n0 = signatureAppearance.GetLayer0();
float x = n0.GetBBox().ToRectangle().GetLeft();
float y = n0.GetBBox().ToRectangle().GetBottom();
float width = n0.GetBBox().ToRectangle().GetWidth();
float height = n0.GetBBox().ToRectangle().GetHeight();
PdfCanvas canvas = new PdfCanvas(n0, pdfSigner.GetDocument());
canvas.SetFillColor(ColorConstants.LIGHT_GRAY);
canvas.Rectangle(x, y, width, height);
canvas.Fill();
// Set the signature information on layer 2
PdfFormXObject n2 = signatureAppearance.GetLayer2();
Paragraph p = new Paragraph("This document was signed by Bruno Specimen.");
new Canvas(n2, pdfSigner.GetDocument()).Add(p);

signatureAppearance.SetCertificate(x509Certificate);
PreSigning external = new PreSigning(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached);
pdfSigner.SignExternalContainer(external, estimatedSize);
signingResponse.DocumentHash = external.getHash();
signingResponse.D2S = signingResponse.DocumentHash;
signingResponse.DocumentBytes = ((MemoryStream)outputStream).ToArray();
return signingResponse;

And the code of creating signature field is as follows:

byte[] documentBytes = null;
foreach (PDFSignatureField field in signatureFields)
{
    using (Stream memoryStream = new MemoryStream())
    using (PdfReader _pdfReader = new PdfReader(new MemoryStream(_documentBytes)).SetUnethicalReading(true))
    using (PdfDocument pdfDocument = new PdfDocument(_pdfReader, new PdfWriter(memoryStream)))
    {
        PdfAcroForm pdfAcroForm = PdfAcroForm.GetAcroForm(pdfDocument, true);
        //Initializing signature position object
        PDFSignaturePosition SigPosition = field.Position;
        for (int i = 0 ; i < SigPosition.Pages.Length ; ++i)
        {
            //Getting PDF document page
            PdfPage page = pdfDocument.GetPage(SigPosition.Pages[i]);
            if (page == null)
            {
                page = pdfDocument.GetPage(SigPosition.PageNumber);
            }
            //Getting PDF document page rotation
            int rotation = page.GetRotation();
            //Getting signature field rects according to PDF page
            iText.Kernel.Geom.Rectangle rect;
            if (rotation > 0 && SigPosition.Position == PDFSignaturePosition.DefaultSignaturePosition.Custom)
            {
                rect = GetSignaturePositionAccordingToRotation(SigPosition.Rect, page.GetCropBox(), rotation);
            }
            else
            {
                rect = GetSignaturePositionRect(SigPosition.Position, SigPosition.Rect, page.GetCropBox());
            }
            //Creating signature field into PDF page
            PdfFormField sig = PdfFormField.CreateSignature(pdfDocument, rect);
            //Setting signature field visible flag
            if (field.Display == (int)SignatureDisplayType.INVISIBLE)
            {
                sig.SetFieldFlags(PdfFormField.HIDDEN);
                sig.SetVisibility(PdfFormField.HIDDEN);
            }
            else
            {
                sig.SetFieldFlags(PdfFormField.VISIBLE);
            }
            //Setting signature field font information
            sig.Put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g"));
            //Setting signature field name
            sig.SetFieldName(i == 0 ? field.Name : field.Name + " - " + SigPosition.Pages[i]);
            //Setting signature field page
            sig.SetPage(SigPosition.Pages[i]);
            //Adding signature field into AcroForm
            pdfAcroForm.AddField(sig, page);
            //Making indirect reference of the added signature field into PDF
            sig.MakeIndirect(pdfDocument);
            //Closing PDF document object
            pdfDocument.Close();
            //Getting latest document bytes after adding PDF field
            documentBytes = ((MemoryStream)memoryStream).ToArray();
            if (i + 1 == SigPosition.Pages.Length)
            {
                break;
            }
        }
        _documentBytes = documentBytes;
    }
}

回答1:


As you use a lot of variables defined, declared, and filled outside of the code you show, I had to reduce your code considerably. Furthermore, I don't have your example documents to tests with and, therefore, had to test with documents I have at hand here.

Nonetheless, I could reproduce the issue and found a solution for it in my setup. I hope that in spite of all the differences in setup you can use this solution.

The reason for the signature field becoming invisible in my setup turned out to be that while adding the signature fields to the document in append mode, the Fields array in the document-wide AcroForms dictionary was not marked as modified. The signer on the other hand relies on the signature field to sign to be found in that Fields array. The signer, therefore, did not find the prepared, visible field and created a new, invisible field with that name.

A work-around is to manually mark the array in question as modified:

pdfAcroForm.GetPdfObject().Get(PdfName.Fields).SetModified();
pdfAcroForm.GetPdfObject().SetModified();

//Closing PDF document object
pdfDocument.Close();


来源:https://stackoverflow.com/questions/59346843/itext7-converting-signature-as-an-invisible-signature-after-using-append-mode-pr

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!