【发布时间】:2017-11-28 07:28:13
【问题描述】:
我已经使用 iTextSharp Dll 实现了数字签名,以使用创建空签名字段的单个签名对 PDF 文件进行签名,并使用签名哈希工作正常更新签名字段。现在,我想在 pdf 的每一页中放置相同的数字签名。这是我的客户要求。
我正在使用以下代码:
public class MyExternalSignatureContainer : IExternalSignatureContainer
{
private readonly byte[] signedBytes;
public MyExternalSignatureContainer(byte[] signedBytes)
{
this.signedBytes = signedBytes;
}
public byte[] Sign(Stream data)
{
return signedBytes;
}
public void ModifySigningDictionary(PdfDictionary signDic)
{
}
}
以下程序中使用的代码
PdfReader reader = new PdfReader(unsignedPdf);
FileStream os = File.OpenWrite(tempPdf);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = "Reason1";
appearance.Contact = "";
appearance.Location = "Location1";
appearance.Acro6Layers = false;
appearance.Image = null;
appearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.DESCRIPTION;
appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(36, 748, 144, 780), 1, null);
for (int i = 1; i < 8; i++)
{
var signatureField = PdfFormField.CreateSignature(stamper.Writer);
var signatureRect = new Rectangle(200, 200, 100, 100);
signatureField.Put(PdfName.T, new PdfString("ClientSignature_"+i.ToString()));
PdfIndirectReference PRef = stamper.Writer.PdfIndirectReference;
signatureField.Put(PdfName.V, PRef);
signatureField.Put(PdfName.F, new PdfNumber("132"));
signatureField.SetWidget(signatureRect, null);
signatureField.Put(PdfName.SUBTYPE, PdfName.WIDGET);
PdfDictionary xobject1 = new PdfDictionary();
PdfDictionary xobject2 = new PdfDictionary();
xobject1.Put(PdfName.N, appearance.GetAppearance().IndirectReference);
xobject2.Put(PdfName.AP, xobject1);
signatureField.Put(PdfName.AP, xobject1);
signatureField.SetPage();
PdfDictionary xobject3 = new PdfDictionary();
PdfDictionary xobject4 = new PdfDictionary();
xobject4.Put(PdfName.FRM, appearance.GetAppearance().IndirectReference);
xobject3.Put(PdfName.XOBJECT, xobject4);
signatureField.Put(PdfName.DR, xobject3);
stamper.AddAnnotation(signatureField, i);
}
IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKMS, PdfName.ADBE_PKCS7_DETACHED);
MakeSignature.SignExternalContainer(appearance, external, 8192);
stamper.Close();
byte[] SignedHash = DoEsign(SHA256Managed.Create().ComputeHash(appearance.GetRangeStream());
os.close();
reader.close();
reader = new PdfReader(tempPdf))
os = File.OpenWrite(signedPdf)
IExternalSignatureContainer external1 = new MyExternalSignatureContainer(SignedHash);
MakeSignature.SignDeferred(reader, signatureFieldName, os, external1);
os.close();
reader.close();
请建议我完成任务
【问题讨论】:
-
“客户要求” - 您是否让您的客户意识到当前 PDF 规范 ISO 32000-2 规定“文档中签名的位置可以包含影响其法律意义。因此,签名字段不得引用多个注释。和“一个给定的注释字典应该从只有一页的 Annots 数组中引用。”因此,该要求使 PDF 无效,并允许任何查看者立即或在签名验证期间拒绝它。
-
也就是说,this answer 显示了选项的概述(使用 ISO 32000-2 之前的 cmets); the other answer 对同一个问题给出了如何修补 iText 5.5.x 以获得所需结果的提示;该补丁是针对 Java 版本描述的,但应该很容易移植到 .Net。
-
我使用相同的代码做了同样的事情。请再看一遍。
-
“我通过使用相同的代码做了同样的事情” - 嗯,不是真的。您的方法试图走另一条路,您不要尝试从许多页面中引用单个签名字段(或像在其他地方所做的那样为单个签名字段创建多个小部件注释),您尝试创建多个签名字段共享相同的价值!作为一个有趣的想法。我不确定如果实施得当,PDF查看器会对此有何反应,据我所知,规范尚未明确禁止这样做,但也不预期......
-
也就是说,你已经展示了你的代码;你跑了吗?它有效吗?如果不是,那是什么问题? (对我来说,您为签名值分配新的间接引用看起来很虚假。如果您想在所有签名字段中使用相同的签名值,所有这些字段都应该使用相同的引用...)
标签: itext