iOS - PublicKey erzeugen (modulus, exponent) und RSA Encryption

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • iOS - PublicKey erzeugen (modulus, exponent) und RSA Encryption

    Hallo Leute,

    ich sitze zur Zeit an einer App, die per API mit einem Server kommuniziert.

    Für ein bestimmtes Request muss ein Passwort encrypted werden.
    Dazu bekommt man bei einem "generatePublicKey"-Request einen
    entsprechenden Schlüssel.
    Da dachte ich mir, "ok kein Problem... einfach das Security Framework
    von Apple nutzen und fertig!".
    Naja so einfach war es dann doch nicht, da der Schlüssel als Pärchen aus
    "modulus" und "exponent" daherkommen.
    Das ist mir vorher leider noch nicht so oft über den Weg gelaufen.
    Also habe ich erstmal recherchiert. Leider gibt es dazu kaum
    Infos in Verbindung mit iOS oder Swift.
    Habe eine Menge externer Libaries und Ansätze mit Objective-C
    gefunden, aber nichts was mir diese Struktur mal genauer erklärt.

    Ist die KeyID ein Teil des publicKeys ? Muss der PublicKey aus Modulus
    und Exponent "berechnet" werden oder passiert nur eine "Umformung" ?
    Habe gelesen, dass der Modulus Teil eigentlich ein Hex-String ist... stimmt das ?

    Gibt es die Möglichkeit mittels Swift "Bordmitteln" einen korrekten
    publicKey aus modulus und exponent zu erzeugen ??
    Ich will damit ein User-Passwort RSA Verschlüsseln. Dazu kann
    man ja problemlos das Security Framework von Apple nutzen.

    Hat Jemand eine Idee, ein Tipp zur Problemlösung oder Erfahrung damit ?

    Ich versuche möglichst nur Apple eigene API's bzw. Frameworks zu nutzen
    und auf externe Libaries zu verzichten. Wenn es allerdings gar nicht anders
    geht, dann bin ich auch für solche Lösungsvorschläge offen.

    PS: Ich habe natürlich auch von openSSL gelesen, aber auch, dass es sehr
    umständlich sein soll zu implementieren und die meisten versuchen es in iOS Apps
    zu vermeiden. Stimmt das ?

    Vielen herzlichen Dank schonmal an Alle, die mir weiterhelfen können.

    LG Benjamin
  • C-Quellcode

    1. NSString *modulusString = @"c19bccae1e67743fab1c978f03122fb1a78ef05d565a2964728062ad0365e4751b8253df5fd13ab4ecb95c81ff17b91f969e4fb3d8274c30533338684278f6e5548027df775c055943a24a4117b0274c296c68b722c71670d4b21489a3da05d37ba06f2fb771b671a2c746bae4a049dc718fba19a75f1fb8ae1dd715b33d66a3";
    2. NSString *exponentString = @"010001";
    3. NSData *pubKeyModData = bytesFromHexString(modulusString);
    4. NSData *pubKeyExpData = bytesFromHexString(exponentString);
    5. NSArray *keyArray = @[pubKeyModData, pubKeyExpData];
    6. //Given that you are using SCZ-BasicEncodingRules-iOS:
    7. NSData *berData = [keyArray berData];
    8. NSLog(@"berData:\n%@", berData);
    9. NSString *berBase64 = [berData base64EncodedStringWithOptions:0];
    10. NSString *preamble = @"-----BEGIN CERTIFICATE REQUEST-----";
    11. NSString *postamble = @"-----END CERTIFICATE REQUEST-----";
    12. NSString *pem = [NSString stringWithFormat:@"%@\n%@\n%@", preamble, berBase64, postamble];
    13. NSLog(@"pem:\n%@", pem);
    Alles anzeigen
    Das ist ja ein Teil des Codes auf der Seite.

    Quellcode

    1. //Given that you are using SCZ-BasicEncodingRules-iOS:
    2. NSData *berData = [keyArray berData];
    3. NSLog(@"berData:\n%@", berData);

    Und hier steht "Given that you using SCZ-BasicEncodingRules-iOS:"

    Und ich glaube diese Libary stellt die Erweiterung für NSData bereit...

    "NSData *berData = [keyArray berData];"

    Zumindest scheint es mir so ...
  • Also, ich hab's mir die letzten 2 Jahre nicht mehr angesehen, aber damals waren die entsprechenden Klassen von Apple nur sehr rudimentär. Gerade für das Problem: Du hast einen öffentlichen Schlüssel deines Partners und möchtest etwas verschlüsseln gab's keine Lösung. Außerdem hat mir das Zeug immer ungefragt meine erzeugten Schlüsselpärchen in den Schlüsselbund geklatscht. Also eigentlich unbrauchbar.

    Die Lösung war: openSSL weiter verwenden. Auch wenn's wehtut. Andererseits: Bei solchen Sachen Wrapper-Frameworks zu verwenden, ohne zu wissen worauf es ankommt ist auch nicht so der Bringer.
  • gandhi schrieb:

    Also, ich hab's mir die letzten 2 Jahre nicht mehr angesehen, aber damals waren die entsprechenden Klassen von Apple nur sehr rudimentär. Gerade für das Problem: Du hast einen öffentlichen Schlüssel deines Partners und möchtest etwas verschlüsseln gab's keine Lösung. Außerdem hat mir das Zeug immer ungefragt meine erzeugten Schlüsselpärchen in den Schlüsselbund geklatscht. Also eigentlich unbrauchbar.

    Die Lösung war: openSSL weiter verwenden. Auch wenn's wehtut. Andererseits: Bei solchen Sachen Wrapper-Frameworks zu verwenden, ohne zu wissen worauf es ankommt ist auch nicht so der Bringer.

    Hmm, ... und hast du für dieses Dilemma auch eventuell eine Lösungs-Idee ? Ich bin halt darauf angewiesen, da ich sonst den nötigen Login-Request auf meinen Server nicht machen kann.
    Dieses Scheiß Ding will nämlich unbedingt das Passwort RSA encrypted mittels des vorherigen Requests bekommenen pubKeys.

    Ich sitze jetzt schon 3 volle Tage an dem Problem und habe langsam einen mittleren Nervenzusammenbruch ?( :D

    Bin für jede Hilfe dankbar.

    Gruß Benjamin

    //EDIT:
    stackoverflow.com/questions/43…blic-key-generation-swift
    Das hier habe ich auch noch gefunden und schon ausprobiert, aber scheinbar
    verstehe ich das nicht richtig. Es kommt jedenfalls nichts bei raus.


    //EDIT:

    Ich habe mal ein bisschen rumprobiert und bin der Lösung eventuell nahe. Bin mir nicht ganz sicher.
    Vielleicht schaut sich das mal einer von euch an...

    Als erstes habe ich diese Libary gefunden, um aus Modulus und Exponent ein "korrektes" NSData
    Objekt für den Public Key zu bekommen.

    C-Quellcode

    1. - (NSData *)generateRSAPublicKeyWithModulus:(NSData*)modulus exponent:(NSData*)exponent {
    2. const uint8_t DEFAULT_EXPONENT[] = {0x01, 0x00, 0x01,}; //default: 65537
    3. const uint8_t UNSIGNED_FLAG_FOR_BYTE = 0x81;
    4. const uint8_t UNSIGNED_FLAG_FOR_BYTE2 = 0x82;
    5. const uint8_t UNSIGNED_FLAG_FOR_BIGNUM = 0x00;
    6. const uint8_t SEQUENCE_TAG = 0x30;
    7. const uint8_t INTEGER_TAG = 0x02;
    8. uint8_t* modulusBytes = (uint8_t*)[modulus bytes];
    9. uint8_t* exponentBytes = (uint8_t*)(exponent == nil ? DEFAULT_EXPONENT : [exponent bytes]);
    10. //(1) calculate lengths
    11. //- length of modulus
    12. int lenMod = (int)[modulus length];
    13. if(modulusBytes[0] >= 0x80)
    14. lenMod ++; //place for UNSIGNED_FLAG_FOR_BIGNUM
    15. int lenModHeader = 2 + (lenMod >= 0x80 ? 1 : 0) + (lenMod >= 0x0100 ? 1 : 0);
    16. //- length of exponent
    17. int lenExp = exponent == nil ? sizeof(DEFAULT_EXPONENT) : (int)[exponent length];
    18. int lenExpHeader = 2;
    19. //- length of body
    20. int lenBody = lenModHeader + lenMod + lenExpHeader + lenExp;
    21. //- length of total
    22. int lenTotal = 2 + (lenBody >= 0x80 ? 1 : 0) + (lenBody >= 0x0100 ? 1 : 0) + lenBody;
    23. int index = 0;
    24. uint8_t* byteBuffer = malloc(sizeof(uint8_t) * lenTotal);
    25. memset(byteBuffer, 0x00, sizeof(uint8_t) * lenTotal);
    26. //(2) fill up byte buffer
    27. //- sequence tag
    28. byteBuffer[index ++] = SEQUENCE_TAG;
    29. //- total length
    30. if(lenBody >= 0x80)
    31. byteBuffer[index ++] = (lenBody >= 0x0100 ? UNSIGNED_FLAG_FOR_BYTE2 : UNSIGNED_FLAG_FOR_BYTE);
    32. if(lenBody >= 0x0100)
    33. {
    34. byteBuffer[index ++] = (uint8_t)(lenBody / 0x0100);
    35. byteBuffer[index ++] = lenBody % 0x0100;
    36. }
    37. else
    38. byteBuffer[index ++] = lenBody;
    39. //- integer tag
    40. byteBuffer[index ++] = INTEGER_TAG;
    41. //- modulus length
    42. if(lenMod >= 0x80)
    43. byteBuffer[index ++] = (lenMod >= 0x0100 ? UNSIGNED_FLAG_FOR_BYTE2 : UNSIGNED_FLAG_FOR_BYTE);
    44. if(lenMod >= 0x0100)
    45. {
    46. byteBuffer[index ++] = (int)(lenMod / 0x0100);
    47. byteBuffer[index ++] = lenMod % 0x0100;
    48. }
    49. else
    50. byteBuffer[index ++] = lenMod;
    51. //- modulus value
    52. if(modulusBytes[0] >= 0x80)
    53. byteBuffer[index ++] = UNSIGNED_FLAG_FOR_BIGNUM;
    54. memcpy(byteBuffer + index, modulusBytes, sizeof(uint8_t) * [modulus length]);
    55. index += [modulus length];
    56. //- exponent length
    57. byteBuffer[index ++] = INTEGER_TAG;
    58. byteBuffer[index ++] = lenExp;
    59. //- exponent value
    60. memcpy(byteBuffer + index, exponentBytes, sizeof(uint8_t) * lenExp);
    61. index += lenExp;
    62. if(index != lenTotal)
    63. NSLog(@"lengths mismatch: index = %d, lenTotal = %d", index, lenTotal);
    64. NSMutableData* buffer = [NSMutableData dataWithBytes:byteBuffer length:lenTotal];
    65. free(byteBuffer);
    66. return buffer;
    67. }
    Alles anzeigen

    Anschließend habe ich versucht eine Art "Pem" File zu bauen. Also das was aus der o.g. Libary Funktion herauskommt
    base64 kodieren und dann Header und Footer dranz hängen.
    Das Ergebnis und die einzelnen Schritte sieht man in der Konsole...

    Jetzt muss das ganze zum encrypten ja in ein SecKey Format gebracht werden. Da hänge ich nun...
    Bildschirmfoto 2017-06-24 um 01.00.08.png

    Hoffe das sagt Jemandem etwas :D

    Vielen Dank und viele Grüße

    Benjamin

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von H@ckz0r ()

  • H@ckz0r schrieb:

    Hmm, ... und hast du für dieses Dilemma auch eventuell eine Lösungs-Idee ?
    Ja, wie schon gesagt: Ich habe openSSL verwendet. Da ist bei gegebenem public-key eine asymmetrische Verschlüsselung kein großes Ding. Davon abgesehen, daß das openSSl-API nicht gerade das eleganteste der Welt ist. Anders gesagt, wenn es eine Oscar in der Kategorie "weird API" geben würde, wäre openSSL sicher ein Anwärter.

    Aber, ich gebe zu bedenken: Du bastelst Da was sicherheitskritisches zusammen, hast aber Probleme das in einer der am meist verbreiteten Libs zu implementieren. Finde den Fehler...