views:

1765

answers:

1

I know this is a similar question to this one but before I head down the Bouncey Castle route, does anyone know if its possible to load an RSA KeyPair from a .pem file (-----BEGIN RSA PRIVATE KEY-----) directly with the .NET 3.5 crypto library without having to go to a 3rd party or roll my own?

+5  A: 

http://www.jensign.com/opensslkey/index.html

with source at http://www.jensign.com/opensslkey/opensslkey.cs

edit: excerpted relevant code:

first, extract the text between the ---- BEGIN ---- and ---- END ---- sections, and base64-decode it into a byte array (see link above for details), then pass it to:

//------- Parses binary ans.1 RSA private key; returns RSACryptoServiceProvider  ---
public static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
{
 byte[] MODULUS, E, D, P, Q, DP, DQ, IQ ;

// ---------  Set up stream to decode the asn.1 encoded RSA private key  ------
 MemoryStream  mem = new MemoryStream(privkey) ;
 BinaryReader binr = new BinaryReader(mem) ;    //wrap Memory Stream with BinaryReader for easy reading
 byte bt = 0;
 ushort twobytes = 0;
 int elems = 0;
 try {
  twobytes = binr.ReadUInt16();
  if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
   binr.ReadByte(); //advance 1 byte
  else if (twobytes == 0x8230)
   binr.ReadInt16(); //advance 2 bytes
  else
   return null;

  twobytes = binr.ReadUInt16();
  if (twobytes != 0x0102) //version number
   return null;
  bt = binr.ReadByte();
  if (bt !=0x00)
   return null;


//------  all private key components are Integer sequences ----
  elems = GetIntegerSize(binr);
  MODULUS = binr.ReadBytes(elems);

  elems = GetIntegerSize(binr);
  E = binr.ReadBytes(elems) ;

  elems = GetIntegerSize(binr);
  D = binr.ReadBytes(elems) ;

  elems = GetIntegerSize(binr);
  P = binr.ReadBytes(elems) ;

  elems = GetIntegerSize(binr);
  Q = binr.ReadBytes(elems) ;

  elems = GetIntegerSize(binr);
  DP = binr.ReadBytes(elems) ;

  elems = GetIntegerSize(binr);
  DQ = binr.ReadBytes(elems) ;

  elems = GetIntegerSize(binr);
  IQ = binr.ReadBytes(elems) ;

  Console.WriteLine("showing components ..");
  if (verbose) {
   showBytes("\nModulus", MODULUS) ;
   showBytes("\nExponent", E);
   showBytes("\nD", D);
   showBytes("\nP", P);
   showBytes("\nQ", Q);
   showBytes("\nDP", DP);
   showBytes("\nDQ", DQ);
   showBytes("\nIQ", IQ);
  }

// ------- create RSACryptoServiceProvider instance and initialize with public key -----
  RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
  RSAParameters RSAparams = new RSAParameters();
  RSAparams.Modulus =MODULUS;
  RSAparams.Exponent = E;
  RSAparams.D = D;
  RSAparams.P = P;
  RSAparams.Q = Q;
  RSAparams.DP = DP;
  RSAparams.DQ = DQ;
  RSAparams.InverseQ = IQ;
  RSA.ImportParameters(RSAparams);
  return RSA;
 }
 catch (Exception) {
  return null;
 }
 finally {
  binr.Close();
 }
}
Stobor
Never mind; that was the solution from the other question.
Stobor
I'll give this a go...what did you mean that was the solution for the other question? The accepted answer to question I referenced used the Bouncy Castle library (which works for me as well by the way). I am just wanting to minimise my reliance on 3rd party libraries where possible. Even those with very generous licensing.
Tim Jarvis
@Tim Jarvis: the top answer for the other question currently is "You might take a look at JavaScience's source for OpenSSLKey." That's the same as what I've linked and copied above. (BouncyCastle is how the questioner answered it themselves, not the accepted answer...)
Stobor
ah, of course. Cheers. Haven't tried this yet...about to go have some lunch. Will let you know how it goes. (thx by the way +1 with maybe a +15 to come)
Tim Jarvis
Well, I don't know why this didn't work for the poster of the other question, but it worked fine for me. (with a couple minor mods.)
Tim Jarvis