Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
634 views
in Technique[技术] by (71.8m points)

encryption - How to parse(Convert to RSAParameters) X.509 private key in C#?

I'm working on an encryption channel to encrypt the communication between two devices. So I'm creating a helper class to do the encryption and decryption. I've googled a lot and found a piece of code that can parse RSA Public Key Into RSACryptoServiceProvider.

This is the code:

public static RSACryptoServiceProvider DecodeX509PublicKey(byte[] x509key)
{
    byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
    byte[] seq = new byte[15];
    MemoryStream mem = new MemoryStream(x509key);
    BinaryReader binr = new BinaryReader(mem);
    byte bt = 0;
    ushort twobytes = 0;

    try
    {

        twobytes = binr.ReadUInt16();
        if (twobytes == 0x8130)
            binr.ReadByte();
        else if (twobytes == 0x8230)
            binr.ReadInt16();
        else
            return null;

        seq = binr.ReadBytes(15);
        if (!CompareBytearrays(seq, SeqOID))
            return null;

        twobytes = binr.ReadUInt16();
        if (twobytes == 0x8103)
            binr.ReadByte();
        else if (twobytes == 0x8203)
            binr.ReadInt16();
        else
            return null;

        bt = binr.ReadByte();
        if (bt != 0x00)
            return null;

        twobytes = binr.ReadUInt16();
        if (twobytes == 0x8130)
            binr.ReadByte();
        else if (twobytes == 0x8230)
            binr.ReadInt16();
        else
            return null;

        twobytes = binr.ReadUInt16();
        byte lowbyte = 0x00;
        byte highbyte = 0x00;

        if (twobytes == 0x8102)
            lowbyte = binr.ReadByte();
        else if (twobytes == 0x8202)
        {
            highbyte = binr.ReadByte();
            lowbyte = binr.ReadByte();
        }
        else
            return null;
        byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
        int modsize = BitConverter.ToInt32(modint, 0);

        byte firstbyte = binr.ReadByte();
        binr.BaseStream.Seek(-1, SeekOrigin.Current);

        if (firstbyte == 0x00)
        {
            binr.ReadByte();
            modsize -= 1;
        }

        byte[] modulus = binr.ReadBytes(modsize);

        if (binr.ReadByte() != 0x02)
            return null;
        int expbytes = (int)binr.ReadByte();
        byte[] exponent = binr.ReadBytes(expbytes);

        RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
        RSAParameters RSAKeyInfo = new RSAParameters();
        RSAKeyInfo.Modulus = modulus;
        RSAKeyInfo.Exponent = exponent;
        RSA.ImportParameters(RSAKeyInfo);
        return RSA;
    }
    catch (Exception)
    {
        return null;
    }

    finally { binr.Close(); }
}

It works awesome with a public key. But my question is how can I parse a X.509 private key? I'm not really familiar with structure of the RSA key.

The keys are generated from node-rsa in node.js

Thanks in advance. <3

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You currently have a functioning reader for the RSAPublicKey structure. That structure, and the RSAPrivateKey structure, can be found in (RFC 3447 Appendix A.1)[https://www.rfc-editor.org/rfc/rfc3447#appendix-A].

.NET does not support "multi-prime" (more than 2) RSA (but neither does anyone else), so you can stick with the version 0 format. The field names should be clear from the alternative names in the comments, but if it is unclear:

  • modulus -> Modulus
  • publicExponent -> Exponent
  • privateExponent -> D
  • prime1 -> P
  • prime2 -> Q
  • exponent1 -> DP
  • exponent2 -> DQ
  • coefficient -> InverseQ

You will also need to add (or remove) padding zeros (on the left) to the values such that

  • D.Length == Modulus.Length
  • hm = (Modulus.Length + 1) / 2 // half round up
  • P, Q, DP, DQ, InverseQ each have Length == hm.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...