2014-11-14 4 views
3

Я пытаюсь написать программу на C++ для шифрования и дешифрования определенных файлов. Шифрование работает отлично, но когда я прихожу для дешифрования функции, похоже, вызывает сбои в программе.Расшифровать AES-зашифрованный файл, вызвав ошибку

Вот функция, я использую для дешифрования:

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); из кода, который запускает эту функцию, окно сообщения не создается.

С помощью отладки кажется, что проблема каким-то образом маршрутизируется во время цикла, который у меня есть для шифрования файла, поэтому мне интересно, не закрываю ли я что-то, что я должен или что-то еще? Не совсем уверен, что делать с этим, так что любой, кто может предложить любую помощь, будет отличным!?!

Заранее спасибо.

Я забыл упомянуть, что это работало много лет назад - единственное недавнее изменение заключается в том, что мы сейчас компилируем код в Windows 7, а ранее это Windows XP. Будет ли это иметь значение для чего-либо в функции?

Обновление: Следует отметить, что если я удаляю цикл while и запускаю содержимое цикла только один раз, возникает та же проблема. Если я удалю aesEncryption.DecryptBlock((char *)szBlockOut,szBlockDec);, проблема исчезнет, ​​но, очевидно, мне нужна эта строка. Поэтому проблема направлена ​​на эту функцию, я думаю. Хотя эта функция существует в библиотеке, я hvae включил его ниже:

//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

Является ли это, что 'GetBuffer (0) 'call? http://msdn.microsoft.com/en-us/library/aa314880%28v=vs.60%29.aspx Поскольку CString является ссылочной подсчитанной строкой, вам может потребоваться вызвать 'ReleaseBuffer' – PaulMcKenzie

+0

Спасибо за это, ReleaseBuffer должно быть обязательно там. К сожалению, это не помогло проблемы с подвеской :( – Raiden616

+0

Возможно, вам стоит использовать другую библиотеку AES, поскольку тот, который вы используете, похоже, не попал под многоуровневый обзор: http://www.codeproject.com/Articles/1380/AC-Implementation-of-the-the-Rijndael-Encryption-Decr – PaulMcKenzie

ответ

0

не ясно, хотите ли вы C++ решение только; если вы в порядке с решением Python, попробуйте модуль PyCrypto. Вот что я использую, чтобы пронестись текущий каталог, за исключением некоторых шаблонов игнорирования, и шифровать .zip под ./bin (большая часть его код копируется из других на 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) 
Смежные вопросы