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

求助:在C#中利用API返回的签名与证书实现PDF数字签名

在.NET中使用API返回的签名值和证书链完成PDF数字签名

你的场景不需要依赖PFX文件,核心是把API返回的Base64签名值和证书链解析成.NET对象,再嵌入PDF中。下面是具体实现步骤(以iText 7 for .NET为例,这是处理PDF签名的主流库):

1. 解析API返回的证书链

先把证书链的Base64字符串转换成X509Certificate2集合,再构建完整的证书链:

// 假设API返回的证书链是Base64字符串列表
List<string> certChainBase64s = new List<string> { "证书1Base64", "证书2Base64" };
List<X509Certificate2> certs = new List<X509Certificate2>();

foreach (string base64 in certChainBase64s)
{
    byte[] certBytes = Convert.FromBase64String(base64);
    // 只加载公钥证书,不需要私钥
    X509Certificate2 cert = new X509Certificate2(certBytes);
    certs.Add(cert);
}

// 构建证书链用于后续验证(可选,但建议做)
X509Chain chain = new X509Chain();
foreach (var cert in certs)
{
    chain.ChainPolicy.ExtraStore.Add(cert);
}
chain.Build(certs[0]); // 验证证书链有效性

2. 解码API返回的签名值

把API返回的Base64签名字符串转成字节数组:

string apiSignatureBase64 = "ZFHl/+5jhJX .... 82Y9pA==";
byte[] signatureBytes = Convert.FromBase64String(apiSignatureBase64);

3. 生成带签名的PDF

因为签名已经由API预计算完成,我们需要实现iText的IExternalSignatureContainer接口来填充预生成的签名,同时嵌入证书链:

using iText.Kernel.Pdf;
using iText.Signatures;
using System.Security.Cryptography.X509Certificates;

// 处理PDF签名
using (PdfReader reader = new PdfReader("未签名的输入文件.pdf"))
using (FileStream outputStream = new FileStream("已签名的输出文件.pdf", FileMode.Create))
{
    PdfSigner signer = new PdfSigner(reader, outputStream, new StampingProperties());

    // 设置签名的基本属性
    signer.SetFieldName("DocumentSignature"); // 自定义签名字段名
    signer.SetSignatureCreator("你的.NET应用名称");
    signer.SetReason("通过API完成文档签名");
    signer.SetLocation("签名地点");

    // 把.NET的X509Certificate2转成iText兼容的X509Certificate
    List<X509Certificate> itextCertChain = new List<X509Certificate>();
    foreach (X509Certificate2 cert in certs)
    {
        itextCertChain.Add(new X509Certificate(cert.Export(X509ContentType.Cert)));
    }

    // 实例化自定义签名容器
    IExternalSignatureContainer signatureContainer = new PreComputedSignature(signatureBytes, itextCertChain);

    // 执行签名,8192是预留的签名占位大小,足够容纳大多数签名和证书链
    signer.SignExternalContainer(signatureContainer, 8192);
}

// 自定义预计算签名容器实现
public class PreComputedSignature : IExternalSignatureContainer
{
    private readonly byte[] _preComputedSignature;
    private readonly List<X509Certificate> _certChain;

    public PreComputedSignature(byte[] signature, List<X509Certificate> certChain)
    {
        _preComputedSignature = signature;
        _certChain = certChain;
    }

    // 直接返回预计算好的签名
    public byte[] Sign(Stream data)
    {
        return _preComputedSignature;
    }

    // 修改PDF签名字典,添加证书链和签名属性
    public void ModifySigningDictionary(PdfDictionary signDic)
    {
        signDic.Put(PdfName.Filter, PdfName.Adobe_PPKLite);
        signDic.Put(PdfName.SubFilter, PdfName.Adbe_pkcs7_detached); // 分离式签名,PDF标准格式

        // 将证书链写入签名字典
        PdfArray certArray = new PdfArray();
        foreach (var cert in _certChain)
        {
            certArray.Add(new PdfString(cert.GetEncoded()));
        }
        signDic.Put(PdfName.Cert, certArray);
    }
}

核心注意事项

  • 哈希算法一致性:必须确保API签名时使用的哈希算法(如SHA256、SHA512)和PDF签名流程中使用的完全一致,否则签名无法通过验证。
  • 证书链完整性:API返回的证书链必须包含从用户证书到根CA的所有层级,否则PDF阅读器会提示证书不可信。
  • 待签哈希匹配:传给API的待签哈希必须是iText生成的待签数据流的哈希(即Sign方法中data参数的哈希),否则签名会不匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 18:33:34