如何使用openssl使用CCCrypt解密在Objective-C中创建的文件?

时间:2014-05-14 20:30:38

标签: ios encryption openssl commoncrypto

我有一个iOS移动应用程序,可以加密数据并将其存储在应用程序沙箱中的文件中。文件使用CCCrypt()加密,如下所示:

    CCCryptorStatus aCryptStatus = CCCrypt(kCCEncrypt, 
                                       kCCAlgorithmAES128, 
                                       kCCOptionPKCS7Padding,
                                       aKeyPtr, 
                                       kCCKeySizeAES256,
                                       aIVPtr,
                                       [self bytes], 
                                       aDataLength, 
                                       aBuffer, 
                                       aBufferSize, 
                                       &aNumBytesEncrypted);

密钥长256位,IV长128位。我不是加密专家,但这应该是使用CBC模式(CCCrypt()的默认值),我的理解是这里指定的PKCS#7填充选项等同于openssl的PKCS#5填充。

将数据写入文件,如下所示:

     NSData* aSerializedData = [[self serialize]  dataUsingEncoding:NSUTF8StringEncoding];
     NSData* aEncryptedData = [aSerializedData AES256EncryptWithKey:ENCKey 
                                               InitializationVector:ENCIv]; 
     NSFileManager* aFileManager = [[NSFileManager alloc] init];
     BOOL aFileWritten = [aFileManager createFileAtPath:aFilePath 
                                               contents:aEncryptedData 
                                             attributes:nil];

我试图使用openssl解密文件,如下所示(key和iv替换为0):

$ openssl enc -aes-128-cbc -d -K 00000000000000000000000000000000 -iv 0000000000000000 -in encrypted.dat -out decrypted.txt 

$ openssl enc -aes-256-cbc -d -K 00000000000000000000000000000000 -iv 0000000000000000 -in encrypted.dat -out decrypted.txt 

两者都返回相同的错误:

  解密不好   28969:错误:06065064:数字信封   套路:EVP_DecryptFinal_ex:坏   解密:/SourceCache/OpenSSL098/OpenSSL098-50/src/crypto/evp/evp_enc.c:330:

我还尝试过其他模式和其他选项,例如-nosalt和-a。没有人回复明文。

我花了好几个小时试图找到一个如何在网上做到这一点的例子,但没有任何帮助我解决问题的方法。帮助将不胜感激。

==========

答案:CCCrypt中的密钥是一个32字符串,可以转换为256位。 openssl期望的密钥是来自该字符串的二进制表示的64位十六进制数字。类似地,CCCrypt中的iv是一个16字符串,可以转换为128位。 openssl期望的iv是该字符串的十六进制表示。一旦我使用了那两个的十六进制表示,它就很容易解密。

1 个答案:

答案 0 :(得分:4)

使用-K和-iv指定的openssl键和iv被指定为二进制数据的十六进制表示。
来自openssl docs:

  

要使用的实际密钥:必须将其表示为包含的字符串   只有十六进制数字。

示例中的两个openssl密钥都是128位,对于AES 256,它们需要是256位。 iv必须是块大小,128位,但在上面的例子中,iv只有64位。

我测试了,这有效:

uint8_t *zeros     = calloc(1, 256);
NSData  *keyData   = [NSData dataWithBytes:zeros length:16];
NSData  *ivData    = [NSData dataWithBytes:zeros length:16];
NSData  *clearData = [@"0123456789abcdef" dataUsingEncoding:NSUTF8StringEncoding];

NSData *encryptedData = [AESTest doCipher:clearData iv:ivData key:keyData context:kCCEncrypt error:&error];
[encryptedData writeToFile:@"/Users/dan/Desktop/encrypted.dat" atomically:YES];

openssl enc -aes-128-cbc -d -K 00000000000000000000000000000000 -iv 00000000000000000000000000000000 -in /Users/dan/Desktop/encrypted.dat -out /Users/dan/Desktop/decrypted.txt

cat /Users/dan/Desktop/decrypted.txt
0123456789ABCDEF

对于方法doCipher,请参阅此SO answer