【问题标题】:AES encryption algorithm not decrypting for few document formatsAES 加密算法无法解密少数文档格式
【发布时间】:2014-03-30 12:10:49
【问题描述】:

我正在尝试使用 AES 加密算法解密文档。

我从 enc 文件中获取密钥并在算法中使用它。

当我尝试解密文档时,我无法解密少数格式的文档,例如docx, xlsx, pptx and txt 文件。请在下面找到我的代码。

- (NSData *)AES256Decrypt
{

NSString* path = [[NSBundle mainBundle] pathForResource:<filename> ofType:@"enc"];

// fetch key data from the key file
NSData *keyData = [NSData dataWithContentsOfFile:path];

NSUInteger dataLength = [self length];

size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);

size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionECBMode,
                                      [keyData bytes], kCCKeySizeAES256,
                                      NULL
                                      [self bytes], dataLength, /* input */
                                      buffer, bufferSize, /* output */
                                      &numBytesDecrypted);

if (cryptStatus == kCCSuccess)
{
    return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}

free(buffer);
return nil;
}

我将上述方法添加为 NSData 的类别。

我尝试在客户端进行加密和解密。即使该文件也无法正确解密。当我尝试打开解密文件时,使用 QLPreviewController 查看文档时出现office open xml word processing document 错误。

我无法找到仅在少数文档中发生这种情况的原因。谁能帮我解决这个问题。 谢谢

【问题讨论】:

    标签: ios iphone objective-c encryption aes


    【解决方案1】:

    我跳出来的第一个问题是您指定了 AES128 算法,但还为 AES256 算法设置了密钥长度。据我所知,您需要使用与算法匹配的密钥长度。

    我会按如下方式更改 CCrypt 调用,看看是否能解决问题。

    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionECBMode,
                                          [keyData bytes], kCCKeySizeAES128,
                                          NULL
                                          [self bytes], dataLength, /* input */
                                          buffer, bufferSize, /* output */
                                          &numBytesDecrypted);
    

    当然,如果您打算使用 AES256,也可以这样做:

    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES256, kCCOptionECBMode,
                                          [keyData bytes], kCCKeySizeAES256,
                                          NULL
                                          [self bytes], dataLength, /* input */
                                          buffer, bufferSize, /* output */
                                          &numBytesDecrypted);
    

    对于解密,您实际上并不需要填充输出缓冲区大小,尽管这样做肯定没有坏处。

    其次,与其使用 malloc 作为输出缓冲区,不如使用 NSMutableData。这是我成功使用的一些代码来做类似的事情:

    NSMutableData * buffer = [NSMutableData dataWithLength:bufferSize];
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES256, kCCOptionECBMode,
                                          [keyData bytes], kCCKeySizeAES256,
                                          NULL
                                          [self bytes],
                                          dataLength,
                                          buffer.mutableBytes,
                                          buffer.length,
                                          &numBytesDecrypted);
    
    if (cryptStatus == kCCSuccess)
    {
        [buffer setLength:numBytesDecrypted];
        return buffer;
    }
    return nil;
    

    最后,可以在 Rob Napier 的著作中找到有关 Crypto 的重要资源。请参阅http://robnapier.net/aes-commoncrypto/ 了解一下。

    【讨论】:

    • 我没有找到你提到的任何算法(kCCAlgorithmAES256)。即使在 Napier 的示例中也使用了 kCCAlgorithmAES128。你能检查一下并告诉我。当我尝试使用可变数据而不是使用 malloc 时,之前的解密也无法正常工作。
    • 嗨 Raja - 你是对的 - 我查看了 CommonCrypto.h,发现该软件包目前仅支持 128 位 AES。我的意思是密钥长度必须与块长度匹配,并且我没有检查是否支持 256 位。
    • 关于 NSMutableData,如果您有其他成功使用 malloc 作为缓冲区的情况,我会说坚持使用它是安全的。但是,不确定为什么 NSMutableData 不适合您。回到您的主要问题 - 您确定数据提供者使用 256 位算法进行加密吗?您是否尝试过使用 128 位算法解密?此外,加密数据是否可能是 Base64 编码或其他某种编码?以这种方式对加密数据进行编码以进行传输是很常见的。
    【解决方案2】:

    如果您能够解密一些但不是所有指向可能存在填充问题的文件。我注意到您没有提供kCCOptionPKCS7Padding。如果数据的大小不是偶数块倍数,则需要某种形式的填充。 (当然,可以使用像 CTR 模式这样的流密码,但这通常是一个糟糕的选择。)

    使用 ECB 模式 (kCCOptionECBMode) 真的很糟糕,您应该真正使用默认的 CBC 以及 iv。

    Bob ‘n Alice On Security

    原创


    ECB模式(夏娃爱ECB)


    CBC模式

    看到区别了吗?还想使用欧洲央行吗?

    【讨论】:

    • 在服务器端,该算法使用 ECB 模式实现对文档的加密。更改服务器算法也不在我手中。无论如何都需要使用此算法解密。谢谢。
    • 对,我明白了:安全性真的不是那么重要。我敢打赌塔吉特也说了同样的话,结果很好——哦等等。看,如果您是专业人士,您不会做这种事情:因为您不愿意表明立场而牺牲安全性。如果您是专业人士,请告诉他们不。 Easy:不——我几乎因为不接受糟糕的加密而被解雇——但我没有。我从未磕头,也从未因此被解雇。你和其他许多人必须学会为这些事情挺身而出。每次我都做得很好,我得到了尊重。你也可以。
    • 如果我们想被视为专业人士,我们需要像专业人士一样行事。
    • 对不起,我很严厉,但安全性不同。程序(应用程序)中的一些错误不是杀手,它是罕见的没有几个错误的程序。但是安全方面的一个错误使这一切都变得毫无用处。攻击者只需要找到一个。以下是建议:架构师需要花费大量时间研究与加密相关的安全性,然后聘请领域专家来审查设计和代码,或者聘请领域专家来设计专家。我走第一条路。我让公司聘请了一位领域专家来审查每个项目的安全性,预计每天支付大约 2000 美元。这是值得的。
    【解决方案3】:

    我在这里看到一个问题:

    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionECBMode,
                                      [keyData bytes], kCCKeySizeAES256,
                                      NULL
                                      [self bytes], dataLength, /* input */
                                      buffer, bufferSize, /* output */
                                      &numBytesDecrypted);
    

    在此代码中,[keyData bytes] 应该是您的密码。但你正在这样做:

    NSData *keyData = [NSData dataWithContentsOfFile:path];
    

    您的文档数据应在您当前拥有[self bytes] 的参数中传递。

    编辑: 看到您的评论后,我意识到该文件包含密钥。

    我在我的一个项目中使用 AES,并使用以下代码:

    // '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: (char *)keyPtr maxLength: sizeof(keyPtr) encoding: NSUTF8StringEncoding];
    

    最后一行'key'是我的密码。我这样调用CCCrypt 函数:

    CCCryptorStatus result = CCCrypt( kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                     keyPtr, kCCKeySizeAES256,
                                     NULL /* initialization vector (optional) */,
                                     [self bytes], dataLength, /* input */
                                     buffer, bufferSize, /* output */
                                     &numBytesDecrypted );
    

    【讨论】:

    • keyData bytes 是密码,[self bytes] 是文档。 [NSData dataWithContentsOfFile:path] 是我获取算法密钥的 enc 文件(密钥文件)内容的地方。而 [self bytes] 是加密文档的内容。
    • 是的。我也在其中一个项目中使用了相同的方法。现在我需要使用 enc 文件中的密钥。当我尝试使用它时,无法单独解密少数文件。那是我的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-27
    • 2021-05-19
    • 2014-09-14
    • 1970-01-01
    • 2019-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多