我正在尝试编写一个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;
}
这是调用函数的代码片段:
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;
}
}
答案 0 :(得分:0)
目前尚不清楚您是否只想要C ++解决方案;如果您对Python解决方案没问题,请尝试使用PyCrypto模块。这是我用来压缩当前目录的内容,除了一些忽略模式,并加密./bin下的.zip(大部分是从SO上其他地方复制的代码):
import sys
import os
import zipfile
import getpass
from contextlib import contextmanager
from hashlib import md5
from Crypto.Cipher import AES
from Crypto import Random
def derive_key_and_iv(password, salt, key_length, iv_length):
d = d_i = ''
while len(d) < key_length + iv_length:
d_i = md5(d_i + password + salt).digest()
d += d_i
return d[:key_length], d[key_length:key_length+iv_length]
def encrypt(in_file, out_file, password, key_length=32):
bs = AES.block_size
salt = Random.new().read(bs - len('Salted__'))
key, iv = derive_key_and_iv(password, salt, key_length, bs)
cipher = AES.new(key, AES.MODE_CBC, iv)
out_file.write('Salted__' + salt)
finished = False
while not finished:
chunk = in_file.read(1024 * bs)
if len(chunk) == 0 or len(chunk) % bs != 0:
padding_length = (bs - len(chunk) % bs) or bs
chunk += padding_length * chr(padding_length)
finished = True
out_file.write(cipher.encrypt(chunk))
def decrypt(in_file, out_file, password, key_length=32):
bs = AES.block_size
salt = in_file.read(bs)[len('Salted__'):]
key, iv = derive_key_and_iv(password, salt, key_length, bs)
cipher = AES.new(key, AES.MODE_CBC, iv)
next_chunk = ''
finished = False
while not finished:
chunk, next_chunk = next_chunk, cipher.decrypt(in_file.read(1024 * bs))
if len(next_chunk) == 0:
padding_length = ord(chunk[-1])
chunk = chunk[:-padding_length]
finished = True
out_file.write(chunk)
def query_yes_no(question, default="yes", quiet=False):
"""Ask a yes/no question via raw_input() and return their answer.
"question" is a string that is presented to the user.
"default" is the presumed answer if the user just hits <Enter>.
It must be "yes" (the default), "no" or None (meaning
an answer is required of the user).
The "answer" return value is True for "yes" or False for "no".
"""
valid = {"yes": True, "y": True, "ye": True,
"no": False, "n": False}
if default is None:
prompt = " [y/n] "
elif default == "yes":
prompt = " [Y/n] "
elif default == "no":
prompt = " [y/N] "
else:
raise ValueError("invalid default answer: '%s'" % default)
while True:
if not quiet:
sys.stdout.write(question + prompt)
if quiet and default is not None:
choice=default
else:
choice = raw_input().lower()
if default is not None and choice == '':
return valid[default]
elif choice in valid:
return valid[choice]
else:
sys.stdout.write("Please respond with 'yes' or 'no' "
"(or 'y' or 'n')\n")
dircurr=os.path.abspath('.').replace('\\','/')
dirwithenc=dircurr+'/bin'
if os.path.isfile(dirwithenc+'/bak.enc'):
if query_yes_no("\nDo you want to decrypt '"+dirwithenc+"/bak.enc'?",'no'):
password=getpass.getpass('\nDecryption password: ')
with open(dirwithenc+'/bak.enc', 'rb') as in_file, open(dircurr+'/bak.zip', 'wb') as out_file:
decrypt(in_file,out_file,password)
print("\nFile '"+dircurr+"/bak.enc' decrypted to '"+dircurr+"/bak.zip'")
raw_input("""
***DONE***
Press Enter...""")
exit(0)
else:
print("\nAnswered 'no'")
print("\nEncrypting files will overwrite any preexisting file '"+dirwithenc+"/bak.enc'")
password=getpass.getpass('\nSet an encryption password (will not be saved): ')
print('\nZipping files, excepting certain ignore patterns...')
zf = zipfile.ZipFile(dircurr+'/bak.zip', 'w')
for dirname, subdirs, files in os.walk(os.path.abspath('.')):
#Do not archive system files beginning with period
for filename in files:
if filename[:1]=='.':
files.remove(filename)
#Do not archive the binaries directory, it should just be delivered as is
if 'bin' in subdirs:
subdirs.remove('bin')
#Do not archive any previous archives, or you will just make a giant snowball
if 'bak.zip' in files:
files.remove('bak.zip')
if 'bak.enc' in files:
files.remove('bak.enc')
zf.write(dirname)
for filename in files:
zf.write(os.path.join(dirname, filename))
#If there was a folder 'dat' under the binaries folder, then archive it too,
#so that you have everything you need to rebuild the project
print("Including files under 'bin/dat'")
if os.path.isdir(dircurr+'/bin/dat'):
for dirname, subdirs, files in os.walk(dircurr+'/bin/dat'):
if 'bin' in subdirs:
subdirs.remove('bin')
zf.write(dirname)
for filename in files:
zf.write(os.path.join(dirname, filename))
#If there were any files '*.ico' under the binaries folder, then archive them too,
#so that you have everything you need to rebuild the project
print("Including .ico files under 'bin'")
for dirname, subdirs, files in os.walk(dircurr+'/bin'):
for filename in files:
if filename[-4:]=='.ico':
zf.write(os.path.join(dirname, filename))
zf.close()
print("\nZipped to '"+dircurr+"/bak.zip'")
print("\nEncrypting zipped file and removing unencrypted zipped file...")
with open(dircurr+'/bak.zip', 'rb') as in_file, open(dirwithenc+'/bak.enc', 'wb') as out_file:
encrypt(in_file, out_file, password)
os.remove(dircurr+'/bak.zip')
print("\nEncrypted to '"+dirwithenc+"/bak.enc'")
raw_input("""
***DONE***
Press Enter...""")
exit(0)