Objective-c中的AES256解密问题 [英] AES256 decryption issue in Objective-c

查看:67
本文介绍了Objective-c中的AES256解密问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用以下代码片段解密文件,该文件已使用32字节密钥加密.因此,当我尝试加密文件数据时,一切正常.但是当我尝试解密时,程序甚至没有通过CryptoExtensions.m中的条件if (cryptStatus == kCCSuccess).我真的很累找出一个问题.我试图使用Base64解码,但是我的文件以UTF8编码保存,因此当我将其内容从NSData记录到日志中时,我没有任何问题:

I am trying to use the following snippet to decrypt file, which was encrypted with 32 byte key. So when I am trying to encrypt file data, everything is going ok. But when I am trying do decrypt, program even don't pass the condition if (cryptStatus == kCCSuccess) in CryptoExtensions.m. I am really tired figuring out a problem. I was trying to use Base64 decoding, but my file is saved in UTF8 encoding, so I have no problems when I just put it's content in log from NSData:

NSData *fileData = [[[NSData alloc] initWithContentsOfFile:destPath] autorelease];

NSLog(@"File data:%@",[[NSString alloc] initWithData:fileData encoding:NSUTF8StringEncoding]);

但是当我尝试解密它时,我是从 CryptoExtensions 方法获得的nil:

But when I am trying to decrypt it, I am getting nil from CryptoExtensions method:

NSData *aesResponse = [fileData AES256DecryptWithKey:@"4QXcCZlgRAIchiaqkMVpF3nkpARmdL3z"];
NSLog(@"AES:%@",[[NSString alloc] initWithData:aesResponse encoding:NSUTF8StringEncoding]);

这是加密代码段的内容:

This is contents of crypto snippet:

CryptoExtensions.h

#import <Foundation/Foundation.h>
@interface NSData (CryptoExtensions)
- (NSData*)AES256EncryptWithKey:(NSString*)key;
- (NSData*)AES256DecryptWithKey:(NSString*)key;
@end

CryptoExtensions.m

#import "CryptoExtensions.h"
#import <CommonCrypto/CommonCryptor.h>
@implementation NSData (CryptoExtensions)
- (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

推荐答案

此代码存在重大的安全问题.它错误地构造了AES密钥,从而极大地减少了密钥空间,并且没有IV,从而给第一个块造成了问题.我强烈建议不要使用此代码.

This code has significant security issues. It incorrectly constructs the AES key, drastically reducing the keyspace and has no IV, creating problems for the first block. I strongly recommend against this code.

在为这个常用代码段开发替代程序的过程中,我是最主要的方法.参见 https://github.com/rnapier/RNCryptor .如果开箱即用对您不起作用,请告诉我.我正在努力使人们在不再使用AES256EncryptWithKey的所有常见情况下使用起来都很容易.

I'm most of the way through developing a replacement for this commonly-used snippet. See https://github.com/rnapier/RNCryptor. If it doesn't work for you out of the box, let me know. I'm trying to make it easy enough to use for all the common cases that people will stop using AES256EncryptWithKey.

有关此代码问题的详细讨论,请参见使用CommonCrypto使用AES正确加密.我喜欢有人将AES加密归类为易于使用的类别.我只希望它没有那么多安全问题.

For a much longer discussion about the problems with this code, see Properly encrypting with AES with CommonCrypto. I love that someone wrapped up AES encryption into an easy to use category. I just wish that it hadn't had so many security issues.

回到您的实际问题,您是否使用AES256EncryptWithKey加密此数据?如果不是,则特定格式可能会根本不同.几乎每种AES加密实现都使用不同的方法来生成其输入参数,然后生成其输出(多数情况也不能很好地证明这一点).您必须匹配参数和格式.例如,您不能使用AES256EncryptWithKey来解密使用openssl enc生成的内容.

Coming back to your actual question, did you use AES256EncryptWithKey to encrypt this data? If not, then the specific format is likely radically different. Almost every AES encryption implementation uses a different approach in generating its input parameters and then generating its output (most don't document this well, either). You have to match the parameters and format. For example, you can't use AES256EncryptWithKey to decrypt something generated with openssl enc.

这篇关于Objective-c中的AES256解密问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆