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

升级SafeNet驱动后C#调用ComputeSignature()报错,需替换为eTpkcs11.dll

问题描述

我开发的应用原本支持通过内置证书的USB令牌签署XML文件,近期将SafeNet Authentication Client驱动从9版本升级至10版本后,程序调用ComputeSignature()函数时出现异常:

'System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll,The system cannot find the file specified.

厂商提示需替换原生mscorlib.dll为指定的eTpkcs11.dll,但尝试导入该DLL时遇到编译错误:"the feature of local function attributes is not available in C#7.3",不知道该怎么着手替换。相关代码如下:

public void InsertSignature(...)
{
    //Opens the local user certificates store
    X509Store store = new X509Store(StoreLocation.CurrentUser);
    store.Open(OpenFlags.ReadOnly);

    X509Certificate2Collection certs = store.Certificates;

    XmlDocument documento = new XmlDocument();
    documento.PreserveWhitespace = true;            

    try
    {
        documento.Load(pathDocument);                
       
        SignedXml firmado = new SignedXml(documento);

        X509Certificate2 certificado = null;

        foreach (X509Certificate2 cert in certs)
        {                    
            if (cert.Thumbprint == huella)
            {
                certificado = new X509Certificate2(cert.GetRawCertData(), "");
                certificado.PrivateKey = cert.PrivateKey;                        
                break;                        
            }
        }

        if (certificado == null)
        {
            MessageBox.Show("Check the token/certificate", "Certificate not found", MessageBoxButtons.OK);
            return;
        }

        store.Close();

        firmado.SigningKey = certificado.PrivateKey;
        firmado.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA1Url;

        #region looking for the reference (the structure of the file to sign may vary)
        #endregion

        //Add the reference to the SignedXml object.
        firmado.AddReference(referencia);
        KeyInfo keyInfo = new KeyInfo();
        keyInfo.AddClause(new RSAKeyValue((RSA)certificado.PrivateKey));
        keyInfo.AddClause(new KeyInfoX509Data(certificado));
        firmado.KeyInfo = keyInfo;
        
        //HERE HAPPENS THE ERROR/EXCEPTION 
        firmado.ComputeSignature();

        XmlElement xmlDigitalSignature = null;
        xmlDigitalSignature = firmado.GetXml();

        #region looking the place to set the sign
        #endregion

        //Insert the signature
        XmlNode parent = elemento.ParentNode;
        parent.InsertAfter(xmlDigitalSignature, elemento);


        #region location routes
        #endregion

        //File is saved
        XmlWriter writer = XmlWriter.Create(ruta_completa, _xmlWriterSettings);
        documento.Save(writer);
        writer.Close();                

    }
    catch (Exception ex)
    {
        MessageBox.Show("Excepción producida en: " + ex.Source.ToString() + ". " + (ex.ToString()).Substring(0,107) , "Error en Try/Catch");
    }
    
}
解决方案

一、解决DLL导入的编译错误

编译提示的局部函数属性问题,是因为eTpkcs11.dll的导入代码可能使用了C# 8.0及以上才支持的特性(比如局部函数上的[UnmanagedCallersOnly]属性),而你的项目当前使用的是C# 7.3。解决步骤:

  • 右键项目 → 属性 → 生成 → 高级 → 语言版本,选择C# 8.0或更高版本(建议选最新稳定版)。
  • 确认项目的.NET框架版本适配所选C#版本:.NET Framework 4.7.2及以上支持C# 8.0,若框架版本过低需先升级。

二、正确适配SafeNet 10的PKCS#11接口

厂商所说的“替换mscorlib.dll”表述不准确,实际是要通过PKCS#11标准接口直接调用eTpkcs11.dll,而非依赖系统默认的证书存储和PrivateKey对象。原代码依赖X509Certificate2.PrivateKey在驱动升级后无法定位令牌私钥,需重构签名逻辑:

1. 导入PKCS#11核心函数

可以通过P/Invoke手动声明eTpkcs11.dll的关键函数,示例:

[DllImport("eTpkcs11.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern int C_Initialize(IntPtr pInitArgs);

[DllImport("eTpkcs11.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern int C_GetSlotList(bool tokenPresent, IntPtr pSlotList, ref uint pulCount);

// 按需添加其他必要函数:C_OpenSession、C_Login、C_SignInit、C_Sign等

也可以使用现成的PKCS#11封装库(如Pkcs11Interop),避免手动声明大量函数。

2. 替换签名逻辑

不再通过X509Store获取私钥,改为直接通过PKCS#11接口从令牌中获取签名密钥:

  • 初始化PKCS#11库,获取令牌所在的slot
  • 打开会话并登录令牌(如需PIN验证)
  • 查找对应的签名密钥对象
  • 调用C_Sign完成签名,将结果注入SignedXml对象

3. 自定义SignedXml签名方式

原代码的ComputeSignature()会调用系统默认实现,需改为自定义逻辑:

  • 继承SignedXml类,重写Sign方法,在方法内调用PKCS#11签名接口
  • 或手动计算待签名数据的哈希,用PKCS#11签名后,将结果赋值给SignedXml的SignatureValue属性

三、验证驱动配置

  • 确保SafeNet Authentication Client 10安装正确,eTpkcs11.dll路径已加入系统环境变量,或复制到程序运行目录
  • 打开SafeNet管理工具,确认令牌及证书状态正常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 11:50:00