无法将私钥强制转换为RSACryptoServiceProvider

时间:2019-05-02 09:33:20

标签: c# rsa private-key

我有一个X509Certificate2变量,我正在尝试将该变量的私钥转换为RSACryptoServiceProvider

RSACryptoServiceProvider pkey = (RSACryptoServiceProvider)cert.PrivateKey;

但是我得到这个例外。

  

System.InvalidCastException:'无法将类型为'System.Security.Cryptography.RSACng'的对象转换为类型为'System.Security.Cryptography.RSACryptoServiceProvider'。'

发生这种情况很奇怪,因为SO中的其他答案建议的程序与我的相同,但我得到了例外。有什么解决办法吗?

4 个答案:

答案 0 :(得分:2)

只是要注意,还有一种扩展方法可以使用:

using System.Security.Cryptography.X509Certificates;

...

//certificate is a X509Certificate2
using (var rsa = certificate.GetRSAPrivateKey())
{
  //the var rsa is an RSA object
  //...
}

答案 1 :(得分:1)

因此,在评论中进行了几次尝试和讨论之后,我提出了以下解决方案。

            RSA rsa = (RSA)cert.PrivateKey;
        (cert.PrivateKey as RSACng).Key.SetProperty(
            new CngProperty(
                "Export Policy",
                BitConverter.GetBytes((int)CngExportPolicies.AllowPlaintextExport),
                CngPropertyOptions.Persist));

        RSAParameters RSAParameters = rsa.ExportParameters(true);                      

        AsymmetricCipherKeyPair keypair = DotNetUtilities.GetRsaKeyPair(RSAParameters);

问题是变量rsa不可导出。要更改此设置,我为导出策略设置了一个新的CngProperty。现在可以正常运行

答案 2 :(得分:0)

在我的情况下,尝试将本地商店证书转换为RSACryptoServiceProvider时发生了相同的问题,如下所示:

RSACryptoServiceProvider encryptProvider = 
                         certificate.PrivateKey as RSACryptoServiceProvider;

使用RSA而不是RSACryptoServiceProvider修复了问题。


在此处放置说明,以防有人好奇该怎么做))。

要将某些证书存储到您的计算机中,请打开 Visual Studio Developer命令并输入以下内容:

makecert -n "CN=JohnDoe" -sr currentuser -ss someCertStore

...您可以在其中指定和值,而不是“ JohnDoe”和“ demoCertStore”。

现在,您可以使用以下代码从本地证书存储区访问证书:

public class Program
{
    static void DumpBytes(string title, byte[] bytes)
    {
        Console.Write(title);
        foreach (byte b in bytes)
        {
            Console.Write("{0:X} ", b);
        }

        Console.WriteLine();
    }

    static void Main(string[] args)
    {
        // This will convert our input string into bytes and back
        var converter = new ASCIIEncoding();

        // Get a crypto provider out of the certificate store
        // should be wrapped in using for production code
        var store = new X509Store("someCertStore", StoreLocation.CurrentUser);

        store.Open(OpenFlags.ReadOnly);

        // should be wrapped in using for production code
        X509Certificate2 certificate = store.Certificates[0];

        RSA rsa = (RSA)certificate.PrivateKey;
        (certificate.PrivateKey as RSACng)?.Key.SetProperty(
                                                new CngProperty(
                                                    "Export Policy",
                                                    BitConverter.GetBytes((int)CngExportPolicies.AllowPlaintextExport),
                                                    CngPropertyOptions.Persist));

        string messageToSign = "This is the message I want to sign";
        Console.WriteLine("Message: {0}", messageToSign);
        byte[] messageToSignBytes = converter.GetBytes(messageToSign);

        // need to calculate a hash for this message - this will go into the
        // signature and be used to verify the message
        // Create an implementation of the hashing algorithm we are going to us
        // should be wrapped in using for production code
        DumpBytes("Message to sign in bytes: ", messageToSignBytes);
        HashAlgorithm hasher = new SHA1Managed();

        // Use the hasher to hash the message
        byte[] hash = hasher.ComputeHash(messageToSignBytes);
        DumpBytes("Hash for message: ", hash);

        // Now sign the hash to create a signature
        byte[] signature = rsa.SignHash(hash, HashAlgorithmName.SHA1, RSASignaturePadding.Pss);
        DumpBytes("Signature: ", messageToSignBytes);

        // Now use the signature to perform a successful validation of the mess
        bool validSignature = rsa.VerifyHash(hash: hash,
                                             signature: signature,
                                             hashAlgorithm: HashAlgorithmName.SHA1,
                                             padding: RSASignaturePadding.Pss);
        Console.WriteLine("Correct signature validated OK: {0}", validSignature);

        // Change one byte of the signature
        signature[0] = 99;

        // Now try the using the incorrect signature to validate the message
        bool invalidSignature = rsa.VerifyHash(hash: hash,
                                               signature: signature,
                                               hashAlgorithm: HashAlgorithmName.SHA1,
                                               padding: RSASignaturePadding.Pss);

        Console.WriteLine("Incorrect signature validated OK: {0}", invalidSignature);
        Console.ReadKey();
}

答案 3 :(得分:0)

通过仅使用正确的导出策略创建证书,就可以完全避免设置导出策略的代码。我使用New-SelfSignedCertificate PowerShell实用程序创建了一个可从创建之初导出的证书。
PS C:> New-SelfSignedCertificate -CertStoreLocation“ Cert:\ CurrentUser \”-主题“ CN = JUSTIN” -KeyExportPolicy可导出

这不需要:

(certificate.PrivateKey as RSACng)?.Key.SetProperty(new CngProperty("Export Policy", BitConverter.GetBytes((int)CngExportPolicies.AllowPlaintextExport),CngPropertyOptions.Persist));