web-dev-qa-db-fra.com

Casting de la clé privée à RsacryptoServiceProvider ne fonctionne pas

J'ai une variable X509Certificate2 et j'essaie de jeter la clé privée de la variable à un rsacryptoserviceProvider

RSACryptoServiceProvider pkey = (RSACryptoServiceProvider)cert.PrivateKey;

Cependant, je reçois cette exception.

System.InvalidcastException: 'Impossible de lancer Objet de type' System.Security.Cryptography.rsacng 'Pour taper' System.Security.Cryptography.rsacryptoServiceProvider '.'

C'est bizarre que cela se produit parce que d'autres réponses dans SO ont suggéré la même procédure que la mienne, mais je reçois une exception. Des solutions à cela?

6
Vins

Dans mon cas, le même problème se passe lors de la tentative de convertir Certificat de magasin local à RSACryptoServiceProvider comme ci-dessous:

RSACryptoServiceProvider encryptProvider = 
                         certificate.PrivateKey as RSACryptoServiceProvider;

Problème corrigé en utilisant RSA au lieu de RSACryptoServiceProvider.


Mettre les instructions ici au cas où quelqu'un sera curieux de faire cela)).

Pour stocker un certain certificat dans votre machine ouverte Commande Visual Studio Developer et tapez après:

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

... où vous pouvez spécifier et valoriser vos valeurs au lieu de "Johndoe" et "DemoCertStore".

Vous pouvez maintenant utiliser le code ci-dessous pour accéder à des certificats à partir du Certificat local Store:

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();
}
1
Arsen Khachaturyan

Vous pouvez éviter le code qui définit la stratégie d'exportation en créant simplement le certificat avec la stratégie d'exportation étant déjà correcte. J'ai utilisé l'utilitaire New-SelfSignedCertificate PowerShell pour créer un certificat exportable de la création.
(

Cela annule la nécessité de:

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