自从为iOS应用程序添加64位支持后,加密就破了

时间:2014-12-16 21:04:36

标签: ios encryption 64-bit

我在我的应用中使用以下代码进行加密。我刚刚更改了我的应用程序以获得Apple所需的64位支持。由于启用64位,加密不再有效。我不知道加密或解密是否有问题,但是当加密某些数据然后解密时,我最终会变成垃圾。

#import "AES256.h"
#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];

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

    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

更新 我发现我的密钥有问题可能是原因的一部分。密钥创建的一部分使用散列字符串。这种散列函数在32位iPhone上产生不同的摘要值,而不是64位iPhone。我不知道为什么会这样。 keydata长度永远不会超过32位整数。如果我硬编码一个字符串返回此处,加密/解密仍然不起作用,所以仍然存在问题。

+ (NSString *)hashString:(NSString *)string
{
    const char *s = [string cStringUsingEncoding:NSASCIIStringEncoding];
    NSData *keyData = [NSData dataWithBytes:s length:strlen(s)];

    // This is the destination
    uint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0};
    // This one function does an unkeyed SHA1 hash of your hash data
    CC_SHA1(keyData.bytes, (CC_LONG)keyData.length, digest);

    // Now convert to NSData structure to make it usable again
    NSData *convertedData = [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];
    // description converts to hex but puts <> around it and spaces every 4 bytes
    NSString *hash = [convertedData description];
    hash = [hash stringByReplacingOccurrencesOfString:@" " withString:@""];
    hash = [hash stringByReplacingOccurrencesOfString:@"<" withString:@""];
    hash = [hash stringByReplacingOccurrencesOfString:@">" withString:@""];
    return hash;
}

更新2:我注意到使用少于16个字节的数据时只会出现问题。 16和更大的作品。

2 个答案:

答案 0 :(得分:1)

检查所有 32位和64位加密方法的输入:Key,IV,plaintext。确保它们逐字节相同。追踪任何差异并修复它们。 Crypto旨在为小输入差异提供较大的输出差异。

在某些时候,系统更改可能会在其中一个输入中引入意外更改。

你说整个输出都是垃圾;在那种情况下首先看看钥匙。有故障的IV只会破坏AES中的前16个字节。如果输出被破坏,我很惊讶你没有出现错误的填充错误。

答案 1 :(得分:0)

使用此,

#import "NSString+MD5Addition.h"
#import <CommonCrypto/CommonDigest.h>

@implementation NSString(MD5Addition)

- (NSString *) stringFromMD5{

    if(self == nil || [self length] == 0)
        return nil;

    const char *value = [self UTF8String];

    unsigned char outputBuffer[CC_MD5_BLOCK_BYTES];
    CC_MD5(value, strlen(value), outputBuffer);

    NSMutableString *outputString = [[NSMutableString alloc] initWithCapacity:CC_MD5_BLOCK_BYTES * 2];
    for(NSInteger count = 0; count < CC_MD5_BLOCK_BYTES; count++){
        [outputString appendFormat:@"%02x",outputBuffer[count]];
    }

    return outputString;
}