[英]Reading PEM RSA Public Key Only using Bouncy Castle
I am trying to use C# to read in a .pem
file that contains only a RSA public key.我正在尝试使用 C# 读取仅包含 RSA 公钥的
.pem
文件。 I do not have access to the private key information, nor does my application require it.我无权访问私钥信息,我的应用程序也不需要它。 The file
myprivatekey.pem
file begins with文件
myprivatekey.pem
文件以
-----BEGIN PUBLIC KEY-----
and ends with -----END PUBLIC KEY-----
. -----BEGIN PUBLIC KEY-----
并以-----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但是代码会抛出一个
InvalidCastException
消息
Unable to cast object of type 'Org.BouncyCastle.Crypto.Parameters.DsaPublicKeyParameters' to type 'Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair'.
无法将“Org.BouncyCastle.Crypto.Parameters.DsaPublicKeyParameters”类型的对象转换为类型“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?当没有可用的私钥信息时,如何使用 Bouncy Castle 的
PemReader
只读取公钥?
The following code will read a public key from a given filename.以下代码将从给定文件名中读取公钥。 The exception handling should be changed for any production code.
应针对任何生产代码更改异常处理。 This method returns an
AsymetricKeyParameter
:此方法返回一个
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;
}
Here's a possible solution that reads both public and private PEM files into RSACryptoServiceProvider:这是将公共和私有 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());
}
}
Hope this helps someone.希望这对某人有帮助。
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.在回答 c0d3Junk13 时,我遇到了与 PEM 私钥相同的问题,我花了整个下午才找到使用 C# BouncyCastle 1.7 版和 Visual Studio 2013 Desktop Express 的解决方案。 Don't forget to add the project reference to BouncyCastle.Crypto.dll
不要忘记将项目引用添加到 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));
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
.对于ssh-keygen密钥,私钥似乎具有
AsymmetricCipherKeyPair
类型,但对于openssl密钥,私钥具有RsaPrivateCrtKeyParameters
类型。
Bryan Jyh Herng Chong's answer no longer appears to work for me (at least with Bouncy Castle version v1.8.5). Bryan Jyh Herng Chong 的回答似乎不再适合我(至少对于 Bouncy Castle 版本 v1.8.5)。 It appears
kp.GetType().GetProperty("Private")
is no longer set differently for public vs private key PEM objects.看起来
kp.GetType().GetProperty("Private")
不再为公钥和私钥 PEM 对象设置不同。 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.看起来使用
PemReader.ReadObject()
返回的对象现在直接是RsaPrivateCrtKeyParameters
对象,因此不再需要先通过AsymmetricCipherKeyPair
对象进行转换。
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);
Instead of:代替:
keyPair = (Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair)new Org.BouncyCastle.OpenSsl.PemReader(reader).ReadObject();
Use:采用:
keyPair = (Org.BouncyCastle.Crypto.AsymmetricKeyParameter)new Org.BouncyCastle.OpenSsl.PemReader(reader).ReadObject();
Since you are only using a public key and you don't actually have a pair of keys (public & private) you can't cast it as 'AsymmetricCipherKeyPair' you should cast it as 'AsymmetricKeyParameter'.由于您只使用公钥并且实际上没有一对密钥(公钥和私钥),因此您不能将其转换为“AsymmetricCipherKeyPair”,您应该将其转换为“AsymmetricKeyParameter”。
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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.