我从OPENSL中剪出了一部分3DES加密的源码,放在一个基于对话框的程序中对文件进行加解密,从小文件nKBytes,到大文件20M左右,均加密与解密十分正确正常,即文件经一次加密,再经一次解密后,不发生变化.但当把这个工程改成DLL时,出现加解密不一致的错误.多次测试发现部分现象:文件小时;nKBytes,加密正确,但解密时,除了前16个字节与原文件相同外,后面解密还原的内容全是零,即0x00,请有加解密及DLL编程注意事项的大侠及高手指点迷津,谢谢,问题能得到解决,另开2贴送分.
解决方案 »
- 本人在学opengl,求高手帮忙怎样(if(dlg.DoModal()==IDOK) )得到图片的Filename和长宽,并代人下面的源码中(vc++)
- vc++6.0 的问题
- VC 怎么实现
- 请问哪位仁兄能提供一个"俄罗斯方块"的文章?
- 如何在ACTIVEX中创建窗体,很急?
- 想找一个可以查询程序使用的API及相关DLL的工具
- 请问如何做一个简单的编辑工具
- 悬赏啦!!关于汉信码,谢谢
- 哪位大侠有关于流程控制中间件的相关文章和资料!!
- 关于串口与jpeg的问题,新人求助!!!求各位大神帮忙!!!
- 求助:制作二进制文件读取对话框。急!急!急!急!急!
- 在.h文件中定义, 在.cpp文件中实现, 可以吗?
#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;
}
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;
}
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;
}