Frage

Kann mich jemand in der richtigen Richtung der Lage sein, eine Zeichenfolge zu verschlüsseln, eine andere Zeichenfolge mit den verschlüsselten Daten zurückkehrt? (Ich habe mit AES256 Verschlüsselung versucht.) Ich möchte ein Verfahren schreiben, die zwei NSString Instanzen nehmen, eine die Nachricht sein zu verschlüsseln und die andere ein ‚Passcode‘ ist es mit zu verschlüsseln - ich vermute, ich habe zu erzeugen der Verschlüsselungsschlüssel mit dem Passcode, in einer Weise, die rückgängig gemacht werden kann, wenn das Passwort mit den verschlüsselten Daten versorgt wird. Das Verfahren soll dann wieder ein NSString aus den verschlüsselten Daten erstellt.

Ich habe die Technik versucht detailliert in CryptoExercise hat sicherlich etwas, aber ich kann nicht Sinn daraus machen. .. ich habe viele Verweise auf CCCrypt , aber es in jedem Fall versagt hat ich es benutzt habe.

Ich würde auch einen verschlüsselten String in der Lage sein muß, um zu entschlüsseln, aber ich hoffe, dass so einfach wie kCCEncrypt / kCCDecrypt.

War es hilfreich?

Lösung

Da Sie keinen Code geschrieben haben, ist es schwierig, genau zu wissen, welche Probleme Sie stoßen. Allerdings verbinden die Blog-Post Sie scheint ziemlich anständig zu arbeiten ... abgesehen von dem zusätzlichen Komma in jedem Aufruf CCCrypt(), welche Fehler verursacht kompilieren.

Ein späterer Kommentar zu diesem Beitrag enthält diese angepasst Code , was für mich funktioniert, und scheint ein bisschen mehr einfach. Wenn Sie ihren Code für die NSData Kategorie gehören, können Sie so etwas schreiben: (Anmerkung: Der printf() fordert den Zustand der Daten an verschiedenen Stellen für den Nachweis nur sind - in einer realen Anwendung, wäre es nicht sinnvoll, so drucken Werte).

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSString *key = @"my password";
    NSString *secret = @"text to encrypt";

    NSData *plain = [secret dataUsingEncoding:NSUTF8StringEncoding];
    NSData *cipher = [plain AES256EncryptWithKey:key];
    printf("%s\n", [[cipher description] UTF8String]);

    plain = [cipher AES256DecryptWithKey:key];
    printf("%s\n", [[plain description] UTF8String]);
    printf("%s\n", [[[NSString alloc] initWithData:plain encoding:NSUTF8StringEncoding] UTF8String]);

    [pool drain];
    return 0;
}

Mit diesem Code gegeben, und die Tatsache, dass die verschlüsselten Daten nicht immer schön in ein NSString zu übersetzen, kann es bequemer sein, zwei Methoden zu schreiben, die die Funktionalität, die Sie benötigen, in Vorwärts- und Rückwärts wickeln ...

- (NSData*) encryptString:(NSString*)plaintext withKey:(NSString*)key {
    return [[plaintext dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptWithKey:key];
}

- (NSString*) decryptData:(NSData*)ciphertext withKey:(NSString*)key {
    return [[[NSString alloc] initWithData:[ciphertext AES256DecryptWithKey:key]
                                  encoding:NSUTF8StringEncoding] autorelease];
}

Dies funktioniert auf jeden Fall auf Snow Leopard und @Boz berichtet, dass CommonCrypto Teil des Core Betriebssystem auf dem iPhone ist. Sowohl 10.4 und 10.5 haben /usr/include/CommonCrypto, obwohl 10.5 eine Manpage CCCryptor.3cc hat und 10.4 nicht der Fall, so YMMV.


EDIT: finden Sie unter diese Follow-up-Frage zur Verwendung von Base64-Codierung für den verschlüsselten Datenbytes darstellen als String (falls gewünscht) unter Verwendung von sicherem, lossless Konvertierungen.

Andere Tipps

Ich habe für NSData und NSString eine Sammlung von Gruppen unterteilt, die auf Jeff LaMarche Blog und https://gist.github.com/838614

Vielen Dank für all die hilfreichen Hinweise!

- Michael

@owlstead, in Bezug auf Ihre Anfrage für „eine kryptografisch sicheren Variante eines der gegebenen Antworten“ finden Sie unter RNCryptor . Es wurde entwickelt, genau das zu tun, was Sie anfordern (und wurde als Reaktion auf die Probleme mit dem Code aufgeführt hier gebaut).

RNCryptor verwendet PBKDF2 mit Salz, bietet ein zufälliges IV und legt HMAC (auch aus PBKDF2 mit seinem eigenen Salz erzeugt wird. Es synchronen und asynchronen Betrieb unterstützen.

wartete ich ein bisschen auf @QuinnTaylor seine Antwort zu aktualisieren, aber da er nicht, hier ist die Antwort ein bisschen mehr klar und in einer Weise, dass es auf XCode7 geladen werden kann (und vielleicht auch mehr). Ich habe dies in einer Cocoa-Anwendung, aber es wird wahrscheinlich auch mit einer iOS-Anwendung in Ordnung arbeiten. Hat keine ARC Fehler.

Einfügen vor jedem @implementation Abschnitt in Ihrer AppDelegate.m oder AppDelegate.mm Datei.

#import <CommonCrypto/CommonCryptor.h>

@implementation NSData (AES256)

- (NSData *)AES256EncryptWithKey:(NSString *)key {
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [self length];

    //See the doc: For block ciphers, the output size will always be less than or 
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                     keyPtr, kCCKeySizeAES256,
                                     NULL /* initialization vector (optional) */,
                                     [self bytes], dataLength, /* input */
                                     buffer, bufferSize, /* output */
                                     &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }

    free(buffer); //free the buffer;
    return nil;
}

- (NSData *)AES256DecryptWithKey:(NSString *)key {
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [self length];

    //See the doc: For block ciphers, the output size will always be less than or 
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                     keyPtr, kCCKeySizeAES256,
                                     NULL /* initialization vector (optional) */,
                                     [self bytes], dataLength, /* input */
                                     buffer, bufferSize, /* output */
                                     &numBytesDecrypted);

    if (cryptStatus == kCCSuccess) {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
    }

    free(buffer); //free the buffer;
    return nil;
}

@end

Fügen Sie diese beiden Funktionen in der @implementation Klasse, die Sie wünschen. In meinem Fall habe ich @implementation AppDelegate in meiner AppDelegate.mm oder AppDelegate.m Datei.

- (NSString *) encryptString:(NSString*)plaintext withKey:(NSString*)key {
    NSData *data = [[plaintext dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptWithKey:key];
    return [data base64EncodedStringWithOptions:kNilOptions];
}

- (NSString *) decryptString:(NSString *)ciphertext withKey:(NSString*)key {
    NSData *data = [[NSData alloc] initWithBase64EncodedString:ciphertext options:kNilOptions];
    return [[NSString alloc] initWithData:[data AES256DecryptWithKey:key] encoding:NSUTF8StringEncoding];
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top