2012-11-06 48 views
1

我想在C++中使用crypto ++实现2键三重DES。试图解密2键三元组的无效块填充DES

我的实现基于位于here的crypto ++ wiki中的代码。

维基上的代码正确构建;当我运行示例程序时,我可以看到它正在加密和解密。

对于我的实现,我想做到以下几点:

  1. 用户可以运行 “desimp.exe加密的test.txt”。该程序将加密test.txt,然后输出一个名为test.txt.des的加密文件。这似乎工作正常。

  2. 用户可以运行“desimp.exe decrypt test.txt.des”,程序将解密test.txt.des并将解密后的文本输出到文件“decrypted.txt”我无法获得此信息工作。我得到的错误是“StreamTransformationFilter:无效的PKCS#7块填充发现

我认为我可能需要的数据在四在加密时保存到一个文件中。它是否正确?我试过这样做,我认为我能够将iv保存到一个文件中,但我认为,为了读取要用于解密的iv文件,需要将其作为数组读取8个字节。当我尝试保存iv时,test.txt.iv的文件大小为21个字节。如果这是正确的方法,我不知道如何继续。如果这是错误的做法,我想知道我需要做什么不同。下面是代码:

#ifndef CRYPTOPP_DLL_ONLY 
#define CRYPTOPP_DEFAULT_NO_DLL 
#endif 

#include "dll.h" 
#include "rc6.h" 
#include <stdio.h> 
#include <string.h> 
#include <fstream> 
#include <stdlib.h> 
#include <string> 
#include <streambuf> 

USING_NAMESPACE(CryptoPP) 
USING_NAMESPACE(std) 

#ifdef CRYPTOPP_IMPORTS 
static PNew s_pNew = NULL; 
static PDelete s_pDelete = NULL; 
#endif 
#ifdef CRYPTOPP_DLL_ONLY 

int __cdecl main(int argc, char *argv[]) 
{ 

    AutoSeededRandomPool prng; 
    SecByteBlock key(DES_EDE2::DEFAULT_KEYLENGTH); 
    prng.GenerateBlock(key, key.size()); 
    byte iv[DES_EDE2::BLOCKSIZE]; 
    prng.GenerateBlock(iv, sizeof(iv)); 
    string plain = "CBC Mode Test"; 
    string cipher, encoded, recovered; 


    char *fileName = argv[1]; 
    char *runMode = argv[2]; 
    char *ivFile = argv[3]; 

    cout << "ARGUMENT 1: " << fileName << endl; 
    cout << "ARGUMENT 2: " << runMode << endl; 

    string fileNameString(fileName); 
    string encryptedFileNameString = fileNameString + ".des";//add .des to the filename of the encrypted file once it's generated 
    string ivString = fileNameString + ".iv";//iv file 
    string runModeString(runMode); 

    if (runModeString == "encrypt") 
    { 
     ifstream t(fileName); 
     string str((std::istreambuf_iterator<char>(t)), 
     istreambuf_iterator<char>()); 
     try 
     { 
      cout << "plain text: " << str << endl; 

      CBC_Mode<DES_EDE2>::Encryption e; 
      e.SetKeyWithIV(key, key.size(), iv); 

      // The StreamTransformationFilter adds padding 
      // as required. ECB and CBC Mode must be padded 
      // to the block size of the cipher. 
      StringSource ss1(str, true, 
       new StreamTransformationFilter(e, 
        new StringSink(cipher) 
       ) // StreamTransformationFilter  
      ); // StringSource 
     } 
     catch(const CryptoPP::Exception& e) 
     { 
      cerr << e.what() << endl; 
      exit(1); 
     } 
     // Pretty print 
     StringSource ss2(cipher, true, 
      new HexEncoder(
       new StringSink(encoded) 
      ) // HexEncoder 
     ); // StringSource 

     cout << "cipher text: " << encoded << endl;//"encoded" is just the pretty print version of the ciphertext. 
     ofstream fout(encryptedFileNameString); 
     fout << cipher; 
     fout.close();//outputs/saves the encrypted file 
     cout << "Encrypted file was saved to local path as " << encryptedFileNameString << endl; 

     ofstream fout2(ivString); 
     fout2 << iv; 
     fout2.close(); 
     cout << "iv was saved to local path as " << ivString << endl; 
    } 

    if (runModeString == "decrypt")// USER WANTS TO DECRYPT A FILE 
     {   
      ifstream t2(fileName); 
      string str2((istreambuf_iterator<char>(t2)),istreambuf_iterator<char>()); 
      cipher = str2; 

     try 
     { 
      CBC_Mode<DES_EDE2>::Decryption d; 
      d.SetKeyWithIV(key, key.size(), iv); 
      // The StreamTransformationFilter removes 
      // padding as required. 
      StringSource ss3(cipher, true, 
       new StreamTransformationFilter(d, 
        new StringSink(recovered) 
       ) // StreamTransformationFilter 
      ); // StringSource 

      cout << "recovered text: " << recovered << endl; 
     } 
     catch(const CryptoPP::Exception& e) 
      { 
       cerr << e.what() << endl; 
       exit(1); 
      } 
     } 
     return 0; 
    }//end main 

    extern "C" __declspec(dllexport) void __cdecl SetNewAndDeleteFromCryptoPP(PNew pNew, PDelete pDelete, PSetNewHandler pSetNewHandler) 
    { 
     s_pNew = pNew; 
     s_pDelete = pDelete; 
    } 

    void * __cdecl operator new (size_t size) 
    { 
     return s_pNew(size); 
    } 

    void __cdecl operator delete (void * p) 
    { 
     s_pDelete(p); 
    } 

    #endif 
+0

我最终实现了Botan加密库,所以我不再需要这个问题的解决方案。 – Krondorian

回答

1

我想你需要打开你的加密文件与模式std::ios_base::binary(无论是阅读和写作);否则,I/O库将破坏看起来像线端的序列。