Example #1
0
        private static RSACryptoServiceProvider DecodePrivateKeyInfo(byte[] pkcs8)
        {
            // encoded OID sequence for  PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
            // this byte[] includes the sequence byte and terminal encoded null
            byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
            byte[] seq    = new byte[15];
            // ---------  Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob  ------
            MemoryStream mem       = new MemoryStream(pkcs8);
            int          lenstream = (int)mem.Length;
            BinaryReader binr      = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
            byte         bt        = 0;
            ushort       twobytes  = 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);
                }


                bt = binr.ReadByte();
                if (bt != 0x02)
                {
                    return(null);
                }

                twobytes = binr.ReadUInt16();

                if (twobytes != 0x0001)
                {
                    return(null);
                }

                seq = binr.ReadBytes(15);                   //read the Sequence OID
                if (!Binary.CompareBytearrays(seq, SeqOID)) //make sure Sequence for OID is correct
                {
                    return(null);
                }

                bt = binr.ReadByte();
                if (bt != 0x04) //expect an Octet string
                {
                    return(null);
                }

                bt = binr.ReadByte();           //read next byte, or next 2 bytes is  0x81 or 0x82; otherwise bt is the byte count
                if (bt == 0x81)
                {
                    binr.ReadByte();
                }
                else
                if (bt == 0x82)
                {
                    binr.ReadUInt16();
                }
                //------ at this stage, the remaining sequence should be the RSA private key

                byte[] rsaprivkey = binr.ReadBytes((int)(lenstream - mem.Position));
                RSACryptoServiceProvider rsacsp = DecodeRSAPrivateKey(rsaprivkey);
                return(rsacsp);
            }

            catch (Exception)
            {
                return(null);
            }

            finally { binr.Close(); }
        }
Example #2
0
        private 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   = Binary.GetIntegerSize(binr);
                MODULUS = binr.ReadBytes(elems);

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

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

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

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

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

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

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

                Console.WriteLine("showing components ..");

                // ------- 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(); }
        }
Example #3
0
        private static RSACryptoServiceProvider DecodePrivateKey(byte[] keyBytes, string password)
        {
            // encoded OID sequence for  PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
            // this byte[] includes the sequence byte and terminal encoded null
            byte[] OIDpkcs5PBES2  = { 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0D };
            byte[] OIDpkcs5PBKDF2 = { 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0C };
            byte[] OIDdesEDE3CBC  = { 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x07 };
            byte[] seqdes         = new byte[10];
            byte[] seq            = new byte[11];
            byte[] salt;
            byte[] IV;
            byte[] encryptedpkcs8;
            byte[] pkcs8;

            int saltsize, ivsize, encblobsize;
            int iterations;

            // ---------  Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob  ------
            MemoryStream mem       = new MemoryStream(keyBytes);
            BinaryReader binReader = new BinaryReader(mem);    //wrap Memory Stream with BinaryReader for easy reading
            byte         bt        = 0;
            ushort       twobytes  = 0;

            try
            {
                twobytes = binReader.ReadUInt16();
                if (twobytes == 0x8130)
                {
                    //data read as little endian order (actual data order for Sequence is 30 81)
                    binReader.ReadByte();       //advance 1 byte
                }
                else if (twobytes == 0x8230)
                {
                    binReader.ReadInt16();      //advance 2 bytes
                }
                else
                {
                    return(null);
                }

                twobytes = binReader.ReadUInt16();      //inner sequence
                if (twobytes == 0x8130)
                {
                    binReader.ReadByte();
                }
                else if (twobytes == 0x8230)
                {
                    binReader.ReadInt16();
                }


                seq = binReader.ReadBytes(11);                     //read the Sequence OID
                if (!Binary.CompareBytearrays(seq, OIDpkcs5PBES2)) //is it a OIDpkcs5PBES2 ?
                {
                    return(null);
                }

                twobytes = binReader.ReadUInt16();      //inner sequence for pswd salt
                if (twobytes == 0x8130)
                {
                    binReader.ReadByte();
                }
                else if (twobytes == 0x8230)
                {
                    binReader.ReadInt16();
                }

                twobytes = binReader.ReadUInt16();      //inner sequence for pswd salt
                if (twobytes == 0x8130)
                {
                    binReader.ReadByte();
                }
                else if (twobytes == 0x8230)
                {
                    binReader.ReadInt16();
                }

                seq = binReader.ReadBytes(11);                      //read the Sequence OID
                if (!Binary.CompareBytearrays(seq, OIDpkcs5PBKDF2)) //is it a OIDpkcs5PBKDF2 ?
                {
                    return(null);
                }

                twobytes = binReader.ReadUInt16();
                if (twobytes == 0x8130)
                {
                    binReader.ReadByte();
                }
                else if (twobytes == 0x8230)
                {
                    binReader.ReadInt16();
                }

                bt = binReader.ReadByte();
                if (bt != 0x04)         //expect octet string for salt
                {
                    return(null);
                }
                saltsize = binReader.ReadByte();
                salt     = binReader.ReadBytes(saltsize);

                bt = binReader.ReadByte();
                if (bt != 0x02)         //expect an integer for PBKF2 interation count
                {
                    return(null);
                }

                int itbytes = binReader.ReadByte();     //PBKD2 iterations should fit in 2 bytes.
                if (itbytes == 1)
                {
                    iterations = binReader.ReadByte();
                }
                else if (itbytes == 2)
                {
                    iterations = 256 * binReader.ReadByte() + binReader.ReadByte();
                }
                else
                {
                    return(null);
                }

                twobytes = binReader.ReadUInt16();
                if (twobytes == 0x8130)
                {
                    binReader.ReadByte();
                }
                else if (twobytes == 0x8230)
                {
                    binReader.ReadInt16();
                }


                seqdes = binReader.ReadBytes(10);                     //read the Sequence OID
                if (!Binary.CompareBytearrays(seqdes, OIDdesEDE3CBC)) //is it a OIDdes-EDE3-CBC ?
                {
                    return(null);
                }

                bt = binReader.ReadByte();
                if (bt != 0x04)         //expect octet string for IV
                {
                    return(null);
                }
                ivsize = binReader.ReadByte();  // IV byte size should fit in one byte (24 expected for 3DES)
                IV     = binReader.ReadBytes(ivsize);

                bt = binReader.ReadByte();
                if (bt != 0x04)         // expect octet string for encrypted PKCS8 data
                {
                    return(null);
                }


                bt = binReader.ReadByte();

                if (bt == 0x81)
                {
                    encblobsize = binReader.ReadByte(); // data size in next byte
                }
                else if (bt == 0x82)
                {
                    encblobsize = 256 * binReader.ReadByte() + binReader.ReadByte();
                }
                else
                {
                    encblobsize = bt;           // we already have the data size
                }
                encryptedpkcs8 = binReader.ReadBytes(encblobsize);
                SecureString secpswd = new SecureString();
                foreach (char c in password)
                {
                    secpswd.AppendChar(c);
                }

                pkcs8 = DecryptPBDK2(encryptedpkcs8, salt, IV, secpswd, iterations);
                if (pkcs8 == null)      // probably a bad pswd entered.
                {
                    return(null);
                }

                RSACryptoServiceProvider rsa = DecodePrivateKeyInfo(pkcs8);
                return(rsa);
            }

            catch (Exception)
            {
                return(null);
            }
            finally { binReader.Close(); }
        }