C# 仅使用Bouncy Castle读取PEM RSA公钥

C# 仅使用Bouncy Castle读取PEM RSA公钥,c#,bouncycastle,public-key,pem,C#,Bouncycastle,Public Key,Pem,我正在尝试使用C#读入只包含RSA公钥的.pem文件。我无权访问私钥信息,我的应用程序也不需要它。文件myprivatekey.pem以开头 ----开始公钥--- 以 ----结束公钥--- 我目前的代码如下: Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair keyPair; using (var reader = File.OpenText(@"c:\keys\myprivatekey.pem")) keyPa

我正在尝试使用C#读入只包含RSA公钥的
.pem
文件。我无权访问私钥信息,我的应用程序也不需要它。文件
myprivatekey.pem
以开头

----开始公钥---
----结束公钥---

我目前的代码如下:

    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();
但是,代码会在消息中抛出一个
InvalidCastException

无法强制转换类型为的对象 “Org.BouncyCastle.Crypto.Parameters.DsaPublicKeyParameters”以键入 “Org.bounchycastle.Crypto.asymmetricipherkeypair”


当没有私钥信息可用时,如何使用Bouncy Castle的
PemReader
仅读取公钥?

以下代码将从给定文件名读取公钥。对于任何生产代码,都应更改异常处理。此方法返回一个
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;
}

在回答c0d3Junk13时,我遇到了PEM私钥的同样问题,我花了整个下午的时间使用C#BouncyCastle 1.7版和Visual Studio 2013 Desktop Express找到了解决方案。别忘了将项目引用添加到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));

下面是一个可能的解决方案,它可以将公共和私有PEM文件读入RSACryptServiceProvider:

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());
    }
}
公共类读卡器
{
公共静态RSACryptServiceProvider GetRSProviderFromPEM(字符串PEMSR)
{
CspParameters CspParameters=新的CspParameters();
cspParameters.KeyContainerName=“MyKeyContainer”;
RSACryptoServiceProvider rsaKey=新的RSACryptoServiceProvider(cspParameters);
Func MakePublicRCSP=(RSACryptServiceProvider rcsp,RsaKeyParameters rkp)=>
{
rsapameters rsapameters=DotNetUtilities.ToRSAParameters(rkp);
rcsp.进口参数(RSA参数);
返回密钥;
};
Func MakePrivateCSP=(RSACryptServiceProvider rcsp,RsaPrivateCrtKeyParameters rkp)=>
{
rsapameters rsapameters=DotNetUtilities.ToRSAParameters(rkp);
rcsp.进口参数(RSA参数);
返回密钥;
};
PemReader=新PemReader(新StringReader(PEMSR));
object kp=reader.ReadObject();
//如果对象具有私有/公共属性,则我们具有私有PEM
return(kp.GetType().GetProperty(“Private”)!=null)?MakePrivateCSP(rsaKey,(RsaPrivateCrtKeyParameters)(((不对称密码对)kp.Private)):MakePublicRCSP(rsaKey,(RsaKeyParameters)kp);
}
公共静态RSACryptServiceProvider GetRSProviderFromPEMFile(字符串pemfile)
{
返回GetRSAProviderFromPem(File.ReadAllText(pemfile.Trim());
}
}

希望这对某人有所帮助。

请尝试以下代码:

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;
编辑: 看起来这取决于您使用的密钥文件的类型。对于ssh-keygen密钥,私钥的类型似乎为
asymmetricipherkeypair
,但对于openssl密钥,私钥的类型为
RsaPrivateCrtKeyParameters


Bryan Jyh Herng Chong的答案似乎不再适用于我(至少对于Bouncy Castle v1.8.5版而言)。看起来,
kp.GetType().GetProperty(“Private”)
对于公钥和私钥PEM对象的设置不再不同。另外,使用
PemReader.ReadObject()
返回的对象现在直接是
rsaprovatecrtkeyparameters
对象,因此不再需要首先转换
asymmetricipherkeypair
对象

我把那句话改成了这句话,效果很好:

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

keyPair = (Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair)new Org.BouncyCastle.OpenSsl.PemReader(reader).ReadObject();
使用:


由于您只使用公钥,而实际上没有一对密钥(公钥和私钥),因此不能将其转换为“AsymmetricHipherKeyPair”,您应该将其转换为“AsymmetricKeyParameter”。

单个公钥不是密钥对。密钥对是公钥和私钥。这也可以用来读取私钥吗?然后在密码函数中传入false,例如:cipher.Init(false,privatekey)。对于Linux/.NET标准,我只是使用无参数构造函数创建了一个新的RSACryptServiceProvider。
keyPair = (Org.BouncyCastle.Crypto.AsymmetricKeyParameter)new Org.BouncyCastle.OpenSsl.PemReader(reader).ReadObject();