.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
相关产品推荐
相关产品推荐

