iOS中的AES256 NSString加密

时间:2011-11-27 18:05:47

标签: objective-c encryption nsstring ios5 aes

我的应用使用 256位加密,使用另一个NSString(关键字)加密和解密(或应该)NSString(要加密/解密的文本)。当我运行我的项目并运行加密方法时,没有任何内容被加密,文本字段只是清除自己。这是我的代码:

-(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 File containing AES Implementation

我被告知我需要使用字符串的Base-64编码来获得任何结果。如果这是真的,那我该怎么做呢?

我也被告知在iOS 5中加密已更改,而我的应用程序是iOS 5+ ONLY应用程序。如果这是真的,那么我需要做些什么来使这个加密在iOS 5上工作,或者在哪里可以找到另一个可以在NSString上工作的AES 256位实现。

为什么这段代码不会产生结果?

2 个答案:

答案 0 :(得分:11)

编辑:下面的链接指的是较旧的实现。最新版本称为RNCryptor

您的代码不使用iOS的内置AES实现。它有自己的自定义实现。 AESEncryptWithPassphrase:也错误地生成密钥,丢弃了密码中的大部分熵。

在iOS上,您应该使用AES的CCCrypt*()功能。您还应确保了解加密和解密例程中发生的情况。编写看起来正确的加密代码非常容易(因为你无法通过检查读取输出),但是非常不安全。

有关上述实施问题的解释,以及如何在iOS上正确使用AES,请参阅Properly encrypting with AES with CommonCrypto。请注意,iOS 5现在提供CCKeyDerivationPBKDF

在加密之前,不要求对字符串进行Base-64编码。如果您需要将二进制数据转换为可以通过电子邮件或其他控制字符出现问题的地方轻松发送的表单,则使用Base-64编码。它以7位ASCII数据转换8位二进制数据。这在这里没有必要或有用。


编辑:请务必仔细阅读有关如何使用此代码的说明。简单地剪切和粘贴安全代码并希望它起作用是危险的。也就是说,RNCryptManager的完整源代码可作为iOS 5 Programming Pushing the Limits的第11章示例代码的一部分提供,可能会有所帮助 [编辑:这是旧代码;我现在推荐RNCryptor,链接在答案的顶部] 。这本书(应该在下周提供,尽管网站上说的内容)包含了关于如何使用此代码的更长时间的讨论,包括如何提高性能和处理非常大的数据集。

答案 1 :(得分:7)

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