我从OPENSL中剪出了一部分3DES加密的源码,放在一个基于对话框的程序中对文件进行加解密,从小文件nKBytes,到大文件20M左右,均加密与解密十分正确正常,即文件经一次加密,再经一次解密后,不发生变化.但当把这个工程改成DLL时,出现加解密不一致的错误.多次测试发现部分现象:文件小时;nKBytes,加密正确,但解密时,除了前16个字节与原文件相同外,后面解密还原的内容全是零,即0x00,请有加解密及DLL编程注意事项的大侠及高手指点迷津,谢谢,问题能得到解决,另开2贴送分.

解决方案 »

  1.   

    估计转换的尺寸小了,应为全是零。可能你的dll只转换了before 16bytes
      

  2.   

    谢谢Pipi0714(老顽童),代码较长,关键处贴于下;
    #include "stdafx.h"
    #include "resource.h"#include "ShellExt.h"
    #include "CtxMenu.h"#include <shlobj.h>
    #include <shlguid.h>#include "ShUtils.h"
    #include <io.h>
    #include <direct.h>
    #include "des.h"CShellExt::CShellExt()
    {
       AFX_MANAGE_STATE(AfxGetStaticModuleState( ));   ODS("CShellExt::CShellExt()\r\n");   m_cRef = 0L;
       m_pDataObj = NULL;   g_cRefThisDll++;      m_menuBmp0.LoadBitmap(IDB_MENU_BMP);
       m_menuBmp1.LoadBitmap(IDB_BITMAP1);
       m_menuBmp2.LoadBitmap(IDB_BITMAP2);
       m_menuBmp3.LoadBitmap(IDB_BITMAP3);
       BuildDogFileHeaderFlag();
     }void CShellExt::CreateRandomKey(UCHAR *szEncryptKey,int nkeyLen)
    {
    srand((unsigned)time(NULL));
    for (int i=0;i<nkeyLen;i++)
    {
    szEncryptKey[i]=rand()%255;
    }
    }void CShellExt::BuildDogFileHeaderFlag()
    {
       UCHAR szSSNC[100];
       memset(szSSNC,0,100);
       m_nLengthOfCompanyName=strlen(g_szSSNC);
       memcpy(szSSNC,g_szSSNC,m_nLengthOfCompanyName);
       for (ULONG i=0;i<m_nLengthOfCompanyName;i++)
       {
       szSSNC[i] &= i%8;
       }
       memset(m_szDogFileFlag,0,sizeof(m_szDogFileFlag));
       memcpy(m_szDogFileFlag,szSSNC,m_nLengthOfCompanyName); 
       memcpy(cbc_key,m_szDogFileFlag,8);
       memcpy(cbc2_key,m_szDogFileFlag+8,8);
       memcpy(cbc3_key,m_szDogFileFlag+16,8);
    }STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                       LPDATAOBJECT pDataObj,
                                       HKEY hRegKey)
    {   AFX_MANAGE_STATE(AfxGetStaticModuleState( ));   ODS("CShellExtFld::Initialize()\r\n");   // this can be called more than once
       if (m_pDataObj)
       m_pDataObj->Release();   // duplicate the object pointer and registry handle
       if (pDataObj)
       {
       m_pDataObj = pDataObj;
       pDataObj->AddRef();
       } 
       else
       {
       return E_FAIL;
       }   return GetSelectedFiles(pIDFolder, m_pDataObj, m_csaPaths);}STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
    {
    AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
    HINSTANCE hInst = AfxGetInstanceHandle();
        ODS("CShellExt::InvokeCommand()\r\n");

    HWND hParentWnd = lpcmi->hwnd;
    HRESULT hr = NOERROR; int AllFileNUM=0,systemFileNUM=0,OKEncryNUM=0;
    // int nFileReturn; UINT idCmd = 0;
    int DelOldFile=0,NoProcessSysFile=0;
    // GetRegStatus(&DelOldFile,&NoProcessSysFile);

    CString strPlainFileName = _T("");
    CString strCipherFileName = _T("");
    CString strExtension = _T("");
    int nPos=-1;
    char pOriginalDir[256];
    char pDestFileNameTmp[1024]; if (!HIWORD(lpcmi->lpVerb)) //lpcmi->lpVerb的高序字为0
    {
    idCmd = LOWORD(lpcmi->lpVerb);
    // process it
    switch (idCmd) 
    {
    default:
    break;
    case 0: // 软件算法加密
    {
    //1.检查PIN口令
    // if (FALSE==CheckPIN())
    // {
    // //AfxMessageBox("PIN口令错误,无法对文件进行加密!",MB_OK|MB_ICONSTOP,NULL);
    // return NOERROR;
    // } strCipherFileName = strPlainFileName = m_csaPaths.GetAt(0);
    nPos=strCipherFileName.ReverseFind('.');
    if (nPos>0)
    strCipherFileName.SetAt(nPos,'_');
    strCipherFileName = strCipherFileName+_T(".VPN"); memset(pOriginalDir,0x00,256);
    memset(pDestFileNameTmp,0x00,1024); memcpy(pOriginalDir,strPlainFileName.GetBuffer(0),strPlainFileName.GetLength());
    if(pOriginalDir[strlen(pOriginalDir)-1]!='\\')
    {
    pOriginalDir[strlen(pOriginalDir)]='\\';
    pOriginalDir[strlen(pOriginalDir)+1]='\0';
    }
    ::MessageBox(NULL,"软件算法加密:原文件名:"+strPlainFileName+"\n密文:"+strCipherFileName,"警告",MB_OK+MB_ICONWARNING);
    if (_chdir(strPlainFileName.GetBuffer(0))==-1)  //文件加密
    {
    EncryptVPNFile(strPlainFileName,strCipherFileName,ALG_3DES,1);
    ::MessageBox(NULL,"已对文件已经进行软件算法加密保护!","提示信息",MB_ICONINFORMATION|MB_OK); /*if (nFileReturn==0)
    MessageBox(NULL,"文件已经进行了保护!"," 身份认证",MB_ICONINFORMATION|MB_OK);
    */
    }
    else if (_chdir(strPlainFileName.GetBuffer(0))==0)  //目录加密
    {
    /*
    EncryptDIR(pOriginalDir,csFile2,DelOldFile,NoProcessSysFile,AllFileNUM,systemFileNUM,OKEncryNUM);
    CString tmpStr1;
    char MSGStr[200] ;
    tmpStr1="共有";
    sprintf( MSGStr,     "%d", AllFileNUM );
    tmpStr1=tmpStr1+MSGStr;
    tmpStr1=tmpStr1+"个文件;\r\n其中隐含文件或系统文件共";
    sprintf( MSGStr,     "%d", systemFileNUM );
    tmpStr1=tmpStr1+MSGStr;
    tmpStr1=tmpStr1+"个文件;\r\n保护完成!";
    sprintf( MSGStr,     "%d", OKEncryNUM );
    tmpStr1=tmpStr1+MSGStr;
    tmpStr1=tmpStr1+"个文件。";
    ::MessageBox(NULL,tmpStr1,"提示信息",MB_ICONINFORMATION|MB_OK);*/
    ::MessageBox(NULL,"本软件暂不对目录进行加密,但可同时选定多个文件进行加密!","提示信息",MB_ICONINFORMATION|MB_OK);
    }
    else
    {
    ;
    }
    break;
    }
    case 1://硬件算法加密
    strCipherFileName = strPlainFileName = m_csaPaths.GetAt(0);
    nPos=strCipherFileName.ReverseFind('.');
    if (nPos>0)
    strCipherFileName.SetAt(nPos,'_');
    strCipherFileName = strCipherFileName+_T(".VPN"); memset(pOriginalDir,0x00,256);
    memset(pDestFileNameTmp,0x00,1024); memcpy(pOriginalDir,strPlainFileName.GetBuffer(0),strPlainFileName.GetLength());
    if(pOriginalDir[strlen(pOriginalDir)-1]!='\\')
    {
    pOriginalDir[strlen(pOriginalDir)]='\\';
    pOriginalDir[strlen(pOriginalDir)+1]='\0';
    }
    ::MessageBox(NULL,"硬件算法加密:原文件 "+strPlainFileName+"\n密文:"+strCipherFileName,"警告",MB_OK+MB_ICONWARNING);
    if (_chdir(strPlainFileName.GetBuffer(0))==-1)  //文件加密
    {
    EncryptVPNFile(strPlainFileName,strCipherFileName,ALG_SCB2,1);
    ::MessageBox(NULL,"已对文件已经进行硬件算法加密保护!","提示信息",MB_ICONINFORMATION|MB_OK);

    /*if (nFileReturn==0)
    MessageBox(NULL,"文件已经进行了保护!"," 身份认证",MB_ICONINFORMATION|MB_OK);
    */
    }
    else if (_chdir(strPlainFileName.GetBuffer(0))==0)  //目录加密
    {
    ::MessageBox(NULL,"本软件暂不对目录进行加密,但可同时选定多个文件进行加密!","提示信息",MB_ICONINFORMATION|MB_OK);
    }
    else
    {
    ;
    }
    break;
    case 2: // 文件解密
    //1.检查PIN口令
    strPlainFileName = strCipherFileName = m_csaPaths.GetAt(0);
    strExtension=strPlainFileName.Right(4);
    if (strExtension.CompareNoCase(".VPN"))
    {
    ::MessageBox(NULL,"文件类型不正确,不能进行解密还原!","错误",MB_OK|MB_ICONERROR);
    }
    else
    {
    strPlainFileName=strPlainFileName.Left(strPlainFileName.GetLength()-4);
    int nPos=strPlainFileName.ReverseFind('_');
    if (nPos>0)
    strPlainFileName.SetAt(nPos,'.');
    MessageBox(NULL,strCipherFileName,"待解密文件",0);
    MessageBox(NULL,strPlainFileName,"明文文件名称",0);

    DecryptVPNFile(strCipherFileName,strPlainFileName,1);
    ::MessageBox(NULL,"文件解密还原完成!","三江客户端VPN",MB_ICONINFORMATION|MB_OK);
    }
    break;
    }
    }
    return hr;
    }
      

  3.   


    int CShellExt::Encrypt3DESFile(LPCTSTR strPlainFile,LPCTSTR strCipherFile,int DelOldFile)
    {
    int nRetValue = -1;
    //1.get file attribute and length
    WIN32_FILE_ATTRIBUTE_DATA fad;
    BOOL bSuccess=GetFileAttributesEx((LPCTSTR) strPlainFile,GetFileExInfoStandard,&fad);//,lpFileInformation);
    if (bSuccess==FALSE || (fad.dwFileAttributes &= (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)) )
    {
    nRetValue=-1;//文件属性不正确,不能进行加密保护
    ::MessageBox(NULL,"文件不存在或是系统/隐藏/只读文件,不进行保护!","提示信息",MB_ICONINFORMATION|MB_OK);
    return nRetValue;
    }
    DWORD nFileLength=fad.nFileSizeLow;
    //2.Open the file 
    FILE *fpPlain=NULL,*fpCipher=NULL;
    fpPlain=fopen((char *)(LPCTSTR) strPlainFile,"rb");
    if (fpPlain==NULL)
    {
    nRetValue=-1;//文件打开失败,不能进行加密保护
    ::MessageBox(NULL,"打开要加密的文件失败,不能进行加密保护!","提示信息",MB_ICONINFORMATION|MB_OK);
    return nRetValue;
    }
    //3.check whether encrypt the file:read the file header and compare
    UCHAR szHeader[100];
    memset(szHeader,0,100);
    fread(szHeader,1,m_nLengthOfCompanyName,fpPlain);
    nRetValue=memcmp(szHeader,this->m_szDogFileFlag,m_nLengthOfCompanyName);
    if (nRetValue==0)
    {
    ::MessageBox(NULL,"文件已经进行了保护!","提示信息",MB_ICONINFORMATION|MB_OK);
    fclose(fpPlain);
    return nRetValue;
    }
    //6.get the Encrypt key
    UCHAR szEncryptKey[KEY_LENGTH+1];
    memset(szEncryptKey,0,KEY_LENGTH+1);
    CreateRandomKey(szEncryptKey,KEY_LENGTH/2);//16*8/2=64位的密钥长
    //7.Create the cipher file to write
    fpCipher=fopen((char *)strCipherFile,"wb");
    if (fpCipher==NULL)
    {
    nRetValue=-1;//文件打开失败,不能进行加密保护
    ::MessageBox(NULL,"创建加密文件失败,不能进行加密保护!","提示信息",MB_ICONINFORMATION|MB_OK);
    fclose(fpPlain);
    return nRetValue;
    }
    //8.write the dog file header to cipherfile
    fwrite((UCHAR*)&m_szDogFileFlag,1,m_nLengthOfCompanyName,fpCipher);
    //9.write the encrypt key to cipherfile
    fputc(ALG_3DES,fpCipher);//用软件3DES算法加密写入0
    //9.write the encrypt key to cipherfile
    // fwrite(szEncryptKey,1,KEY_LENGTH/2,fpCipher);
    fwrite(szEncryptKey,1,KEY_LENGTH,fpCipher); memcpy(cbc_iv,szEncryptKey,KEY_LENGTH/2);
    //10 write the plainfile length to the cipher file
    fwrite((BYTE *)&nFileLength,1,4,fpCipher);
    //11.locate the file pointer to begin of plain file
    fseek(fpPlain,0,SEEK_SET);
    //12.request memory for plain content
    UCHAR szBuffer[DATA_LENGTH+1],enData[DATA_LENGTH+1];
    memset(szBuffer,0,DATA_LENGTH+1);
    ULONG nBytes=0;
    #if DEBUG_PRG
    UCHAR szMessage[200];
    ULONG nRepeat=0;
    CString TmpStr,strErrorDataFile="C:\\ErrorData.txt";
    char ch[10];
    UCHAR szText[DATA_LENGTH+1],deData[DATA_LENGTH+1];
    memset(szText,0,DATA_LENGTH+1);
    #endif
    //13.read content from plain file des_cblock iv3;
    des_key_schedule ks,ks2,ks3;
    CString strError;/* int j,err=0;
    if ((j=DES_set_key_checked(&cbc_key,&ks)) != 0)
    {
    strError.Format("Key error %d\n",j);
    MessageBox(strError,"错误!",MB_OK|MB_ICONSTOP);
    }
    if ((j=DES_set_key_checked(&cbc2_key,&ks2)) != 0)
    {
    strError.Format("Key error %d\n",j);
    MessageBox(strError,"错误!",MB_OK|MB_ICONSTOP);
    }
    if ((j=DES_set_key_checked(&cbc3_key,&ks3)) != 0)
    {
    strError.Format("Key error %d\n",j);
    MessageBox(strError,"错误!",MB_OK|MB_ICONSTOP);
    }
    */
    DES_set_key_checked(&cbc_key,&ks);
    DES_set_key_checked(&cbc2_key,&ks2);
    DES_set_key_checked(&cbc3_key,&ks3); while((nBytes=fread(szBuffer,1,DATA_LENGTH,fpPlain))>0)
    {
    //14.can be divided by 16 
    nBytes=((nBytes+15)/16)*16;
    #if DEBUG_PRG
    memcpy(szText,szBuffer,nBytes);
        #endif
    //15.encrypt data
    memcpy(iv3,cbc_iv,sizeof(cbc_iv));
    memset(enData,0,DATA_LENGTH+1);
    des_ede3_cbc_encrypt(szBuffer,enData,16L,ks,ks2,ks3,&iv3,DES_ENCRYPT);
    des_ede3_cbc_encrypt(&(szBuffer[16]),&(enData[16]),(nBytes+1)-16,ks,ks2,ks3,&iv3,DES_ENCRYPT);
    #if DEBUG_PRG
    //17.解密检查
    memset(deData,0,DATA_LENGTH+1);
    memcpy(iv3,cbc_iv,sizeof(cbc_iv));
    des_ede3_cbc_encrypt(enData,deData,nBytes+1,ks,ks2,ks3,&iv3,DES_DECRYPT);
    nRetValue=memcmp(szText,deData,nBytes);
    if (nRetValue)
    {
    FILE *fpError=fopen((char *)(LPCTSTR) strErrorDataFile,"at");
    if(fpError)
    {
    sprintf((char *)szMessage,"\n在文件:%s,位置:nRepeat=%d,%d,加密出错,内容如下:\n",(char *)(LPCTSTR) strPlainFile,nRepeat,nRepeat*DATA_LENGTH);
    fwrite(szMessage,1,strlen((char *)szMessage),fpError);
    char *strHeader="\n00   01   02   03   04   05   06   07   08   09   0A   0B   0C   0D   0E   0F\n";
    fwrite(strHeader,1,strlen(strHeader),fpError);
    char szPlain[100],szDeData[100];
    memset(szPlain,0,100);
    memset(szDeData,0,100);
    for(UINT t=0;t<nBytes;t++)
    {
    memset(ch,0,10);
    sprintf(ch,"0x%02x,",szText[t]);
    strcat(szPlain,ch);
    memset(ch,0,10);
    sprintf(ch,"0x%02x,",deData[t]);
    strcat(szDeData,ch);
    if ((t+1)%16==0)
    {
    fputs(szPlain,fpError);
    fwrite("--ok\n",1,5,fpError);
    fputs(szDeData,fpError);
    fwrite("--er\n",1,5,fpError);
    memset(szPlain,0,100);
    memset(szDeData,0,100);
    }
    }
    fclose(fpError);
    }
    TmpStr.Format("加解密前后不等: nRepeat = %d,退出否?",nRepeat);
    int nRetValue=::MessageBox(NULL,TmpStr,"错误", MB_YESNO|MB_ICONQUESTION);
    if( nRetValue==IDYES)
    return -1;
    }
    nRepeat++;
    #endif
    //17.encrypt date success and write to the cipher file
    fwrite(enData,1,nBytes,fpCipher);
    memset(szBuffer,0,DATA_LENGTH+1);
    Sleep(10);
    #if DEBUG_PRG
    memset(szText,0,DATA_LENGTH+1);
    #endif
    }
    fclose(fpCipher);
    fclose(fpPlain);
    if (DelOldFile)
    ::DeleteFile((char *)(LPCTSTR) strPlainFile);
    nRetValue=1;
    ::MessageBox(NULL,"文件保护完成!","文件加密",MB_ICONINFORMATION|MB_OK);
    return nRetValue;
    }
      

  4.   


    int CShellExt::Decrypt3DESFile(FILE *fpCipher,LPCTSTR strPlainFile)
    {
    int nRetValue = -1;
    //1. get the data encrypt key
    UCHAR szEncryptKey[KEY_LENGTH+1];
    memset(szEncryptKey,0,KEY_LENGTH+1);
    fread(szEncryptKey,1,KEY_LENGTH,fpCipher);
    memcpy(cbc_iv,szEncryptKey,KEY_LENGTH/2);//64 bit 
    //2 get the length of the old plain file
    UCHAR szBuffer[DATA_LENGTH+1],enData[DATA_LENGTH+1];
    memset(szBuffer,0,DATA_LENGTH+1);
    fread(szBuffer,1,4,fpCipher);
    DWORD nOldPlainFileLength = *((DWORD *)szBuffer);
    //3.open the plain file to write
    FILE *fpPlain=fopen((char *)(LPCTSTR) strPlainFile,"wb");
    if (fpPlain==NULL)
    {
    nRetValue=-1;//文件打开失败,不能进行加密保护
    ::MessageBox(NULL,"待解密的文件打开失败,不能进行解密还原!","提示信息",MB_ICONINFORMATION|MB_OK);
    fclose(fpCipher);
    return nRetValue;
    }
    //4.request the memory for the plain content
    memset(szBuffer,0,4);//DATA_LENGTH+1);
    ULONG nBytes=0,nByteCount=0;
    #if DEBUG_PRG
    UCHAR szMessage[200];
    ULONG nRepeat=0;
    CString TmpStr,strErrorDataFile="E:\\ErrorData.txt";
    char ch[10];
    UCHAR deData[DATA_LENGTH+1],szText[DATA_LENGTH+1];
    memset(szText,0,DATA_LENGTH+1);
    #endif
    //5.define keys for triple des
    des_cblock iv3;
    des_key_schedule ks,ks2,ks3;
    CString strError;
    /* int j,err=0;
    if ((j=DES_set_key_checked(&cbc_key,&ks)) != 0)
    {
    strError.Format("Key error %d\n",j);
    MessageBox(strError,"错误!",MB_OK|MB_ICONSTOP);
    }
    if ((j=DES_set_key_checked(&cbc2_key,&ks2)) != 0)
    {
    strError.Format("Key error %d\n",j);
    MessageBox(strError,"错误!",MB_OK|MB_ICONSTOP);
    }
    if ((j=DES_set_key_checked(&cbc3_key,&ks3)) != 0)
    {
    strError.Format("Key error %d\n",j);
    MessageBox(strError,"错误!",MB_OK|MB_ICONSTOP);
    }*/
    //6.get keys
    DES_set_key_checked(&cbc_key,&ks);
    DES_set_key_checked(&cbc2_key,&ks2);
    DES_set_key_checked(&cbc3_key,&ks3);
    // memcpy(iv3,cbc_iv,sizeof(cbc_iv));
    while((nBytes=fread(szBuffer,1,DATA_LENGTH,fpCipher))>0) //DATA_LENGTH=4000
    {
    //7.can be divided by 16 
    nBytes=((nBytes+15)/16)*16;
    #if DEBUG_PRG
    memcpy(szText,szBuffer,nBytes);
        #endif
    //8.decrypt data
    memcpy(iv3,cbc_iv,sizeof(cbc_iv));
    memset(enData,0,DATA_LENGTH+1);
    des_ede3_cbc_encrypt(szBuffer,enData,nBytes+1,ks,ks2,ks3,&iv3,DES_DECRYPT);
    #if DEBUG_PRG
    //9.加密检查
    memset(deData,0,DATA_LENGTH+1);
    memcpy(iv3,cbc_iv,sizeof(cbc_iv));
    des_ede3_cbc_encrypt(enData,deData,16L,ks,ks2,ks3,&iv3,DES_ENCRYPT);
    des_ede3_cbc_encrypt(&(szBuffer[16]),&(enData[16]),(nBytes+1)-16,ks,ks2,ks3,&iv3,DES_ENCRYPT);
    nRetValue=memcmp(szText,deData,nBytes);
    if (nRetValue)
    {
    FILE *fpError=fopen((char *)(LPCTSTR) strErrorDataFile,"at");
    if(fpError)
    {
    memset(szMessage,0,200);
    sprintf((char *)szMessage,"\n文件:%s,位置:nRepeat=%d,%d,解密出错,内容如下:\n",(char *)(LPCTSTR) strPlainFile,nRepeat,nRepeat*DATA_LENGTH);
    fwrite(szMessage,1,strlen((char *)szMessage),fpError);
    char *strHeader="\n00   01   02   03   04   05   06   07   08   09   0A   0B   0C   0D   0E   0F\n";
    fwrite(strHeader,1,strlen(strHeader),fpError);
    char szPlain[100],szDeData[100];
    memset(szPlain,0,100);
    memset(szDeData,0,100);
    for(UINT t=0;t<nBytes;t++)
    {
    memset(ch,0,10);
    sprintf(ch,"0x%02x,",szText[t]);
    strcat(szPlain,ch);
    memset(ch,0,10);
    sprintf(ch,"0x%02x,",deData[t]);
    strcat(szDeData,ch);
    if ((t+1)%16==0)
    {
    fputs(szPlain,fpError);
    fwrite("--ok\n",1,5,fpError);
    fputs(szDeData,fpError);
    fwrite("--er\n",1,5,fpError);
    memset(szPlain,0,100);
    memset(szDeData,0,100);
    }
    }
    fclose(fpError);
    }
    TmpStr.Format("解加密前后不等: nRepeat = %d,退出否?",nRepeat);
    int nRetValue=::MessageBox(NULL,TmpStr,"错误", MB_YESNO|MB_ICONQUESTION);
    if( nRetValue==IDYES)
    return -1;
    }
    nRepeat++;
    #endif
    //10.write to the plain file
    if ((nByteCount+nBytes)>nOldPlainFileLength)
    {
    nBytes=nOldPlainFileLength-nByteCount;
    fwrite(enData,1,nBytes,fpPlain);
    }
    else
    {
    fwrite(enData,1,nBytes,fpPlain);
    nByteCount+=nBytes;
    }
    Sleep(10);
    memset(szBuffer,0,DATA_LENGTH+1);
    #if DEBUG_PRG
    memset(szText,0,DATA_LENGTH+1);
        #endif
    }
    //11.close these files
    fclose(fpCipher);
    fclose(fpPlain);
    ::MessageBox(NULL,"文件解密完成!","提示信息",MB_ICONINFORMATION|MB_OK);
    return 0;
    }