example ejemplo decrypt c# .net cryptography rsa

decrypt - rsa c# ejemplo



Cómo leer una clave privada PEM RSA de.NET (8)

Compruebe http://msdn.microsoft.com/en-us/library/dd203099.aspx

en Bloque de aplicaciones de criptografía.

No sé si obtendrás tu respuesta, pero vale la pena intentarlo.

Editar después de comentar .

Ok, entonces revisa este código.

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

Tengo una clave privada RSA en formato PEM , ¿hay una manera directa de leer eso de .NET y crear instancias de un RSACryptoServiceProvider para descifrar los datos cifrados con la clave pública correspondiente?


Con respecto a la fácil importación de la clave privada RSA, sin utilizar un código de terceros como BouncyCastle, creo que la respuesta es "No, no con un PEM de la clave privada solo".

Sin embargo, como se mencionó anteriormente por Simone, puede simplemente combinar el PEM de la clave privada (* .key) y el archivo de certificado usando esa clave (* .crt) en un archivo * .pfx que luego puede importarse fácilmente.

Para generar el archivo PFX desde la línea de comando:

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

Luego, use normalmente con la clase de certificado .NET, como:

using System.Security.Cryptography.X509Certificates; X509Certificate2 combinedCertificate = new X509Certificate2(@"C:/path/to/file.pfx");

Ahora puede seguir el ejemplo de MSDN para encriptar y descifrar a través de RSACryptoServiceProvider:

Dejé fuera que para descifrar necesitarías importar usando la contraseña PFX y la bandera Exportable. (ver: BouncyCastle RSAPrivateKey para .NET RSAPrivateKey )

X509KeyStorageFlags flags = X509KeyStorageFlags.Exportable; X509Certificate2 cert = new X509Certificate2("my.pfx", "somepass", flags); RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert.PrivateKey; RSAParameters rsaParam = rsa.ExportParameters(true);


Creé la biblioteca PemUtils que hace exactamente eso. El código está disponible en GitHub y se puede instalar desde NuGet :

PM> Install-Package PemUtils

o si solo quieres un convertidor DER:

PM> Install-Package DerConverter

Uso para leer una clave RSA de datos PEM:

using (var stream = File.OpenRead(path)) using (var reader = new PemReader(stream)) { var rsaParameters = reader.ReadRsaKey(); // ... }


El material entre el

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

y

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

es la codificación base64 de PKCS # 8 PrivateKeyInfo (a menos que indique RSA ENCRYPTED PRIVATE KEY en cuyo caso es EncryptedPrivateKeyInfo).

No es tan difícil decodificar manualmente, pero de lo contrario su mejor CryptImportPKCS8 es P / Invocar a CryptImportPKCS8 .

Actualización: la función CryptImportPKCS8 ya no está disponible para Windows Server 2008 y Windows Vista. En su lugar, use la función PFXImportCertStore .


Lo solucioné, gracias. En caso de que alguien esté interesado, bouncycastle hizo el truco, solo me tomó un tiempo debido a la falta de conocimiento por mi parte y la documentación. Este es el código:

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));


Para las personas que no quieren usar Bouncy, y están probando algunos de los códigos incluidos en otras respuestas, he descubierto que el código funciona la MAYORÍA del tiempo, pero se activa en algunas cadenas privadas de RSA, como la que yo uso. he incluido abajo Al mirar el código de anotación, modifiqué el código provisto por wprl para

RSAparams.D = ConvertRSAParametersField(D, MODULUS.Length); RSAparams.DP = ConvertRSAParametersField(DP, P.Length); RSAparams.DQ = ConvertRSAParametersField(DQ, Q.Length); RSAparams.InverseQ = ConvertRSAParametersField(IQ, Q.Length); private static byte[] ConvertRSAParametersField(byte[] bs, int size) { if (bs.Length == size) return bs; if (bs.Length > size) throw new ArgumentException("Specified size too small", "size"); byte[] padded = new byte[size]; Array.Copy(bs, 0, padded, size - bs.Length, bs.Length); return padded; } -----BEGIN RSA PRIVATE KEY----- MIIEoQIBAAKCAQEAxCgWAYJtfKBVa6Px1Blrj+3Wq7LVXDzx+MiQFrLCHnou2Fvb fxuDeRmd6ERhDWnsY6dxxm981vTlXukvYKpIZQYpiSzL5pyUutoi3yh0+/dVlsHZ UHheVGZjSMgUagUCLX1p/augXltAjgblUsj8GFBoKJBr3TMKuR5TwF7lBNYZlaiR k9MDZTROk6MBGiHEgD5RaPKA/ot02j3CnSGbGNNubN2tyXXAgk8/wBmZ4avT0U4y 5oiO9iwCF/Hj9gK/S/8Q2lRsSppgUSsCioSg1CpdleYzIlCB0li1T0flB51zRIpg JhWRfmK1uTLklU33xfzR8zO2kkfaXoPTHSdOGQIDAQABAoIBAAkhfzoSwttKRgT8 sgUYKdRJU0oqyO5s59aXf3LkX0+L4HexzvCGbK2hGPihi42poJdYSV4zUlxZ31N2 XKjjRFDE41S/Vmklthv8i3hX1G+Q09XGBZekAsAVrrQfRtP957FhD83/GeKf3MwV Bhe/GKezwSV3k43NvRy2N1p9EFa+i7eq1e5i7MyDxgKmja5YgADHb8izGLx8Smdd +v8EhWkFOcaPnQRj/LhSi30v/CjYh9MkxHMdi0pHMMCXleiUK0Du6tnsB8ewoHR3 oBzL4F5WKyNHPvesYplgTlpMiT0uUuN8+9Pq6qsdUiXs0wdFYbs693mUMekLQ4a+ 1FOWvQECgYEA7R+uI1r4oP82sTCOCPqPi+fXMTIOGkN0x/1vyMXUVvTH5zbwPp9E 0lG6XmJ95alMRhjvFGMiCONQiSNOQ9Pec5TZfVn3M/w7QTMZ6QcWd6mjghc+dGGE URmCx8xaJb847vACir7M08AhPEt+s2C7ZokafPCoGe0qw/OD1fLt3NMCgYEA08WK S+G7dbCvFMrBP8SlmrnK4f5CRE3pV4VGneWp/EqJgNnWwaBCvUTIegDlqS955yVp q7nVpolAJCmlUVmwDt4gHJsWXSQLMXy3pwQ25vdnoPe97y3xXsi0KQqEuRjD1vmw K7SXoQqQeSf4z74pFal4CP38U3pivvoE4MQmJeMCfyJFceWqQEUEneL+IYkqrZSK 7Y8urNse5MIC3yUlcose1cWVKyPh4RCEv2rk0U1gKqX29Jb9vO2L7RflAmrLNFuA J+72EcRxsB68RAJqA9VHr1oeAejQL0+JYF2AK4dJG/FsvvFOokv4eNU+FBHY6Tzo k+t63NDidkvb5jIF6lsCgYEAlnQ08f5Y8Z9qdCosq8JpKYkwM+kxaVe1HUIJzqpZ X24RTOL3aa8TW2afy9YRVGbvg6IX9jJcMSo30Llpw2cl5xo21Dv24ot2DF2gGN+s peFF1Z3Naj1Iy99p5/KaIusOUBAq8pImW/qmc/1LD0T56XLyXekcuK4ts6Lrjkit FaMCgYAusOLTsRgKdgdDNI8nMQB9iSliwHAG1TqzB56S11pl+fdv9Mkbo8vrx6g0 NM4DluCGNEqLZb3IkasXXdok9e8kmX1en1lb5GjyPbc/zFda6eZrwIqMX9Y68eNR IWDUM3ckwpw3rcuFXjFfa+w44JZVIsgdoGHiXAdrhtlG/i98Rw== -----END RSA PRIVATE KEY-----


Puede echar un vistazo a JavaScience''s fuente de OpenSSLKey para OpenSSLKey . ( OpenSSLKey.cs )

Hay un código ahí que hace exactamente lo que quieres hacer.

De hecho, tienen una gran cantidad de código criptográfico disponible aquí .

Fragmento de código fuente:

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


ok, estoy usando mac para generar mis claves autofirmadas. Aquí está el método de trabajo que utilicé.

Creé un script de shell para acelerar la generación de mi clave.

genkey.sh

#/bin/sh ssh-keygen -f host.key openssl req -new -key host.key -out request.csr openssl x509 -req -days 99999 -in request.csr -signkey host.key -out server.crt openssl pkcs12 -export -inkey host.key -in server.crt -out private_public.p12 -name "SslCert" openssl base64 -in private_public.p12 -out Base64.key

agregue el indicador + x execute al script

chmod +x genkey.sh

luego llama a genkey.sh

./genkey.sh

Ingresé una contraseña (importante incluir una contraseña al menos para la exportación al final)

Enter pass phrase for host.key: Enter Export Password: {Important to enter a password here} Verifying - Enter Export Password: { Same password here }

Luego tomo todo en Base64.Key y lo coloco en una cadena llamada sslKey

private string sslKey = "MIIJiAIBA...................................." + "......................ETC...................." + "......................ETC...................." + "......................ETC...................." + ".............ugICCAA=";

Luego usé un Property getter de carga lenta para obtener mi X509 Cert con una clave privada.

X509Certificate2 _serverCertificate = null; X509Certificate2 serverCertificate{ get { if (_serverCertificate == null){ string pass = "Your Export Password Here"; _serverCertificate = new X509Certificate(Convert.FromBase64String(sslKey), pass, X509KeyStorageFlags.Exportable); } return _serverCertificate; } }

Quería seguir este camino porque estoy usando .net 2.0 y Mono en Mac y quería usar el código vainilla del Framework sin bibliotecas compiladas ni dependencias.

Mi uso final para esto fue el SslStream para asegurar la comunicación TCP a mi aplicación

SslStream sslStream = new SslStream(serverCertificate, false, SslProtocols.Tls, true);

Espero que esto ayude a otras personas.

NOTA

Sin una contraseña, no pude desbloquear correctamente la clave privada para exportar.