你不能这样做。
.NET不支持它。
你看,PEM编码支持多种密钥类型(例如ECDSA)。
因此,如果有人提供了一种从PEM文件中读取.NET RSA密钥的方法,如果PEM也具有D、P、Q、DP、DQ、InverseQ,则您可以读取该RSA密钥,但这与读取PEM还有很长的路要走。
另外,RSA的.NET版本仅基于(Modulus、Exponent和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
{
public class KeyImportExport
{
public static PrivatePublicPemKeyPair GetPemKeyPair(Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair keyPair)
{
PrivatePublicPemKeyPair result = new PrivatePublicPemKeyPair();
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();
}
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();
}
return result;
}
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;
}
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;
}
return keyPair.Private;
}
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;
}
return keyPair;
}
public static Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair ReadKeyPairFromFile(string fileName)
{
Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair KeyPair = null;
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();
}
}
return KeyPair;
}
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();
}
return keyParameter;
}
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();
}
System.Console.WriteLine(privateKey);
}
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());
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);
}
}
}
哦,还有关于PFX的操作方法:
namespace SelfSignedCertificateGenerator
{
public class PfxData
{
public Org.BouncyCastle.X509.X509Certificate Certificate;
public Org.BouncyCastle.Crypto.AsymmetricKeyParameter PrivateKey;
}
public class PfxFile
{
public static void Create(
string fileName
, Org.BouncyCastle.X509.X509Certificate certificate
, Org.BouncyCastle.Crypto.AsymmetricKeyParameter privateKey
, string password = "")
{
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";
Org.BouncyCastle.Asn1.Pkcs.PrivateKeyInfo keyInfo = Org.BouncyCastle.Pkcs.PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey);
Org.BouncyCastle.Pkcs.Pkcs12StoreBuilder builder = new Org.BouncyCastle.Pkcs.Pkcs12StoreBuilder();
builder.SetUseDerEncoding(true);
Org.BouncyCastle.Pkcs.Pkcs12Store store = builder.Build();
store.SetCertificateEntry(friendlyName, certEntry);
store.SetKeyEntry(
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())
{
store.Save(stream, password == null ? "".ToCharArray() : password.ToCharArray(), new Org.BouncyCastle.Security.SecureRandom());
pfxBytes = stream.ToArray();
}
#if WITH_MS_PFX
WithMsPfx(pfxBytes, fileName, password);
#else
byte[] result = Org.BouncyCastle.Pkcs.Pkcs12Utilities.ConvertToDefiniteLength(pfxBytes);
using (System.IO.BinaryWriter writer = new System.IO.BinaryWriter(System.IO.File.Open(fileName, System.IO.FileMode.Create)))
{
writer.Write(result);
}
#endif
}
private static void WithMsPfx(byte[] pfxBytes, string fileName, string password)
{
System.Security.Cryptography.X509Certificates.X509Certificate2 convertedCertificate =
new System.Security.Cryptography.X509Certificates.X509Certificate2(pfxBytes,
"",
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);
}
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());
}
foreach (string alias in store.Aliases)
{
Org.BouncyCastle.Pkcs.X509CertificateEntry certEntry = store.GetCertificate(alias);
Org.BouncyCastle.X509.X509Certificate cert = certEntry.Certificate;
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
};
}
}
return null;
}
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;
}
}
}