电子签章本质是数字签名+可信时间戳+可视化呈现三者绑定,核心是用私钥加密文档摘要;c#需用rsacryptoserviceprovider等实现pkcs#7签名,pdf嵌入须借助itextsharp或pdfpig,并确保证书链完整、sha256哈希、时间同步及字节范围精确计算。

电子签章不是加个图片水印
很多人以为在 PDF 或 Word 文档上用 Graphics.DrawImage 盖个 PNG 就是电子签章——这连法律效力的边都没摸到。真正的电子签章本质是「数字签名 + 可信时间戳 + 签章可视化呈现」三者绑定,其中核心是用私钥对文档摘要做非对称加密,生成可验证的 SignatureValue。C# 里必须走 RSACryptoServiceProvider 或更现代的 RSASignatureFormatter / RSASignatureDeformatter,而不是简单哈希后存字符串。
PDF 中嵌入符合 PKCS#7 的签名需要 iTextSharp 或 PdfPig
原生 .NET 没有 PDF 签名支持。iTextSharp(v5.x)虽已停止维护但仍是实际项目中最常用的方案;若用 .NET 6+,推荐 PdfPig(由 UglyToad 开发),它支持增量更新和 CMS 签名容器写入。关键点:
-
PdfPig不自带签名逻辑,需配合System.Security.Cryptography.Pkcs.SignedCms构造符合PKCS#7的签名数据,再注入到 PDF 的/Sig字典中 - iTextSharp 的
MakeSignature.SignDetached会自动处理字节范围计算(即只对 /ByteRange 指定区域哈希),漏掉这步会导致 Adobe Reader 显示“签名已损坏” - 务必用
SHA256以上哈希算法,MD5和SHA1在 Acrobat 中已被标记为“不安全”,直接拒绝验证
证书链校验失败常因缺失中间 CA 或时间不准
签名能生成,但 Acrobat 提示“签名者身份未知”或“证书吊销状态未知”,大概率不是代码问题,而是环境配置疏漏:
- Windows 证书存储中必须同时存在:用户证书(含私钥)、中间 CA 证书、根 CA 证书;仅导入用户证书,
SignedCms.ComputeSignature虽成功,但生成的CMS包不含完整证书链,验证端无法构建信任路径 - 调用
X509Chain.Build()前,手动设置chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck仅用于调试,生产环境必须联网校验 CRL/OCSP,否则签名不可信 - 系统时间偏差超过 5 分钟,会导致 OCSP 响应被判定为过期,进而使整个签名链验证失败——别忽略服务器 NTP 同步
可视化签章位置与实际签名范围必须严格分离
签章图像(如带公司 Logo 的 PNG)只是视觉提示,它本身不参与签名计算。真正被签名的是原始文档字节流(不含签章图层)。常见错误:
- 先用
Graphics把印章画进 PDF 页面,再对该 PDF 签名 → 错!此时签的是“已盖章的 PDF”,后续任何修改(包括页面旋转)都会让签名失效 - 正确做法:用
PdfPig打开原始 PDF → 计算待签名字节范围(跳过未来要插入的签名字段)→ 生成 CMS 签名 → 将签名数据 + 可视化签章 Widget 写入同一处/Sig字典 → 最后保存为增量更新 - 签章 Widget 的
/Rect是显示坐标,而签名计算依据的是 PDF 文件字节偏移(/ByteRange),二者完全独立,改位置不影响签名有效性,但改/ByteRange值就立刻失效
底层没搞清字节级结构和密码学绑定关系,所有“盖章”操作都只是伪需求。PDF 签名字段、CMS 容器、证书链、时间戳服务响应——每个环节断掉,法律效力就归零。











