Skip to content

Instantly share code, notes, and snippets.

@Ariex
Forked from misaxi/BytesExtensions.cs
Last active December 16, 2016 00:53
Show Gist options
  • Save Ariex/e82ac4ed1c492068d262761d5b621fa6 to your computer and use it in GitHub Desktop.
Save Ariex/e82ac4ed1c492068d262761d5b621fa6 to your computer and use it in GitHub Desktop.
using System;
namespace RsaKeyConverter.Converter
{
public static class BytesExtensions
{
public static string ToBase64(this byte[] bytes)
{
return Convert.ToBase64String(bytes);
}
}
}
using System.Security.Cryptography;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
namespace RsaKeyConverter.Converter
{
public static class RsaExtensions
{
public static AsymmetricCipherKeyPair GetKeyPair(this RSA rsa)
{
try
{
return DotNetUtilities.GetRsaKeyPair(rsa);
}
catch
{
return null;
}
}
public static RsaKeyParameters GetPublicKey(this RSA rsa)
{
try
{
return DotNetUtilities.GetRsaPublicKey(rsa);
}
catch
{
return null;
}
}
}
}
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Threading.Tasks;
namespace RsaKeyConverter.Converter
{
public static class RsaKeyConverter
{
public static string XmlToPem(string xml)
{
using (RSA rsa = RSA.Create())
{
rsa.FromXmlString(xml);
AsymmetricCipherKeyPair keyPair = rsa.GetKeyPair(); // try get private and public key pair
if (keyPair != null) // if XML RSA key contains private key
{
using (var ms = new MemoryStream())
using (var sw = new StreamWriter(ms))
{
var pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(sw);
pemWriter.WriteObject(keyPair.Private);
sw.Flush();
ms.Position = 0;
return new StreamReader(ms).ReadToEnd();
}
}
RsaKeyParameters publicKey = rsa.GetPublicKey(); // try get public key
if (publicKey != null) // if XML RSA key contains public key
{
using (var ms = new MemoryStream())
using (var sw = new StreamWriter(ms))
{
var pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(sw);
pemWriter.WriteObject(publicKey);
sw.Flush();
ms.Position = 0;
return new StreamReader(ms).ReadToEnd();
}
}
}
throw new InvalidKeyException("Invalid RSA Xml Key");
}
public static async Task<string> XmlToPemAsync(string xml)
{
return await Task.Run(() => XmlToPem(xml));
}
public static string PemToXml(string pem)
{
if (pem.StartsWith("-----BEGIN RSA PRIVATE KEY-----")
|| pem.StartsWith("-----BEGIN PRIVATE KEY-----"))
{
return GetXmlRsaKey(pem, obj =>
{
if ((obj as RsaPrivateCrtKeyParameters) != null)
return DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)obj);
var keyPair = (AsymmetricCipherKeyPair)obj;
return DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)keyPair.Private);
}, rsa => rsa.ToXmlString(true));
}
if (pem.StartsWith("-----BEGIN PUBLIC KEY-----"))
{
return GetXmlRsaKey(pem, obj =>
{
var publicKey = (RsaKeyParameters)obj;
return DotNetUtilities.ToRSA(publicKey);
}, rsa => rsa.ToXmlString(false));
}
throw new InvalidKeyException("Unsupported PEM format...");
}
public static async Task<string> PemToXmlAsync(string pem)
{
return await Task.Run(() => PemToXml(pem));
}
private static string GetXmlRsaKey(string pem, Func<object, RSA> getRsa, Func<RSA, string> getKey)
{
using (var ms = new MemoryStream())
using (var sw = new StreamWriter(ms))
using (var sr = new StreamReader(ms))
{
sw.Write(pem);
sw.Flush();
ms.Position = 0;
var pr = new PemReader(sr);
object keyPair = pr.ReadObject();
using (RSA rsa = getRsa(keyPair))
{
var xml = getKey(rsa);
return xml;
}
}
}
}
}
@Ariex
Copy link
Author

Ariex commented Dec 16, 2016

somehow when I use the origin XmlToPem to get Pem for private key, it throws exception when using PemToXml method. so I rewrite the XmlToPem method to use build-in PemWriter.WriteObject(object) to create Pem text.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment