如何在.NET中验证PDF双签名并提取签署人姓名?
在.NET中读取PDF签名、验证有效性并提取签署人信息的实现方案
嘿,我刚好折腾过类似的需求,针对你要验证PDF合同的两个签名、提取签署人姓名的问题,给你几个在.NET生态里可行的方案,都是亲测能用的:
1. 使用iText7(推荐,功能全面)
iText是处理PDF的老牌库,不管是加签还是验签、读取签名信息都很成熟。你需要安装几个NuGet包:
iText.Kernel(核心PDF处理)iText.Signatures(签名相关功能)BouncyCastle.Crypto(依赖的加密库,iText验签需要它)
示例代码:
using iText.Kernel.Pdf; using iText.Signatures; using Org.BouncyCastle.Security; using System; using System.Collections.Generic; public class PdfSignatureReader { public static void ReadAndValidateSignatures(string pdfPath) { // 加载PDF文档 using var pdfReader = new PdfReader(pdfPath); using var pdfDocument = new PdfDocument(pdfReader); // 获取所有签名域名称 var signatureNames = pdfDocument.GetSignatureNames(); foreach (var name in signatureNames) { Console.WriteLine($"=== 签名信息: {name} ==="); // 获取对应签名对象 var signature = pdfDocument.GetSignature(name); // 1. 验证签名完整性与真实性 var signerInfo = signature.GetSignerInfo(); var pkcs7 = new PdfPKCS7(signerInfo.GetEncoded()); bool isSignatureValid = pkcs7.VerifySignatureIntegrityAndAuthenticity(); Console.WriteLine($"签名是否有效: {isSignatureValid}"); // 2. 提取签署人姓名 var signerName = pkcs7.GetSignerName(); Console.WriteLine($"签署人姓名: {signerName}"); // 可选:获取签署时间 var signDate = pkcs7.GetSignDate().Time; Console.WriteLine($"签署时间: {signDate}"); } } }
如果是带时间戳的签名,iText也支持通过pkcs7.VerifyTimestamp()验证时间戳的有效性,按需扩展即可。
2. 使用PdfPig(轻量开源,适合简单场景)
PdfPig是另一个开源的PDF处理库,API更简洁,适合只需要读取签名基础信息的场景。安装NuGet包UglyToad.PdfPig即可。
示例代码:
using UglyToad.PdfPig; using UglyToad.PdfPig.Signatures; using System; public class PdfPigSignatureReader { public static void ExtractSignatureInfo(string pdfPath) { using var document = PdfDocument.Open(pdfPath); if (document.AcroForm?.Fields == null) { Console.WriteLine("文档无签名域"); return; } foreach (var field in document.AcroForm.Fields) { if (field is SignatureField signatureField) { Console.WriteLine($"=== 签名域: {signatureField.PartialName} ==="); var signatureDict = signatureField.SignatureDictionary; if (signatureDict == null) { Console.WriteLine("未找到签名内容"); continue; } // 提取签署人姓名(通常存储在/Name键下) if (signatureDict.TryGet(NameToken.Name, out string signerName)) { Console.WriteLine($"签署人姓名: {signerName}"); } // 如需验签,可结合BouncyCastle解析/Contents键下的签名字节 if (signatureDict.TryGet(NameToken.Contents, out byte[] signatureBytes)) { // 这里可以用BouncyCastle解析PKCS#7格式的签名数据,实现验签逻辑 } } } } }
3. 关键注意事项
- 签名有效性的意义:如果验证通过,说明文档在签署后未被篡改;如果失效,要么文档被修改,要么签署人的证书不被信任。
- 证书信任链验证:生产环境中建议添加信任根证书,验证签署人证书的合法性,iText可通过
pkcs7.VerifyCertificateChain()实现。 - 兼容多种签名类型:不管是Adobe标准的PKCS#7签名还是PAdES签名,上述库都能原生支持,无需额外适配。
内容的提问来源于stack exchange,提问作者Paulo Vaz
相关产品推荐
相关产品推荐

