Convert RSA public key from XML to PEM format (.NET) (Part 1)

Probably the people working with asymmetric cryptography have struggled for a way to convert the XML format of the RSA public key to the more widely used PEM format. Although there is a solution for the reverse transformation (from PEM to XML) on the following address I have not found anywhere a solution to this problem.

So after a bit of reading and examining the code in the above mentioned link I've come up with a small code that does the conversion and the resulting key is parsed OK from OpenSSL.

NOTE: you will need to download and use the assemblies from

NOTE2: The code bellow only works under Windows 7 and Windows Server 2008 R2, because it uses the Cryptographic Next Generation (CNG) that were added only to those operating systems.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.IO;

namespace ConsoleApplication1
    class Program
        static void Main(string[] args)
            RSACng rsa = new RSACng();
            X509Certificate2 cert;
            List<byte> arrBinaryPublicKey = new List<byte>();

            byte[] oid = 
            { 0x30, 0xD, 0x6, 0x9, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0xD, 0x1, 0x1, 0x1, 0x5, 0x0 }; // Object ID for RSA


            cert = rsa.Key.CreateSelfSignedCertificate(new X500DistinguishedName("CN=something"));

            //Transform the public key to PEM Base64 Format
            arrBinaryPublicKey = cert.PublicKey.EncodedKeyValue.RawData.ToList();
            arrBinaryPublicKey.Insert(0, 0x0); // Add NULL value

            CalculateAndAppendLength(ref arrBinaryPublicKey);

            arrBinaryPublicKey.Insert(0, 0x3);
            arrBinaryPublicKey.InsertRange(0, oid);

            CalculateAndAppendLength(ref arrBinaryPublicKey);

            arrBinaryPublicKey.Insert(0, 0x30);
            //End Transformation

            Console.WriteLine("-----BEGIN PUBLIC KEY-----");
            Console.WriteLine("-----END PUBLIC KEY-----");


        private static void CalculateAndAppendLength(ref List<byte> arrBinaryData)
            int nLen;
            nLen = arrBinaryData.Count;
            if (nLen <= byte.MaxValue)
                arrBinaryData.Insert(0, Convert.ToByte(nLen));
                arrBinaryData.Insert(0, 0x81); //This byte means that the length fits in one byte
                arrBinaryData.Insert(0, Convert.ToByte(nLen % (byte.MaxValue + 1)));
                arrBinaryData.Insert(0, Convert.ToByte(nLen / (byte.MaxValue + 1)));
                arrBinaryData.Insert(0, 0x82); //This byte means that the length fits in two byte



Compiled source available here

Labels: , , , , ,