2016-03-26 4 views
3

入力ファイルには、次のものがあります。
最初の行には、16進数で16バイトの長さでエンコードされたキーがあります。
2行目暗号化メッセージ(CBCモードのAES128、暗号化されたメッセージの前にランダムivが付いています)。

Crypto ++ライブラリを使用したCBCモード実装のAES128

これは私が解読しようとした方法である:

#include<iostream> 
using namespace std; 

#include <fstream> 
#include <string.h> 
#include <cryptopp/aes.h> 
#include <cryptopp/modes.h> 
#include <cryptopp/filters.h> 

using namespace CryptoPP; 

int main(void) { 
    ifstream in("input0.txt"); 
    ofstream out("output0.txt"); 

    string hex_key = "", hex_ct = ""; 
    in >> hex_key >> hex_ct; 

    byte key[ AES::DEFAULT_KEYLENGTH ], iv[ AES::BLOCKSIZE ]; 
    string ciphertext = "", recoveredtext = ""; 

    for(int i = 0; i < hex_key.size(); i+=2) { 
     key[i/2] = (char) strtol((hex_key.substr(i, 2)).c_str(), 0, 16); 
    } 

    //then I divide iv from the text 
    for(int i = 0; i < AES::BLOCKSIZE*2; i+=2) { 
     iv[i/2] = (char) strtol((hex_ct.substr(i, 2)).c_str(), 0, 16); 
    } 

    for(int i = AES::BLOCKSIZE*2; i < hex_ct.size(); i++) { 
     ciphertext.push_back(hex_ct[i]); 
    } 

    //decryption 
    CBC_Mode<AES>::Decryption d; 
    d.SetKeyWithIV(key, AES::DEFAULT_KEYLENGTH, iv); 

    StringSink sink(recoveredtext); 

    StreamTransformationFilter stf (
     d, 
     &sink 
    ); 

    StringSource ss (
     ciphertext, 
     true, 
     &stf 
    ); 

    out << recoveredtext; 

    return 0; 
} 

私は Wiki次この実装を使用していました。
私も thisで試してみましたが、キーと暗号文をmyで置き換えずに動作しました。このコードを使用している間

AES128CBC: /usr/local/include/cryptopp/misc.h:304: void CryptoPP::memcpy_s(void*, size_t, const void*, size_t): Assertion `dest != __null' failed. 
Aborted (core dumped) 

//decryption 

AES::Decryption aesDecryption(key, AES::DEFAULT_KEYLENGTH); 
CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv); 

StreamTransformationFilter stfDecryptor(
    cbcDecryption, 
    new StringSink(recoveredtext), 
    BlockPaddingSchemeDef::NO_PADDING 
); 

stfDecryptor.Put(reinterpret_cast<const unsigned char*>(ciphertext.c_str()), ciphertext.size()); 
stfDecryptor.MessageEnd(); 

それは動作しますが、出力が文字の有効なシーケンスではありません、私はこの出力を持っている上記のコードを使用して
まあ、。

私はlibがインストールさ:私が間違っているものを見つけることができません

g++ -o AESCBC128 AESCBC128.cpp -lcryptopp 


sudo apt-get install libcrypto++-dev libcrypto++-doc libcrypto++-utils 

と私はそれをコンパイル。
ご協力いただきありがとうございます。

入力のサンプル:

140b41b22a29beb4061bda66b6747e14 
4ca00ff4c898d61e1edbf1800618fb2828a226d160dad07883d04e008a7897ee2e4b7465d5290d0c0e6c6822236e1daafb94ffe0c5da05d9476be028ad7c1d81 


これは演習で、私の目標は、秘密のメッセージを発見することですので、私は、出力のサンプルを知りません。バイト配列への入力に変換に
試験:

out << "KEY:\n" << hex_key << endl; 

for(int i = 0; i < AES::DEFAULT_KEYLENGTH; i++) { 
    out << setfill('0') << setw(2) << hex << (int)key[i]; 
} 

out << endl << "Received message:\n" << hex_ct << endl; 

out << "IV:\n"; 
for(int i = 0; i < AES::BLOCKSIZE; i++) { 
    out << setfill('0') << setw(2) << hex << (int)iv[i]; 
} 

out << endl << "CT:\n" << ciphertext << endl; 

結果:彼らが期待されているように

KEY: 
140b41b22a29beb4061bda66b6747e14 
140b41b22a29beb4061bda66b6747e14 
Received message: 
4ca00ff4c898d61e1edbf1800618fb2828a226d160dad07883d04e008a7897ee2e4b7465d5290d0c0e6c6822236e1daafb94ffe0c5da05d9476be028ad7c1d81 
IV: 
4ca00ff4c898d61e1edbf1800618fb28 
CT: 
28a226d160dad07883d04e008a7897ee2e4b7465d5290d0c0e6c6822236e1daafb94ffe0c5da05d9476be028ad7c1d81 

+0

デバッグコード。あなたはサンプルデータと入力/対話を忘れました。キー、iv、暗号化されたデータ、望ましくは16進数で復号化されたデータを印刷する。彼らは正しいのですか?短い入力データでテストします。暗号化はPKCS#7パディングを使用しているため、復号化ではPKCS#7パディングが必要です。 – zaph

+0

私は入力で質問を編集しましたが、いくつかのテストでは正しいです。パッドについては、パッドの影響を受けていますか?申し訳ありませんが、これは私の初めての暗号化であり、これはまた、stackoverflowの私の最初の質問です。 – user123456789

+0

OK、StreamPransformationFilterコンストラクタにブロック埋め込みスキームパラメータ(NO_PADDING)を追加すると、2番目のコードは機能しますが、出力は文字のないシーケンスです。私は入力について確信しています、何がうまくいかなかったのですか? – user123456789

答えて

1

パディングエラーが発生する原因はパディングではなく、復号化が間違っている可能性が高いため、パラメータの入力方法が間違っている可能性があります。

提供されているKEY、IV、CTで暗号化を暗号化しました。その結果、8バイトの0x08のPKCS#7パディングが行われます。

パディング除去と

復号(IV除去する正しい):

42617369 63204342 43206d6f 64652065 6e637279 7074696f 6e206e65 65647320 70616464 696e672e

またはテキストで:

基本的なCBCモードの暗号化では、埋め込みが必要です。無傷のパディングと

復号(パディングの末尾8つの文字に注意):出力とほとんどASCIIある

42617369 63204342 43206d6f 64652065 6e637279 7074696f 6e206e65 65647320 70616464 696e672e 08080808 08080808

3バイト目の0xfcなどの例外がいくつかあります。

パディングが正しいので、これは暗号化された真のデータだと思います。ここでは、過度に好奇心のために

は私のテストコードです:

NSData *key = [Utilities dataFromHexString:@"140b41b22a29beb4061bda66b6747e14"]; 
NSData *iv  = [Utilities dataFromHexString:@"4ca00ff4c898d61e1edbf1800618fb28"]; 
NSData *dataIn = [Utilities dataFromHexString:@"28a226d160dad07883d04e008a7897ee2e4b7465d5290d0c0e6c6822236e1daafb94ffe0c5da05d9476be028ad7c1d81"]; 

size_t   cryptBytes = 0; 
NSMutableData *dataOut = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128]; 

CCCrypt(kCCDecrypt, 
     kCCAlgorithmAES, 
     kCCOptionPKCS7Padding, 
     key.bytes, key.length, 
     iv.bytes, 
     dataIn.bytes, dataIn.length, 
     dataOut.mutableBytes, dataOut.length, 
     &cryptBytes); 
dataOut.length = cryptBytes; 

NSLog(@"dataOut: %@", dataOut); 
NSLog(@"dataOut: %@", [[NSString alloc] initWithData:dataOut encoding:NSUTF8StringEncoding]); 
+0

IV(16バイト)を取り除いて16進数から16進数にデコードした結果、正しい答えです。どのように復号化をコード化したのですか?それとも、私のコードでどこが間違っていたのですか? – user123456789

+0

訂正された回答、ivを含むバージョンが選択されました。 – zaph

+0

私は別の言語とライブラリ(Common Crypto)を使用しているので、私のコードは役に立ちません。基本的に正しい入力を提供し、正しい出力を得られます。単なる関数です。私の推測では、正しい形式で入力を提供していないということです。私が使っているライブラリは単純にデータベースなので、ほとんど推測がありません。パディングエラーが発生する理由はパディングではなく、パラメータの供給方法が間違っていることです。 – zaph

1

はい、問題は入力していた:私は進からASCIIに暗号文を変換しませんでした。

だからソリューションは、これを使用することです。これの代わりに

for(int i = AES::BLOCKSIZE*2; i < hex_ct.size(); i+=2) { 
     ciphertext.push_back((char) strtol((hex_ct.substr(i, 2)).c_str(), 0, 16)); 
    } 

for(int i = AES::BLOCKSIZE*2; i < hex_ct.size(); i++) { 
     ciphertext.push_back(hex_ct[i]); 
    } 

IVとPADが自動的に削除されます。

だから、ソリューションのコードは次のとおりです。

#include<iostream> 
using namespace std; 

#include <fstream> 
#include <string.h> 
#include <cryptopp/aes.h> 
#include <cryptopp/modes.h> 
#include <cryptopp/filters.h> 

using namespace CryptoPP; 

int main(void) { 
    ifstream in("input0.txt"); 
    ofstream out("output0.txt"); 

    string hex_key = "", hex_ct = ""; 
    in >> hex_key >> hex_ct; 

    byte key[ AES::DEFAULT_KEYLENGTH ], iv[ AES::BLOCKSIZE ]; 
    string ciphertext, recoveredtext; 

    for(int i = 0; i < hex_key.size(); i+=2) { 
     key[i/2] = (char) strtol((hex_key.substr(i, 2)).c_str(), 0, 16); 
    } 

    for(int i = 0; i < AES::BLOCKSIZE*2; i+=2) { 
     iv[i/2] = (char) strtol((hex_ct.substr(i, 2)).c_str(), 0, 16); 
    } 

    for(int i = AES::BLOCKSIZE*2; i < hex_ct.size(); i+=2) { 
     ciphertext.push_back((char) strtol((hex_ct.substr(i, 2)).c_str(), 0, 16)); 
    } 

    //decryption 

    AES::Decryption aesDecryption(key, AES::DEFAULT_KEYLENGTH); 
    CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv); 

    StreamTransformationFilter stfDecryptor(
     cbcDecryption, 
     new StringSink(recoveredtext) 
    ); 

    stfDecryptor.Put(reinterpret_cast<const unsigned char*>(ciphertext.c_str()), ciphertext.size()); 
    stfDecryptor.MessageEnd(); 

    out << recoveredtext; 

    return 0; 
} 
関連する問題