代码之家  ›  专栏  ›  技术社区  ›  Ben J

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

  •  0
  • Ben J  · 技术社区  · 16 年前

    我正在尝试编写一个应用程序,其中除其他外,该应用程序使用openssl blowfish实现(blowfish.h)通过一个简单的服务器/客户机对传输文件。

    然而,虽然一些文件被正确地加密、传输、接收和解密,但在最终解密阶段之后,有些文件最终会被损坏。这让我觉得加密例程没有被正确调用(因为我也尝试过使用等效的des-library调用,得到相同的“间歇性损坏”结果)。

    相关代码粘贴在下面。

    基本上,它从函数send_file(由连接的客户机调用)开始。这会将文件分割成块。每个1024字节块分别加密,然后发送。然后,服务器在接收文件功能中接收每个块,解密并保存到磁盘。

    知道有什么问题吗?(注意,如果需要,我将添加整个应用程序的代码)。

    干杯, 本。

    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 回复  |  直到 16 年前
        1
  •  2
  •   anon    16 年前

    我假设:

    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++代码通常不需要强制转换。基本上,你需要重新思考你在做什么。

        2
  •  0
  •   jspcal    16 年前

    不确定,可能是某个地方的缓冲区溢出或内存损坏…

    你可以用 valgrind 要检测问题,或者尝试简化转换/…。

        3
  •  0
  •   Ben J    16 年前

    通过问其他几个问题解决了一些错误之后,我已经使文件加密过程正常工作,但只有当客户机和服务器都在同一个本地主机上时。当它们驻留在不同的机器上时,文件仍然会损坏。我认为这是因为发送文件和接收文件是从线程调用的,如下所示:

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

    ….然后,接收文件或发送文件函数调用blowfish函数进行加密。现在,如果在pthread中调用了一个函数(即send_file和receive_file),那么如果该函数调用了另一个函数(即encrypthelper——blowfish),那么调用函数是否可能不会“正确地”等待被调用函数正确完成?

        4
  •  0
  •   Ben J    16 年前

    固定的:

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

    问题是,不能确保加密缓冲区的所有n个字节都被传输。因此,只发送一些加密的字节,从而导致接收端的解密不一致。