public static RSAParameters ReadRSAPublicKey(Stream s)
        {
            using (StreamReader sR = new StreamReader(s))
            {
                if (sR.ReadLine() != "-----BEGIN RSA PUBLIC KEY-----")
                {
                    throw new IOException("The data should begin with header: -----BEGIN RSA PUBLIC KEY-----");
                }

                StringBuilder base64Data = new StringBuilder(2048);

                do
                {
                    string line = sR.ReadLine();

                    if (line == "-----END RSA PUBLIC KEY-----")
                    {
                        break;
                    }

                    base64Data.Append(line);
                }while (true);

                return(DEREncoding.DecodeRSAPublicKey(Convert.FromBase64String(base64Data.ToString())));
            }
        }
        public static void WriteRSAPrivateKey(RSAParameters parameters, Stream s)
        {
            byte[] header = Encoding.UTF8.GetBytes("-----BEGIN RSA PRIVATE KEY-----\n");
            byte[] footer = Encoding.UTF8.GetBytes("-----END RSA PRIVATE KEY-----\n");
            byte[] base64data;

            //get base64 encoded DER formatted data
            base64data = Encoding.UTF8.GetBytes(Convert.ToBase64String(DEREncoding.EncodeRSAPrivateKey(parameters)));

            //write PEM format
            s.Write(header, 0, header.Length);

            int offset         = 0;
            int bytesRemaining = base64data.Length;
            int count          = 65;

            while (bytesRemaining > 0)
            {
                if (bytesRemaining < count)
                {
                    count = bytesRemaining;
                }

                s.Write(base64data, offset, count);
                s.WriteByte(0x0A);

                offset         += count;
                bytesRemaining -= count;
            }

            s.Write(footer, 0, footer.Length);
        }
        public static RSAParameters ReadRSAPrivateKey(Stream s)
        {
            using (StreamReader sR = new StreamReader(s))
            {
                if (sR.ReadLine() != "-----BEGIN RSA PRIVATE KEY-----")
                {
                    throw new IOException("The data should begin with header: -----BEGIN RSA PRIVATE KEY-----");
                }

                StringBuilder base64Data = new StringBuilder(2048);

                do
                {
                    string line = sR.ReadLine();

                    if (line == "-----END RSA PRIVATE KEY-----")
                    {
                        break;
                    }

                    base64Data.Append(line);
                }while (true);

                DEREncoding obj = DEREncoding.Decode(Convert.FromBase64String(base64Data.ToString()));

                using (Stream sV = obj.GetValueStream())
                {
                    DEREncoding objVer = DEREncoding.Decode(sV);

                    if (objVer.Value[0] != 0)
                    {
                        throw new IOException("Unknown version number for RSA private key data.");
                    }

                    DEREncoding objModulus  = DEREncoding.Decode(sV);
                    DEREncoding objExponent = DEREncoding.Decode(sV);
                    DEREncoding objD        = DEREncoding.Decode(sV);
                    DEREncoding objP        = DEREncoding.Decode(sV);
                    DEREncoding objQ        = DEREncoding.Decode(sV);
                    DEREncoding objDP       = DEREncoding.Decode(sV);
                    DEREncoding objDQ       = DEREncoding.Decode(sV);
                    DEREncoding objInverseQ = DEREncoding.Decode(sV);

                    RSAParameters parameters = new RSAParameters();

                    parameters.Modulus  = objModulus.GetIntegerValue();
                    parameters.Exponent = objExponent.GetIntegerValue();
                    parameters.D        = objD.GetIntegerValue();
                    parameters.P        = objP.GetIntegerValue();
                    parameters.Q        = objQ.GetIntegerValue();
                    parameters.DP       = objDP.GetIntegerValue();
                    parameters.DQ       = objDQ.GetIntegerValue();
                    parameters.InverseQ = objInverseQ.GetIntegerValue();

                    return(parameters);
                }
            }
        }
        public static void WriteRSAPrivateKey(RSAParameters parameters, Stream s)
        {
            byte[] header = Encoding.UTF8.GetBytes("-----BEGIN RSA PRIVATE KEY-----\n");
            byte[] footer = Encoding.UTF8.GetBytes("-----END RSA PRIVATE KEY-----\n");
            byte[] base64data;

            //encode using DER Encoding
            using (MemoryStream derStream = new MemoryStream())
            {
                using (MemoryStream seqStream = new MemoryStream())
                {
                    DEREncoding.Encode(DEREncodingASN1Type.INTEGER, new byte[] { 0 }, seqStream); //version

                    DEREncoding.EncodeIntegerValue(parameters.Modulus, seqStream);
                    DEREncoding.EncodeIntegerValue(parameters.Exponent, seqStream);
                    DEREncoding.EncodeIntegerValue(parameters.D, seqStream);
                    DEREncoding.EncodeIntegerValue(parameters.P, seqStream);
                    DEREncoding.EncodeIntegerValue(parameters.Q, seqStream);
                    DEREncoding.EncodeIntegerValue(parameters.DP, seqStream);
                    DEREncoding.EncodeIntegerValue(parameters.DQ, seqStream);
                    DEREncoding.EncodeIntegerValue(parameters.InverseQ, seqStream);

                    //write sequence
                    DEREncoding.Encode(DEREncodingASN1Type.SEQUENCE, seqStream.ToArray(), derStream);
                }

                //get base64 formatted DER data
                base64data = Encoding.UTF8.GetBytes(Convert.ToBase64String(derStream.ToArray()));
            }

            //write PEM format
            s.Write(header, 0, header.Length);

            int offset         = 0;
            int bytesRemaining = base64data.Length;
            int count          = 65;

            while (bytesRemaining > 0)
            {
                if (bytesRemaining < count)
                {
                    count = bytesRemaining;
                }

                s.Write(base64data, offset, count);
                s.WriteByte(0x0A);

                offset         += count;
                bytesRemaining -= count;
            }

            s.Write(footer, 0, footer.Length);
        }
        public static RSAParameters DecodeRSAPublicKey(Stream s)
        {
            DEREncoding seq = Decode(s);

            using (Stream seqStream = seq.GetValueStream())
            {
                DEREncoding objModulus  = Decode(seqStream);
                DEREncoding objExponent = Decode(seqStream);

                RSAParameters parameters = new RSAParameters();

                parameters.Modulus  = objModulus.GetIntegerValue();
                parameters.Exponent = objExponent.GetIntegerValue();

                return(parameters);
            }
        }
        public static RSAParameters DecodeRSAPrivateKey(Stream s)
        {
            DEREncoding seq = Decode(s);

            using (Stream seqStream = seq.GetValueStream())
            {
                DEREncoding objVer = Decode(seqStream);

                if (objVer.Value[0] != 0)
                {
                    throw new IOException("Unknown version number for RSA private key data.");
                }

                DEREncoding objModulus  = Decode(seqStream);
                DEREncoding objExponent = Decode(seqStream);
                DEREncoding objD        = Decode(seqStream);
                DEREncoding objP        = Decode(seqStream);
                DEREncoding objQ        = Decode(seqStream);
                DEREncoding objDP       = Decode(seqStream);
                DEREncoding objDQ       = Decode(seqStream);
                DEREncoding objInverseQ = Decode(seqStream);

                RSAParameters parameters = new RSAParameters();

                parameters.Modulus  = objModulus.GetIntegerValue();
                parameters.Exponent = objExponent.GetIntegerValue();
                parameters.D        = objD.GetIntegerValue();
                parameters.P        = objP.GetIntegerValue();
                parameters.Q        = objQ.GetIntegerValue();
                parameters.DP       = objDP.GetIntegerValue();
                parameters.DQ       = objDQ.GetIntegerValue();
                parameters.InverseQ = objInverseQ.GetIntegerValue();

                return(parameters);
            }
        }