3

データを暗号化し、アプリ サンドボックス内のファイルに保存する 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を使用してファイルの復号化を試みました(キーと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 のキーは、256 ビットに変換される 32 文字の文字列です。openssl が期待するキーは、その文字列のバイナリ表現からの 64 の 16 進数です。同様に、CCCrypt の iv は 16 文字の文字列で、128 ビットに変換されます。openssl が期待する iv は、その文字列の 16 進表現です。これら 2 つの 16 進表現を使用すると、簡単に復号化できました。

4

1 に答える 1

4

-K および -iv で指定された openssl キーと iv は、バイナリ データの 16 進数表現として指定されます。
openssl ドキュメントから:

使用する実際のキー: これは、16 進数のみで構成される文字列として表す必要があります。

この例の 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 0000000000000000000000000000000 -iv 000000000000000000000000000000 -in /Users/dan/Desktop/encrypted.dat -out /Users/dan/Desktop/decrypted.txt

猫/Users/dan/Desktop/decrypted.txt
0123456789abcdef

メソッドdoCipherについては、このSOの回答を参照してください

于 2014-05-14T21:58:57.130 に答える