2013-07-31 4 views
0

Я пытаюсь зашифровать файл с помощью AES из OpenSSL, а затем записать вывод в файл. Но я получаю грязные результаты, иногда дешифруемые, а иногда и нет.Почему мой код OpenSSL C++ создает двоичный файл шифрования?

Основной код основан здесь: https://github.com/shanet/Crypto-Example/blob/master/crypto-example.cpp

Вот код:

int Crypt::__aesEncrypt(const unsigned char *msg, size_t msgLen, unsigned char **encMsg) { 
EVP_CIPHER_CTX *aesEncryptCtx = (EVP_CIPHER_CTX*)malloc(sizeof(EVP_CIPHER_CTX)); 
EVP_CIPHER_CTX_init(aesEncryptCtx); 

unsigned char *aesKey = (unsigned char*)malloc(AES_KEYLEN/8); 
unsigned char *aesIV = (unsigned char*)malloc(AES_KEYLEN/8); 

unsigned char *aesPass = (unsigned char*)malloc(AES_KEYLEN/8); 
unsigned char *aesSalt = (unsigned char*)malloc(8); 

if(RAND_bytes(aesPass, AES_KEYLEN/8) == 0) { 
    return FAILURE; 
} 

if(RAND_bytes(aesSalt, 8) == 0) { 
    return FAILURE; 
} 

if(EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), aesSalt, aesPass, AES_KEYLEN/8, AES_ROUNDS, aesKey, aesIV) == 0) { 
    return FAILURE; 
} 

strncpy((char*)aesKey, (const char*)"B374A26A71490437AA024E4FADD5B4AA", AES_KEYLEN/8); 
strncpy((char*)aesIV, (const char*)"7E892875A52C59A3B588306B13C31FBD", AES_KEYLEN/16); 

size_t blockLen = 0; 
size_t encMsgLen = 0; 

*encMsg = (unsigned char*)malloc(msgLen + AES_BLOCK_SIZE); 
if(encMsg == NULL) return FAILURE; 

if(!EVP_EncryptInit_ex(aesEncryptCtx, EVP_aes_256_cbc(), NULL, aesKey, aesIV)) { 
    return FAILURE; 
} 

if(!EVP_EncryptUpdate(aesEncryptCtx, *encMsg, (int*)&blockLen, (unsigned char*)msg, msgLen)) { 
    return FAILURE; 
} 
encMsgLen += blockLen; 

if(!EVP_EncryptFinal_ex(aesEncryptCtx, *encMsg + encMsgLen, (int*)&blockLen)) { 
    return FAILURE; 
} 

EVP_CIPHER_CTX_cleanup(aesEncryptCtx); 
free(aesEncryptCtx); 

free(aesKey); 
free(aesIV); 

return encMsgLen + blockLen; 

}

Im называя так:

unsigned char *encMsg = NULL; 
    __aesEncrypt((const unsigned char*)decrypted_string.c_str(), decrypted_string.size(), &encMsg); 

    std::stringstream ss; 
    ss << encMsg; 
    //write ss to file... 

Спасибо.

+0

Вы хотите, чтобы это шифрование было читаемым шестнадцатеричным текстом (например, Base64 encoded или BinHex)? Вам нужно будет сделать это самостоятельно в блоке с зашифрованными сообщениями, прежде чем записывать его в текстовый поток. Кроме того, похоже, что вы хотите использовать ключ как * bytes *, но вы передаете строку ascii * string *. Я раньше не использовал OpenSSL, но я не думаю, что он просто переведет его для вас до шифрования. – WhozCraig

+0

Думаю, для меня нет разницы, спасибо. –

+0

Я думаю, вы пропустили мою мысль. Текстовый поток через 'operator <<' ожидает * символов *. Это не то, что вы даете. – WhozCraig

ответ

3

Я на самом деле автор примера, на котором вы основали свой код. Как указал WhozCraig в комментариях выше, вы используете stringstream для записи зашифрованного сообщения в файл. Проблема в том, что зашифрованные сообщения не являются регулярными строками ASCII. Это двоичные данные (значения больше 127, следовательно, необходимость в массиве без знака), а двоичные данные не могут обрабатываться так же, как строки ASCII.

Я не очень человек на С ++, поэтому я бы написал данные в файл с кодом 0 с помощью fwrite, но если вы хотите сделать это на C++, я думаю, что вы ищете ifstream, а не stringstream.

Боковое примечание, я готов поспорить, что это только для отладки, но я все же укажу на это, чтобы убедиться: Hardcoding ваш ключ AES и IV (strncpy((char*)aesKey, (const char*)"B374A26A71490437AA024E4FADD5B4AA", AES_KEYLEN/8)) полностью побеждает цель шифрования. Если вы хотите избежать PBKDF (EVP_BytesToKey), вы можете просто использовать RAND_Bytes, чтобы получить случайные данные для вашего ключа AES.

+0

Спасибо! Его работа сейчас ... –

+1

+1. Использование форматированного потока строк с шестнадцатеричным кодированием (эффективно бит hex) является одним из вариантов для написания текста. Другой использует встроенный кодер Base64 для OpenSSL. Я бы, вероятно, воспользовался последним, так как ваш процесс расшифровки может использовать тот же набор API для декодирования в байтах перед расшифровкой (и, как я уже сказал, это было некоторое время, но я не был бы удивлен, если OpenSSL имеет возможность делать как в одном шаге * где-то * в их API). – WhozCraig

+0

@WhozCraig Хорошая идея с базой64. Я добавлю это к моему примеру, поскольку у меня возникают вопросы о том, что зашифрованные сообщения являются двоичными данными все время. – shanet

Смежные вопросы