【发布时间】:2015-01-12 00:10:12
【问题描述】:
我正在尝试编写一个 C++ 程序来加密和解密某些文件。加密工作正常,但是当我来解密该函数时似乎导致程序崩溃。
这是我用来解密的函数:
CString DecryptFile(CString csSourceFile)
{
CString csDecryptedFile = csSourceFile;
CRijndael aesEncryption;
int nPos = csDecryptedFile.ReverseFind('.');
if(nPos == -1)
{
//Log("ERROR:: file name not proper");
return CString("");
}
csDecryptedFile = csDecryptedFile.Left(nPos);
csDecryptedFile += ".wav";
FILE *fIn = fopen(csSourceFile.GetBuffer(0),"rb");
FILE *fOut = fopen(csDecryptedFile.GetBuffer(0),"wb");
if(!fIn || !fOut)
{
//Log("ERROR:: failed to Open File for encryption");
return CString("");
}
int nlen = -1;
aesEncryption.MakeKey(AM_ENC_KEY,AM_NULL_KEY,BLOCK_SIZE,BLOCK_SIZE);
int nRead = 0;
while (true) {
char szBlockIn[EBLOCK_SIZE+1] = {0};
char szBlockOut[BLOCK_SIZE+1] = {0};
char szBlockDec[BLOCK_SIZE+1] = {0};
memset(szBlockIn,0,sizeof(char)*(EBLOCK_SIZE+1));
memset(szBlockOut,0,sizeof(char)*(BLOCK_SIZE+1));
memset(szBlockDec,0,sizeof(char)*(BLOCK_SIZE+1));
int nRead = fread(szBlockIn,sizeof(char),EBLOCK_SIZE, fIn);
if(nRead <= 0) {
break;
}
nlen = EBLOCK_SIZE;
Decode(szBlockIn,szBlockOut,nlen);
aesEncryption.DecryptBlock((char *)szBlockOut,szBlockDec);
fwrite(szBlockDec,sizeof(char),BLOCK_SIZE,fOut);
}
fclose(fIn);
fclose(fOut);
RemoveEndTag(csDecryptedFile.GetBuffer(0));
AfxMessageBox(csDecryptedFile);
AfxMessageBox(_T("returning"));
return csDecryptedFile;
}
这是调用函数的代码sn-p:
CString strTest = DecryptFile(m_DecompressedTempFile);
AfxMessageBox(strTest);
奇怪的是解密执行得非常好 - 如果我到达文件位置,我可以看到解密的文件并访问它。不幸的是,该程序必须做更多的事情,并且该程序只是紧随其后而挂起。特别奇怪的是,如您所见,我在函数结束之前调用了AfxMessageBox(_T("returning"));:这会产生一个消息框。但是当我从运行该函数的代码中调用AfxMessageBox(strTest); 时,不会生成任何消息框。
通过调试,问题似乎以某种方式在我用于加密文件的while循环中路由,所以我想知道我是否没有关闭我应该关闭的东西或其他东西?虽然不太确定从哪里开始,所以任何可以提供任何帮助的人都会很棒!?!
提前致谢。
我忘了提到这已经工作多年了——最近唯一的变化是我们现在在 Windows 7 上编译代码,而之前是在 Windows XP 上。这会对函数中的任何内容产生影响吗?
更新: 值得注意的是,如果我删除 while 循环并只运行一次循环的内容,就会出现同样的问题。如果我删除aesEncryption.DecryptBlock((char *)szBlockOut,szBlockDec);,那么问题就会消失,但显然我需要那条线。所以问题是我认为的那个功能。虽然这个函数存在于库中,但我将它包含在下面:
//Decrypt exactly one block of ciphertext.
// in - The ciphertext.
// result - The plaintext generated from a ciphertext using the session key.
void CRijndael::DecryptBlock(char const* in, char* result)
{
if(false==m_bKeyInit)
throw exception(sm_szErrorMsg1);
if(DEFAULT_BLOCK_SIZE == m_blockSize)
{
DefDecryptBlock(in, result);
return;
}
int BC = m_blockSize / 4;
int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2);
int s1 = sm_shifts[SC][1][1];
int s2 = sm_shifts[SC][2][1];
int s3 = sm_shifts[SC][3][1];
//Temporary Work Arrays
int i;
int tt;
int* pi = t;
for(i=0; i<BC; i++)
{
*pi = ((unsigned char)*(in++) << 24);
*pi |= ((unsigned char)*(in++) << 16);
*pi |= ((unsigned char)*(in++) << 8);
(*(pi++) |= (unsigned char)*(in++)) ^= m_Kd[0][i];
}
//Apply Round Transforms
for(int r=1; r<m_iROUNDS; r++)
{
for(i=0; i<BC; i++)
a[i] = (sm_T5[(t[i] >> 24) & 0xFF] ^
sm_T6[(t[(i + s1) % BC] >> 16) & 0xFF] ^
sm_T7[(t[(i + s2) % BC] >> 8) & 0xFF] ^
sm_T8[ t[(i + s3) % BC] & 0xFF]) ^ m_Kd[r][i];
memcpy(t, a, 4*BC);
}
int j;
//Last Round is Special
for(i=0,j=0; i<BC; i++)
{
tt = m_Kd[m_iROUNDS][i];
result[j++] = sm_Si[(t[i] >> 24) & 0xFF] ^ (tt >> 24);
result[j++] = sm_Si[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16);
result[j++] = sm_Si[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8);
result[j++] = sm_Si[ t[(i + s3) % BC] & 0xFF] ^ tt;
}
}
【问题讨论】:
-
是
GetBuffer(0)打来的电话吗? msdn.microsoft.com/en-us/library/aa314880%28v=vs.60%29.aspx 由于 CString 是引用计数字符串,您可能需要调用ReleaseBuffer -
谢谢你,ReleaseBuffer 肯定应该在那里。不幸的是,这对悬挂问题没有帮助:(
-
也许你应该使用另一个 AES 库,因为你使用的那个似乎没有经过很多同行评审:codeproject.com/Articles/1380/…
-
我忘了提到这已经工作了好几年了——最近唯一的变化是我们现在在 Windows 7 上编译代码,而之前是在 Windows XP 上。这会对函数中的任何内容产生影响吗?
-
有加密++。 cryptopp.com 只需确保您采用现有示例并根据您的需要对其进行定制。该库是稳定的,但往往难以使用(我的看法)。