2012-07-05 13 views
8

Sto cercando di utilizzare C# per leggere in un file .pem che contiene solo una chiave pubblica RSA. Non ho accesso alle informazioni sulla chiave privata, né la mia applicazione lo richiede. Il file myprivatekey.pem inizia conLettura della chiave pubblica PEM RSA utilizzando solo il castello gonfiabile

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

Il mio codice attuale è la seguente:

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

Tuttavia il codice genera un InvalidCastException con il messaggio

Impossibile eseguire il cast oggetto di tipo 'Org.BouncyCastle.Crypto.Parameters.DsaPublicKeyParameters 'per digitare ' Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair '.

Come posso utilizzare Bouncy Castle PemReader per leggere solo una chiave pubblica, quando non sono disponibili informazioni sulla chiave privata?

+2

Una singola chiave pubblica non è una coppia di chiavi. Una coppia di chiavi è una chiave pubblica * e * una chiave privata. –

risposta

14

Il codice seguente leggerà una chiave pubblica solo con un nome file. La gestione delle eccezioni dovrebbe essere modificata per qualsiasi codice di produzione. Questo metodo restituisce 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

Può essere utilizzato anche per leggere una chiave privata? Quindi basta passare falso nella funzione di cifratura come: cipher.Init (false, privatekey). Ho provato questo senza fortuna. – c0d3Junk13

2

In risposta alla c0d3Junk13, ho avuto lo stesso problema per una chiave privata PEM e mi c'è voluto tutto il pomeriggio per trovare la soluzione utilizzando il C# BouncyCastle Versione 1.7 e Visual Studio 2013 Desktop Express. Non dimenticate di aggiungere il riferimento al progetto di 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

Ecco una possibile soluzione che legge i file pubblici e privati ​​PEM in 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()); 
    } 
} 

Spero che questo aiuti qualcuno.

Problemi correlati