2017-10-02 4 views
0

私のプログラムでは、crypto++ライブラリを使用しています。 は、私はそう構造体があります。行内のいくつかの値を暗号化および復号化する方法

struct crypt_struct{ 
    //consists of encrypted data 
    string name1; 
    string name2; 
    string name3; 
} 
struct decrypt_struct{ 
    //consists of decrypted data 
    int name1; 
    string name2; 
    double name3; 
} 

私は暗号化してきた機能:

crypt_struct encrypt(decrypt_struct struct_in) { 
    //Key and IV setup 
    //AES encryption uses a secret key of a variable length (128-bit, 196-bit or 256- 
    //bit). This key is secretly exchanged between two parties before communication 
    //begins. DEFAULT_KEYLENGTH= 16 bytes 
    byte key[CryptoPP::AES::DEFAULT_KEYLENGTH], iv[CryptoPP::AES::BLOCKSIZE]; 
    memset(key, 0x00, CryptoPP::AES::DEFAULT_KEYLENGTH); 
    memset(iv, 0x00, CryptoPP::AES::BLOCKSIZE); 
    //output encrypt struct 
    crypt_struct struct_out; 

    //encrypt text 
    string ciphertext; 

    CryptoPP::AES::Encryption aesEncryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH); 
    CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv); 
    CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(ciphertext)); 


    //int name1 
    stfEncryptor.Put(reinterpret_cast<const unsigned char*> ((to_string(struct_in.name1)).c_str()), (to_string(struct_in.name1)).length() + 1); 
    stfEncryptor.MessageEnd(); 
    struct_out.name1 = ciphertext; 
    cout << ciphertext << endl; 
    ciphertext.clear(); 

    //string name2 
    stfEncryptor.Put(reinterpret_cast<const unsigned char*> (struct_in.name2.c_str()), struct_in.name2.length() + 1); 
    stfEncryptor.MessageEnd(); 
    struct_out.name2 = ciphertext; 
    cout << ciphertext << endl; 
    ciphertext.clear(); 

    //double name3 
    stfEncryptor.Put(reinterpret_cast<const unsigned char*> ((to_string(struct_in.name3)).c_str()), (to_string(struct_in.name3)).length() + 1); 
    stfEncryptor.MessageEnd(); 
    struct_out.name3 = ciphertext; 
    cout << ciphertext << endl; 
    ciphertext.clear(); 

    return struct_out; 
} 

と復号化機能:

decrypt_struct decrypt(crypt_struct struct_in) 
{ 
    //Key and IV setup 
    //AES encryption uses a secret key of a variable length (128-bit, 196-bit or 256- 
    //bit). This key is secretly exchanged between two parties before communication 
    //begins. DEFAULT_KEYLENGTH= 16 bytes 

    byte key[CryptoPP::AES::DEFAULT_KEYLENGTH], iv[CryptoPP::AES::BLOCKSIZE]; 
    memset(key, 0x00, CryptoPP::AES::DEFAULT_KEYLENGTH); 
    memset(iv, 0x00, CryptoPP::AES::BLOCKSIZE); 
    // 
    // Decrypt 
    // 
    decrypt_struct struct_out; 
    string decryptedtext; 
    CryptoPP::AES::Decryption aesDecryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH); 
    CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv); 
    CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(decryptedtext)); 

    stfDecryptor.Put(reinterpret_cast<const unsigned char*>(struct_in.name1.c_str()), struct_in.name1.length()); 
    struct_out.name1= atoi(decryptedtext.c_str()); 
    stfDecryptor.MessageEnd(); 
    decryptedtext.clear(); 

    stfDecryptor.Put(reinterpret_cast<const unsigned char*>(struct_in.name2.c_str()), struct_in.name2.length()); 
    struct_out.name2= atoi(decryptedtext.c_str()); 
    stfDecryptor.MessageEnd(); 
    decryptedtext.clear(); 

    stfDecryptor.Put(reinterpret_cast<const unsigned char*>(struct_in.name3.c_str()), struct_in.name3.length()); 
    struct_out.name3= atoi(decryptedtext.c_str()); 
    stfDecryptor.MessageEnd(); 
    decryptedtext.clear(); 

    return struct_out; 

}

を私は暗号化だけで一つの変数をしようとすると、すべてが正しく復号化されます。しかし、複数の変数を同時に暗号化しようとすると、エラーが発生します。さらに、変数int型を暗号化するときにも同じエラーが発生します。それが接続できるものであれば誰の考えですか?

おそらく理由は、この機能が一度に1行だけ暗号化できるということです。

+0

暗号化されたデータを 'C++ '文字列に格納するのはちょっと危険なようですが、暗号化されたデータそのものには中間のヌルターミネータが含まれている可能性があります - したがって、 'c_str'はデータを解読しようとすると正しい表現を返さないかもしれません - バイト/文字バッファーを使う方がはるかに安全です。 – Prediluted

+0

@Prediluted、私はこれについてはわからないので、私はこのライブラリのソースコードに従ってすべてを実装しようとしました。 –

+0

結果を 'std :: string'に復号化できるはずですが、暗号化されたデータを' std :: string'として保存しようとするときに問題が発生することは間違いありません。バイナリデータに 'std :: string'によってヌルターミネータとして解釈され、暗号化されたデータを切り捨てる0x00がある場合。 – Prediluted

答えて

0

問題は次のとおりです。 このライブラリのソースコードでは、解読するときにはc_str()関数が使用されます。これら:

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

公式ドキュメントは言う:

文字列オブジェクトが他のヌル文字が含まれていない場合c_str()から取得したポインタが唯一のnullで終わる文字列へのポインタとして扱うことができます。

暗号化関数では、ゼロ文字が文字列に追加され、c_str()関数で復号化しようとすると、最初のゼロ文字で文字列がトリミングされます。

しかし、с++ 11の標準では、NULL文字を考慮しない点を除いて、data()関数と同じ動作を実行する類似の関数が追加されました。

その結果、私が受け取っ:

stfDecryptor.Put(reinterpret_cast<const unsigned char*> (struct_in.name1.data()), struct_in.name1.size()); 

をまた、それはあなたが最初name1を暗号化する場合name2そして、重要だった、とname3。それと同じシーケンスで解読する必要があります。

+2

[BSON](http://bsonspec.org/)やGoogleの[プロトコルバッファ](https://developers.google.com/protocol-buffers/)などのデータをシリアル化する必要があります。 ITUのASN.1を使用することもできますが、使用するのは少し難しくなります。シリアル化の後、ブロブを暗号化します。 – jww

関連する問題