92 votes

Comment lire un PEM clé privée RSA de .NET

J'ai une clé privée RSA au format PEM, est-il un moyen simple de lire ça .NET et instancier une RSACryptoServiceProvider pour déchiffrer les données chiffrées avec la clé publique correspondante?

87voto

Simone Points 662

J'ai résolu, merci. Dans le cas où ça intéresse quelqu'un, bouncycastle a fait le tour, tout m'a fallu un certain temps en raison du manque de connaissances à partir de mon côté et de la documentation. C'est le code:

var bytesToDecrypt = Convert.FromBase64String("la0Cz.....D43g=="); // string to decrypt, base64 encoded

AsymmetricCipherKeyPair keyPair; 

using (var reader = File.OpenText(@"c:\myprivatekey.pem")) // file containing RSA PKCS1 private key
    keyPair = (AsymmetricCipherKeyPair) new PemReader(reader).ReadObject(); 

var decryptEngine = new Pkcs1Encoding(new RsaEngine());
decryptEngine.Init(false, keyPair.Private); 

var decrypted = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(bytesToDecrypt, 0, bytesToDecrypt.Length));

35voto

SeventhPath Points 86

À l'égard de l'importation de la clé privée RSA, sans l'aide de la 3e partie du code tel que BouncyCastle, je pense que la réponse est "non, pas avec un PEM de la clé privée seul."

Cependant, comme mentionné ci-dessus, par Simone, vous pouvez simplement combiner le PEM de la clé privée (*.la clé) et le fichier de certificat à l'aide de cette touche (*.crt) dans un *.fichier pfx qui peut ensuite être facilement importées.

Pour générer le fichier PFX à partir de la ligne de commande:

openssl pkcs12 -in a.crt -inkey a.key -export -out a.pfx

Ensuite, utilisez normalement avec le .NET certificat de classe tels que:

using System.Security.Cryptography.X509Certificates;

X509Certificate2 combinedCertificate = new X509Certificate2(@"C:\path\to\file.pfx");

Maintenant, vous pouvez suivre l'exemple de MSDN pour le cryptage et le décryptage via RSACryptoServiceProvider: http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.aspx

EDIT: j'ai quitté que pour le déchiffrement vous auriez besoin de les importer à l'aide de la PFX mot de passe et Exportable drapeau. (voir: BouncyCastle RSAPrivateKey pour .NET RSAPrivateKey)

X509KeyStorageFlags flags = X509KeyStorageFlags.Exportable;
X509Certificate2 cert = new X509Certificate2("my.pfx", "somepass", flags);

RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert.PrivateKey;
RSAParameters rsaParam = rsa.ExportParameters(true); 

32voto

wprl Points 6139

Vous pouvez prendre un coup d'oeil à JavaScience de la source pour OpenSSLKey. (OpenSSLKey.cs)

Il y a du code qui fait exactement ce que vous voulez faire.

En fait, ils ont beaucoup de crypto code source disponible ici.


Source de l'extrait de code:

//------- Parses binary ans.1 RSA private key; returns RSACryptoServiceProvider  ---
public static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
{
        byte[] MODULUS, E, D, P, Q, DP, DQ, IQ ;

        // ---------  Set up stream to decode the asn.1 encoded RSA private key  ------
        MemoryStream  mem = new MemoryStream(privkey) ;
        BinaryReader binr = new BinaryReader(mem) ;    //wrap Memory Stream with BinaryReader for easy reading
        byte bt = 0;
        ushort twobytes = 0;
        int elems = 0;
        try {
                twobytes = binr.ReadUInt16();
                if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
                        binr.ReadByte();        //advance 1 byte
                else if (twobytes == 0x8230)
                        binr.ReadInt16();       //advance 2 bytes
                else
                        return null;

                twobytes = binr.ReadUInt16();
                if (twobytes != 0x0102) //version number
                        return null;
                bt = binr.ReadByte();
                if (bt !=0x00)
                        return null;


                //------  all private key components are Integer sequences ----
                elems = GetIntegerSize(binr);
                MODULUS = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                E = binr.ReadBytes(elems) ;

                elems = GetIntegerSize(binr);
                D = binr.ReadBytes(elems) ;

                elems = GetIntegerSize(binr);
                P = binr.ReadBytes(elems) ;

                elems = GetIntegerSize(binr);
                Q = binr.ReadBytes(elems) ;

                elems = GetIntegerSize(binr);
                DP = binr.ReadBytes(elems) ;

                elems = GetIntegerSize(binr);
                DQ = binr.ReadBytes(elems) ;

                elems = GetIntegerSize(binr);
                IQ = binr.ReadBytes(elems) ;

                Console.WriteLine("showing components ..");
                if (verbose) {
                        showBytes("\nModulus", MODULUS) ;
                        showBytes("\nExponent", E);
                        showBytes("\nD", D);
                        showBytes("\nP", P);
                        showBytes("\nQ", Q);
                        showBytes("\nDP", DP);
                        showBytes("\nDQ", DQ);
                        showBytes("\nIQ", IQ);
                }

                // ------- create RSACryptoServiceProvider instance and initialize with public key -----
                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
                RSAParameters RSAparams = new RSAParameters();
                RSAparams.Modulus =MODULUS;
                RSAparams.Exponent = E;
                RSAparams.D = D;
                RSAparams.P = P;
                RSAparams.Q = Q;
                RSAparams.DP = DP;
                RSAparams.DQ = DQ;
                RSAparams.InverseQ = IQ;
                RSA.ImportParameters(RSAparams);
                return RSA;
        }
        catch (Exception) {
                return null;
        }
        finally {
                binr.Close();
        }
}

4voto

Rasmus Faber Points 24195

Le truc entre les

-----BEGIN RSA PRIVATE KEY---- 

et

-----END RSA PRIVATE KEY----- 

est l'encodage base64 d'un fichier PKCS#8 PrivateKeyInfo (à moins qu'elle indique RSA CHIFFRÉE de la CLÉ PRIVÉE dans ce cas c'est une EncryptedPrivateKeyInfo).

Il n'est pas difficile à décoder manuellement, mais sinon, votre meilleur pari est de P/Invoke pour CryptImportPKCS8.


Mise à jour: Le CryptImportPKCS8 fonction n'est plus disponible pour l'utilisation de Windows Server 2008 et Windows Vista. Au lieu de cela, utilisez la PFXImportCertStore fonction.

1voto

João Augusto Points 1614

Vérifier http://msdn.microsoft.com/en-us/library/dd203099.aspx

en vertu de la Cryptographie Bloc d'Application.

Ne sais pas si vous aurez votre réponse, mais il vaut la peine d'essayer.

Edit après le Commentaire.

Ok puis vérifier ce code.

using System.Security.Cryptography;


public static string DecryptEncryptedData(stringBase64EncryptedData, stringPathToPrivateKeyFile) { 
    X509Certificate2 myCertificate; 
    try{ 
        myCertificate = new X509Certificate2(PathToPrivateKeyFile); 
    } catch{ 
        throw new CryptographicException("Unable to open key file."); 
    } 

    RSACryptoServiceProvider rsaObj; 
    if(myCertificate.HasPrivateKey) { 
         rsaObj = (RSACryptoServiceProvider)myCertificate.PrivateKey; 
    } else 
        throw new CryptographicException("Private key not contained within certificate."); 

    if(rsaObj == null) 
        return String.Empty; 

    byte[] decryptedBytes; 
    try{ 
        decryptedBytes = rsaObj.Decrypt(Convert.FromBase64String(Base64EncryptedData), false); 
    } catch { 
        throw new CryptographicException("Unable to decrypt data."); 
    } 

    //    Check to make sure we decrpyted the string 
   if(decryptedBytes.Length == 0) 
        return String.Empty; 
    else 
        return System.Text.Encoding.UTF8.GetString(decryptedBytes); 
} 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X