C# RSA Public Key Output Not Correct

Unfortunately, the code in the answer you referenced isn't really correct - it exports a private key PEM format, but with only the public key fields correctly set, this is not the same as exporting an RSA public key in standard format.

I actually wrote the code in the other answer to that question, and at the time wrote a mode for exporting the public key in the standard format, but didn't include it in that answer as it wasn't required. Here it is:

private static void ExportPublicKey(RSACryptoServiceProvider csp, TextWriter outputStream)
{
    var parameters = csp.ExportParameters(false);
    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);
            innerWriter.Write((byte)0x30); // SEQUENCE
            EncodeLength(innerWriter, 13);
            innerWriter.Write((byte)0x06); // OBJECT IDENTIFIER
            var rsaEncryptionOid = new byte[] { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
            EncodeLength(innerWriter, rsaEncryptionOid.Length);
            innerWriter.Write(rsaEncryptionOid);
            innerWriter.Write((byte)0x05); // NULL
            EncodeLength(innerWriter, 0);
            innerWriter.Write((byte)0x03); // BIT STRING
            using (var bitStringStream = new MemoryStream())
            {
                var bitStringWriter = new BinaryWriter(bitStringStream);
                bitStringWriter.Write((byte)0x00); // # of unused bits
                bitStringWriter.Write((byte)0x30); // SEQUENCE
                using (var paramsStream = new MemoryStream())
                {
                    var paramsWriter = new BinaryWriter(paramsStream);
                    EncodeIntegerBigEndian(paramsWriter, parameters.Modulus); // Modulus
                    EncodeIntegerBigEndian(paramsWriter, parameters.Exponent); // Exponent
                    var paramsLength = (int)paramsStream.Length;
                    EncodeLength(bitStringWriter, paramsLength);
                    bitStringWriter.Write(paramsStream.GetBuffer(), 0, paramsLength);
                }
                var bitStringLength = (int)bitStringStream.Length;
                EncodeLength(innerWriter, bitStringLength);
                innerWriter.Write(bitStringStream.GetBuffer(), 0, bitStringLength);
            }
            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 PUBLIC KEY-----");
        for (var i = 0; i < base64.Length; i += 64)
        {
            outputStream.WriteLine(base64, i, Math.Min(64, base64.Length - i));
        }
        outputStream.WriteLine("-----END PUBLIC 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]);
        }
    }
}

Comments

  1. Sterling

    • 2019/7/16

    that is ideal for developing firmware or portable applications. Originally intended for writing system software, C was developed at Bell Labs by Dennis Ritchie for the Unix Operating System in the early 1970s.

  2. Alfredo

    • 2015/7/5

    News Citigroup Inc.C. Consumer-Service Stocks Have Underperformed. Why It's Their Time to Shine. The Price to Earnings (P/E) ratio, a key valuation measure, is calculated by dividing the stock's

  3. Ari

    • 2015/5/30

    which form a major part of Windows, UNIX, and Linux operating system. C is a general-purpose programming language and can efficiently work on enterprise applications, games, graphics, and applications requiring calculations, etc.

  4. Anson

    • 2015/1/7

    Citigroup, Inc. Common Stock (C) Stock Quotes - Nasdaq offers stock quotes & market activity data for US and global markets.

  5. Lucca

    • 2015/12/2

    , and it still reigns as one of the fundamental building blocks of our software-defined world. But sometimes a technology sticks around because people just haven't gotten around to replacing it.

  6. Atreus

    • 2020/8/14

    Discover historical prices for C stock on Yahoo Finance. View daily, weekly or monthly format back to when Citigroup, Inc. stock was issued.

  7. Adan

    • 2017/10/3

    C is a powerful general-purpose programming language. It can be used to develop software like operating systems, databases, compilers, and so on.

  8. Brown

    • 2018/2/2

    The Centers for Disease Control and Prevention (CDC) cannot attest to the accuracy of a non-federal website. Linking to a non-federal website does not constitute an endorsement by CDC or any of its employees of the sponsors or the information and products presented on the website. You will be

  9. Lucca

    • 2017/3/7

    C programming is a general-purpose, procedural, imperative computer programming language developed in 1972 by Dennis M. Ritchie at the Bell Telephone 

  10. Hayden

    • 2017/5/14

    c = a + b; Here, ‘+’ is the operator known as addition operator and ‘a’ and ‘b’ are operands. The addition operator tells the compiler to add both of the operands ‘a’ and ‘b’. C/C++ has many built-in operator types and they are classified as follows:

  11. Turner

    • 2015/5/5

    learn-c.org is a free interactive C tutorial for people who want to learn C, fast.

  12. King

    • 2018/5/17

    C. diff (also known as Clostridioides difficile or C. difficile) is a germ (bacterium) that causes severe diarrhea and colitis (an inflammation of the colon). It’s estimated to cause almost half a million infections in the United States each year. About 1 in 6 patients who get C. diff will get it again in the subsequent 2-8 weeks.

  13. Dangelo

    • 2021/6/7

    Amazon.com: C Programming Language, 2nd Edition: 8601410794231: Brian W. Kernighan, Dennis M. Ritchie: Books.

  14. Jay

    • 2017/6/16

    C is considered as a middle-level language because it supports the feature of both low-level and high-level languages. C language program is converted into 

  15. Jeremiah

    • 2020/12/4

    The best site for C and C++ programming. Popular, beginner-friendly C and C++ tutorials to help you become an expert!

Comments are closed.

Recent Posts