在简单的客户端/服务器应用程序中使用blowfish.h

发布于 2024-08-16 20:25:13 字数 5046 浏览 3 评论 0原文

我正在尝试编写一个应用程序,其中除其他外使用 openssl Blowfish 实现(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);
 }

I am trying to write an application which amongst other things uses the openssl blowfish implementation (blowfish.h) to transport files over a simple server/client pair.

However, whilst some files are encrypted, transported, received and decrypted correctly, some end up being corrupted, after the final decryption stage. This leads me to think that the encryption routines are not being called correctly (since I have also tried with equivalent DES library calls, with the same 'intermittent corruption' results).

The relevant code is pasted below.

Basically, it starts with the function send_file (called by a connected client). This splits the file into chunks. Each 1024 byte chunk is encrypted separately and then sent. Each chunk is then received by the server in the receive_file function, decrypted and saved to disc.

Any idea what the problem could be? (Note if necessary, I will add the code for the whole application).

Cheers,
Ben.

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);
 }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

朕就是辣么酷 2024-08-23 20:25:13

我假设:

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

解密为 pb,它实际上是临时字符串的缓冲区。您根本不能像这样使用 std::string 。您必须使用如此多的 casrs 来执行此操作的事实应该是一个警告 - 好的 C 和 C++ 代码通常根本不需要强制转换。基本上,你需要重新考虑你正在做的事情。

I'm assuming that:

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

decrypts into pb, which is actually the buffer of a temporary string. You simply cannot use std::string like this. The fact that you had to use so many casrs to do this shouldhave been a warning - good C and C++ code does not normally require casts at all. Basically, you need to rethink what you are doing.

痴者 2024-08-23 20:25:13

不确定,可能是某处缓冲区溢出或内存损坏...

您可以使用 valgrind 来检测问题或尝试简化转换/...

not sure, could be a buffer overrun somewhere or memory corruption...

you could use valgrind to detect the issue or perhaps try simplifying the conversions/...

兲鉂ぱ嘚淚 2024-08-23 20:25:13

通过询问其他一些问题修复了一些错误后,我已经使文件加密过程正常工作,但前提是客户端和服务器都位于同一台本地主机计算机上。当它们驻留在不同的计算机上时,文件最终仍然会被损坏。我认为这是因为 send_file 和 receive file 是从线程调用的,如下所示:

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),调用函数是否可能不会“正确”等待被调用函数完成正确吗?

Having fixed a few bugs by asking a few other questions, I have gotten the file encryption process working, but only when the client and server are both on the same localhost machine. When they reside on different machines, the file still ends up being corrupted. I think it is due to the fact that send_file and receive file are called from threads as follows:

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);
}

....and then the receive_file or send_file functions are calling the blowfish function to carry out the encryption. Now if a function is called within a pthread (i.e. send_file and receive_file), then if that function calls another function (i.e. encryptHelper -- blowfish), is it possible that the calling function will not 'properly' wait for the called function to finish correctly?

2024-08-23 20:25:13

已修复:

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

问题在于无法确保加密缓冲区的所有 n 个字节均已传输。因此,仅发送部分加密字节,导致接收端解密不一致。

Fixed:

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

The problem was, was that it cannot be ensured that all n bytes of the encrypted buffer are transferred. Thus only some of the encrypted bytes are sent leading to inconsistent decryption on the receiving end.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文