尝试解密2键三重DES的无效块填充

时间:2012-11-06 06:11:19

标签: c++ encryption des crypto++

我正在尝试用C ++中的crypto ++实现2键三重DES。

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

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

对于我的实施,我正在尝试执行以下操作:

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

  2. 用户可以运行“desimp.exe decrypt test.txt.des”并且程序将解密test.txt.des并将解密的文本输出到文件“decrypted.txt”我无法得到这个上班。我得到的错误是“ StreamTransformationFilter:找到无效的PKCS#7块填充

  3. 我相信我可能还需要在加密时将iv中的数据保存到文件中。它是否正确?我已经尝试过这样做了,我想我能够将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
    

1 个答案:

答案 0 :(得分:1)

我认为您需要在模式下使用std::ios_base::binary打开加密文件(用于读取和写入);否则,I / O库将破坏看起来像行尾的序列。