要使用远程服务器使用 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您的文档中的设置会导致 Adobe Reader 不显示顶部签名栏。
您可能想要更改估算值
int estimatedSize = 12000;
签名容器大小,特别是如果您检索的签名容器始终小得多或有时大于 12000 字节。