iOS中的AES256 NSString加密

Sam*_*cer 14 encryption aes objective-c nsstring ios5

我的应用程序使用 256-Bit Encryption 加密和解密(或应该)使用另一个NSString(关键字)的NSString(要加密/解密的文本).当我运行我的项目并运行encrypt方法时,没有任何内容被加密,textfield就会自行清除.这是我的代码:

-(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);
}
Run Code Online (Sandbox Code Playgroud)

单击此链接可以下载头文件:包含AES实现的ZIP文件

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

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

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

Rob*_*ier 11

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

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

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

有关上述实施问题的解释,以及如何在iOS上正确使用AES,请参阅使用CommonCryptoAES进行正确加密.请注意,iOS 5现已CCKeyDerivationPBKDF推出.

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


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


Fat*_*mez 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
Run Code Online (Sandbox Code Playgroud)

使用它的包装函数;

- (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];
}
Run Code Online (Sandbox Code Playgroud)