2012-07-05 107 views
8

Estoy tratando de usar C# para leer en un archivo .pem que contiene solo una clave pública de RSA. No tengo acceso a la información de la clave privada, ni mi aplicación lo requiere. El archivo archivo myprivatekey.pem comienza conLectura de PEM Clave pública de RSA Solo usando Bouncy Castle

-----BEGIN PUBLIC KEY----- y termina con -----END PUBLIC KEY-----.

Mi código actual es la siguiente:

Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair keyPair; 

    using (var reader = File.OpenText(@"c:\keys\myprivatekey.pem")) 
     keyPair = (Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair)new Org.BouncyCastle.OpenSsl.PemReader(reader).ReadObject(); 

Sin embargo, el código se emite una InvalidCastException con el mensaje

No se puede convertir objeto de tipo 'Org.BouncyCastle.Crypto.Parameters.DsaPublicKeyParameters 'para escribir ' Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair '.

¿Cómo puedo usar Bouncy Castle's PemReader para leer solo una clave pública, cuando no hay información de clave privada disponible?

+2

Una sola clave pública no es un par de claves. Un par de claves es una clave pública * y * una clave privada. –

Respuesta

14

El siguiente código leerá una clave pública solo con un nombre de archivo. El manejo de excepciones debe cambiarse para cualquier código de producción. Este método devuelve un AsymetricKeyParameter.

public Org.BouncyCastle.Crypto.AsymmetricKeyParameter ReadAsymmetricKeyParameter(string pemFilename) 
{ 
    var fileStream = System.IO.File.OpenText (pemFilename); 
    var pemReader = new Org.BouncyCastle.OpenSsl.PemReader (fileStream); 
    var KeyParameter = (Org.BouncyCastle.Crypto.AsymmetricKeyParameter)pemReader.ReadObject(); 
    return KeyParameter; 
} 
+0

¿Se puede utilizar esto también para leer una clave privada? Luego simplemente ingrese "falso" en la función de cifrado, como: "cipher.Init" (false, privatekey). Intenté esto sin suerte. – c0d3Junk13

2

En respuesta a c0d3Junk13, he tenido el mismo problema para una clave privada PEM y me tomó toda la tarde para encontrar la solución con el C# BouncyCastle versión 1.7 y Visual Studio 2013 de escritorio Express. No se olvide de agregar la referencia al proyecto BouncyCastle.Crypto.dll

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using System.Collections; 
using System.IO; 
using Org.BouncyCastle.Asn1.X509; 
using Org.BouncyCastle.Asn1.Pkcs; 
using Org.BouncyCastle.Crypto.Digests; 
using Org.BouncyCastle.Crypto.Parameters; 
using Org.BouncyCastle.Crypto.Signers; 
using Org.BouncyCastle.X509; 
using Org.BouncyCastle.Math; 
using Org.BouncyCastle.Math.EC; 
using Org.BouncyCastle.Utilities.Collections; 
using Org.BouncyCastle.Utilities.Encoders; 
using Org.BouncyCastle.Crypto; 
using Org.BouncyCastle.Crypto.Engines; 
using Org.BouncyCastle.OpenSsl; 

/* 
    For an Active Directory generated pem, strip out everything in pem file before line: 
    "-----BEGIN PRIVATE KEY-----" and re-save. 
*/ 
string privateKeyFileName = @"C:\CertificateTest\CS\bccrypto-net-1.7-bin\private_key3.pem"; 

TextReader reader = File.OpenText(privateKeyFileName); 

Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters key; 

using (reader = File.OpenText(privateKeyFileName)) 
{ 
    key = (Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters)new PemReader(reader).ReadObject(); 
} 

cipher.Init(false, key); 

//Decrypting the input bytes 

byte[] decipheredBytes = cipher.ProcessBlock(cipheredBytes, 0, cipheredBytes.Length); 

MessageBox.Show(Encoding.UTF8.GetString(decipheredBytes)); 
1

Aquí hay una solución posible que lee los archivos tanto públicos como privados PEM en RSACryptoServiceProvider:

public class PemReaderB 
{ 
    public static RSACryptoServiceProvider GetRSAProviderFromPem(String pemstr) 
    { 
     CspParameters cspParameters = new CspParameters(); 
     cspParameters.KeyContainerName = "MyKeyContainer"; 
     RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParameters); 

     Func<RSACryptoServiceProvider, RsaKeyParameters, RSACryptoServiceProvider> MakePublicRCSP = (RSACryptoServiceProvider rcsp, RsaKeyParameters rkp) => 
     { 
      RSAParameters rsaParameters = DotNetUtilities.ToRSAParameters(rkp); 
      rcsp.ImportParameters(rsaParameters); 
      return rsaKey; 
     }; 

     Func<RSACryptoServiceProvider, RsaPrivateCrtKeyParameters, RSACryptoServiceProvider> MakePrivateRCSP = (RSACryptoServiceProvider rcsp, RsaPrivateCrtKeyParameters rkp) => 
     { 
      RSAParameters rsaParameters = DotNetUtilities.ToRSAParameters(rkp); 
      rcsp.ImportParameters(rsaParameters); 
      return rsaKey; 
     }; 

     PemReader reader = new PemReader(new StringReader(pemstr)); 
     object kp = reader.ReadObject(); 

     // If object has Private/Public property, we have a Private PEM 
     return (kp.GetType().GetProperty("Private") != null) ? MakePrivateRCSP(rsaKey, (RsaPrivateCrtKeyParameters)(((AsymmetricCipherKeyPair)kp).Private)) : MakePublicRCSP(rsaKey, (RsaKeyParameters)kp); 
    } 

    public static RSACryptoServiceProvider GetRSAProviderFromPemFile(String pemfile) 
    { 
     return GetRSAProviderFromPem(File.ReadAllText(pemfile).Trim()); 
    } 
} 

Espero que esto ayude a alguien.

Cuestiones relacionadas