【问题标题】:Using certificate from store for RSACryptoServiceProvider为 RSACryptoServiceProvider 使用来自商店的证书
【发布时间】:2017-03-21 03:19:10
【问题描述】:

我对来自商店的证书有疑问。在我的应用程序中,用户可以使用文件中的证书或商店中的证书。加载证书后,我将证书用于签名数据。

使用文件中的证书可以,但我不能使用商店中的等效证书。

符号代码:

// Sign data
using (RSACryptoServiceProvider csp = new RSACryptoServiceProvider())
{
    byte[] dataToSign = Encoding.UTF8.GetBytes(plainText);
    csp.ImportParameters(((RSACryptoServiceProvider)_certPopl.PrivateKey).ExportParameters(true));
    byte[] signature = csp.SignData(dataToSign, "SHA256");
    // Verify signature
    if (!csp.VerifyData(dataToSign, "SHA256", signature))
        throw new Exception("Nepodařilo se vytvořit platný podpisový kód poplatníka.");
    PKP = Convert.ToBase64String(signature);
}

从文件中读取证书的代码:

X509Certificate2Collection certStore = new X509Certificate2Collection();
certStore.Import(fileName, password, X509KeyStorageFlags.Exportable);
foreach (X509Certificate2 cert in certStore)
{
    // Find the first certificate with a private key
    if (cert.HasPrivateKey)
    {
        _certPopl = cert;
        break;
    }
}

从商店读取证书的代码。从商店加载证书后,我无法签署数据:

public void LoadCertificate(string certificateName, DateTime notAfter, string password)
{
    var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    store.Open(OpenFlags.MaxAllowed);
    foreach (var certificate in store.Certificates)
    {
        if (certificate.FriendlyName.Equals(certificateName) && certificate.NotAfter.Equals(notAfter))
        {
            //X509Certificate2Collection certStore = new X509Certificate2Collection();
            //certStore.Import(certificate.Export(X509ContentType.SerializedCert), password, X509KeyStorageFlags.Exportable);
            //_certPopl = certStore[0];

            X509Certificate2Collection certStore = new X509Certificate2Collection();
            certStore.Import(certificate.GetRawCertData());
            foreach (X509Certificate2 cert in certStore)
            {
                // Find the first certificate with a private key
                if (cert.HasPrivateKey)
                {
                    _certPopl = cert;
                    break;
                }
            }

            break;
        }
    }
}

我没有使用证书的经验。但我需要相当于从商店获取证书进行签名。

在 ExportParameters(true) 上引发 System.Security.Cryptography.CryptographicException。 异常的附加信息:密钥在指定状态下无效。

谢谢。

【问题讨论】:

  • I am unable to sign data -- 这对我们没有任何帮助。引发错误的错误消息和代码段会很有帮助。
  • 添加了有关异常的信息:在 ExportParameters(true) 上引发 System.Security.Cryptography.CryptographicException。异常的附加信息:密钥在指定状态下无效。

标签: c# .net certificate x509certificate certificate-store


【解决方案1】:

我不清楚您为什么要尝试导出 CSP 参数。 CSP 参数导出取决于密钥导出选项,如果密钥不可导出,则会失败。相反,您应该直接在X509Certificate2 对象的PrivateKey 属性上使用RSACryptoServiceProvider

// assuming, you have X509Certificate2 object with existing private key in _certPol variable
// retrieve private key
var key = _certPol.PrivateKey as RSACryptoServiceProvider;
// check if it is legacy RSA, otherwise return.
if (key == null) { return; }
byte[] dataToSign = Encoding.UTF8.GetBytes(plainText);
// sign data
byte[] signature = key.SignData(dataToSign, "SHA256");
// Verify signature
if (!key.VerifyData(dataToSign, "SHA256", signature))
    throw new Exception("Nepodařilo se vytvořit platný podpisový kód poplatníka.");
...

【讨论】:

  • 我得到 System.Security.Cryptography.CryptographicException 附加信息:指定的算法无效。 on byte[] signature = key.SignData(dataToSign, "SHA256");
  • 用于存储密钥的 CSP 似乎不支持 SHA2 算法。
  • 好的,但是我能用它做什么呢?是同一个证书。
【解决方案2】:

工作状态为:

从商店加载证书:

var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
{
    store.Open(OpenFlags.ReadOnly);
    foreach (var certificate in store.Certificates)
    {
        if (certificate.FriendlyName.Equals(certificateName) && certificate.NotAfter.Equals(notAfter))
        {
            _certPopl = certificate;
            break;
        }
    }
}
finally
{
    store.Close();
}

签署和验证数据:

byte[] dataToSign = Encoding.UTF8.GetBytes(plainText);
var privKey = (RSACryptoServiceProvider)_certPopl.PrivateKey;
// Force use of the Enhanced RSA and AES Cryptographic Provider with openssl-generated SHA256 keys
var enhCsp = new RSACryptoServiceProvider().CspKeyContainerInfo;
var cspparams = new CspParameters(enhCsp.ProviderType, enhCsp.ProviderName, privKey.CspKeyContainerInfo.KeyContainerName);
privKey = new RSACryptoServiceProvider(cspparams);
byte[] signature = privKey.SignData(dataToSign, "SHA256");
// Verify signature
if (!privKey.VerifyData(dataToSign, "SHA256", signature))
    throw new Exception("Nepodařilo se vytvořit platný podpisový kód poplatníka.");

【讨论】:

    【解决方案3】:

    如果您可以使用 .NET 4.6,这会简单得多,访问私钥的新方法对于 SHA-2 签名更可靠:

    using (RSA rsa = cert.GetRSAPrivateKey())
    {
        if (rsa == null)
        {
            throw new Exception("Wasn't an RSA key, or no private key was present");
        }
    
        bool isValid = rsa.VerifyData(
            Encoding.UTF8.GetBytes(plainText),
            signature,
            HashAlgorithmName.SHA256,
            RSASignaturePadding.Pkcs1);
    
        if (!isValid)
        {
            throw new Exception("VerifyData failed");
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-15
      • 2010-12-10
      • 2012-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-19
      相关资源
      最近更新 更多