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

如何在单页PDF中添加多个电子签名?(iText7 .NET报错解决)

问题原因

调用SignDetached完成签名后,PdfSigner会自动关闭文档相关的流对象,同一个PdfSigner实例仅能完成一次签名操作。你的代码尝试复用同一个PdfSigner执行多次签名,第二次调用时文档已被关闭,因此抛出Document was closed异常。

解决方案

每次签名都需要基于上一次签名后的PDF文件,重新创建PdfReader和PdfSigner实例,并启用追加模式。具体修改如下:

修改后的完整代码

public void sign() 
{
    string KEYSTORE = @"D:\resources\cert.pfx";
    char[] PASSWORD = "password".ToCharArray();

    Pkcs12Store pk12 = new Pkcs12Store(new FileStream(KEYSTORE, FileMode.Open, FileAccess.Read), PASSWORD);
    string alias = null;
    foreach (object a in pk12.Aliases)
    {
        alias = ((string)a);
        if (pk12.IsKeyEntry(alias))
        {
            break;
        }
    }

    ICipherParameters pk = pk12.GetKey(alias).Key;
    X509CertificateEntry[] ce = pk12.GetCertificateChain(alias);
    IX509Certificate[] chain = new IX509Certificate[ce.Length];
    for (int k = 0; k < ce.Length; ++k)
    {
        chain[k] = new X509CertificateBC(ce[k].Certificate);
    }

    string SRC = "D:\\resources\\PR.pdf";
    // 临时文件存储中间签名结果
    string temp1 = "D:\\resources\\PR_signed_temp1.pdf";
    string DEST = "D:\\resources\\PR_signed.pdf";

    Rectangle requesterPosition = new Rectangle(10, 140, 130, 180);
    Rectangle headOfPosition = new Rectangle(160, 140, 300, 180);
    Rectangle thirdSignPosition = new Rectangle(480, 140, 130, 180); // 第三个签名位置

    // 第一次签名:原文件→临时文件
    SignSingleDocument(SRC, temp1, chain, pk, requesterPosition);
    // 第二次签名:临时文件→最终文件
    SignSingleDocument(temp1, DEST, chain, pk, headOfPosition);
    // 第三次签名:基于最终文件继续追加(如果需要)
    // SignSingleDocument(DEST, DEST, chain, pk, thirdSignPosition);

    // 清理临时文件(可选)
    File.Delete(temp1);
}

public void SignSingleDocument(string srcPath, string destPath, IX509Certificate[] chain, ICipherParameters pk, Rectangle rect) 
{
    using (PdfReader reader = new PdfReader(srcPath))
    {
        using (FileStream fs = new FileStream(destPath, FileMode.Create))
        {
            PdfSigner signer = new PdfSigner(reader, fs, new StampingProperties().PreserveEncryption().UseAppendMode());
            
            signer.SetFieldName(signer.GetNewSigFieldName());
            // 仅第一次签名需要设置认证级别,后续签名无需重复设置(设置也不会改变原有级别)
            signer.SetCertificationLevel(PdfSigner.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS);
            
            PdfSignatureAppearance appearance = signer.GetSignatureAppearance();
            appearance.SetReason("test signature")
                .SetLocation("VN")
                .SetPageRect(rect)
                .SetPageNumber(1);
            
            IExternalSignature pks = new PrivateKeySignature(new PrivateKeyBC(pk), DigestAlgorithms.SHA256);
            signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CMS);
        }
    }
}

关键说明

  • 每次签名创建独立的PdfReader和PdfSigner实例,确保文档流未被关闭,可正常执行签名操作。
  • 使用临时文件存储中间结果,避免签名失败导致最终文件损坏,完成所有签名后可删除临时文件。
  • 认证级别CERTIFIED_FORM_FILLING_AND_ANNOTATIONS允许后续添加签名,符合多签名场景需求;若设置为CERTIFIED_NO_CHANGES_ALLOWED,后续将无法添加任何签名,需注意区分。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 17:22:47