AES256 NSString шифрование в iOS - PullRequest
14 голосов
/ 27 ноября 2011

Мое приложение шифрует и дешифрует (или оно должно) NSString (текст, который должен быть зашифрован / расшифрован) с помощью другой NSString (ключевое слово), используя 256-битное шифрование. Когда я запускаю свой проект и запускаю метод encrypt, ничего не шифруется, текстовое поле просто очищается. Вот код, который у меня есть:

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

Заголовочные файлы можно скачать, перейдя по этой ссылке: ZIP-файл, содержащий реализацию AES

Мне сказали, что мне нужно использовать кодирование Base-64 моей строки, чтобы получить какой-либо результат. Если это правда, то как мне это сделать?

Мне также сообщили, что в iOS 5 изменилось шифрование, и мое приложение является приложением ТОЛЬКО для iOS 5+. Если это так, то что мне нужно сделать, чтобы заставить это шифрование работать на iOS 5 или где я могу найти другую 256-битную реализацию AES, которая будет работать на NSString.

Почему этот код не дает результата?

Ответы [ 2 ]

11 голосов
/ 27 ноября 2011

РЕДАКТИРОВАТЬ: ссылки ниже относятся к более старой реализации. Последняя версия называется RNCryptor .

Ваш код не использует встроенную в iOS реализацию AES. У него есть своя собственная реализация. AESEncryptWithPassphrase: также неправильно генерирует ключ, отбрасывая большую часть энтропии в парольной фразе.

В iOS вы должны использовать функции CCCrypt*() для AES. Вы также должны убедиться, что понимаете, что происходит в ваших процедурах шифрования и дешифрования. Очень легко написать код шифрования, который выглядит правильно (в том смысле, что вы не можете прочитать вывод при проверке), но крайне небезопасен.

См. Правильное шифрование с AES с помощью CommonCrypto для объяснения проблем с вышеупомянутой реализацией и как правильно использовать AES на iOS. Обратите внимание, что в iOS 5 теперь доступно CCKeyDerivationPBKDF.

Не требуется, чтобы Base-64 кодировал вашу строку перед шифрованием. Кодировка Base-64 используется в тех случаях, когда вам необходимо преобразовать двоичные данные в форму, которую можно легко отправить по электронной почте или в другие места, где могут возникнуть проблемы с управляющими символами. Он преобразует 8-битные двоичные данные в 7-битные данные ASCII. Это не нужно или полезно здесь.


РЕДАКТИРОВАТЬ : очень важно внимательно прочитать объяснение того, как использовать этот код. Опасно просто вырезать и вставлять код безопасности и надеяться, что он работает. Тем не менее, полный исходный код RNCryptManager доступен как часть примера кода главы 11 для Программирование на iOS 5 с превышением пределов и может быть полезным [РЕДАКТИРОВАТЬ: Это старый код; Я рекомендую RNCryptor сейчас, ссылка вверху ответа] . Книга (которая должна быть доступна на следующей неделе, несмотря на то, что говорится на сайте) содержит гораздо более длительное обсуждение того, как использовать этот код, в том числе о том, как повысить производительность и работать с очень большими наборами данных.

7 голосов
/ 27 ноября 2011

NSData с категорией просто отлично подходит для шифрования AES, я не проверял zip-файл, но это должно работать для вас;

#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

Используйте его функции-оболочки, такие как;

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