2015-02-09 17 views
12

Obecnie próbuję wygenerować i wysłać publiczny klucz RSA przy użyciu C#. Powinien to być klucz o długości 2048 bitów w formacie PEM. Udało się zrobić, więc przy użyciu komendy OpenSSL z następującym (jakiegoś wyjścia są skrócone):Wynik klucza publicznego RSA RSA niepoprawny

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

Poniższy kod jest co używam do generowania klucza publicznego przy użyciu 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 można znaleźć z tego wątku: https://stackoverflow.com/a/25591659/2383179

moje wyjście w C# wygląda następująco:

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

Prawidłowe wyjście użyciu OpenSSL wygląda następująco:

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

Oczywiście istnieje coś innego z formatami między dwoma klucza publicznego.

Kluczem OpenSSL zawsze starst z "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA"

mój klucz zaczyna się od "MIIBKwIBAAKCAQEA"

+0

Klucz publiczny zawsze będzie wyglądać inaczej, ponieważ opiera się ona na nowo i losowo generowane * p * i * q *. –

Odpowiedz

30

Niestety, kod odpowiedź ty odwołanie nie jest do końca poprawne - to eksportuje prywatny format klucza PEM , ale z prawidłowo ustawionymi tylko polami klucza publicznego, to nie jest to samo, co eksportowanie klucza publicznego RSA w standardowym formacie.

Właściwie napisałem kod do other answer na to pytanie i w tym czasie napisałem tryb eksportu klucza publicznego w standardowym formacie, ale nie uwzględniłem go w tej odpowiedzi, ponieważ nie było to wymagane. Korzysta z tych samych metod pomocniczych przewidzianych w drugiej odpowiedzi, więc wykluczono je tutaj dla uproszczenia:

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]); 
     } 
    } 
} 
Powiązane problemy