C#RSA公钥输出不正确

我目前正在尝试使用C#生成并发送公共RSA密钥。 它应该是PEM格式的2048位长密钥。 我使用OpenSSL命令成功完成了以下操作(缩短了一些输出):

$ 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----- 

以下代码是我用来使用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) { } 

可以从以下线程找到ExportPublicKeyToPEMFormat : https : //stackoverflow.com/a/25591659/2383179

我在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密钥总是与 “MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA”相关联

我的钥匙以 “MIIBKwIBAAKCAQEA” 开头

遗憾的是,您引用的答案中的代码并不正确 – 它导出私钥 PEM格式,但只有正确设置的公钥字段,这与导出标准格式的RSA公钥不同。

我实际上在该问题的另一个答案中编写了代码,并且当时编写了一种以标准格式导出公钥的模式,但由于不需要,因此没有将其包含在该答案中。 这里是:

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