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?
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();
}
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));