我正在尝试使用C#读取仅包含RSA公钥的.pem
文件。我无权访问私钥信息,我的应用程序也不需要它。文件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'。
如果没有私钥信息,我如何使用Bouncy Castle的PemReader
只读取公钥?
答案 0 :(得分:18)
以下代码仅在给定文件名的情况下读取公钥。应该为任何生产代码更改异常处理。此方法返回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;
}
答案 1 :(得分:9)
这是一个可以将公共和私有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());
}
}
希望这有助于某人。
答案 2 :(得分:1)
在回答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));
答案 3 :(得分: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”。
答案 4 :(得分:0)
尝试以下代码:
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 :(得分:0)
编辑:
看起来这取决于您使用的密钥文件类型。对于 ssh-keygen 密钥,私钥似乎具有AsymmetricCipherKeyPair
类型,但是对于 openssl 密钥,私钥具有{{1 }}。
Bryan Jyh Herng Chong的答案似乎不再对我有用(至少在Bouncy Castle版本v1.8.5中)。看来RsaPrivateCrtKeyParameters
的公钥和私钥PEM对象的设置不再相同。看来,使用kp.GetType().GetProperty("Private")
返回的对象现在直接是PemReader.ReadObject()
对象,因此不再需要先强制转换RsaPrivateCrtKeyParameters
对象。
我将该行更改为此行,它就像一种魅力:
AsymmetricCipherKeyPair