2014-04-25 64 views
1

我运行Crypto ++在加密算法上进行速度测试。我试图花费多长时间来加密,然后解密数据(最终使用更多的文件大小和不同的算法)。我遇到了无法循环访问代码的问题。在下面的代码,我使用的河豚,但是当我到加密的一部分,它给我的错误:如何循环Blowfish加密++

HashVerificationFilter: message hash or MAC not valid 

我能做些什么来解决这个问题?我需要把它放在一个函数中吗?如果是这样,我该怎么做?

/** 
* g++ encryption_tests.cpp -o encryption_tests -lcryptopp -lpthread -L. 
*/ 
#include <iostream> 
#include <string> 
#include <iomanip> 
#include <fstream> 
#include <ctime> 


#include "cryptoplusplus/osrng.h" 
using CryptoPP::AutoSeededRandomPool; 

#include "cryptoplusplus/cryptlib.h" 
using CryptoPP::Exception; 

#include "cryptoplusplus/hex.h" 
using CryptoPP::HexEncoder; 
using CryptoPP::HexDecoder; 

#include "cryptoplusplus/modes.h" 
#include "cryptoplusplus/aes.h" 

#include "cryptoplusplus/filters.h" 
using CryptoPP::StringSink; 
using CryptoPP::StringSource; 
using CryptoPP::AuthenticatedEncryptionFilter; 
using CryptoPP::AuthenticatedDecryptionFilter; 
using namespace std; 

#include "cryptoplusplus/filters.h" 
using CryptoPP::StringSink; 
using CryptoPP::StringSource; 
using CryptoPP::AuthenticatedEncryptionFilter; 
using CryptoPP::AuthenticatedDecryptionFilter; 

#include "cryptoplusplus/blowfish.h" 
using CryptoPP::Blowfish; 

#include "crypto++/eax.h" 
using CryptoPP::EAX; 

#include "cryptoplusplus/secblock.h" 
using CryptoPP::SecByteBlock; 

int main(int argc, char* argv[]) { 
    // Declaring variables 
    const int NUMBER_OF_RUNS = 3; 
    const int NUMBER_OF_TXT_FILES = 9; 
    const int NUMBER_OF_JPG_FILES = 6; 
    const int NUMBER_OF_PNG_FILES = 6; 
    const int NUMBER_OF_AVI_FILES = 2; 

    string file_names_txt[NUMBER_OF_TXT_FILES] = { "10B.txt", "100B.txt", "1KB.txt", "10KB.txt", "100KB.txt", "1MB.txt", "5MB.txt", "10MB.txt", "20MB.txt" }; 
    string file_names_jpg[NUMBER_OF_JPG_FILES] = { "1KB.jpg", "10KB.jpg", "100KB.jpg", "1MB.jpg", "3MB.jpg", "5MB.jpg" }; 
    string file_names_png[NUMBER_OF_PNG_FILES] = { "100B.png", "500B.png","1KB.png", "10KB.png","1MB.png", "5MB.png" }; 
    string file_names_avi[NUMBER_OF_AVI_FILES] = { "4MB.avi", "10MB.avi" }; 

    int time_data [NUMBER_OF_RUNS]; 
    string plaintext, cipher, encoded, recovered, sample_files_path, data_file, line_contents; 
    string initial_cpp_time_data = ""; 
    clock_t time_start, time_stop; 
    double run_time, time_difference, time_average = 0; 

    // This loop will run the test NUMBER_OF_RUNS times 
    for (int i = 0 ; i < NUMBER_OF_RUNS ; i++) { 
     time_start = clock(); 

    // This class seeds itself using an operating system provided RNG 
    AutoSeededRandomPool prng; 
    // Generate a random key 
    SecByteBlock key(Blowfish::DEFAULT_KEYLENGTH); 
    prng.GenerateBlock(key, key.size()); 
    // Generate a random initialization vector 
    byte iv[Blowfish::BLOCKSIZE]; 
    prng.GenerateBlock(iv, sizeof(iv)); 
    // Set key width 
    EAX<Blowfish>::Encryption e; 
    e.SetKeyWithIV(key, key.size(), iv); 

    // Grab the data from the file we want to run the test on 
    sample_files_path = "sample_files/" + file_names_txt[8]; 
    ifstream initial_file_contents (sample_files_path.c_str()); 
    if (initial_file_contents.is_open()) { 
     while (getline(initial_file_contents, line_contents)) { 
      plaintext = plaintext + line_contents; 
      plaintext.push_back('\n'); 
      initial_file_contents.close(); 
     } 
    } else { 
     cout << "Unable to open file" << endl; 
    } 

    // Encrypts the plaintext 
    try { 
     StringSource(plaintext, true, new AuthenticatedEncryptionFilter(e, new StringSink(cipher))); 
    } catch (const CryptoPP::Exception& e) { 
     cerr << e.what() << endl; 
     exit(1); 
    } 


     // Decrypts the test 
     try { 
      EAX<Blowfish>::Decryption d; 
      d.SetKeyWithIV(key, key.size(), iv); 
      StringSource s(cipher, true, new AuthenticatedDecryptionFilter(d, new StringSink(recovered))); 
     } catch (const CryptoPP::Exception& e) { 
      cerr << e.what() << endl; 
      exit(1); 
     } 

     // Stop the clock, calculate the time difference, turn to milliseconds 
     time_stop = clock(); 
     time_difference = time_stop - time_start; 
     run_time = time_difference/(CLOCKS_PER_SEC/1000); 
     time_data[i] = run_time; 
     cout << "time_data[" << i << "]: " << time_data[i] << " milliseconds" << endl; 
    } 

    //Grab the data from the old file 
    ifstream initial_cpp_time_data_file ("cpp_time_data.txt"); 
    if (initial_cpp_time_data_file.is_open()) { 
     while (getline(initial_cpp_time_data_file, line_contents)) { 
      initial_cpp_time_data = initial_cpp_time_data + line_contents; 
      initial_cpp_time_data.push_back('\n'); 
     } 
      initial_cpp_time_data_file.close(); 
    } else { 
     initial_cpp_time_data = ""; 
    } 

    // Created a new file 
    ofstream time_data_file; 
    time_data_file.open("cpp_time_data.txt"); 

    // Insert old data first 
    time_data_file << initial_cpp_time_data << endl; 

    // Show the file the test ran on and insert the new data 
    time_data_file << sample_files_path << endl; 
    for (int i = 0 ; i < NUMBER_OF_RUNS ; i++) { 
     time_data_file << "time_data[" << i << "]: " << time_data[i] << " milliseconds" << endl; 
     time_average = time_average + time_data[i]; 
    } 
    time_average = time_average/NUMBER_OF_RUNS; 
    time_data_file << "The average time for this is " << time_average << " milliseconds" << endl; 
    cout << "The average time for this is " << time_average << " milliseconds" << endl; 
    time_data_file.close(); 
    cout << "Done!\n"; 

    return 0; 
} 
+0

您的代码缺少你谈论循环。另外,如果你可以通过字符串(而不是文件)简化测试用例,那么它将帮助人们测试你的代码(我尝试运行提供的代码)。 – jww

回答

2

在循环的每次迭代中,你必须调用:

  • cipher.clear()
  • recovered.clear()

否则,StringSink的只是不断增加的结束先前的值。你会在你的循环的第二次和以后的迭代中失败(第一次应该是OK)。

此外,没有Resynchronize,因此您不能拨打e.Resynchronize(iv)重新启动密码。您必须在循环的每次迭代中调用e.SetKeyWithIV(key, key.size(), iv)

下面,我无法重复您的重复使用问题。加密对象被重用,而解密对象是为每次迭代创建的。运行该程序的结果是:

$ ./cryptopp-test.exe 
plain text: String 1 
recovered text: String 1 
plain text: String 2 
recovered text: String 2 
plain text: String 3 
recovered text: String 3 
plain text: String 4 
recovered text: String 4 
plain text: String 5 
recovered text: String 5 

AutoSeededRandomPool prng; 

SecByteBlock key(Blowfish::DEFAULT_KEYLENGTH); 
prng.GenerateBlock(key, key.size()); 

byte iv[ Blowfish::BLOCKSIZE ]; 
prng.GenerateBlock(iv, sizeof(iv)); 

vector<string> vv; 
vv.push_back("String 1"); 
vv.push_back("String 2"); 
vv.push_back("String 3"); 
vv.push_back("String 4"); 
vv.push_back("String 5"); 

string plain, cipher, recovered; 

try { 

    EAX<Blowfish>::Encryption e1; 
    e1.SetKeyWithIV(key, key.size(), iv, sizeof(iv)); 

    for(unsigned i = 0; i < vv.size(); i++) 
    { 
     /*********************************\ 
     \*********************************/ 

     plain = vv[i]; 
     cout << "plain text: " << plain << endl; 

     e1.SetKeyWithIV(key, key.size(), iv, sizeof(iv)); 

     cipher.clear(); 
     StringSource ss1(plain, true, 
         new AuthenticatedEncryptionFilter(e1, 
          new StringSink(cipher) 
         ) ); // StringSource 

     /*********************************\ 
     \*********************************/ 

     EAX<Blowfish>::Decryption d2; 
     d2.SetKeyWithIV(key, key.size(), iv, sizeof(iv)); 

     recovered.clear(); 
     StringSource ss2(cipher, true, 
         new AuthenticatedDecryptionFilter(d2, 
          new StringSink(recovered), 
          AuthenticatedDecryptionFilter::THROW_EXCEPTION 
         )); // StringSource 

     cout << "recovered text: " << recovered << endl; 
    } 

} catch (const Exception& ex) { 
    cerr << ex.what() << endl; 
}