我的签名结构干扰了使用itext7嵌入签名 [英] My signature structure disturbs on embedding signature using itext7

查看:60
本文介绍了我的签名结构干扰了使用itext7嵌入签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的应用程序中使用的是itext7版本7.1.5.我的情况如下: -取文档的哈希值 -从外部签名服务器签名哈希并获取Pkcs7 -使用itext7将签名的pkcs7嵌入PDF文档中

I am using itext7 version 7.1.5 in my application. My scenario is as following: - Take the hash of the document - Sign the hash from external signing server and get Pkcs7 - Embed the signed pkcs7 into the PDF document using itext7

嵌入后,adobe无法验证我在文档中的签名.当我检查签名结构时,签名结构是错误的.

After embedding adobe fails to validate my signature in the document. When I check the signature structure, the signature structure is wrong.

这是逐步的代码:

1:文档散列:

string hashAlgorithm = "SHA256";

Stream documentStream = new MemoryStream(_latestDocumentBytes);

PdfSigner _pdfSigner = new PdfSigner(pdfReader, outputStream, new StampingProperties());

_pdfSigner.SetFieldName("Signature1");

ImageData imageData = ImageDataFactory.Create(imageBytes);

PdfSignatureAppearance sigAppearance = _pdfSigner.GetSignatureAppearance();
sigAppearance.SetContact("ContactInfo");
sigAppearance.SetLocation("Location");
sigAppearance.SetPageNumber(1);
sigAppearance.SetReason("SigningReason");
sigAppearance.SetSignatureGraphic(imageData);
sigAppearance.SetRenderingMode(sigAppearance.RenderingMode.GRAPHIC)
sigAppearance.SetSignatureCreator("Malik");

PdfSignature signature = new PdfSignature(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached);
signature.SetContact(sigAppearance.GetContact());
signature.SetDate(new PdfDate(DateTime.Now));
signature.SetLocation(sigAppearance.GetLocation());
signature.SetReason(sigAppearance.GetReason());
signature.SetSignatureCreator(sigAppearance.GetSignatureCreator());
signature.MakeIndirect(_pdfDocument);

documentHash = DigestAlgorithms.Digest(documentStream, DigestAlgorithms.SHA256);

SHA256 sha256 = new SHA256Managed();
byte[] documentHash = sha256.ComputeHash(documentHash);

2:从文档服务器获取签名哈希

3:将签名嵌入PDF

Stream readerStream = new MemoryStream(_latestDocumentBytes);

PdfPKCS7 pdfPKCS7 = new PdfPKCS7(pdfSignatureBytes, PdfName.Adbe_pkcs7_detached);

PdfSignatureAppearance signatureAppearance = _pdfSigner.GetSignatureAppearance();

signatureAppearance.SetCertificate(pdfPKCS7.GetSigningCertificate());

signature.SetContents(pdfSignatureBytes);

IExternalSignatureContainer externalSignatureContainer = new ExternalBlankSignatureContainer(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached);

_pdfSigner.SignExternalContainer(externalSignatureContainer, 8192);

_latestDocumentBytes = ((MemoryStream)outputStream).ToArray();

我的签名结构差异如下:

  • 正确的签名结构:

  • Correct signature structure:

<</Type/Sig/Reason(I have approved ad signed the document)/Contents ><[CONTENT]>/Prop_Build<</App<</Name/Malik>>>>/ByteRange [0 10857 522859 2584 >]                                                          >/SubFilter/adbe.pkcs7.detached/Filter/Adobe.PPKLite/M(D:20190719103520+00'00>>')/ContactInfo(923399999999)/Name(John Clark)/Location(Pakistan)>>

  • 不正确(Itext实现):

  • InCorrect (Itext Implementation):

    <</ByteRange [0 157 16543 260086 ]  [Large Space] >/ContactInfo(email@email.com)/Contents ><[CONTENT]>/Filter/Adobe.PPKLite/Location(Pakistan)/M(D:20190719154813+05'00'>)/Prop_Build<</App<</Name/Malik>>>>/Reason(Test Signing >Reason)/SubFilter/adbe.pkcs7.detached/Type/Sig>>
    

  • 在Adobe中打开签名的PDF时,在验证签名时显示错误 BER解码时发生错误

    While opening the signed PDF in Adobe, an error displayed while validating the signature that ERROR ENCOUNTERED WHILE BER DECODING

    原始文档在这里: https://www.dropbox.com/s /ajscg8j74opuwxe/SigFieldDoc%20-%20Original.pdf?dl=0

    已签名的文档在这里: https://www.dropbox.com/s /h72u360rl5iy6fq/SigFieldDoc%20-%20AfterSign.pdf?dl=0

    在这方面的任何帮助将不胜感激.

    Any help in this regard will be highly appreciated.

    推荐答案

    要使用远程服务器使用iText 7对PDF进行签名以创建实际的加密签名,您只需实现一个iText签名接口即可执行远程调用.服务使用其Sign方法处理给定数据.

    To sign a PDF with iText 7 using a remote server to create the actual cryptographic signature, you can simply implement an iText signature interface which executes the call of the remote service in its Sign method for the given data.

    此外,您在评论中澄清了您的

    Furthermore, you clarified in a comment that your

    外部签名服务器返回PKCS7签名签名的数据.

    external signing server returns PKCS7 signature signed data.

    因此,要使用的接口是IExternalSignatureContainer(而不是IExternalSignature,如果服务器仅返回原始签名字节,则将使用该接口).

    Thus, the interface to use is an IExternalSignatureContainer (and not a IExternalSignature which one would have used if the server returned merely the primitive signature bytes).

    我不知道您如何与服务器通信;特别是我不知道您使用的API是否要求您提供完整的签名数据或仅提供其哈希值;在前一种情况下,是将它们提供为流还是数组.因此,对于每种情况,我都会在Sign方法中添加提示:

    I don't know how you communicate with your server; in particular I don't know whether the API you use requires you to provide the complete signed data or merely the hash thereof; and in the former case, whether to provide them as stream or array. Thus, I put hints into the Sign method for each case:

    public class ExternalServiceSignatureContainer : IExternalSignatureContainer
    {
        public void ModifySigningDictionary(PdfDictionary signDic)
        {
            signDic.Put(PdfName.Filter, PdfName.Adobe_PPKLite);
            signDic.Put(PdfName.SubFilter, PdfName.Adbe_pkcs7_detached);
        }
    
        public byte[] Sign(Stream data)
        {
            // Call your external signing service to create a CMS signature container
            // for the data in the InputStream
    
            // Depending on your API to access that service you may either be able to
            // directly call it with the stream
         // return YOUR_SIGNING_API_CALL_FOR_STREAM(data);
            // (or a byte[] generated from the stream contents)
         // return YOUR_SIGNING_API_CALL_FOR_ARRAY(StreamUtil.InputStreamToArray(data));
            // as parameter, or you may first have to hash the data yourself
            // (e.g. as follows) and send your hash to the service.
         // byte[] hash = DigestAlgorithms.Digest(data, DigestAlgorithms.SHA256);
         // return YOUR_SIGNING_API_CALL_FOR_HASH(hash)
    
            // dummy
            return new byte[0];
        }
    }
    

    然后可以按如下方式使用此类:

    You can then use this class as follows:

    PdfReader pdfReader = new PdfReader(DOCUMENT_TO_SIGN);
    PdfSigner pdfSigner = new PdfSigner(pdfReader, RESULT_STREAM, new StampingProperties().UseAppendMode());
    
    pdfSigner.SetFieldName("Signature1");
    
    ImageData imageData = ImageDataFactory.Create(SIGNATURE_IMAGE);
    
    PdfSignatureAppearance sigAppearance = pdfSigner.GetSignatureAppearance();
    sigAppearance.SetContact("ContactInfo");
    sigAppearance.SetLocation("Location");
    sigAppearance.SetPageNumber(1);
    sigAppearance.SetPageRect(new Rectangle(100, 500, imageData.GetWidth() / 2, imageData.GetHeight() / 2));
    sigAppearance.SetReason("SigningReason");
    sigAppearance.SetSignatureGraphic(imageData);
    sigAppearance.SetRenderingMode(RenderingMode.GRAPHIC);
    sigAppearance.SetSignatureCreator("Malik");
    
    pdfSigner.GetDocument().GetCatalog().SetModified();
    
    int estimatedSize = 12000;
    pdfSigner.SignExternalContainer(new ExternalServiceSignatureContainer(), estimatedSize);
    


    一些评论:


    Some remarks:

    我添加了

    sigAppearance.SetPageRect(new Rectangle(100, 500, imageData.GetWidth() / 2, imageData.GetHeight() / 2));
    

    因为我还使用了其他文档进行测试.由于该其他文档最初不包含名为 Signature1 的签名字段,因此我需要设置矩形以获取可见的签名.如果您的文档已经具有这样的签名字段,则可以删除该行,但无论如何都将忽略该行.

    because I also used a different document to test. As that other document does not originally contain a signature field named Signature1, I needed to set the rectangle to get a visible signature. In case of your document which already has such a signature field, that line can be dropped but is ignored anyways.

    pdfSigner.GetDocument().GetCatalog().SetModified();
    

    由于iText中的一个小错误而需要添加:对现有字段(而非新字段)签名时,请使用 AcroForm 词典(尤其是直接包含在 Catalog (例如文档中的/strong>),则未标记为已修改,因此不会在增量更新中进行更新.这样可以防止在文档中设置 SigFlags ,这会导致Adobe Reader无法显示顶部签名栏.

    needs to be added because of a small bug in iText: When signing an existing field (not a new field), the AcroForm dictionary (in particular if contained directly in the Catalog like in your document), is not marked as modified and, therefore, not updated in the incremental update. This prevents the SigFlags in your document from being set which causes Adobe Reader not display the top signature bar.

    您可能要更改估算值

    int estimatedSize = 12000;
    

    签名容器的大小,特别是如果您检索的签名容器总是小得多或有时大于12000字节时.

    of the signature container size, in particular if the signature containers you retrieve always are much smaller or sometimes larger than 12000 bytes.

    这篇关于我的签名结构干扰了使用itext7嵌入签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆