.net - How to load RSA Public Key generated by openSSL into RSACryptoServiceProvider? -


i writing .net class reads cookie our central authentication server. contains userid, timestamps , signature created openssl_sign() using 2048 bit rsa key , sha1 hash.

the current public key provided in openssl pem format on server , changes on occasion. cannot read key using .net managed code alone (yet) , worked out following procedure working:

  • extract exponent , modulus public key
  • check key still 2048 bit
  • store key length, exponent modulus in source, compile , deploy (drop leading zeroes modulus make work)

the class creates new rsacryptoserviceprovider(2048) , feeds public components using rsaparameters structure csp. verification of signature succeeds.

i working without me creating, compiling , deploying new assembly each time key changes. make things interesting stick managed code (rules out examples found). sounds perfect internal asn.1 reader when creating instance of asnencodeddata(oid, data) oid found match, rsa aka 1.2.840.113549.1.1.1, did not work , produced raw bytes only.

added: former public key

-----begin public key-----
mfwwdqyjkozihvcnaqebbqadswawsajbamw90o6c17fapbs35aukolsy7ki0foe1
c08y5hqgz0rmxoocv4nhshybm2hvx2qsr5olqtergwdmxou+vwu1gxucaweaaq==
-----end public key-----

i found pempublic.cs wich seems solve using (as seems) sourcecode openssl. leave question open see if there other solutions.

to load private key let's use code:

private rsacryptoserviceprovider getprivatekey(string privatekey)     {         byte[] privkey = convert.frombase64string(privatekey);         byte[] modulus, e, d, p, q, dp, dq, iq;          // --------- set stream decode asn.1 encoded rsa private key ------         memorystream mem = new memorystream(privkey);         binaryreader binr = new binaryreader(mem);  //wrap memory stream binaryreader easy reading         byte bt = 0;         ushort twobytes = 0;         int elems = 0;         try         {             twobytes = binr.readuint16();             if (twobytes == 0x8130) //data read little endian order (actual data order sequence 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;               //------ private key components 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);              // ------- create rsacryptoserviceprovider instance , initialize public key -----             cspparameters cspparameters = new cspparameters();             cspparameters.flags = cspproviderflags.usemachinekeystore;             rsacryptoserviceprovider rsa = new rsacryptoserviceprovider(1024, cspparameters);             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 ex)         {             return null;         }                 {             binr.close();         }     } 

to load public key let's use code:

private rsacryptoserviceprovider getpublickey(string publickeystring)     {         // encoded oid sequence  pkcs #1 rsaencryption szoid_rsa_rsa = "1.2.840.113549.1.1.1"         byte[] seqoid = {0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00} ;         byte[] x509key;         byte[] seq = new byte[15];         int x509size;          x509key = convert.frombase64string(publickeystring);         x509size = x509key.length;          // ---------  set stream read asn.1 encoded subjectpublickeyinfo blob  ------         memorystream mem = new memorystream(x509key);         binaryreader binr = new binaryreader(mem);    //wrap memory stream binaryreader easy reading         byte bt = 0;         ushort twobytes = 0;          try         {              twobytes = binr.readuint16();             if (twobytes == 0x8130) //data read little endian order (actual data order sequence 30 81)                 binr.readbyte();    //advance 1 byte             else if (twobytes == 0x8230)                 binr.readint16();   //advance 2 bytes             else                 return null;              seq = binr.readbytes(15);       //read sequence oid             if (!comparebytearrays(seq, seqoid))    //make sure sequence oid correct                 return null;              twobytes = binr.readuint16();             if (twobytes == 0x8103) //data read little endian order (actual data order bit string 03 81)                 binr.readbyte();    //advance 1 byte             else if (twobytes == 0x8203)                 binr.readint16();   //advance 2 bytes             else                 return null;              bt = binr.readbyte();             if (bt != 0x00)     //expect null byte next                 return null;              twobytes = binr.readuint16();             if (twobytes == 0x8130) //data read little endian order (actual data order sequence 30 81)                 binr.readbyte();    //advance 1 byte             else if (twobytes == 0x8230)                 binr.readint16();   //advance 2 bytes             else                 return null;              twobytes = binr.readuint16();             byte lowbyte = 0x00;             byte highbyte = 0x00;              if (twobytes == 0x8102) //data read little endian order (actual data order integer 02 81)                 lowbyte = binr.readbyte();  // read next bytes bytes in modulus             else if (twobytes == 0x8202)             {                 highbyte = binr.readbyte(); //advance 2 bytes                 lowbyte = binr.readbyte();             }             else                 return null;             byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };   //reverse byte order since asn.1 key uses big endian order             int modsize = bitconverter.toint32(modint, 0);              int firstbyte = binr.peekchar();             if (firstbyte == 0x00)             {   //if first byte (highest order) of modulus zero, don't include                 binr.readbyte();    //skip null byte                 modsize -= 1;   //reduce modulus buffer size 1             }              byte[] modulus = binr.readbytes(modsize);   //read modulus bytes              if (binr.readbyte() != 0x02)            //expect integer exponent data                 return null;             int expbytes = (int)binr.readbyte();        // should need 1 byte actual exponent data (for useful values)             byte[] exponent = binr.readbytes(expbytes);              // ------- create rsacryptoserviceprovider instance , initialize public key -----             rsacryptoserviceprovider rsa = new rsacryptoserviceprovider();             rsaparameters rsakeyinfo = new rsaparameters();             rsakeyinfo.modulus = modulus;             rsakeyinfo.exponent = exponent;             rsa.importparameters(rsakeyinfo);              return rsa;         }                  {             binr.close();         }     } 

you can read original post here more detail


Comments

Popular posts from this blog

c# - how to write client side events functions for the combobox items -

exception - Python, pyPdf OCR error: pyPdf.utils.PdfReadError: EOF marker not found -