Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Export Private/Public RSA key from RSACryptoServiceProvider to PEM string

I have an instance of System.Security.Cryptography.RSACryptoServiceProvider, i need to export it's key to a PEM string - like this:

-----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDUNPB6Lvx+tlP5QhSikADl71AjZf9KN31qrDpXNDNHEI0OTVJ1 OaP2l56bSKNo8trFne1NK/B4JzCuNP8x6oGCAG+7bFgkbTMzV2PCoDCRjNH957Q4 Gxgx1VoS6PjD3OigZnx5b9Hebbp3OrTuqNZaK/oLPGr5swxHILFVeHKupQIDAQAB AoGAQk3MOZEGyZy0fjQ8eFKgRTfSBU1wR8Mwx6zKicbAotq0CBz2v7Pj3D+higlX LYp7+rUOmUc6WoB8QGJEvlb0YZVxUg1yDLMWYPE7ddsHsOkBIs7zIyS6cqhn0yZD VTRFjVST/EduvpUOL5hbyLSwuq+rbv0iPwGW5hkCHNEhx2ECQQDfLS5549wjiFXF gcio8g715eMT+20we3YmgMJDcviMGwN/mArvnBgBQsFtCTsMoOxm68SfIrBYlKYy BsFxn+19AkEA82q83pmcbGJRJ3ZMC/Pv+/+/XNFOvMkfT9qbuA6Lv69Z1yk7I1ie FTH6tOmPUu4WsIOFtDuYbfV2pvpqx7GuSQJAK3SnvRIyNjUAxoF76fGgGh9WNPjb DPqtSdf+e5Wycc18w+Z+EqPpRK2T7kBC4DWhcnTsBzSA8+6V4d3Q4ugKHQJATRhw a3xxm65kD8CbA2omh0UQQgCVFJwKy8rsaRZKUtLh/JC1h1No9kOXKTeUSmrYSt3N OjFp7OHCy84ihc8T6QJBANe+9xkN9hJYNK1pL1kSwXNuebzcgk3AMwHh7ThvjLgO jruxbM2NyMM5tl9NZCgh1vKc2v5VaonqM1NBQPDeTTw= -----END RSA PRIVATE KEY----- 

But there is no such option according to the MSDN documentation, there is only some kind of XML export. I can't use any third party libraries like BouncyCastle. Is there any way to generate this string?

like image 326
nidzo732 Avatar asked May 19 '14 09:05

nidzo732


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

Which language is C?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.

Is C language easy?

Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.

What is C of computer?

The C programming language is a procedural and general-purpose language that provides low-level access to system memory. A program written in C must be run through a C compiler to convert it into an executable that a computer can run.


1 Answers

Please note: The code below is for exporting a private key. If you are looking to export the public key, please refer to my answer given here.

The PEM format is simply the ASN.1 DER encoding of the key (per PKCS#1) converted to Base64. Given the limited number of fields needed to represent the key, it's pretty straightforward to create quick-and-dirty DER encoder to output the appropriate format then Base64 encode it. As such, the code that follows is not particularly elegant, but does the job:

private static void ExportPrivateKey(RSACryptoServiceProvider csp, TextWriter outputStream) {     if (csp.PublicOnly) throw new ArgumentException("CSP does not contain a private key", "csp");     var parameters = csp.ExportParameters(true);     using (var stream = new MemoryStream())     {         var writer = new BinaryWriter(stream);         writer.Write((byte)0x30); // SEQUENCE         using (var innerStream = new MemoryStream())         {             var innerWriter = new BinaryWriter(innerStream);             EncodeIntegerBigEndian(innerWriter, new byte[] { 0x00 }); // Version             EncodeIntegerBigEndian(innerWriter, parameters.Modulus);             EncodeIntegerBigEndian(innerWriter, parameters.Exponent);             EncodeIntegerBigEndian(innerWriter, parameters.D);             EncodeIntegerBigEndian(innerWriter, parameters.P);             EncodeIntegerBigEndian(innerWriter, parameters.Q);             EncodeIntegerBigEndian(innerWriter, parameters.DP);             EncodeIntegerBigEndian(innerWriter, parameters.DQ);             EncodeIntegerBigEndian(innerWriter, parameters.InverseQ);             var length = (int)innerStream.Length;             EncodeLength(writer, length);             writer.Write(innerStream.GetBuffer(), 0, length);         }          var base64 = Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length).ToCharArray();         outputStream.WriteLine("-----BEGIN RSA PRIVATE KEY-----");         // Output as Base64 with lines chopped at 64 characters         for (var i = 0; i < base64.Length; i += 64)         {             outputStream.WriteLine(base64, i, Math.Min(64, base64.Length - i));         }         outputStream.WriteLine("-----END RSA PRIVATE KEY-----");     } }  private static void EncodeLength(BinaryWriter stream, int length) {     if (length < 0) throw new ArgumentOutOfRangeException("length", "Length must be non-negative");     if (length < 0x80)     {         // Short form         stream.Write((byte)length);     }     else     {         // Long form         var temp = length;         var bytesRequired = 0;         while (temp > 0)         {             temp >>= 8;             bytesRequired++;         }         stream.Write((byte)(bytesRequired | 0x80));         for (var i = bytesRequired - 1; i >= 0; i--)         {             stream.Write((byte)(length >> (8 * i) & 0xff));         }     } }  private static void EncodeIntegerBigEndian(BinaryWriter stream, byte[] value, bool forceUnsigned = true) {     stream.Write((byte)0x02); // INTEGER     var prefixZeros = 0;     for (var i = 0; i < value.Length; i++)     {         if (value[i] != 0) break;         prefixZeros++;     }     if (value.Length - prefixZeros == 0)     {         EncodeLength(stream, 1);         stream.Write((byte)0);     }     else     {         if (forceUnsigned && value[prefixZeros] > 0x7f)         {             // Add a prefix zero to force unsigned if the MSB is 1             EncodeLength(stream, value.Length - prefixZeros + 1);             stream.Write((byte)0);         }         else         {             EncodeLength(stream, value.Length - prefixZeros);         }         for (var i = prefixZeros; i < value.Length; i++)         {             stream.Write(value[i]);         }     } } 
like image 136
Iridium Avatar answered Sep 19 '22 04:09

Iridium