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

如何在C#中使用SafeNet Token的私钥签名PDF哈希数据

根因分析

  • 你当前代码的核心错误是尝试修改RSACng的导出策略并调用ExportParameters(true)导出私钥明文,SafeNet这类智能卡的私钥是硬件级不可导出的,修改导出策略的操作对硬件保护的密钥完全无效,直接触发权限异常,这就是你看到“Key not valid for use in specified state”报错的直接原因。
  • XML签名能正常工作的原因是SignedXml直接使用原始的RSACng密钥实例调用系统CNG接口完成签名,全程不触碰私钥导出逻辑,签名运算直接在智能卡硬件内部执行,会正常触发密码输入弹窗。

修复方案

你完全不需要把私钥导出给BouncyCastle做签名,直接用系统原生的RSACng实例完成签名运算即可,修改后的签名逻辑如下:

public static byte[] Sign(X509Certificate2Collection selectedCert, byte[] hashByteArray)
{
    X509Certificate2 cert = selectedCert[0];
    // 转换证书链给PdfPKCS7用,这部分不需要修改
    var bouncyCertChains = ConvertX509Cert2ListToBouncyCastleX509CertList(selectedCert);
    // 直接获取原生RSACng实例,不要做任何私钥导出操作
    var rsaCng = cert.GetRSAPrivateKey() as RSACng;
    // 初始化PdfPKCS7,计算待签名的认证属性字节
    PdfPKCS7 pdfpkcs7 = new PdfPKCS7(null, bouncyCertChains.ToArray(), DigestAlgorithms.SHA256, false);
    byte[] authenticatedAttrBytes = pdfpkcs7.GetAuthenticatedAttributeBytes(hashByteArray, PdfSigner.CryptoStandard.CMS, null, null);
    
    // 直接用原生RSACng做签名,运算在智能卡硬件内执行,会自动触发密码输入弹窗
    byte[] signature = rsaCng.SignData(authenticatedAttrBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
    
    // 剩余PKCS7封装逻辑保持不变
    pdfpkcs7.SetExternalDigest(signature, null, "RSA");
    return pdfpkcs7.GetEncodedPKCS7(hashByteArray, null, null, null, PdfSigner.CryptoStandard.CMS);
}

额外注意事项

  • 加载证书时请确保X509KeyStorageFlags参数配置正确,建议加上X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.PersistKeySet,确保程序能正确关联到智能卡的密钥容器。
  • 不要对智能卡的密钥调用任何修改属性、导出私钥的操作,所有签名运算都直接调用原生RSA实例的签名接口即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 07:24:01