如何使用openssl使用CCCrypt解密在Objective-C中创建的文件?(How can I decrypt a file created in Objective-C using CCCrypt by using openssl?)

我有一个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

两者都返回相同的错误:

bad decrypt 28969:错误:06065064:数字信封例程:EVP_DecryptFinal_ex:bad decrypt:/SourceCache/OpenSSL098/OpenSSL098-50/src/crypto/evp/evp_enc.c:330:

我也尝试了其他模式和其他选项,如-naltalt和-a。 没有人回复明文。

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

==========

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

I have an iOS mobile app that encrypts data and stores it in files in the app sandbox. Files are encrypted using CCCrypt() as follows:

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

The key is 256 bits long, the IV is 128 bits long. I'm a not an expert with encryption, but this should be using CBC mode (default for CCCrypt()) and it is my understanding that the PKCS#7 padding option specified here is equivalent to openssl's PKCS#5 padding.

The data is written to a file as follows:

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

I have attempted to decrypt the file using openssl as follows (key and iv replaced with 0's):

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

and

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

Both return the same error:

bad decrypt 28969:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:/SourceCache/OpenSSL098/OpenSSL098-50/src/crypto/evp/evp_enc.c:330:

I've also tried other modes and other options such as -nosalt and -a. None have returned the cleartext.

I've spent hours trying to find an example of how to do this anywhere online, but nothing that has helped me resolve the problem. Help would be appreciated.

==========

Answer: The key in CCCrypt is a 32 char string that gets converted to 256 bits. The key expected by openssl is the 64 hex digits from the binary representation of that string. Similarly, the iv in CCCrypt is a 16 char string that gets converted into 128 bits. The iv expected by openssl is the hex representation of that string. Once I used the hex representations of those two, it decrypted easily.

最满意答案

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

要使用的实际密钥:必须将其表示为仅由十六进制数字组成的字符串。

示例中的两个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答案

The openssl key and iv as specified with -K and -iv are specified as a hex representation of the binary data. From the openssl docs:

the actual key to use: this must be represented as a string comprised only of hex digits.

Both of the openssl keys in the example are 128 bits, for AES 256 they need to be 256 bits. The iv must be block size, 128 bits but in the above example the iv is only 64 bits.

I tested and this works:

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

For the method doCipher see this SO answer

更多推荐