首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AES CBC中的CCCrypt解密即使没有IV也能工作。

AES CBC中的CCCrypt解密即使没有IV也能工作。
EN

Stack Overflow用户
提问于 2014-11-19 10:18:45
回答 4查看 16.9K关注 0票数 10

我有一个令人困惑的问题,就是用CCCrypt的AES-CBC模式用随机的16字节IV解密一个文件,无论我传递相同的用于加密的正确IV,还是根本不传递,都会产生完全相同的输出。

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

为了完整起见,下面是重要的代码片段,iv作为16字节安全随机NSData传入。

我在这里有什么不懂的?CCCrypt是否在某种程度上从加密的数据中计算出IV?我在文件里什么都找不到。

代码语言:javascript
复制
- (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;
    }
}

编辑:

为了详细说明这一点,无论我使用哪种IV进行解密(尝试了几个不同的随机IV),我总是得到字节的字节--相同的结果。即使我只解密了加密文件的部分块,也是从加密文件的中间位置解密的。

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

当我只是将一些实际加密文件的任意块传递给解密器时,是否应该要求数据块之前的块(我没有显式地作为IV提供数据块)来进行正确的解密?我个人能想到的唯一解释是,CCCrypt总是使用前16个字节作为IV,而不是解密这些字节,而是将它们删除到输出中。

编辑2:

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

代码语言:javascript
复制
# 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>

编辑3:

-dataForHex:的代码是:

代码语言:javascript
复制
+ (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;
}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-11-19 14:27:14

用于格式化注释。

第四部分:

代码语言:javascript
复制
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>

四次0次:

代码语言:javascript
复制
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>

很明显,在OP代码中没有使用iv。

以上代码:

代码语言:javascript
复制
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;
票数 6
EN

Stack Overflow用户

发布于 2015-03-05 22:30:01

这也是值得指出的,一个人不应该包括与填充选项的模式。我已经看到了很多这样的情况,实际上,我也陷入了同样的陷阱,试图成为一个“尽可能明确的”。

代码语言:javascript
复制
kCCOptionPKCS7Padding | kCCModeCBC

应:

代码语言:javascript
复制
kCCOptionPKCS7Padding

有趣的事实1: -- kCCModeEBCkCCOptionPKCS7Padding --共享相同的值: 1,并将实际计算为使用kCCOptionPKCS7Padding,这将默认为kCCModeCBC

有趣的事实2:使用kCCOptionPKCS7Padding | kCCModeCBC计算结果为设置了kCCOptionPKCS7Padding标志和kCCOptionECBMode,这实际上导致使用了kCCModeEBC

票数 7
EN

Stack Overflow用户

发布于 2014-11-19 14:34:12

iv只用于解密时的第一个块,进一步的块使用来自前一个块的密码文本,因此它具有一定的自同步性。

维基百科图片:

来自维基百科分组密码工作方式

因此,在块边界上CBC加密流的中间提取解密除第一个块外是可行的。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27014292

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档