2011-11-27 13 views
13

miei cripta app e decodifica (o dovrebbe) un NSString (il testo da cifrare/decifrato) con un altro NSString (la parola) utilizzando 256-bit di crittografia. Quando eseguo il mio progetto ed eseguo il metodo di crittografia, niente viene crittografato, il campo di testo si cancella da solo. Ecco il codice che ho:AES256 NSString di crittografia in iOS

-(void)EncryptText { 
    //Declare Keyword and Text 
    NSString *plainText = DataBox.text; 
    NSString *keyword = Keyword.text; 

    //Convert NSString to NSData 
    NSData *plainData = [plainText dataUsingEncoding:NSUTF8StringEncoding]; 

    //Encrypt the Data 
    NSData *encryptedData = [plainData AESEncryptWithPassphrase:keyword]; 

    //Convert the NSData back to NSString 
    NSString* cypherText = [[NSString alloc] initWithData:encryptedData encoding:NSUTF8StringEncoding]; 

    //Place the encrypted sting inside the Data Box 
    NSLog(@"Cipher Text: %@", cypherText); 
} 

I file di intestazione possono essere scaricati cliccando questo link: ZIP File containing AES Implementation

Mi è stato detto che ho bisogno di usare Base 64 codifica della mia stringa per ottenere qualsiasi risultato . Se questo è vero, allora come lo faccio?

Mi è stato anche detto che la crittografia è cambiata in iOS 5 e la mia app è un'app iOS 5+. Se questo è vero, allora cosa devo fare per far funzionare questa crittografia su iOS 5 o dove posso trovare un'altra implementazione AES a 256 bit che funzionerà su NSString.

Perché questo codice non produce un risultato?

risposta

11

MODIFICA: i collegamenti sottostanti si riferiscono a un'implementazione precedente. L'ultima versione è denominata RNCryptor.

Il codice non utilizza l'implementazione AES integrata di iOS. Ha una sua implementazione personalizzata. AESEncryptWithPassphrase: genera anche erroneamente la chiave, gettando via la maggior parte dell'entropia nella passphrase.

Su iOS, si dovrebbero usare le funzioni CCCrypt*() per AES. Dovresti anche assicurarti di capire cosa sta succedendo nelle tue routine di crittografia e decrittografia. È molto facile scrivere codice di crittografia che sembra corretto (nel senso che non è possibile leggere l'output tramite ispezione), ma è estremamente insicuro.

Vedere Properly encrypting with AES with CommonCrypto per una spiegazione dei problemi con l'implementazione di cui sopra e su come utilizzare correttamente AES su iOS. Nota che iOS 5 ora ha CCKeyDerivationPBKDF disponibile.

Non è necessario che Base-64 codifichi la stringa prima della crittografia. La codifica Base-64 viene utilizzata nei casi in cui è necessario convertire i dati binari in un modulo che può essere facilmente inviato tramite e-mail o altri luoghi in cui i caratteri di controllo sarebbero un problema. Converte i dati binari a 8 bit in dati ASCII a 7 bit. Non è necessario o utile qui.


EDIT: è fondamentale leggere attentamente la spiegazione di come utilizzare questo codice. È pericoloso semplicemente tagliare e incollare il codice di sicurezza e sperare che funzioni. Detto questo, l'intera fonte a RNCryptManager è disponibile come parte del codice di esempio Chapter 11 per iOS 5 Programming Pushing the Limits e potrebbe essere utile [MODIFICA: Questo è il vecchio codice; Raccomando RNCryptor ora, collegato all'inizio della risposta]. Il libro (che dovrebbe essere disponibile la prossima settimana nonostante quello che dice il sito) include una discussione molto più lunga su come usare questo codice, incluso come migliorare le prestazioni e gestire dataset molto grandi.

+0

Grazie Rob! Questo è molto utile! –

+0

Dove sarebbe il codice mostrato su: http://robnapier.net/blog/aes-commoncrypto-564 go? Non andrebbe nella sua stessa classe perché non c'è nulla in cui passare un'intestazione e un'implementazione, quindi andrebbe nello stesso file .m del mio metodo? –

+0

In genere lo inserisco in una classe chiamata "RNCryptManager', ma potresti metterlo ovunque. Il codice potrebbe anche essere banalmente convertito in funzioni piuttosto che in metodi di classe. –

6

NSData con categoria corretta per crittografia AES, non ho controllato il file zip, ma questo dovrebbe funzionare per voi;

#import <CommonCrypto/CommonCryptor.h> 
@implementation NSData (AESAdditions) 
- (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 

Utilizzare le funzioni wrapper come;

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

Si noti che questa implementazione è altamente insicuro in quanto getta via la maggior parte lo spazio delle chiavi, non ha IV, e non sale o key-stretching. Vedi http://robnapier.net/blog/aes-commoncrypto-564 per una discussione sul perché evitare questo pezzo di codice comunemente copiato. –

+0

@tylerdurden Si dovrebbe controllare la lunghezza della chiave, perché "getCString: maxlength: codifica" farà nulla se key.length> (kCCKeySizeAES256 + 1) e la cryptor utilizzerà 32 '\ 0' come la sua chiave. È pericoloso. – MasterBeta

Problemi correlati