2015-02-09 21 views
12

Tôi hiện đang cố gắng tạo và gửi khóa RSA công khai bằng C#. Nó phải là khóa dài 2048 bit ở định dạng PEM. Tôi đã thực hiện thành công để sử dụng lệnh OpenSSL như sau (một số đầu ra được rút ngắn):C# RSA Đầu ra Khóa Công khai Không chính xác

$ 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ác mã sau đây là những gì tôi sử dụng để tạo một khóa công khai sử dụng 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) 
{ 
} 

Các ExportPublicKeyToPEMFormat thể được tìm thấy từ chủ đề này: https://stackoverflow.com/a/25591659/2383179

đầu ra của tôi trong C# như sau:

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

Các đúng sản lượng sử dụng OpenSSL trông như thế này:

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

Rõ ràng có cái gì đó khác nhau với các định dạng giữa khóa công khai hai.

Chìa khóa OpenSSL luôn starst với "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA"

bắt đầu quan trọng của tôi với "MIIBKwIBAAKCAQEA"

+0

Khóa công khai sẽ luôn khác nhau, vì nó dựa trên mới và ngẫu nhiên tạo * p * và * q *. –

Trả lời

30

Thật không may, các mã trong các câu trả lời bạn tham chiếu là không thực sự đúng - nó xuất định dạng riêng PEM chính, nhưng chỉ với các trường khóa công khai được đặt chính xác, điều này không giống như xuất khóa công khai RSA ở định dạng chuẩn.

Tôi thực sự đã viết mã trong câu hỏi other answer và tại thời điểm đó đã viết một chế độ xuất khóa công khai ở định dạng chuẩn, nhưng không bao gồm nó trong câu trả lời vì nó không được yêu cầu. Nó sử dụng các phương thức trợ giúp tương tự được cung cấp trong câu trả lời khác, vì vậy tôi đã loại trừ chúng ở đây một cách ngắn gọn:

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]); 
     } 
    } 
} 
Các vấn đề liên quan