CCCrypt解密在AES CBC即使没有IV [英] CCCrypt decrypting in AES CBC works even without IV

查看:594
本文介绍了CCCrypt解密在AES CBC即使没有IV的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个混乱的问题,解密一个文件,使用CCCrypt的AES-CBC模式加密与一个随机,16byte IV产生完全相同的输出,无论我通过相同的正确的IV用于加密或根本没有。 / p>

我期望:使用NULL IV解密不应导致正确的解密。
我观察到:使用NULL IV结果与用于加密的IV结果相同。



为了完整起见,下面是重要的代码snippets, iv 以16字节安全随机NSData的形式传递。



我不明白这里?是CCCrypt以某种方式从加密的数据自己计算出IV吗?我在文档中找不到任何东西。

   - (NSData *)encryptedDataForData:(NSData *)rawData 
withKey:(NSData *)key
iv:(NSData *)iv
错误:(NSError __autoreleasing **)错误
{
size_t outLength;
NSMutableData * cipherData = [NSMutableData dataWithLength:rawData.length + kAlgorithmBlockSize];

CCCryptorStatus result = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCModeCBC,
key.bytes,
key.length,
iv .bytes,
rawData.bytes,
rawData.length,
cipherData.mutableBytes,
cipherData.length,
& outLength);
if(result == kCCSuccess){
cipherData.length = outLength;
return cipherData;
} else {
return nil; (NSData *)密钥错误:(NSError __autoreleasing **)错误
(NSData *)密钥错误(NSError __autoreleasing **)错误



- (NSData *)decryptedDataForData: {
size_t outLength;
NSMutableData * decryptptedData = [NSMutableData dataWithLength:encryptedData.length];

//这行只是为了说明如何设置完全相同的iv - 如果这一个
//用于加密 - 产生与传递时相同的输出iv = NULL
NSData * iv = [Cryptor dataForHex:@724a7fc0 0d8ac9d5 f09ff4c1 64d2d1bb];

CCCryptorStatus result = CCCrypt(kCCDecrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCModeCBC,
key.bytes,
key.length,
iv .bytes,// iv OR NULL - >相同的结果o_O
encryptedData.bytes,
encryptedData.length,
decryptptedData.mutableBytes,
decryptptedData.length,
& outLength);
if(result == kCCSuccess){
decryptptedData.length = outLength;
return decryptedData;
} else {
return nil;
}
}

EDIT: p>

要详细说明,无论我使用哪个IV来解密(尝试了几个不同的随机IV),我总是得到字节的字节相同的结果。即使我只从加密文件的中间某处解密加密文件的一些部分块。



这可能与我正在/解密的实际数据有关mp3文件)?



当我只是将一些实际加密文件的任意块传递给解密器时,应该不需要块的数据我不明确地提供IV)做正确的解密?我可以在这里个人想到的唯一解释是,CCCrypt只是总是使用第一个16字节作为IV,不解密,但它们在输出中丢弃它们。



编辑2:



输出en /解密,显示输入和输出数据的前两个块,键和iv:

 #encryption 
data< 4cd9b050 30c04bf9 2a0cb024 19010a31 400c2261 0069196a d77bcae6 9799ae26&
iv< 724a7fc0 0d8ac9d5 f09ff4c1 64d2d1bb>
key< 78656a1a 337fddd6 fa52e34d 9156d187>
encrypted< cf85cdbe 10a87309 a6fb4c4e ce640619 8f445b70 3738018a e78291a7 b4ea26ce>

#正确的解密IV
data< cf85cdbe 10a87309 a6fb4c4e ce640619 8f445b70 3738018a e78291a7 b4ea26ce&
iv< 724a7fc0 0d8ac9d5 f09ff4c1 64d2d1bb>
key< 78656a1a 337fddd6 fa52e34d 9156d187>
解密< 4cd9b050 30c04bf9 2a0cb024 19010a31 400c2261 0069196a d77bcae6 9799ae26>

#用零解密IV
data< cf85cdbe 10a87309 a6fb4c4e ce640619 8f445b70 3738018a e78291a7 b4ea26ce>
iv< 00000000 00000000 00000000 00000000>
key< 78656a1a 337fddd6 fa52e34d 9156d187>
解密< 4cd9b050 30c04bf9 2a0cb024 19010a31 400c2261 0069196a d77bcae6 9799ae26>

#用不同IV进行解密
数据< cf85cdbe 10a87309 a6fb4c4e ce640619 8f445b70 3738018a e78291a7 b4ea26ce>
iv< 12345678 9abcdef1 23456789 abcdef12>
key< 78656a1a 337fddd6 fa52e34d 9156d187>
解密< 4cd9b050 30c04bf9 2a0cb024 19010a31 400c2261 0069196a d77bcae6 9799ae26>

编辑3:



-dataForHex:是:

  +(NSData *)dataForHex :( NSString *)hex 
{
NSString * hexNoSpaces = [[[hex stringByReplacingOccurrencesOfString:@withString:@]
stringByReplacingOccurrencesOfString:@< withString:@]
stringByReplacingOccurrencesOfString:@> withString:@];

NSMutableData * data = [[NSMutableData alloc] init];
unsigned char whole_byte = 0;
char byte_chars [3] = {'\0','\0','\0'};
for(NSUInteger i = 0; i <[hexNoSpaces length] / 2; i ++){
byte_chars [0] =(unsigned char)[hexNoSpaces characterAtIndex:(NSUInteger)(i * 2) ;
byte_chars [1] =(unsigned char)[hexNoSpaces characterAtIndex:(NSUInteger)(i * 2 + 1)];
whole_byte =(unsigned char)strtol(byte_chars,NULL,16);
[data appendBytes:& whole_byte length:1];
}
返回数据;
}


解决方案

用于格式化注释。 / p>

使用iv:

 清除资料:< 4cd9b050 30c04bf9 2a0cb024 19010a31> ; 
iv data:< 724a7fc0 0d8ac9d5 f09ff4c1 64d2d1bb>
键数据:< 78656a1a 337fddd6 fa52e34d 9156d187>
crypt data:< d2c2efee 54e43781 549eec03 9db688e1 7c4248e7 e2ac1d80 7105ffae 4043ffb3>
解密数据:< 4cd9b050 30c04bf9 2a0cb024 19010a31>

iv为0:

 清除数据:< 4cd9b050 30c04bf9 2a0cb024 19010a31> 
iv data:< 00000000 00000000 00000000 00000000>
键数据:< 78656a1a 337fddd6 fa52e34d 9156d187>
crypt data:< cf85cdbe 10a87309 a6fb4c4e ce640619 6be7b155 9db3f066 97e461e7 ced7960f>
解密数据:< 4cd9b050 30c04bf9 2a0cb024 19010a31>

很明显,iv并未在OP代码中使用。



上述代码:

  CCCryptorStatus ccStatus = kCCSuccess; 
size_t cryptBytes = 0;
NSMutableData * dataOut = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];

ccStatus = CCCrypt(encryptOrDecrypt,// kCCEncrypt或kCCDecrypt
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
key.bytes,
kCCKeySizeAES128,
iv .bytes,
dataIn.bytes,
dataIn.length,
dataOut.mutableBytes,
dataOut.length,
& cryptBytes);

dataOut.length = cryptBytes;


I have a confusing problem, where decrypting a file which was encrypted using CCCrypt's AES-CBC mode with a randomized, 16byte IV produces the exact same output whether I pass in the same correct IV used for encryption or none at all.

What I expect: using a NULL IV for decrypting should not result in a correct decryption. What I observe: using a NULL IV results in the same result as with the IV used for encryption.

Below for sake of completeness, here's the important code snippets, iv is passed in as 16-byte securely randomized NSData.

What am I not understanding here? Is CCCrypt somehow figuring out the IV from the encrypted data by itself? I couldn't find anything around that in the docs.

- (NSData *)encryptedDataForData:(NSData *)rawData
                         withKey:(NSData *)key
                              iv:(NSData *)iv
                           error:(NSError __autoreleasing**)error
{
    size_t outLength;
    NSMutableData *cipherData = [NSMutableData dataWithLength:rawData.length + kAlgorithmBlockSize];

    CCCryptorStatus result = CCCrypt(kCCEncrypt,
                                     kCCAlgorithmAES128,
                                     kCCOptionPKCS7Padding | kCCModeCBC,
                                     key.bytes,
                                     key.length,
                                     iv.bytes,
                                     rawData.bytes,
                                     rawData.length,
                                     cipherData.mutableBytes,
                                     cipherData.length,
                                     &outLength);
    if (result == kCCSuccess) {
        cipherData.length = outLength;
        return cipherData;
    } else {
        return nil;
    }
}

- (NSData *)decryptedDataForData:(NSData *)encryptedData withKey:(NSData *)key error:(NSError __autoreleasing**)error
{
    size_t outLength;
    NSMutableData *decryptedData = [NSMutableData dataWithLength:encryptedData.length];

    // this line is just to illustrate how setting the exact same iv here - if this one
    // was used for encryption - results in same output as when passing iv = NULL
    NSData *iv = [Cryptor dataForHex:@"724a7fc0 0d8ac9d5 f09ff4c1 64d2d1bb"];

    CCCryptorStatus result = CCCrypt(kCCDecrypt,
                                     kCCAlgorithmAES128,
                                     kCCOptionPKCS7Padding | kCCModeCBC,
                                     key.bytes,
                                     key.length,
                                     iv.bytes, // iv OR NULL --> same result o_O
                                     encryptedData.bytes,
                                     encryptedData.length,
                                     decryptedData.mutableBytes,
                                     decryptedData.length,
                                     &outLength);
    if (result == kCCSuccess) {
        decryptedData.length = outLength;
        return decryptedData;
    } else {
        return nil;
    }
}

EDIT:

To elaborate on this, no matter which IV I use for decryption (tried out a couple of different randomized IV's) I always do get byte for byte the identical results. Even when I decrypt only some partial chunk of the encrypted file somewhere from the middle of the encrypted file.

Is this maybe related to the actual data I am en/decrypting (mp3 files)?

When I just pass some arbitrary chunk of the actual encrypted file to the decryptor, shouldn't it require the block right before that chunk of data (which I do not provide explicitly as the IV) to do the proper decryption? The only explanation I could think of here personally is that CCCrypt just always uses the first 16-bytes as the IV and does not decrypt those but drops them in the output.

EDIT 2:

Output of en/decryption, showing the first two blocks of in and output data, the key and the iv:

# encryption
data <4cd9b050 30c04bf9 2a0cb024 19010a31 400c2261 0069196a d77bcae6 9799ae26>
iv <724a7fc0 0d8ac9d5 f09ff4c1 64d2d1bb>
key <78656a1a 337fddd6 fa52e34d 9156d187>
encrypted <cf85cdbe 10a87309 a6fb4c4e ce640619 8f445b70 3738018a e78291a7 b4ea26ce>

# decryption with correct IV
data <cf85cdbe 10a87309 a6fb4c4e ce640619 8f445b70 3738018a e78291a7 b4ea26ce>
iv <724a7fc0 0d8ac9d5 f09ff4c1 64d2d1bb>
key <78656a1a 337fddd6 fa52e34d 9156d187>
decrypted <4cd9b050 30c04bf9 2a0cb024 19010a31 400c2261 0069196a d77bcae6 9799ae26>

# decryption with zero IV
data <cf85cdbe 10a87309 a6fb4c4e ce640619 8f445b70 3738018a e78291a7 b4ea26ce>
iv <00000000 00000000 00000000 00000000>
key <78656a1a 337fddd6 fa52e34d 9156d187>
decrypted <4cd9b050 30c04bf9 2a0cb024 19010a31 400c2261 0069196a d77bcae6 9799ae26>

# decryption with different IV
data <cf85cdbe 10a87309 a6fb4c4e ce640619 8f445b70 3738018a e78291a7 b4ea26ce>
iv <12345678 9abcdef1 23456789 abcdef12>
key <78656a1a 337fddd6 fa52e34d 9156d187>
decrypted <4cd9b050 30c04bf9 2a0cb024 19010a31 400c2261 0069196a d77bcae6 9799ae26>

EDIT 3:

The code for -dataForHex: is:

+ (NSData *)dataForHex:(NSString *)hex
{
    NSString *hexNoSpaces = [[[hex stringByReplacingOccurrencesOfString:@" " withString:@""]
            stringByReplacingOccurrencesOfString:@"<" withString:@""]
            stringByReplacingOccurrencesOfString:@">" withString:@""];

    NSMutableData *data = [[NSMutableData alloc] init];
    unsigned char whole_byte = 0;
    char byte_chars[3] = {'\0','\0','\0'};
    for (NSUInteger i = 0; i < [hexNoSpaces length] / 2; i++) {
        byte_chars[0] = (unsigned char) [hexNoSpaces characterAtIndex:(NSUInteger) (i * 2)];
        byte_chars[1] = (unsigned char) [hexNoSpaces characterAtIndex:(NSUInteger) (i * 2 + 1)];
        whole_byte = (unsigned char)strtol(byte_chars, NULL, 16);
        [data appendBytes:&whole_byte length:1];
    }
    return data;
}

解决方案

Used for formatting comment.

With iv:

clear data:   <4cd9b050 30c04bf9 2a0cb024 19010a31>
iv data:      <724a7fc0 0d8ac9d5 f09ff4c1 64d2d1bb>
key data:     <78656a1a 337fddd6 fa52e34d 9156d187>
crypt data:   <d2c2efee 54e43781 549eec03 9db688e1 7c4248e7 e2ac1d80 7105ffae 4043ffb3>
decrypt data: <4cd9b050 30c04bf9 2a0cb024 19010a31>

With iv of 0's:

clear data:   <4cd9b050 30c04bf9 2a0cb024 19010a31>
iv data:      <00000000 00000000 00000000 00000000>
key data:     <78656a1a 337fddd6 fa52e34d 9156d187>
crypt data:   <cf85cdbe 10a87309 a6fb4c4e ce640619 6be7b155 9db3f066 97e461e7 ced7960f>
decrypt data: <4cd9b050 30c04bf9 2a0cb024 19010a31>

It is clear that the iv is not being used in the OP code.

Code for above:

CCCryptorStatus ccStatus   = kCCSuccess;
size_t          cryptBytes = 0;
NSMutableData  *dataOut    = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];

ccStatus = CCCrypt( encryptOrDecrypt, // kCCEncrypt or kCCDecrypt
                   kCCAlgorithmAES128,
                   kCCOptionPKCS7Padding,
                   key.bytes, 
                   kCCKeySizeAES128,
                   iv.bytes,
                   dataIn.bytes,
                   dataIn.length,
                   dataOut.mutableBytes,
                   dataOut.length,
                   &cryptBytes);

dataOut.length = cryptBytes;

这篇关于CCCrypt解密在AES CBC即使没有IV的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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