0

単純なサーバー/クライアントのペアを介してファイルを転送するために、openssl ブローフィッシュ実装 (blowfish.h) を使用するアプリケーションを作成しようとしています。

ただし、一部のファイルは正しく暗号化、転送、受信、および復号化されますが、一部のファイルは最終的な復号化段階の後で破損します。これにより、暗号化ルーチンが正しく呼び出されていないと思います (同じ「間欠的な破損」の結果で、同等の DES ライブラリ呼び出しでも試したため)。

関連するコードを以下に貼り付けます。

基本的に、関数 send_file (接続されたクライアントによって呼び出されます) で始まります。これにより、ファイルがチャンクに分割されます。各 1024 バイト チャンクは個別に暗号化されてから送信されます。各チャンクはサーバーによって receive_file 関数で受信され、復号化されてディスクに保存されます。

何が問題なのですか?(必要に応じて、アプリケーション全体のコードを追加します)。

乾杯、ベン。

void encryptHelper(const char*,int);
void decryptHelper(const char*,int);

inline void blowfish(unsigned char *data, int data_len, char* key, int enc)
{
    //  hash the key first! 
    unsigned char obuf[20];
    bzero(obuf,20);
    SHA1((const unsigned char*)key, strlen(key), obuf);

    BF_KEY bfkey;
    int keySize = strlen(key);
    BF_set_key(&bfkey, 16, (const unsigned char*)obuf);

    unsigned char ivec[8];
    memset(ivec, 0, 8);

    unsigned char out[1024];// = (unsigned char*) malloc(1024);
    bzero(out,1024);
    int num = 0;
    BF_cfb64_encrypt(data, out, data_len, &bfkey, ivec, &num, enc);

    data=out;

    //memcpy(data, out, data_len);
    //free(out);
}
void MyFrame::encryptHelper(char* orig, int inlength)
{
char *pb=(char*)(std::string((passInput->GetValue()).mb_str()).c_str());
blowfish((unsigned char*)orig, inlength, pb, DES_ENCRYPT);
}

void MyFrame::decryptHelper(char* orig, int inlength)
{
char *pb=(char*)(std::string((passInput->GetValue()).mb_str()).c_str());
blowfish((unsigned char*)orig, inlength, pb, DES_DECRYPT);
}


int MyFrame::send_file(int fd)
{

char rec[10];
struct stat stat_buf;
fstat (fd, &stat_buf);  
int size=stat_buf.st_size;

int remSize=size;

int value=0;

while(size > 0)
{
    char buffer[1030];
    bzero(buffer,1030);
    bzero(rec,10);
    int n;
    if(size>=1024)
    {
        value+=1024;
        n=read(fd, buffer, 1024);

        // encrypt is necessary
        if(encButtonOn->GetValue()) encryptHelper(buffer,1024);

        // Send a chunk of data
        n=send(sockFile_, buffer, 1024, 0 );

        // Wait for an acknowledgement
        n = recv(sockFile_, rec, 10, 0 );
    }
    else // reamining file bytes
    {
        value+=size;
        n=read(fd, buffer, size);
        if(encButtonOn->GetValue()) encryptHelper(buffer,size);
        buffer[size]='\0';
        n=send(sockFile_,buffer, size, 0 );
        n=recv(sockFile_, rec, 10, 0 );
    }

    MyFooEvent event( 0, 992 );
    double firstBit = (double)value/remSize;
    firstBit=firstBit*100.0;
    event.adouble=firstBit;     
    wxPostEvent (this, event);  


    size -= 1024;

}

// Send a completion string
int n = send(sockFile_, "COMP",strlen("COMP"), 0 );
char buf[10];
bzero(buf,10);
// Receive an acknowledgemnt
n = recv(sockFile_, buf, 10, 0 );

return(0);
 }

 int MyFrame::receive_file()
 {

// receive file size and send ack
char sizeBuffer[50];
bzero(sizeBuffer,50);
int n;
//read(This->sockpw,buffer,bufferSize);
n=read(sockFile_, sizeBuffer, 50);
n=send(sockFile_,"OK", strlen("OK"), 0 );

int size = atoi(sizeBuffer);

//std::cout<<size<<std::endl;

// receive file name and send ack
char saveName[256];
bzero(saveName,256);
n=read(sockFile_, saveName, 256);

n=send(sockFile_,"OK",strlen("OK"), 0 );

//std::cout<<saveName_<<std::endl;

// start file writing process to local disk
// decrypt first if necessary
std::cout<<arraySize(saveName)<<std::endl;
std::cout<<strlen(saveName)<<std::endl;
if(encButtonOn->GetValue()) decryptHelper(saveName,strlen(saveName));
ofstream outFile(saveName,ios::out|ios::binary|ios::app);

// vars for status gauge
int remSize=size;
int value=0;

while(size > 0)
{       
    // buffer for storing incoming data
    char buf[1030];
    bzero(buf,1030);
    if(size>=1024)
    {

        value+=1024; // for status gauge

        // receive chunk of data
        n=recv(sockFile_, buf, 1024, 0 );

        // decrypt if necessary
        if(encButtonOn->GetValue()) decryptHelper(buf,1024);

        // write chunk of data to disk
        outFile.write(buf,1024);

        // send acknowledgement
        n = send(sockFile_, "OK", strlen("OK"), 0 );

    }
    else
    {
        value+=size;
        n=recv(sockFile_, buf, size, 0 );
        if(encButtonOn->GetValue()) decryptHelper(buf,size);
        buf[size]='\0';
        outFile.write(buf,size);
        n = send(sockFile_, "OK", strlen("OK"), 0 );
    }

    // Update status gauge
    MyFooEvent event( 0, 992 );
    double firstBit = (double)value/remSize;
    firstBit=firstBit*100.0;
    event.adouble=firstBit;
    wxPostEvent (this, event);  

    size -= 1024;

}

outFile.close();

// Receive 'COMP' and send acknowledgement
// ---------------------------------------
char buf[10];
bzero(buf,10);
n = recv(sockFile_, buf, 10, 0 );
n = send(sockFile_,  "OK", strlen("OK"), 0 );
std::cout<<"File received..."<<std::endl;

// Display image event
MyFooEvent eventF( 0, 995 );
eventF.SetText(wxString(saveName, wxConvUTF8));
wxPostEvent (this, eventF);     

return(0);
 }
4

4 に答える 4

2

私はそれを仮定しています:

char *pb=(char*)(std::string((passInput->GetValue()).mb_str()).c_str());
blowfish((unsigned char*)orig, inlength, pb, DES_DECRYPT);

実際には一時文字列のバッファである pb に復号化します。このように std::string を使用することはできません。これを行うために非常に多くの casr を使用しなければならなかったという事実は、警告であるはずです。通常、適切な C および C++ コードでは、キャストはまったく必要ありません。基本的に、自分がしていることを再考する必要があります。

于 2010-01-03T18:41:31.953 に答える
0

他のいくつかの質問をすることでいくつかのバグを修正したので、ファイル暗号化プロセスが機能するようになりましたが、クライアントとサーバーが両方とも同じローカルホストマシン上にある場合に限ります。それらが別のマシンに存在する場合でも、ファイルは破損してしまいます。send_fileとreceivefileがスレッドから次のように呼び出されるためだと思います。

void 
*MyFrame::send_fileT(void* tid)
{
accessHelper* ah = static_cast<accessHelper*>(tid);
MyFrame* This = ah->This;
This->send_file(fileSendID);
pthread_exit(NULL);
} 

void 
*MyFrame::receive_fileT(void* tid)
{
accessHelper* ah = static_cast<accessHelper*>(tid);
MyFrame* This = ah->This;
This->receive_file();
pthread_exit(NULL);
}

....次に、receive_file関数またはsend_file関数がblowfish関数を呼び出して暗号化を実行します。これで、関数がpthread内で呼び出された場合(つまり、send_fileとreceive_file)、その関数が別の関数(つまり、encryptHelper --blowfish)を呼び出した場合、呼び出し元の関数が、呼び出された関数が終了するのを「適切に」待機しない可能性があります。正しく?

于 2010-01-07T17:55:59.623 に答える
0

よくわかりませんが、どこかでバッファ オーバーランが発生しているか、メモリが破損している可能性があります...

valgrindを使用して問題を検出するか、変換を単純化してみてください/...

于 2010-01-03T18:42:09.300 に答える
0

修理済み:

 n=read(fd, buffer, 2048);
 if(enc)encryptHelper(buffer,n);
 n=send(sockFile_, buffer, n, 0 );
 [called in a loop]

問題は、暗号化されたバッファの n バイトすべてが転送されることを保証できないことでした。したがって、暗号化されたバイトの一部のみが送信され、受信側で復号化の一貫性が失われます。

于 2010-01-12T09:51:22.143 に答える