访问智能卡证书时出现CryptographicException

问题描述 投票:1回答:1

我正在为我工​​作的公司开发一个名为SmartCardService的C#类。桌面应用程序使用虚拟和物理智能卡与我们公司开发的嵌入式PLC通信。为此目的,证书是由我们的IT专门为每个用户颁发的。

SmartCardService提供用于加密,解密和签名数据以及验证签名的基本功能。

public sealed class SmartCardService : ISmartCardService
{
    private RSACryptoServiceProvider CryptoServiceProvider { get; }

    public SmartCardService(X509Certificate2 certificate)
    {
        if(certificate == null) throw new ArgumentNullException("missing certificate");
        CryptoServiceProvider = (RSACryptoServiceProvider)Certificate.PrivateKey;
    }

    public byte[] EncryptData(byte[] data)
    {
        if (data == null) throw new ArgumentNullException("data");
        return CryptoServiceProvider.Encrypt(data, false);
    }

    public byte[] DecryptData(byte[] cipher)
    {
        if (cipher == null) throw new ArgumentNullException("cipher");
        return CryptoServiceProvider.Decrypt(cipher, false);
    }

    public byte[] SignData(byte[] data)
    {
        if (data == null) throw new ArgumentNullException("data");

        using (var sha256 = SHA256.Create())
        {
            return CryptoServiceProvider.SignData(data, sha256);
        }
    }

    public bool VerifySignature(byte[] data, byte[] signature)
    {
        if (data == null) throw new ArgumentNullException("data");
        if (signature == null) throw new ArgumentNullException("signature");

        using (var sha256 = SHA256.Create())
        {
            return CryptoServiceProvider.VerifyData(data, sha256, signature);
        }
    }
}

证书本身是由应用程序组合根目录中的另一个组件CertificateProvider提供的(此组件以后还会处理证书对象)。它只是选择我们公司为用户颁发的第一份证书。

public sealed class CertificateProvider
{
    public X509Certificate2 GetCertificateFromStore(string subjectName)
    {
        using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser))
        {
            store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
            return store.Certificates
                    .Find(X509FindType.FindByIssuerName, "<COMPANY NAME>", true)
                    .Find(X509FindType.FindBySubjectName, subjectName, true)
                    .Cast<X509Certificate2>()
                    .First();

        }
    }
}

在以下示例中发生了问题:

// example data encryption and decryption
var service = new SmartCardService(certificate);
var data = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
var encryptedData = service.EncryptData(data);              // prints a 256 byte long array of hex values
var decryptedData = service.DecryptData(encryptedData);     // prints the original data: 00-01-02-03-04-05-06-07

在Windows 10上,一切正常。结果符合预期。

但是,在Windows 7上,一旦在CryptographicException类的构造函数中单击此行,则相同的代码将导致SmartCardService:>

CryptoServiceProvider = (RSACryptoServiceProvider)Certificate.PrivateKey;

该异常具有以下堆栈跟踪:

Unhandled Exception System.Security.Cryptography.CryptographicException: System cannot find the specified file.

   at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
   at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
   at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()
   at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)
   at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()

我仍然没有找到此问题的原因。如果有人可以帮助我解决这个问题,我将非常感谢。

PS:我发现一个旧的article,但有相同的例外,说明在用户配置文件中存储密钥存在问题。我不确定这是否与我面临的问题有关。

我正在为所工作的公司开发一个名为SmartCardService的C#类。桌面应用程序使用虚拟和物理智能卡与我们公司开发的嵌入式PLC通信。 ...

c# cryptography x509certificate smartcard
1个回答
0
投票

我遵循bartonjs的建议,并使用GetRSAPrivateKey() RSACertificateExtensions方法。这样就解决了问题。

© www.soinside.com 2019 - 2024. All rights reserved.