我有一个.PEM文件,其中包含用于SSL数据传输的公钥和私钥,如下所示:
-----BEGIN RSA PRIVATE KEY-----
private key data
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
public key data
-----END CERTIFICATE-----
当我想通过以下代码加载.PEM文件时:
X509Certificate2 xx = new X509Certificate2("c:\\myKey.pem");
我得到一个异常,上面写着:“找不到请求的对象。” ,有完整的堆栈:
System.Security.Cryptography.CryptographicException was unhandled
Message=Cannot find the requested object.
Source=mscorlib
StackTrace:
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
at System.Security.Cryptography.X509Certificates.X509Utils._QueryCertFileType(String fileName)
at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromFile(String fileName, Object password, X509KeyStorageFlags keyStorageFlags)
at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(String fileName)
at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(String fileName)
at DLLTest.SSL_Test.test() in E:\Projects\DLLTest\DLLTest\SSL_Test.cs:line 165
at DLLTest.SSL_Test.Run() in E:\Projects\DLLTest\DLLTest\SSL_Test.cs:line 21
at DLLTest.Program.Main(String[] args) in E:\Projects\DLLTest\DLLTest\Program.cs:line 21
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
如果我交换私钥部分和公钥部分的位置,代码工作并加载数据,我可以从对象获得公钥信息,例如。发行者名称, 并且它的HasPrivateKey是错误的。为什么?我误解了,做错了什么?
答案 0 :(得分:31)
有一个article on the Code Project,其中包含您执行此操作所需的所有代码。它只是几个类,所以它是一个轻量级的解决方案。
要从PEM文件获取证书或密钥的字节,无论文件中的密钥和证书的顺序如何,以下方法都将起作用。
byte[] GetBytesFromPEM( string pemString, string section )
{
var header = String.Format("-----BEGIN {0}-----", section);
var footer = String.Format("-----END {0}-----", section);
var start= pemString.IndexOf(header, StringComparison.Ordinal);
if( start < 0 )
return null;
start += header.Length;
var end = pemString.IndexOf(footer, start, StringComparison.Ordinal) - start;
if( end < 0 )
return null;
return Convert.FromBase64String( pemString.Substring( start, end ) );
}
将PEM文件加载到字符串中并调用上面的方法以获取表示证书的字节。接下来,将获得的字节传递给X509Certificate2的构造函数:
var pem = System.IO.File.ReadAllText( "c:\\myKey.pem" )
byte[] certBuffer = GetBytesFromPEM( pem, "CERTIFICATE" );
var certificate = new X509Certificate2( certBuffer );
从PEM文件加载(RSA)私钥有点复杂,但您可以使用Crypto.DecodeRsaPrivateKey
方法在上述文章中找到对此的支持。
答案 1 :(得分:16)
AFAIK .NET框架在任何地方都不支持PEM。
您可以轻松解决X509Certificate
部分问题,因为您可以在 ----- BEGIN CERTIFICATE ----- 之间提取base64字符串和 ----- END CERTIFICATE ----- 行,将其转换为byte[]
并从中创建X509Certificate
一个简单的解决方案是从Mono.Security的X509Certificate.cs复制粘贴代码来执行此操作。
获取私钥有点棘手,因为获取byte[]
对重建RSA实例没有太大帮助(我们可以假设,因为PEM头表明它是RSA)。
这次你最好从Mono.Security的PKCS8.cs文件中复制粘贴,然后调用解码方法。
免责声明: 我是上面讨论过的Mono代码的主要作者,并且它都是在MIT.X11许可下提供的
答案 2 :(得分:9)
我遇到了同样的问题 - 为了记录 - 我在这里发布了一个完整的,有效的代码示例(由于已知原因,密钥被删除)。它主要是在互联网和我的家庭项目要求中找到的东西的汇编。
遵循代码的功能
代码:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Principal;
using System.Security.AccessControl;
namespace Test1
{
public static class Test
{
public static int Main()
{
string pemCertWithPrivateKeyText = @"-----BEGIN CERTIFICATE-----
...
bjEdMBsGA1UEChQUVGV4YXMgQSZNIFV5jZTESMBAGA1UEAxMJVXNlciBOYW1lMSA
...
YXMgQSZNIFV5jZTESMBAGA1e2yX28ERsgBD6xx7mJDrPxkqWyV/a9tCF8W6jGSs=
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEow..................
jZMxBWg+imTpbGb+TpR2kxBWctnzFOWRuVYdSQIDAQABAoIBAFSKz/RLtkmZKE1d
....
BWctnzFOWRuVYdSdsf+WDqNxEzrL08SU1w5WuSxIsbxchUvG4
-----END RSA PRIVATE KEY-----
"; // just an example
X509Certificate2 cert = PEMToX509.Convert(pemCertWithPrivateKeyText);
return (cert.HasPrivateKey ? 1 : -1);
}
}
internal static class PEMToX509
{
const string KEY_HEADER = "-----BEGIN RSA PRIVATE KEY-----";
const string KEY_FOOTER = "-----END RSA PRIVATE KEY-----";
internal static X509Certificate2 Convert(string pem)
{
try
{
byte[] pemCertWithPrivateKey = System.Text.Encoding.ASCII.GetBytes(pem);
RSACryptoServiceProvider rsaPK = GetRSA(pem);
X509Certificate2 cert = new X509Certificate2();
cert.Import(pemCertWithPrivateKey, "", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
if (rsaPK != null)
{
cert.PrivateKey = rsaPK;
}
return cert;
}
catch
{
return null;
}
}
private static RSACryptoServiceProvider GetRSA(string pem)
{
RSACryptoServiceProvider rsa = null;
if (IsPrivateKeyAvailable(pem))
{
RSAParameters privateKey = DecodeRSAPrivateKey(pem);
SecurityIdentifier everyoneSI = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
CryptoKeyAccessRule rule = new CryptoKeyAccessRule(everyoneSI, CryptoKeyRights.FullControl, AccessControlType.Allow);
CspParameters cspParameters = new CspParameters();
cspParameters.KeyContainerName = "MY_C_NAME";
cspParameters.ProviderName = "Microsoft Strong Cryptographic Provider";
cspParameters.ProviderType = 1;
cspParameters.Flags = CspProviderFlags.UseNonExportableKey | CspProviderFlags.UseMachineKeyStore;
cspParameters.CryptoKeySecurity = new CryptoKeySecurity();
cspParameters.CryptoKeySecurity.SetAccessRule(rule);
rsa = new RSACryptoServiceProvider(cspParameters);
rsa.PersistKeyInCsp = true;
rsa.ImportParameters(privateKey);
}
return rsa;
}
private static bool IsPrivateKeyAvailable(string privateKeyInPEM)
{
return (privateKeyInPEM != null && privateKeyInPEM.Contains(KEY_HEADER)
&& privateKeyInPEM.Contains(KEY_FOOTER));
}
private static RSAParameters DecodeRSAPrivateKey(string privateKeyInPEM)
{
if (IsPrivateKeyAvailable(privateKeyInPEM) == false)
throw new ArgumentException("bad format");
string keyFormatted = privateKeyInPEM;
int cutIndex = keyFormatted.IndexOf(KEY_HEADER);
keyFormatted = keyFormatted.Substring(cutIndex, keyFormatted.Length - cutIndex);
cutIndex = keyFormatted.IndexOf(KEY_FOOTER);
keyFormatted = keyFormatted.Substring(0, cutIndex + KEY_FOOTER.Length);
keyFormatted = keyFormatted.Replace(KEY_HEADER, "");
keyFormatted = keyFormatted.Replace(KEY_FOOTER, "");
keyFormatted = keyFormatted.Replace("\r", "");
keyFormatted = keyFormatted.Replace("\n", "");
keyFormatted = keyFormatted.Trim();
byte[] privateKeyInDER = System.Convert.FromBase64String(keyFormatted);
byte[] paramModulus;
byte[] paramDP;
byte[] paramDQ;
byte[] paramIQ;
byte[] paramE;
byte[] paramD;
byte[] paramP;
byte[] paramQ;
MemoryStream memoryStream = new MemoryStream(privateKeyInDER);
BinaryReader binaryReader = new BinaryReader(memoryStream);
ushort twobytes = 0;
int elements = 0;
byte bt = 0;
try
{
twobytes = binaryReader.ReadUInt16();
if (twobytes == 0x8130)
binaryReader.ReadByte();
else if (twobytes == 0x8230)
binaryReader.ReadInt16();
else
throw new CryptographicException("Wrong data");
twobytes = binaryReader.ReadUInt16();
if (twobytes != 0x0102)
throw new CryptographicException("Wrong data");
bt = binaryReader.ReadByte();
if (bt != 0x00)
throw new CryptographicException("Wrong data");
elements = GetIntegerSize(binaryReader);
paramModulus = binaryReader.ReadBytes(elements);
elements = GetIntegerSize(binaryReader);
paramE = binaryReader.ReadBytes(elements);
elements = GetIntegerSize(binaryReader);
paramD = binaryReader.ReadBytes(elements);
elements = GetIntegerSize(binaryReader);
paramP = binaryReader.ReadBytes(elements);
elements = GetIntegerSize(binaryReader);
paramQ = binaryReader.ReadBytes(elements);
elements = GetIntegerSize(binaryReader);
paramDP = binaryReader.ReadBytes(elements);
elements = GetIntegerSize(binaryReader);
paramDQ = binaryReader.ReadBytes(elements);
elements = GetIntegerSize(binaryReader);
paramIQ = binaryReader.ReadBytes(elements);
EnsureLength(ref paramD, 256);
EnsureLength(ref paramDP, 128);
EnsureLength(ref paramDQ, 128);
EnsureLength(ref paramE, 3);
EnsureLength(ref paramIQ, 128);
EnsureLength(ref paramModulus, 256);
EnsureLength(ref paramP, 128);
EnsureLength(ref paramQ, 128);
RSAParameters rsaParameters = new RSAParameters();
rsaParameters.Modulus = paramModulus;
rsaParameters.Exponent = paramE;
rsaParameters.D = paramD;
rsaParameters.P = paramP;
rsaParameters.Q = paramQ;
rsaParameters.DP = paramDP;
rsaParameters.DQ = paramDQ;
rsaParameters.InverseQ = paramIQ;
return rsaParameters;
}
finally
{
binaryReader.Close();
}
}
private static int GetIntegerSize(BinaryReader binary)
{
byte bt = 0;
byte lowbyte = 0x00;
byte highbyte = 0x00;
int count = 0;
bt = binary.ReadByte();
if (bt != 0x02)
return 0;
bt = binary.ReadByte();
if (bt == 0x81)
count = binary.ReadByte();
else if (bt == 0x82)
{
highbyte = binary.ReadByte();
lowbyte = binary.ReadByte();
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
count = BitConverter.ToInt32(modint, 0);
}
else
count = bt;
while (binary.ReadByte() == 0x00)
count -= 1;
binary.BaseStream.Seek(-1, SeekOrigin.Current);
return count;
}
private static void EnsureLength(ref byte[] data, int desiredLength)
{
if (data == null || data.Length >= desiredLength)
return;
int zeros = desiredLength - data.Length;
byte[] newData = new byte[desiredLength];
Array.Copy(data, 0, newData, zeros, data.Length);
data = newData;
}
}
}
答案 3 :(得分:6)
另一种方法是将客户端PEM证书转换为Windows支持的PFX格式。这可以使用例如openssl,通过运行:
来完成__prepare__
(其中&#34; cert.pfx&#34;是输出文件,&#34; cert.key&#34;包含私钥,&#34; cert.pem&#34;包含输入证书,和&#34; ca.pem&#34;包含签名者的证书。)
答案 4 :(得分:1)
你不知道。
.NET不支持它。
您会看到,PEM编码确实支持多种密钥类型(例如ECDSA)。
因此,如果有人为您提供了一种从PEM文件中读取.NET RSA密钥的方法,则您也许可以读取该RSA密钥(如果PEM还具有D,P,Q,DP DQ,InverseQ),但这就是距离阅读PEM还有很长的路要走。
此外,.NET版本的RSA仅基于(模数,指数和 D,P,Q,DP,DQ,InverseQ)实现RSA。真正的PEM编码的RSA密钥不需要支持参数D,P,Q,DP,DQ,InverseQ。可以,但不是必须的。 RSA真正需要的只是模量和指数。仅包含模数和指数的PEM编码的RSA密钥是绝对有效的PEM密钥,尤其是当您需要与Python互操作时,这样做。
但是,您可以使用BouncyCastle读取PEM编码的私钥和公钥。
见下文。
要在不添加对BouncyCastle的依赖的情况下,将这些加密密钥(任何类型)通用化至.NET,最好的选择是读取BouncyCastle中的PEM文件,创建一个PFX文件(包含私钥和公钥) ,然后使用System.Security.Cryptography.X509Certificates.X509Certificate2读取该PFX文件。假定它们使用了.NET确实支持的一种加密算法,则可以从该证书中获得已经解码的私钥和公钥。
namespace SslCertificateGenerator
{
// https://gist.github.com/therightstuff/aa65356e95f8d0aae888e9f61aa29414
public class KeyImportExport
{
// KeyImportExport.GetPemKeyPair
public static PrivatePublicPemKeyPair GetPemKeyPair(Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair keyPair)
{
PrivatePublicPemKeyPair result = new PrivatePublicPemKeyPair();
// id_rsa
using (System.IO.TextWriter textWriter = new System.IO.StringWriter())
{
Org.BouncyCastle.OpenSsl.PemWriter pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(textWriter);
pemWriter.WriteObject(keyPair.Private);
pemWriter.Writer.Flush();
result.PrivateKey = textWriter.ToString();
} // End Using textWriter
// id_rsa.pub
using (System.IO.TextWriter textWriter = new System.IO.StringWriter())
{
Org.BouncyCastle.OpenSsl.PemWriter pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(textWriter);
pemWriter.WriteObject(keyPair.Public);
pemWriter.Writer.Flush();
result.PublicKey = textWriter.ToString();
} // End Using textWriter
// // This writes the same as private key, not both
//using (System.IO.TextWriter textWriter = new System.IO.StringWriter())
//{
// Org.BouncyCastle.OpenSsl.PemWriter pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(textWriter);
// pemWriter.WriteObject(keyPair);
// pemWriter.Writer.Flush();
// bothKeys = textWriter.ToString();
//} // End Using textWriter
return result;
} // End Sub GetPemKeyPair
// KeyImportExport.ReadPublicKey
public static Org.BouncyCastle.Crypto.AsymmetricKeyParameter ReadPublicKey(string publicKey)
{
Org.BouncyCastle.Crypto.AsymmetricKeyParameter keyParameter = null;
using (System.IO.TextReader reader = new System.IO.StringReader(publicKey))
{
Org.BouncyCastle.OpenSsl.PemReader pemReader =
new Org.BouncyCastle.OpenSsl.PemReader(reader);
object obj = pemReader.ReadObject();
if ((obj is Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair))
throw new System.ArgumentException("The given publicKey is actually a private key.", "publicKey");
if (!(obj is Org.BouncyCastle.Crypto.AsymmetricKeyParameter))
throw new System.ArgumentException("The given publicKey is not a valid assymetric key.", "publicKey");
keyParameter = (Org.BouncyCastle.Crypto.AsymmetricKeyParameter)obj;
}
return keyParameter;
} // End Function ReadPublicKey
public static Org.BouncyCastle.Crypto.AsymmetricKeyParameter ReadPrivateKey(string privateKey)
{
Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair keyPair = null;
using (System.IO.TextReader reader = new System.IO.StringReader(privateKey))
{
Org.BouncyCastle.OpenSsl.PemReader pemReader =
new Org.BouncyCastle.OpenSsl.PemReader(reader);
object obj = pemReader.ReadObject();
if (obj is Org.BouncyCastle.Crypto.AsymmetricKeyParameter)
throw new System.ArgumentException("The given privateKey is a public key, not a privateKey...", "privateKey");
if (!(obj is Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair))
throw new System.ArgumentException("The given privateKey is not a valid assymetric key.", "privateKey");
keyPair = (Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair)obj;
} // End using reader
// Org.BouncyCastle.Crypto.AsymmetricKeyParameter priv = keyPair.Private;
// Org.BouncyCastle.Crypto.AsymmetricKeyParameter pub = keyPair.Public;
// Note:
// cipher.Init(false, key);
// !!!
return keyPair.Private;
} // End Function ReadPrivateKey
public static Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair ReadKeyPair(string privateKey)
{
Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair keyPair = null;
using (System.IO.TextReader reader = new System.IO.StringReader(privateKey))
{
Org.BouncyCastle.OpenSsl.PemReader pemReader =
new Org.BouncyCastle.OpenSsl.PemReader(reader);
object obj = pemReader.ReadObject();
if (obj is Org.BouncyCastle.Crypto.AsymmetricKeyParameter)
throw new System.ArgumentException("The given privateKey is a public key, not a privateKey...", "privateKey");
if (!(obj is Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair))
throw new System.ArgumentException("The given privateKey is not a valid assymetric key.", "privateKey");
keyPair = (Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair)obj;
}
// Org.BouncyCastle.Crypto.AsymmetricKeyParameter priv = keyPair.Private;
// Org.BouncyCastle.Crypto.AsymmetricKeyParameter pub = keyPair.Public;
// Note:
// cipher.Init(false, key);
// !!!
return keyPair;
} // End Function ReadPrivateKey
public static Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair ReadKeyPairFromFile(string fileName)
{
Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair KeyPair = null;
// Stream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
using (System.IO.FileStream fs = System.IO.File.OpenRead(fileName))
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(fs))
{
Org.BouncyCastle.OpenSsl.PemReader pemReader = new Org.BouncyCastle.OpenSsl.PemReader(sr);
KeyPair = (Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair)pemReader.ReadObject();
// System.Security.Cryptography.RSAParameters rsa = Org.BouncyCastle.Security.
// DotNetUtilities.ToRSAParameters((Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters)KeyPair.Private);
} // End Using sr
} // End Using fs
return KeyPair;
} // End Function ImportKeyPair
//public static void ReadPrivateKeyFile(string privateKeyFileName)
//{
// Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters key = null;
// using (System.IO.StreamReader streamReader = System.IO.File.OpenText(privateKeyFileName))
// {
// Org.BouncyCastle.OpenSsl.PemReader pemReader =
// new Org.BouncyCastle.OpenSsl.PemReader(streamReader);
// key = (Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters) pemReader.ReadObject();
// } // End Using streamReader
// // Note:
// // cipher.Init(false, key);
// // !!!
//} // End Function ReadPrivateKey
public Org.BouncyCastle.Crypto.AsymmetricKeyParameter ReadPublicKeyFile(string pemFilename)
{
Org.BouncyCastle.Crypto.AsymmetricKeyParameter keyParameter = null;
using (System.IO.StreamReader streamReader = System.IO.File.OpenText(pemFilename))
{
Org.BouncyCastle.OpenSsl.PemReader pemReader = new Org.BouncyCastle.OpenSsl.PemReader(streamReader);
keyParameter = (Org.BouncyCastle.Crypto.AsymmetricKeyParameter)pemReader.ReadObject();
} // End Using fileStream
return keyParameter;
} // End Function ReadPublicKey
public static void ExportKeyPair(Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair keyPair)
{
string privateKey = null;
using (System.IO.TextWriter textWriter = new System.IO.StringWriter())
{
Org.BouncyCastle.OpenSsl.PemWriter pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(textWriter);
pemWriter.WriteObject(keyPair.Private);
pemWriter.Writer.Flush();
privateKey = textWriter.ToString();
} // End Using textWriter
System.Console.WriteLine(privateKey);
} // End Sub ExportKeyPair
// https://stackoverflow.com/questions/22008337/generating-keypair-using-bouncy-castle
// https://stackoverflow.com/questions/14052485/converting-a-public-key-in-subjectpublickeyinfo-format-to-rsapublickey-format-ja
// https://stackoverflow.com/questions/10963756/get-der-encoded-public-key
// http://www.programcreek.com/java-api-examples/index.php?api=org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory
public static void CerKeyInfo(Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair keyPair)
{
Org.BouncyCastle.Asn1.Pkcs.PrivateKeyInfo pkInfo = Org.BouncyCastle.Pkcs.PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private);
string privateKey = System.Convert.ToBase64String(pkInfo.GetDerEncoded());
// and following for public:
Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo info = Org.BouncyCastle.X509.SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public);
string publicKey = System.Convert.ToBase64String(info.GetDerEncoded());
System.Console.WriteLine(privateKey);
System.Console.WriteLine(publicKey);
} // End Sub CerKeyInfo
} // End Class KeyImportExport
} // End Namespace RedmineMailService.CertSSL
哦,这是使用PFX进行操作的方法:
namespace SelfSignedCertificateGenerator
{
public class PfxData
{
public Org.BouncyCastle.X509.X509Certificate Certificate;
public Org.BouncyCastle.Crypto.AsymmetricKeyParameter PrivateKey;
}
public class PfxFile
{
// System.Security.Cryptography.X509Certificates.X509Certificate2.Import (string fileName);
// https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509certificate2.import?view=netframework-4.7.2
// https://gist.github.com/yutopio/a217a4af63cf6bcf0a530c14c074cf8f
// https://gist.githubusercontent.com/yutopio/a217a4af63cf6bcf0a530c14c074cf8f/raw/42b2f8cb27f6d22b7e22d65da5bbd0f1ce9b2fff/cert.cs
// https://stackoverflow.com/questions/44755155/store-pkcs12-container-pfx-with-bouncycastle
// https://github.com/Worlaf/RSADemo/blob/328692e28e48db92340d55563480c8724d916384/RSADemo_WinForms/frmRsaDemo.cs
public static void Create(
string fileName
, Org.BouncyCastle.X509.X509Certificate certificate
, Org.BouncyCastle.Crypto.AsymmetricKeyParameter privateKey
, string password = "")
{
// create certificate entry
Org.BouncyCastle.Pkcs.X509CertificateEntry certEntry =
new Org.BouncyCastle.Pkcs.X509CertificateEntry(certificate);
string friendlyName = certificate.SubjectDN.ToString();
if (!friendlyName.Contains("obelix", System.StringComparison.InvariantCultureIgnoreCase))
friendlyName = "Skynet Certification Authority";
else
friendlyName = "Coopérative Ménhir Obelix Gmbh & Co. KGaA";
// get bytes of private key.
Org.BouncyCastle.Asn1.Pkcs.PrivateKeyInfo keyInfo = Org.BouncyCastle.Pkcs.PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey);
//byte[] keyBytes = keyInfo.ToAsn1Object().GetEncoded();
Org.BouncyCastle.Pkcs.Pkcs12StoreBuilder builder = new Org.BouncyCastle.Pkcs.Pkcs12StoreBuilder();
builder.SetUseDerEncoding(true);
Org.BouncyCastle.Pkcs.Pkcs12Store store = builder.Build();
store.SetCertificateEntry(friendlyName, certEntry);
// create store entry
store.SetKeyEntry(
//keyFriendlyName
friendlyName
, new Org.BouncyCastle.Pkcs.AsymmetricKeyEntry(privateKey)
, new Org.BouncyCastle.Pkcs.X509CertificateEntry[] { certEntry }
);
byte[] pfxBytes = null;
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
{
// Cert is contained in store
// null: no password, "": an empty passwords
// note: Linux needs empty password on null...
store.Save(stream, password == null ? "".ToCharArray() : password.ToCharArray(), new Org.BouncyCastle.Security.SecureRandom());
// stream.Position = 0;
pfxBytes = stream.ToArray();
} // End Using stream
#if WITH_MS_PFX
WithMsPfx(pfxBytes, fileName, password);
#else
byte[] result = Org.BouncyCastle.Pkcs.Pkcs12Utilities.ConvertToDefiniteLength(pfxBytes);
// this.StoreCertificate(System.Convert.ToBase64String(result));
using (System.IO.BinaryWriter writer = new System.IO.BinaryWriter(System.IO.File.Open(fileName, System.IO.FileMode.Create)))
{
writer.Write(result);
} // End Using writer
#endif
} // End Sub Create
private static void WithMsPfx(byte[] pfxBytes, string fileName, string password)
{
System.Security.Cryptography.X509Certificates.X509Certificate2 convertedCertificate =
new System.Security.Cryptography.X509Certificates.X509Certificate2(pfxBytes,
"", // PW
System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.PersistKeySet | System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.Exportable);
byte[] bytes = convertedCertificate.Export(System.Security.Cryptography.X509Certificates.X509ContentType.Pfx, password);
System.IO.File.WriteAllBytes(fileName, bytes);
} // End Sub WithMsPfx
public static PfxData Read(string pfxFilePath, string password = "")
{
Org.BouncyCastle.Pkcs.Pkcs12Store store = null;
using (System.IO.Stream pfxStream = System.IO.File.OpenRead(pfxFilePath))
{
store = new Org.BouncyCastle.Pkcs.Pkcs12Store(pfxStream, password.ToCharArray());
}
// System.Console.WriteLine(store);
foreach (string alias in store.Aliases)
{
Org.BouncyCastle.Pkcs.X509CertificateEntry certEntry = store.GetCertificate(alias);
Org.BouncyCastle.X509.X509Certificate cert = certEntry.Certificate;
// Org.BouncyCastle.Crypto.AsymmetricKeyParameter publicKey = cert.GetPublicKey();
// System.Console.WriteLine(publicKey);
// https://7thzero.com/blog/bouncy-castle-convert-a-bouncycastle-asymmetrickeyentry-to-a-.ne
if (store.IsKeyEntry(alias))
{
Org.BouncyCastle.Pkcs.AsymmetricKeyEntry keyEntry = store.GetKey(alias);
Org.BouncyCastle.Crypto.AsymmetricKeyParameter privateKey = keyEntry.Key;
if (privateKey.IsPrivate)
return new PfxData()
{
Certificate = cert,
PrivateKey = privateKey
};
} // End if (store.IsKeyEntry((string)alias))
} // Next alias
return null;
} // End Sub Read
public static System.Security.Cryptography.X509Certificates.X509Certificate2
MicrosoftCertificateFromPfx(string pfxFilePath, string password = "")
{
System.Security.Cryptography.X509Certificates.X509Certificate2 cert =
new System.Security.Cryptography.X509Certificates.X509Certificate2(
pfxFilePath
, password
);
return cert;
}
}
}
答案 5 :(得分:0)
我遇到了相同的问题,并找到了以下解决方案:
首先使用此工具// {https://superdry.apphb.com/tools/online-rsa-key-converter
将prkey.pem转换为prkey.xml。 var dataString = "test";
byte[] dataToEncrypt = Encoding.UTF8.GetBytes(dataString);
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(File.ReadAllText("C:\prkey.xml"));
byte[] signedBytes = provider.SignData(dataToEncrypt, new SHA256CryptoServiceProvider());
textBox3.Text = BitConverter.ToString(signedBytes);
答案 6 :(得分:-1)
我不知道.NET(但是Java),但答案应该是一样的
您的pem文件包含证书和私钥
这是OpenSSL中的常见导出
要在Java中实例化X509Certificate
对象,您只能使用文件中的部分:
-----开始证书-----
证书数据
-----结束证书-----
在.NET中它应该是相同的 只需加载文件并加载PEM的那一部分。
对私钥执行相同操作。
在java中,您将使用相应的对象,即PrivateKey来加载它
使用适用于.NET的
答案 7 :(得分:-1)
您可以在http://pages.infinit.net/ctech/20040812-0816.html找到示例代码,它对我有用。