Reading PEM RSA Public Key Only using Bouncy Castle

狂风中的少年 提交于 2019-12-18 10:45:03

问题


I am trying to use C# to read in a .pem file that contains only a RSA public key. I do not have access to the private key information, nor does my application require it. The file myprivatekey.pem file begins with

-----BEGIN PUBLIC KEY----- and ends with -----END PUBLIC KEY-----.

My current code is as follows:

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

However the code throws an InvalidCastException with the message

Unable to cast object of type 'Org.BouncyCastle.Crypto.Parameters.DsaPublicKeyParameters' to type 'Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair'.

How can I use Bouncy Castle's PemReader to read only a public key, when no private key information is available?


回答1:


The following code will read a public key only given a filename. The exception handling should be changed for any production code. This method returns an 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;
}



回答2:


Here's a possible solution that reads both public and private PEM files into 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());
    }
}

Hope this helps someone.




回答3:


In answer to c0d3Junk13, I had the same issue for a PEM private key and it took me all afternoon to find the solution using the C# BouncyCastle Version 1.7 and Visual Studio 2013 Desktop Express. Don't forget to add the project reference to 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));



回答4:


Try the following code:

Using Org.BouncyCastle.Crypto;


string path = HttpContext.Current.Server.MapPath(@"~\key\ABCD.pem");



AsymmetricCipherKeyPair Key;

TextReader tr = new StreamReader(@path);

 PemReader pr = new PemReader(tr);
        Key = (AsymmetricCipherKeyPair)pr.ReadObject();
        pr.Reader.Close();
        tr.Close();



         AsymmetricKeyParameter keaa = Key.Public;



回答5:


EDIT: It looks like this depends on what type of key file you are using. For ssh-keygen keys, the private key appears to have a type of AsymmetricCipherKeyPair, but for openssl keys, the private key has a type of RsaPrivateCrtKeyParameters.


Bryan Jyh Herng Chong's answer no longer appears to work for me (at least with Bouncy Castle version v1.8.5). It appears kp.GetType().GetProperty("Private") is no longer set differently for public vs private key PEM objects. It also appears that the object returned using PemReader.ReadObject() is now directly a RsaPrivateCrtKeyParameters object, so there's no longer a need to cast through a AsymmetricCipherKeyPair object first.

I changed that line to this and it worked like a charm:

return (kp.GetType() == typeof(RsaPrivateCrtKeyParameters)) ? MakePrivateRCSP(rsaKey, (RsaPrivateCrtKeyParameters)kp)) : MakePublicRCSP(rsaKey, (RsaKeyParameters)kp);


来源:https://stackoverflow.com/questions/11346200/reading-pem-rsa-public-key-only-using-bouncy-castle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!