Шифрование AES для NSString на iPhone

Может ли кто-нибудь указать мне в правильном направлении, чтобы иметь возможность шифровать строку, возвращая другую строку с зашифрованными данными? (Я пытался использовать шифрование AES256.) Я хочу написать метод, который принимает два экземпляра NSString, один из которых является зашифрованным сообщением, а другой – «паролем» для его шифрования. Я подозреваю, что мне придется генерировать ключ шифрования с кодом доступа, таким образом, который может быть отменен, если код доступа снабжен зашифрованными данными. Затем метод должен вернуть NSString, созданную из зашифрованных данных.

Я пробовал технику, подробно описанную в первом комментарии к этому сообщению , но до сих пор мне не повезло. У Apple CryptoExercise есть что-то, но я не могу это понять … Я видел много ссылок на CCCrypt , но в каждом случае я не использовал его.

Я также должен был бы расшифровать зашифрованную строку, но я надеюсь, что это так же просто, как kCCEncrypt / kCCDecrypt.

Поскольку вы не разместили какой-либо код, трудно точно узнать, с какими проблемами вы сталкиваетесь. Тем не менее, сообщение в блоге, на которое вы CCCrypt() похоже, работает довольно прилично … кроме дополнительной запятой в каждом вызове CCCrypt() который вызвал ошибки компиляции.

Более поздний комментарий к этому сообщению включает этот адаптированный код , который работает для меня, и кажется немного более простым. Если вы включите свой код для категории NSData, вы можете написать примерно так: (Примечание: вызовы printf() предназначены только для демонстрации состояния данных в разных точках – в реальном приложении, это не имеет смысла напечатайте такие значения.)

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

Учитывая этот код и тот факт, что зашифрованные данные не всегда хорошо переводятся в NSString, может быть удобнее написать два метода, которые обертывают нужные вам функции, в прямом и обратном …

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

Это определенно работает на Snow Leopard, а @Boz сообщает, что CommonCrypto является частью Core OS на iPhone. И 10.4, и 10.5 имеют /usr/include/CommonCrypto , хотя у 10.5 есть CCCryptor.3cc страница для CCCryptor.3cc и 10.4 нет, поэтому YMMV.


EDIT: см. Этот следующий вопрос об использовании кодировки Base64 для представления зашифрованных байтов данных в виде строки (при желании) с использованием безопасных конверсий без потерь.

Я собрал коллекцию категорий для NSData и NSString, которая использует решения, найденные в блоге Джеффа ЛаМарче, и некоторые намеки Куинна Тейлора здесь на Stack Overflow.

Он использует категории для расширения NSData для обеспечения шифрования AES256, а также предлагает расширение NSString для шифрования данных BASE64 с безопасным доступом к строкам.

Вот пример, чтобы показать использование для шифрования строк:

 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] ); 

Получите полный исходный код здесь:

https://gist.github.com/838614

Спасибо за все полезные подсказки!

— Майкл

@owlstead, в отношении вашего запроса на «криптографически безопасный вариант одного из ответов», см. RNCryptor . Он был разработан для того, чтобы делать то, что вы запрашиваете (и был построен в ответ на проблемы с приведенным здесь кодом).

RNCryptor использует PBKDF2 с солью, обеспечивает случайный IV и присоединяет HMAC (также генерируемый из PBKDF2 с собственной солью. Он поддерживает синхронную и асинхронную работу.

Я немного подождал @QuinnTaylor, чтобы обновить его ответ, но так как он этого не сделал, вот ответ более ясный и способ, которым он будет загружаться на XCode7 (и, возможно, больше). Я использовал это в приложении Cocoa, но, скорее всего, это будет хорошо работать с приложением iOS. Не имеет ошибок ARC.

Вставьте перед любым разделом @implementation в файл AppDelegate.m или AppDelegate.mm.

 #import  @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 

Вставьте эти две функции в class @implementation, который вы желаете. В моем случае я выбрал @implementation AppDelegate в файле AppDelegate.mm или 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]; } 
  • Как я могу зашифровать содержимое CoreData на iPhone
  • Iphone - Как шифровать NSData с открытым ключом и расшифровывать с помощью закрытого ключа?
  • шифрование / дешифрование в Android с помощью AES
  • Шифрование видеофайлов?
  • Преобразование изображения в base64
  • Как шифровать String в Java
  • Формат открытых ключей RSA
  • Как зашифровать файл с SD-карты с помощью AES на Android?
  • Почему неправильный пароль приводит к тому, что «Заполнение недопустима и не может быть удалено»?
  • Шифровать и расшифровывать строку в java
  • Каким образом значения хеша MD5 не являются обратимыми?
  • Давайте будем гением компьютера.