如何让iText7生成的TSAClient时间戳签名可见?
我正在使用iText7为PDF添加来自TSA的时间戳,代码如下:
using (PdfReader reader = new PdfReader(pdf_filename)) { using (FileStream output = new FileStream($"dts_{pdf_filename}", FileMode.Create)) { PdfSigner signer = new PdfSigner(reader, output, new StampingProperties()); signer.SetFieldName("SignatureField"); var tsa_client = new TSAClientBouncyCastle(Config.TSA_URL, null, null, 8192, "sha256"); signer.Timestamp(tsa_client, "SignatureTimeStamp"); } }
时间戳已成功添加且有效,但始终无法使其可见。我尝试使用signer.GetSignatureAppearance()设置页码、原因等信息,时间戳仍不可见。查阅API文档得知:
If you create new signature field (either use SetFieldName(System.String) with the name that doesn't exist in the document or don't specify it at all) then the signature is invisible by default.
但我不确定如何利用该信息解决问题,请问如何让该时间戳签名可见?
解决方案
要让TSA时间戳签名可见,核心是确保签名字段是已存在的可见字段,或者创建新的可见签名字段并配置外观,以下是两种可行方案:
方案1:复用PDF中已有的可见签名字段
如果目标PDF已预先创建好可见签名域(比如通过Acrobat添加的签名框),直接使用该域的名称即可:
- 确认PDF中存在名为
"ExistingVisibleSignatureField"的可见签名域 - 修改代码中
SetFieldName的参数为该域的名称:
signer.SetFieldName("ExistingVisibleSignatureField");
时间戳会自动关联到这个已有的可见字段,直接显示出来。
方案2:创建新的可见签名字段并配置外观
若PDF中无现成可见签名域,需手动创建并配置外观:
- 获取签名外观对象,设置显示的页码、位置和大小
- 配置签名的文本内容(原因、位置、创建者等)
- 无需指定不存在的字段名(或不调用
SetFieldName),iText会自动创建对应的可见签名域
修改后的示例代码:
using (PdfReader reader = new PdfReader(pdf_filename)) { using (FileStream output = new FileStream($"dts_{pdf_filename}", FileMode.Create)) { PdfSigner signer = new PdfSigner(reader, output, new StampingProperties()); // 获取签名外观并配置可见区域 PdfSignatureAppearance appearance = signer.GetSignatureAppearance(); // 设置签名显示在第1页,左下角位置,宽200高100(单位:用户单位) appearance.SetPageNumber(1) .SetPageRect(new Rectangle(36, 36, 200, 100)); // 配置签名文本信息 appearance.SetReason("TSA时间戳验证") .SetLocation("中国") .SetSignatureCreator("iText7"); var tsa_client = new TSAClientBouncyCastle(Config.TSA_URL, null, null, 8192, "sha256"); signer.Timestamp(tsa_client, "SignatureTimeStamp"); } }
关键说明
你之前的问题根源在于:调用SetFieldName("SignatureField")时,该字段在PDF中不存在,iText默认创建了不可见签名域,此时即使配置外观也无法生效。若要创建可见签名,要么复用已有的可见域,要么通过PdfSignatureAppearance配置位置和大小,同时不指定不存在的字段名。
内容的提问来源于stack exchange,提问作者ccasado

