我的签名结构干扰了使用 itext7 嵌入签名

2023-12-30

我在我的应用程序中使用 itext7 版本 7.1.5。我的场景如下: - 获取文档的哈希值 - 从外部签名服务器对哈希进行签名并获取 Pkcs7 - 使用itext7将签名的pkcs7嵌入到PDF文档中

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

这是分步代码:

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();

我的签名结构差异如下:

  • 正确的签名结构:

    <</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 实现):

    <</ByteRange [0 157 16543 260086 ]  [Large Space] >/ContactInfo([email protected] /cdn-cgi/l/email-protection)/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>>
    

在 Adob​​e 中打开已签名的 PDF 时,验证签名时显示错误BER 解码时遇到错误

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

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

在这方面的任何帮助将受到高度赞赏。


要使用远程服务器使用 iText 7 对 PDF 进行签名以创建实际的加密签名,您可以简单地实现一个 iText 签名接口,该接口在其中执行远程服务的调用Sign给定数据的方法。

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

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

因此,要使用的接口是IExternalSignatureContainer(而不是一个IExternalSignature如果服务器仅返回原始签名字节,则会使用哪一个)。

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

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];
    }
}

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

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);

一些备注:

I added

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

因为我还用了不同的文档来测试。由于该其他文档最初并不包含名为的签名字段签名1,我需要设置矩形以获得可见的签名。如果您的文档已经有这样的签名字段,则可以删除该行,但无论如何都会被忽略。

线路

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

由于 iText 中的一个小错误,需要添加:当签署现有字段(而不是新字段)时,AcroForm字典(特别是如果直接包含在Catalog就像您的文档中一样),未标记为已修改,因此不会在增量更新中更新。这可以防止SigFlags您的文档中的设置会导致 Adob​​e Reader 不显示顶部签名栏。

您可能想要更改估算值

int estimatedSize = 12000;

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我的签名结构干扰了使用 itext7 嵌入签名 的相关文章

随机推荐