1

C++ で crypto++ を使用して 2 キー トリプル DES を実装しようとしています。

私の実装は、ここにある crypto++ wiki のコードに基づいています。

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 ブロック パディングが見つかりました」です。

暗号化時にも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
4

1 に答える 1

1

モードで暗号化されたファイルを開く必要があると思いますstd::ios_base::binary(読み取りと書き込みの両方)。そうしないと、I/O ライブラリが行末のように見えるシーケンスを壊してしまいます。

于 2012-11-06T07:04:53.527 に答える