17

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

-----BEGIN PUBLIC KEY----- 并以 . 结尾 -----END PUBLIC KEY-----

我目前的代码如下:

    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.BouncyCastle.Crypto.AsymmetricCipherKeyPair”类型。

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

4

6 回答 6

24

以下代码将从给定文件名中读取公钥。应该为任何生产代码更改异常处理。此方法返回一个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;
}
于 2012-07-06T17:41:02.023 回答
13

这是一个将公共和私有 PEM 文件读入 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());
    }
}

希望这可以帮助某人。

于 2017-10-06T03:55:55.897 回答
2

在回答 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));
于 2015-05-26T20:15:14.190 回答
2

编辑:看起来这取决于您使用的密钥文件类型。对于ssh-keygen密钥,私钥的类型似乎是AsymmetricCipherKeyPair,但对于openssl密钥,私钥的类型是RsaPrivateCrtKeyParameters


Bryan Jyh Herng Chong 的回答似乎不再适合我(至少在 Bouncy Castle v1.8.5 版本中)。kp.GetType().GetProperty("Private")公钥和私钥 PEM 对象的设置似乎不再不同。看起来使用返回的对象PemReader.ReadObject()现在直接是一个RsaPrivateCrtKeyParameters对象,因此不再需要先通过AsymmetricCipherKeyPair对象进行转换。

我把那条线改成了这样,它就像一个魅力:

return (kp.GetType() == typeof(RsaPrivateCrtKeyParameters)) ? MakePrivateRCSP(rsaKey, (RsaPrivateCrtKeyParameters)kp)) : MakePublicRCSP(rsaKey, (RsaKeyParameters)kp);
于 2019-07-26T21:01:40.317 回答
1

代替:

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

利用:

keyPair = (Org.BouncyCastle.Crypto.AsymmetricKeyParameter)new Org.BouncyCastle.OpenSsl.PemReader(reader).ReadObject();

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

于 2020-06-25T17:16:53.963 回答
-1

试试下面的代码:

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;
于 2019-01-03T09:27:47.707 回答