You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iTextSharp 5.5.13 PDF初始签名无效、修订版2签名有效问题咨询

问题描述

使用iTextSharp 5.5.13开发PDF数字签名功能时出现异常:初始证书签名校验无效,但修订版本(2)对应的签名可正常验证通过。
问题对应的C#实现代码如下:

var PdfXPosition = Convert.ToSingle(finalString[j].Split(',')[1].Trim().Replace('"', ' ').Trim()) - .00220f;
var PdfYPosition = Convert.ToSingle(finalString[j].Split(',')[2].Trim().Replace('"', ' ').Trim()) - 33.00000f;
Image Sign = Image.GetInstance(SignatureImagePath);
Sign.SetAbsolutePosition(PdfXPosition, PdfYPosition);
Sign.Alignment = Element.ALIGN_LEFT;
stamper.GetOverContent(1).AddImage(Sign);
appearance.Image = Sign;
appearance.SignDate=Convert.ToDateTime(indianTime);

//appearance.SignDate = Convert.ToDateTime("19-06-2022 12:53:28 AM");
//appearance.CryptoDictionary = pdfSignature;

if (ApproversCount == "1")
{
    stamper.Writer.PdfVersion = PdfWriter.VERSION_1_4;
    //appearance.CertificationLevel = PdfSignatureAppearance.CERTIFIED_FORM_FILLING;// CERTIFIED_FORM_FILLING_AND_ANNOTATIONS;
}
else {
    stamper.Writer.PdfVersion = PdfWriter.VERSION_1_3;
    appearance.CertificationLevel = PdfSignatureAppearance.CERTIFIED_FORM_FILLING;// CERTIFIED_FORM_FILLING_AND_ANNOTATIONS;
}

//For Invisible Signature make Height and Width to zero                                    
appearance.SetVisibleSignature(new Rectangle(0, 0, 0, 0), 1,"Sign"+ guid);
// stamper.AddSignature("Sign" + obj, 1, 0, 0, 0, 0);
}

IExternalSignature externalSignature = new PrivateKeySignature(akp, DigestAlgorithms.SHA512);
MakeSignatures.SignDetachedd(appearance, externalSignature, chain, null, null, null, 0, CryptoStandard.CMS);
根因分析
  • 非法操作签名内容层:代码在签名哈希计算流程外,直接通过stamper.GetOverContent(1).AddImage(Sign)向第一页内容流写入图片。这部分写入操作发生在签名哈希计算完成之后,不会被纳入初始签名的哈希校验范围,直接导致初始签名覆盖的字节被篡改,校验失败。当文件保存生成修订版本2时,这部分额外写入的图片内容被纳入新修订版的签名计算范围,因此修订版2的签名可以正常通过校验。
  • 签名配置逻辑冲突:代码先给appearance.Image赋值了签名图片,后续却调用SetVisibleSignature传入new Rectangle(0, 0, 0, 0)将签名配置为不可见状态,两个矛盾配置会导致iTextSharp的外观写入逻辑异常,额外生成未被签名哈希覆盖的PDF对象。
  • PDF版本设置时机错误:代码在stamper初始化完成、内容已经开始写入后,才修改stamper.Writer.PdfVersion属性,此时修改版本号会导致PDF文件头标识和实际内容结构不匹配,校验器解析初始版本时会出现结构解析偏差。
  • 多签场景版本配置不一致:单签场景设置PDF版本为1.4,多签场景切换为1.3,版本切换会导致增量保存的修订结构兼容性异常。
修复方案
  • 禁止直接通过stamper.GetOverContent()/GetUnderContent()方法添加签名相关元素,所有签名外观内容统一通过PdfSignatureAppearance的属性配置,签名图片仅需赋值给appearance.Image,iTextSharp会自动将这部分内容纳入签名哈希计算范围。
  • 统一签名可见性配置:如果实现可见签名,SetVisibleSignature传入的矩形参数需配置为签名位置对应的实际坐标、宽高,禁止传入0尺寸矩形;如果实现不可见签名,不要给appearance.Image赋值。
  • PDF版本需在stamper创建时就指定,不要在内容写入流程中修改版本属性;多签场景全流程统一使用兼容的PDF版本,不要在不同审批节点切换1.3/1.4版本。
  • 清理注释掉的测试配置代码,避免手动赋值CryptoDictionary、硬编码签名日期这类操作干扰iTextSharp默认的签名逻辑。

调整后的核心参考代码:

var PdfXPosition = Convert.ToSingle(finalString[j].Split(',')[1].Trim().Replace('"', ' ').Trim()) - .00220f;
var PdfYPosition = Convert.ToSingle(finalString[j].Split(',')[2].Trim().Replace('"', ' ').Trim()) - 33.00000f;
Image Sign = Image.GetInstance(SignatureImagePath);
// 移除直接操作overContent添加图片的代码
appearance.Image = Sign;
appearance.SignDate = Convert.ToDateTime(indianTime);

// 统一设置认证级别,不要按审批人数分支切换
appearance.CertificationLevel = PdfSignatureAppearance.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS;
// 版本在stamper初始化时统一设置,此处移除中途修改PdfVersion的逻辑

// 可见签名配置实际尺寸,不可见签名则删除appearance.Image赋值
float signWidth = 100f;
float signHeight = 50f;
appearance.SetVisibleSignature(new Rectangle(PdfXPosition, PdfYPosition, PdfXPosition + signWidth, PdfYPosition + signHeight), 1, "Sign" + guid);

IExternalSignature externalSignature = new PrivateKeySignature(akp, DigestAlgorithms.SHA512);
MakeSignatures.SignDetached(appearance, externalSignature, chain, null, null, null, 0, CryptoStandard.CMS);

内容的提问来源于stack exchange,提问作者tjk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 11:33:20