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

.NET Razor Pages中iText7+Bouncy Castle数字签名报错排查

问题分析与解决方案

核心问题原因

你遇到的两个CS1503错误,本质是iText7 8.x版本使用了独立的BouncyCastle抽象接口层,直接传入原生BouncyCastle的类型(Org.BouncyCastle命名空间下的类)无法与iText的接口兼容,同时NuGet包的选型也存在偏差。

步骤1:调整NuGet包依赖

移除当前的itext7.bouncy-castle-fips-adapter和Portable.BouncyCastle,安装适配非FIPS场景的标准适配器包:

<PackageReference Include="itext7" Version="8.0.1" />
<PackageReference Include="itext7.bouncy-castle-adapter" Version="8.0.1" />
<!-- 适配器会自动依赖正确版本的BouncyCastle,无需手动安装Portable.BouncyCastle -->

步骤2:修改代码适配iText的BouncyCastle抽象层

需要通过iText.Commons.Bouncycastle.Adapter.BouncyCastleAdapter工具类,将原生BouncyCastle对象转换为iText兼容的接口类型,同时修正密钥和证书链的获取逻辑:

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using iText.Kernel.Pdf;
using iText.Signatures;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using SSG.Core.Entitites;
using SSG.Infrastructure.Data;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using iText.Kernel.Geom;
// 新增适配所需命名空间
using iText.Commons.Bouncycastle.Crypto;
using iText.Commons.Bouncycastle.Cert;
using iText.Commons.Bouncycastle.Adapter;

namespace SSG.Web.Pages.Manufacturers
{
    public class IndexModel : PageModel
    {
        public async Task OnGetAsync()
        {
            string KEYSTORE = @"C:\Users\steve\Desktop\resources\cert.pfx";
            char[] PASSWORD = "xhbssjsjshjs".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;
                }
            }

            // 将原生私钥转换为iText兼容的IPrivateKey
            AsymmetricKeyParameter privateKey = (AsymmetricKeyParameter)pk12.GetKey(alias).Key;
            IPrivateKey iTextPrivateKey = BouncyCastleAdapter.Instance.GetPrivateKey(privateKey);

            // 将原生证书链转换为iText兼容的IX509Certificate数组
            X509CertificateEntry[] ce = pk12.GetCertificateChain(alias);
            IX509Certificate[] iTextChain = new IX509Certificate[ce.Length];
            for (int k = 0; k < ce.Length; ++k)
            {
                iTextChain[k] = BouncyCastleAdapter.Instance.GetX509Certificate(ce[k].Certificate);
            }

            string DEST = @"C:\Users\steve\Desktop\resources\SignedPDF.pdf";
            string SRC = @"C:\Users\steve\Desktop\resources\SampleContract.pdf";

            PdfReader reader = new PdfReader(SRC);
            PdfSigner signer = new PdfSigner(reader, new FileStream(DEST, FileMode.Create), new StampingProperties());

            PdfSignatureAppearance appearance = signer.GetSignatureAppearance();
            appearance.SetReason("My reason to sign...")
                .SetLocation("Lahore")
                .SetPageRect(new Rectangle(36, 648, 200, 100))
                .SetPageNumber(1);
            signer.SetFieldName("MyFieldName");

            // 使用转换后的iText私钥创建签名对象
            IExternalSignature pks = new PrivateKeySignature(iTextPrivateKey, DigestAlgorithms.SHA256);
            // 传入转换后的iText证书链执行签名
            signer.SignDetached(pks, iTextChain, null, null, null, 0, PdfSigner.CryptoStandard.CMS);
        }
    }
}

关键修改点说明

  • 私钥转换:将ICipherParameters强转为AsymmetricKeyParameter(PKCS12中获取的私钥实际为此类型),再通过BouncyCastleAdapter转换为iText的IPrivateKey接口实例。
  • 证书链转换:遍历原生证书链,逐个通过BouncyCastleAdapter转换为IX509Certificate,组成iText兼容的数组。
  • 包依赖调整:使用标准的itext7.bouncy-castle-adapter而非FIPS版本,避免不必要的合规限制,同时让适配器自动管理BouncyCastle版本兼容性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 17:40:16