对iPhone上的NSString进行AESencryption

任何人都可以指向正确的方向来encryption一个string,返回另一个string的encryption数据? (我一直在尝试使用AES256encryption。)我想编写一个方法,它需要两个NSString实例,一个是要encryption的消息,另一个是“密码”encryption它 – 我怀疑我必须生成密码与密码一起,如果密码与encryption数据一起提供,则可以反转。 该方法应该返回一个由encryption数据创build的NSString。

我已经尝试过在这篇文章的第一条评论中详细介绍的技术,但到目前为止我还没有运气。 苹果的CryptoExercise肯定有一些东西,但我无法理解它…我已经看到了很多CCCrypt的参考,但是在我使用它的每一种情况下都失败了。

我也必须能够解密一个encryption的string,但我希望这是像kCCEncrypt / kCCDecrypt一样简单。

由于您没有发布任何代码,因此很难确切知道您遇到的问题。 但是,链接到的博客文章似乎工作CCCrypt()体面…除了每次调用CCCrypt()引起编译错误的额外逗号。

后来对这个post的评论包括这个改编的代码 ,这对我很有用,而且看起来更直截了当。 如果你包含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; } 

给定这个代码,并且encryption的数据不会总是很好地转换成一个NSString的事实,编写两个方法可能会更方便,这两个方法包含所需的function,包括正向和反向。

 - (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是iPhone上Core OS的一部分。 10.4和10.5都有/usr/include/CommonCrypto ,虽然10.5有一个CCCryptor.3cc的手册页,10.4没有,所以YMMV。


编辑:看到这个后续问题使用Base64编码表示encryption的数据字节作为一个string(如果需要)使用安全,无损的转换。

我已经把NSData和NSString的类别集合在一起,它使用Jeff LaMarche的博客中find的解决scheme,以及Quinn Taylor在Stack Overflow中的一些提示 。

它使用类别来扩展NSData以提供AES256encryption,并且还提供了NSString到BASE64的扩展 – 将encryption数据安全地编码为string。

下面是一个例子来显示encryptionstring的用法:

 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 。 它的devise是为了完成你所要求的(并且是为了响应这里列出的代码的问题而构build的)。

RNCryptor使用带有盐的PBKDF2,提供一个随机的IV,并且附加HMAC(也是由PBKDF2自己生成的,它支持同步和asynchronous操作。

我在@QuinnTaylor上等了一会儿来更新他的答案,但是因为他没有,所以答案会更清楚一些,并且会加载到XCode7上(也许更多)。 我在Cocoa应用程序中使用了这个,但是它也可能适用于iOS应用程序。 没有ARC错误。

在您的AppDelegate.m或AppDelegate.mm文件中的任何@implementation部分之前粘贴。

 #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 

将这两个函数粘贴到您所需的@implementation类中。 在我的情况下,我在我的AppDelegate.mm或AppDelegate.m文件中select了@implementation AppDelegate。

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