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

使用iText7批量签署PDF,避免多次输入智能卡PIN码

实现iText7单次输入PIN签署多个PDF文件

你当前的代码虽然手动配置了CSP参数,但因密钥上下文未被正确持久化,导致每次签名仍需重新验证PIN。核心解决思路是复用已通过PIN认证的证书私钥上下文,避免重复触发PIN验证。

修改后的代码

using namespace Org.BouncyCastle.Crypto
using namespace Org.BouncyCastle.Pkcs
using namespace Org.BouncyCastle.X509
using namespace System.Security.Cryptography.X509Certificates
using namespace System.Security.Cryptography
using namespace Org.BouncyCastle.Asn1
using namespace Org.BouncyCastle.Math
using namespace System.Security.Cryptography.X509Certificates.RSACertificateExtensions
using namespace System.Security.Cryptography.X509Certificates.DSACertificateExtensions
using namespace System.Security.Cryptography.X509Certificates.ECDsaCertificateExtensions
using namespace iText.Signatures
using namespace iText.Signatures.IExternalSignature
using namespace iText.Signatures.PdfSigner
using namespace iText.Signatures.PdfSigner.CryptoStandard
using namespace iText.Kernel.Pdf

Import-Module "C:\Users\Dactal Sharp\Desktop\itext7module.1.0.34\IText7Module.psd1"

# 获取文档签名证书
$certTemplate = Get-ChildItem Cert:\CurrentUser\My | Where-Object{$_.Extensions.EnhancedKeyUsages.FriendlyName -contains "Document Signing"} | Select-Object -First 1

# 输入PIN并创建带持久化私钥的证书实例
$pin = Read-Host -Prompt "Please Enter Smart Card PIN" -AsSecureString
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2(
    $certTemplate.RawData, 
    $pin, 
    [X509KeyStorageFlags]::PersistKeySet -bor [X509KeyStorageFlags]::Exportable
)

# 转换为BouncyCastle格式证书链
$bccert = [Org.BouncyCastle.Security.DotNetUtilities]::FromX509Certificate($cert)
[Org.BouncyCastle.X509.X509Certificate[]]$chain = $bccert

# 创建复用私钥的签名实例
[IExternalSignature]$signature = [X509Certificate2Signature]::new($cert, [DigestAlgorithms]::SHA256)

$stampingProperties = [StampingProperties]::new()
$i = 0

foreach($file in Get-ChildItem "C:\Users\Dactal Sharp\Downloads\input test" | Where-Object{$_.BaseName -match "testunsig*"}){
    $pdfReader = [PdfReader]::new($file.FullName)
    $outputPath = "C:\Users\Dactal Sharp\Downloads\test\test$i.pdf"
    $stream = [System.IO.FileStream]::new($outputPath, [System.IO.FileMode]::Create)
    $i++

    $pdfSigner = [PdfSigner]::new($pdfReader, $stream, $stampingProperties.UseAppendMode())
    [PdfSignatureAppearance]$appearance = $pdfSigner.GetSignatureAppearance()

    $appearance.SetRenderingMode([PdfSignatureAppearance+RenderingMode]::NAME_AND_DESCRIPTION)
    $appearance.SetCertificate($bccert)
    $appearance.setReasonCaption($null)
    $appearance.SetLocationCaption($null)
    $appearance.setReuseAppearance($true)

    $pdfSigner.SetFieldName("Signature2")
    $pdfSigner.SignDetached($signature, $chain, $null, $null, $null, 0, [iText.Signatures.PdfSigner+CryptoStandard]::CMS)

    # 清理资源
    $stream.Close()
    $pdfReader.Close()
}

关键改动说明

  1. 证书实例初始化:通过X509Certificate2构造函数直接传入PIN,同时指定PersistKeySet标记,确保智能卡的密钥上下文被持久化到CSP中,后续签名无需重复验证PIN。
  2. 签名实例复用:使用X509Certificate2Signature替代手动创建的AsymmetricAlgorithmSignature,该类会直接复用已加载的私钥上下文,避免每次签名重新初始化密钥对象。
  3. 资源清理:在循环中显式关闭文件流和PDF阅读器,避免资源泄漏。

补充提示

如果仍出现PIN弹窗,需检查智能卡驱动是否支持密钥上下文持久化,部分旧版本驱动可能强制每次操作验证PIN,此时需更新驱动或联系厂商确认配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 05:07:50