C#RSA公钥输出不正确

C#RSA公钥输出不正确

本文介绍了C#RSA公钥输出不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在生成和使用C#发送RSA公钥。它应该是PEM格式的2048位长的密钥。我已经成功地这样做使用以下的(一些输出被缩短)OpenSSL的命令:

  $的openssl genrsa 2048 
生成RSA私钥,2048位长模
..................................... ....................... +++
.................... ........................................ +++ $ b $是为65537( 0x10001)
$ OpenSSL的RSA -pubout
----- BEGIN RSA私钥-----
MIIEowIBAAKCAQEAy1MoBtENHBhYLgwP5Hw / xRGaBPHonApChBPBYD6fiq / QoLXA
RmyMoOjXHsKrrwysYIujXADM2LZ0MlFvPbBulvciWnZwp9CUQPwsZ8xnmBWlHyru
xTxNSvV + E / 6 + 2gMOn3I4bmOSIaLx2Y7nCuaenREvD7Mn0vgFnP7yaN8 / 9va4q8Lo
...
...
y5jiKQKBgGAe9DlkYvR6Edr / gzd6HaF4btQZf6idGdmsYRYc2EMHdRM2NVqlvyLc
MR6rYEuViqLN5XWK6ITOlTPrgAuU6Rl4ZpRlS1ZrfjiUS6dzD / jtJJvsYByC7ZoU
NxIzB0r1hj0TIoedu6NqfRyJ6Fx09U5W81xx77T1EBSg4OCH7eyl
----- END RSA PRIVATE KEY -----
写的RSA密钥
----- BEGIN PUBLIC KEY -----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy1MoBtENHBhYLgwP5Hw /
xRGaBPHonApChBPBYD6fiq / QoLXARmyMoOjXHsKrrwysYIujXADM2LZ0MlFvPbBu
lvciWnZwp9CUQPwsZ8xnmBWlHyruxTxNSvV + E / 6 + 2gMOn3I4bmOSIaLx2Y7nCuae
nREvD7Mn0vgFnP7yaN8 / 9va4q8LoMKlceE5fSYl2QIfC5ZxUtkblbycEWZHLVOkv
+ 4Iz0ibD8KGo0PaiZl0jmn9yYXFy747xmwVun + Z4czO8Nu + OOVxsQF4hu1pKvTUx
9yHH / vk5Wr0I09VFyt3BT / RkecJbAAWB9 / e572T + hhmmJ08wCs29oFa2Cdik9yyE
2QIDAQAB
----- END公钥-----

下面的代码是我用用C#生成公钥

  //变量
CspParameters cspParams = NULL;
的RSACryptoServiceProvider rsaProvider = NULL;
的StreamWriter publicKeyFile = NULL;
串公钥=;


{
//创建目标CSP
cspParams =新CspParameters新的密钥对();
cspParams.ProviderType = 1; // PROV_RSA_FULL
cspParams.Flags = CspProviderFlags.CreateEphemeralKey;
rsaProvider =新的RSACryptoServiceProvider(2048,cspParams);

//出口公钥
结果= ExportPublicKeyToPEMFormat(rsaProvider);
}
赶上(异常前)
{
}

ExportPublicKeyToPEMFormat 的可以从这个主题中找到:



我在C#中的输出看起来是这样的:

  ----- BEGIN PUBLIC KEY ----- 
MIIBKwIBAAKCAQEAzMoaInPQ7nAXGWUY2EEtBcPY / Zvfcqf3Uxr7mFrQaxMjdXYi
DVSPh9XBWJlEhQ9ZGyBMpkWwtkrlDw11g / 7pj + u7KTa5nH1ZB8vCrY3TC + YnFXPQ
Nv5dCzW0Lz + HD04rir2 + K + XQCroy7G68uE9dtkbqa1U7IEWOvejbX + sgzo5ISHA
vCz2DFBInqYNJWfkM8OvLnRYYQ4f8MbmvDEMyaEYPGfQybXAs5eFksqm9pwR0xh4
Oxg / DkDas93lNIf + g00IesHvHuavRm2GX8jAXhrAoZY7nWQZpqS5kwx1kjSwtYEg
Vq4mHcaKIalMAoILSV9ttgqiJ5KVuKIvQJ7wRwIDAQABAgMBAAECAwEAAQIDAQAB
AgMBAAECAwEAAQIDAQAB
----- END PUBLIC KEY -----

使用OpenSSL正确的输出是这样的:

  ----- BEGIN PUBLIC KEY ----- 
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy1MoBtENHBhYLgwP5Hw /
xRGaBPHonApChBPBYD6fiq / QoLXARmyMoOjXHsKrrwysYIujXADM2LZ0MlFvPbBu
lvciWnZwp9CUQPwsZ8xnmBWlHyruxTxNSvV + E / 6 + 2gMOn3I4bmOSIaLx2Y7nCuae
nREvD7Mn0vgFnP7yaN8 / 9va4q8LoMKlceE5fSYl2QIfC5ZxUtkblbycEWZHLVOkv
+ 4Iz0ibD8KGo0PaiZl0jmn9yYXFy747xmwVun + Z4czO8Nu + OOVxsQF4hu1pKvTUx
9yHH / vk5Wr0I09VFyt3BT / RkecJbAAWB9 / e572T + hhmmJ08wCs29oFa2Cdik9yyE
2QIDAQAB
----- END PUBLIC KEY -----

显然有一些与两个公钥的格式不同。



OpenSSL的关键始终starst以
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA



我用
MIIBKwIBAAKCAQEA


解决方案

不幸的是,代码中的接听键启动你引用的是不是真的正确的 - 它导出的私人的键PEM格式,但只有公共键字段设置正确,这是不一样的出口标准格式的RSA公钥

其实我写的代码在这个问题,并在当时写了一个模式,出口的标准格式的公钥,但因为它不是必需的不包括在这个问题的答案。它使用对方的回答提供的相同的辅助方法,所以我在这里排除他们为了简洁:

 私有静态无效ExportPublicKey( CSP的RSACryptoServiceProvider,TextWriter的OutputStream中)
{
VAR参数= csp.ExportParameters(假);
使用(VAR流=新的MemoryStream())
{
变种作家=新的BinaryWriter(流);
writer.Write((字节)的0x30); //序列
使用(VAR innerStream =新的MemoryStream())
{
变种innerWriter =新的BinaryWriter(innerStream);
innerWriter.Write((字节)的0x30); //序列
EncodeLength(innerWriter,13);
innerWriter.Write((字节)0×06); //对象标识符
变种rsaEncryptionOid =新的字节[] {0x2a,0x86可以,0x48,0x86可以,0xf7,符进行,0×01,0×01,0×01};
EncodeLength(innerWriter,rsaEncryptionOid.Length);
innerWriter.Write(rsaEncryptionOid);
innerWriter.Write((字节)0×05); // NULL
EncodeLength(innerWriter,0);
innerWriter.Write((字节)×03); // BIT STRING
使用(VAR bitStringStream =新的MemoryStream())
{
变种bitStringWriter =新的BinaryWriter(bitStringStream);
bitStringWriter.Write((字节)×00); //#不使用的位
bitStringWriter.Write((字节)的0x30); //序列
使用(VAR paramsStream =新的MemoryStream())
{
变种paramsWriter =新的BinaryWriter(paramsStream);
EncodeIntegerBigEndian(paramsWriter,parameters.Modulus); //模
EncodeIntegerBigEndian(paramsWriter,parameters.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长度=(INT)innerStream.Length;
EncodeLength(作家,长度);
writer.Write(innerStream.GetBuffer(),0,长度);
}

变种的base64 = Convert.ToBase64String(stream.GetBuffer(),0,(INT)stream.Length).ToCharArray();
outputStream.WriteLine(----- BEGIN PUBLIC KEY -----);
为(VAR I = 0; I< base64.Length; I + = 64)
{
outputStream.WriteLine的(Base64,我,Math.Min(64 base64.Length - 一世));
}
outputStream.WriteLine(----- END PUBLIC KEY -----);
}
}


I am currently trying to generate and send a public RSA key using C#. It should be a 2048 bit long key in PEM format. I have successfully done so using OpenSSL command with the following (some output are shortened):

$ openssl genrsa 2048
Generating RSA private key, 2048 bit long modulus
............................................................+++
............................................................+++
e is 65537 (0x10001)
$ openssl rsa -pubout
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAy1MoBtENHBhYLgwP5Hw/xRGaBPHonApChBPBYD6fiq/QoLXA
RmyMoOjXHsKrrwysYIujXADM2LZ0MlFvPbBulvciWnZwp9CUQPwsZ8xnmBWlHyru
xTxNSvV+E/6+2gMOn3I4bmOSIaLx2Y7nCuaenREvD7Mn0vgFnP7yaN8/9va4q8Lo
...
...
y5jiKQKBgGAe9DlkYvR6Edr/gzd6HaF4btQZf6idGdmsYRYc2EMHdRM2NVqlvyLc
MR6rYEuViqLN5XWK6ITOlTPrgAuU6Rl4ZpRlS1ZrfjiUS6dzD/jtJJvsYByC7ZoU
NxIzB0r1hj0TIoedu6NqfRyJ6Fx09U5W81xx77T1EBSg4OCH7eyl
-----END RSA PRIVATE KEY-----
writing RSA key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy1MoBtENHBhYLgwP5Hw/
xRGaBPHonApChBPBYD6fiq/QoLXARmyMoOjXHsKrrwysYIujXADM2LZ0MlFvPbBu
lvciWnZwp9CUQPwsZ8xnmBWlHyruxTxNSvV+E/6+2gMOn3I4bmOSIaLx2Y7nCuae
nREvD7Mn0vgFnP7yaN8/9va4q8LoMKlceE5fSYl2QIfC5ZxUtkblbycEWZHLVOkv
+4Iz0ibD8KGo0PaiZl0jmn9yYXFy747xmwVun+Z4czO8Nu+OOVxsQF4hu1pKvTUx
9yHH/vk5Wr0I09VFyt3BT/RkecJbAAWB9/e572T+hhmmJ08wCs29oFa2Cdik9yyE
2QIDAQAB
-----END PUBLIC KEY-----

The following code is what I use to generate a public key using C#:

// Variables
CspParameters cspParams = null;
RSACryptoServiceProvider rsaProvider = null;
StreamWriter publicKeyFile = null;
string publicKey = "";

try
{
   // Create a new key pair on target CSP
   cspParams = new CspParameters();
   cspParams.ProviderType = 1; // PROV_RSA_FULL
   cspParams.Flags = CspProviderFlags.CreateEphemeralKey;
   rsaProvider = new RSACryptoServiceProvider(2048, cspParams);

   // Export public key
   result = ExportPublicKeyToPEMFormat(rsaProvider);
}
catch (Exception ex)
{
}

The ExportPublicKeyToPEMFormat can be found from this thread:http://stackoverflow.com/a/25591659/2383179

My output in C# looks like this:

-----BEGIN PUBLIC KEY-----
MIIBKwIBAAKCAQEAzMoaInPQ7nAXGWUY2EEtBcPY/Zvfcqf3Uxr7mFrQaxMjdXYi
DVSPh9XBWJlEhQ9ZGyBMpkWwtkrlDw11g/7pj+u7KTa5nH1ZB8vCrY3TC+YnFXPQ
Nv5dCzW0Lz+HD04rir2+K++XQCroy7G68uE9dtkbqa1U7IEWOvejbX+sgzo5ISHA
vCz2DFBInqYNJWfkM8OvLnRYYQ4f8MbmvDEMyaEYPGfQybXAs5eFksqm9pwR0xh4
Oxg/DkDas93lNIf+g00IesHvHuavRm2GX8jAXhrAoZY7nWQZpqS5kwx1kjSwtYEg
Vq4mHcaKIalMAoILSV9ttgqiJ5KVuKIvQJ7wRwIDAQABAgMBAAECAwEAAQIDAQAB
AgMBAAECAwEAAQIDAQAB
-----END PUBLIC KEY-----

The correct output using OpenSSL looks like this:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy1MoBtENHBhYLgwP5Hw/
xRGaBPHonApChBPBYD6fiq/QoLXARmyMoOjXHsKrrwysYIujXADM2LZ0MlFvPbBu
lvciWnZwp9CUQPwsZ8xnmBWlHyruxTxNSvV+E/6+2gMOn3I4bmOSIaLx2Y7nCuae
nREvD7Mn0vgFnP7yaN8/9va4q8LoMKlceE5fSYl2QIfC5ZxUtkblbycEWZHLVOkv
+4Iz0ibD8KGo0PaiZl0jmn9yYXFy747xmwVun+Z4czO8Nu+OOVxsQF4hu1pKvTUx
9yHH/vk5Wr0I09VFyt3BT/RkecJbAAWB9/e572T+hhmmJ08wCs29oFa2Cdik9yyE
2QIDAQAB
-----END PUBLIC KEY-----

Obviously there is something different with the formats between the two public key.

The OpenSSL key always starst with"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA"

My key starts with"MIIBKwIBAAKCAQEA"

解决方案

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. It uses the same helper methods provided in the other answer, so I have excluded them here for brevity:

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-----");
    }
}

这篇关于C#RSA公钥输出不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 12:42