Domanda

Qualcuno può indicarmi la giusta direzione per poter crittografare una stringa, restituendone un'altra con i dati crittografati? (Ho provato con la crittografia AES256.) Voglio scrivere un metodo che accetta due istanze NSString, una è il messaggio da crittografare e l'altra è un 'passcode' per crittografarlo con - sospetto che dovrei generare la chiave di crittografia con il passcode, in modo che possa essere invertita se il passcode viene fornito con i dati crittografati. Il metodo dovrebbe quindi restituire un NSString creato dai dati crittografati.

Ho provato la tecnica dettagliata in il primo commento su questo post , ma finora non ho avuto fortuna. CryptoExercise di Apple ha sicuramente qualcosa, ma non riesco a capirlo. .. Ho visto molti riferimenti a CCCrypt , ma non è riuscito in tutti i casi in cui l'ho usato.

Dovrei anche essere in grado di decrittografare una stringa crittografata, ma spero che sia semplice come kCCEncrypt / kCCDecrypt.

È stato utile?

Soluzione

Dato che non hai pubblicato alcun codice, è difficile sapere esattamente quali problemi stai riscontrando. Tuttavia, il post sul blog a cui ti colleghi sembra funzionare abbastanza bene ... a parte la virgola aggiuntiva in ogni chiamata a CCCrypt () che ha causato errori di compilazione.

Un commento successivo su quel post include questo codice adattato , che funziona per me e sembra un po 'di più semplice. Se includi il loro codice per la categoria NSData, puoi scrivere qualcosa del genere: (Nota: le chiamate printf () servono solo a dimostrare lo stato dei dati in vari punti: in un'applicazione reale, non avrebbe senso stampare tali valori.)

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

Dato questo codice e il fatto che i dati crittografati non si tradurranno sempre bene in una NSString, potrebbe essere più conveniente scrivere due metodi che racchiudano le funzionalità necessarie, in avanti e indietro ...

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

Funziona sicuramente su Snow Leopard e @Boz riporta che CommonCrypto fa parte del sistema operativo Core su iPhone. Sia 10.4 che 10.5 hanno / usr / include / CommonCrypto , sebbene 10.5 abbia una pagina man per CCCryptor.3cc e 10.4 no, quindi YMMV.


EDIT: vedi questa domanda di follow-up sull'uso della codifica Base64 per rappresentare byte di dati crittografati come stringa (se lo si desidera) utilizzando conversioni sicure e senza perdita di dati.

Altri suggerimenti

Ho messo insieme una raccolta di categorie per NSData e NSString che utilizza soluzioni trovate su il blog di Jeff LaMarche e alcuni suggerimenti di Quinn Taylor qui su Stack Overflow.

Utilizza le categorie per estendere NSData per fornire la crittografia AES256 e offre anche un'estensione di NSString ai dati crittografati con codifica BASE64 in modo sicuro alle stringhe.

Ecco un esempio per mostrare l'utilizzo della crittografia delle stringhe:

NSString *plainString = @"This string will be encrypted";
NSString *key = @"YourEncryptionKey"; // should be provided by a user

NSLog( @"Original String: %@", plainString );

NSString *encryptedString = [plainString AES256EncryptWithKey:key];
NSLog( @"Encrypted String: %@", encryptedString );

NSLog( @"Decrypted String: %@", [encryptedString AES256DecryptWithKey:key] );

Ottieni il codice sorgente completo qui:

  

https://gist.github.com/838614

Grazie per tutti i suggerimenti utili!

- Michael

@owlstead, per quanto riguarda la tua richiesta di " una variante crittograficamente sicura di una delle risposte fornite, " consultare RNCryptor . È stato progettato per fare esattamente ciò che stai richiedendo (ed è stato creato in risposta ai problemi con il codice elencato qui).

RNCryptor utilizza PBKDF2 con sale, fornisce un IV casuale e collega HMAC (anch'esso generato da PBKDF2 con il proprio sale. Supporta il funzionamento sincrono e asincrono.

Ho aspettato un po 'su @QuinnTaylor per aggiornare la sua risposta, ma dato che non l'ha fatto, ecco la risposta un po' più chiaramente e in un modo che verrà caricata su XCode7 (e forse più grande). L'ho usato in un'applicazione Cocoa, ma probabilmente funzionerà bene anche con un'applicazione iOS. Non presenta errori ARC.

Incolla prima di qualsiasi sezione @implementation nel tuo file AppDelegate.m o AppDelegate.mm.

#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

Incolla queste due funzioni nella classe @implementation che desideri. Nel mio caso, ho scelto @implementation AppDelegate nel mio file AppDelegate.mm o AppDelegate.m.

- (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];
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top