I have a problem, when i use http://slproweb.com/products/Win32OpenSSL.html , i try to Init Encryption, but always catch error like
"OpenSSL assertion failed, evp_enc.c(282)"
Can somebody help me with this matter?
My code:
bool do_encrypt(const char *in, unsigned char *out, int *outlen, unsigned char *key, unsigned char *iv)
{
int buflen, tmplen;
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_EncryptInit_ex(&ctx, EVP_rc4(), NULL, key, iv);
if(!EVP_EncryptUpdate(&ctx, out, &buflen, (unsigned char*)in, strlen(in))) // error here
{
return false;
}
if(!EVP_EncryptFinal_ex(&ctx, out + buflen, &tmplen))
{
return false;
}
buflen += tmplen;
*outlen = buflen;
EVP_CIPHER_CTX_cleanup(&ctx);
return true;
}
I use key for test {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, iv is NULL.
Code that uses this function above:
int WINAPI OwnSend(SOCKET s, const char FAR *buff, int len, int flags )
{
if(s == ServerSocket)
{
if(len > 0)
{
int outlen;
unsigned char EncryptBuffer[5500];
do_encrypt(buff, EncryptBuffer, &outlen, KeyTest, NULL);
buff = (const char *) EncryptBuffer;
return pTrampolineSend(s, buff, outlen, flags);
}
}
return pTrampolineSend(s, buff, len, flags);
}
Thanks!
The only assertion in EVP_EncryptUpdate is one that asserts that the buffer length is less than or equal to the block size of the encryption algorithm.
Instead of calling strlen(in) as the size of your input, try looping EVP_EncryptUpdate and each time you go through, make sure to limit the input size with:
int in_size_limit = EVP_CIPHER_CTX_block_size(&ctx);
While looping, be sure to increment the offset of the 2nd and 4th args by the number of bytes you've already encrypted:
if ( EVP_EncryptUpdate(&ctx,
out+encrypted_bytes,
&bytes_encrypted_this_call,
in+encrypted_bytes,
in_size_limit) != 1)
{
/* error */
}
else
{
encrypted_bytes += bytes_encrypted_this_call;
}
Related
I have some openssl code that encrypts and decrypts a file.
Initially I wrote it so the encrypted file is base64 encoded. The problem is certain file sizes are reduced on decryption. i.e I lose upto 16 characters in the decrypted based on the original file
If the file is less that 16 bytes it is fine, greater than that and I start losing characters on decryption with and error on the final decrypt step.
I assumed initially it was a padding issue, but adding padding does bot fix however If I remove the base64 encoding it is fine however.
This is based on open_ssl 1.1.1s
int BIO_enc_header(BIO* file, unsigned char* Salt)
{
RAND_bytes(Salt, SALTSIZE);
int len=BIO_write(file,MAGIC, MAGIC_SIZE);
len=BIO_write(file,Salt, SALTSIZE);
return 0;
}
int BIO_dec_header(BIO* file, unsigned char* Salt)
{
int mlen = 0;
char mBuff[MAGIC_SIZE + 1] = { 0 };
mlen = BIO_read(file,mBuff, MAGIC_SIZE);
if (mlen == MAGIC_SIZE) {
/* Check Magic size */
int salt_len = BIO_read(file,Salt,SALTSIZE);
if (salt_len != SALTSIZE) {
return -1;
}
}
return 0;
}
//#define BASE64 1
int do_crypt_bio(BIO* bio_in, BIO* bio_out, int do_encrypt, unsigned char* szPassword)
{
int Result = OK;
unsigned char salt[8] = { 0 };
int inByte = 0, outByte = 0;
//int Padding;
#ifdef BASE64
BIO *b64 = BIO_new(BIO_f_base64());
if (!b64) {
return ERROR;
}
#endif
#ifdef BASE64
if (do_encrypt) {
/*out base64*/
bio_out = BIO_push(b64, bio_out);
BIO_set_flags(bio_out, BIO_FLAGS_BASE64_NO_NL);
}else {
/* read base 64*/
bio_in = BIO_push(b64, bio_in);
BIO_set_flags(bio_in, BIO_FLAGS_BASE64_NO_NL);
}
#endif
/* Allow enough space in output buffer for additional block */
unsigned char inbuf[ENC_BUFF_SIZE+ EVP_MAX_BLOCK_LENGTH], outbuf[ENC_BUFF_SIZE + EVP_MAX_BLOCK_LENGTH];
int inlen, outlen;
EVP_CIPHER_CTX* ctx=NULL;
#define AES_256_KEY_SIZE 32
unsigned char key[AES_256_KEY_SIZE] = { 0 };
unsigned char iv[AES_BLOCK_SIZE] = { 0 };
int rounds = 5;
int Size=EVP_CIPHER_block_size(EVP_aes_256_cbc());
if (do_encrypt) {
BIO_enc_header(bio_out, salt);
}else {
BIO_dec_header(bio_in, salt);
}
if (!EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha256(), salt, szPassword, strlen((char*)szPassword), rounds, key, iv)) {
#ifdef BASE64
BIO_free(b64);
#endif
return ERROR;
}
/* Don't set key or IV right away; we want to check lengths */
ctx = EVP_CIPHER_CTX_new();
if (!ctx) {
#ifdef BASE64
BIO_free(b64);
#endif
return ERROR;
}
int CipherResult=EVP_CipherInit_ex(ctx, EVP_aes_256_cbc(), NULL, NULL, NULL, do_encrypt);
CipherResult =EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, do_encrypt); /* Now we can set key and IV */
//EVP_CIPHER_CTX_set_padding(ctx, 32);
int len;
for (;;) {
memset(inbuf, 0, ENC_BUFF_SIZE+EVP_MAX_BLOCK_LENGTH);
inlen = BIO_read(bio_in,inbuf, ENC_BUFF_SIZE);
//inByte += inlen;
if (inlen <= 0)break;
if (!EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen)) {
/* Error */
Result = ERROR;
goto error;
}
len=BIO_write(bio_out,outbuf,outlen);
//outByte += outlen;
}
int f_len;
if (!EVP_CipherFinal_ex(ctx, outbuf, &f_len)) {
/* Error */
Result = ERROR;
ERR_print_errors_fp(stderr);
goto error;
}
len= BIO_write(bio_out, outbuf, f_len);
//outByte += f_len;
len = len;
error:
EVP_CIPHER_CTX_free(ctx);
#ifdef BASE64
BIO_free(b64);
#endif
return Result;
}
int EncryptFile(char* input, char *encrypted,char* password)
{
int Result = OK;
BIO* bio_in = BIO_new_file(input, "rb");
if (!bio_in) {
return ERROR;
}
BIO* bio_out = BIO_new_file(encrypted, "wb+");
if (!bio_out) {
BIO_free(bio_in);
return ERROR;
}
Result=do_crypt_bio(bio_in, bio_out, 1, (unsigned char*)password);
BIO_free(bio_in);
BIO_free(bio_out);
return Result;
}
int DecryptFile(char* encrypted, char* output, char* password)
{
int Result = OK;
BIO* bio_in = BIO_new_file(encrypted, "rb");
if (!bio_in) {
return ERROR;
}
BIO* bio_out = BIO_new_file(output, "wb+");
if (!bio_out) {
BIO_free(bio_in);
return ERROR;
}
Result=do_crypt_bio(bio_in, bio_out, 0, (unsigned char*)password);
BIO_free(bio_in);
BIO_free(bio_out);
return Result;
}
I recently started a small side-project to recreate the Minecraft Server in C++ but I stumbled on a problem.
I need to use the AES/CFB8 Cipher according to this link with continuous updating (not finished and restarted every packet).
I surfed trough the internet to try to find a proper solution but could not figure out one that was actually working or it was using the command line interface.
Any help is welcomed !
Cipher.h
class Cipher {
public:
enum CipherType {
ENCRYPT,
DECRYPT
};
private:
EVP_CIPHER_CTX* ctx;
CipherType type;
bool hasFinished;
public:
Cipher(const char* key, const char* iv, CipherType type);
~Cipher();
int update(char* in, int inl, char* out);
int final(char* out);
int getMinimumBufLength(int size);
};
Cipher.cpp
Cipher::Cipher(const char* key, const char* iv, CipherType type) : type(type), hasFinished(false)
{
ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(ctx);
if(type == CipherType::ENCRYPT)
EVP_EncryptInit_ex(ctx, EVP_aes_256_cfb8(), nullptr, (unsigned char*)key, (unsigned char*)iv);
else
EVP_DecryptInit_ex(ctx, EVP_aes_256_cfb8(), nullptr, (unsigned char*)key, (unsigned char*)iv);
}
Cipher::~Cipher()
{
EVP_CIPHER_CTX_free(ctx);
}
int Cipher::getMinimumBufLength(int size)
{
return type == CipherType::DECRYPT ? size : size + AES_BLOCK_SIZE * 2;
}
int Cipher::update(char* in, int inl, char* out)
{
int len;
EVP_CipherUpdate(ctx, (unsigned char*)out, &len, (unsigned char*)in, inl);
return len;
}
int Cipher::final(char* out)
{
int len;
EVP_EncryptFinal_ex(ctx, (unsigned char*)out, &len);
return len;
}
Cipher-test.cpp
TEST_CASE("Cipher AES/CFB8")
{
char* key = "AAAAAAAAAZEFRGUINJFKDFIVJ";
char* iv = "AUJVFEUB";
Cipher encryptionCipher(key, iv, Cipher::CipherType::ENCRYPT);
Cipher decryptionCipher(key, iv, Cipher::CipherType::DECRYPT);
std::string data = "Hello World ! This is some soon to be encrypted string !";
char encData[encryptionCipher.getMinimumBufLength(data.size() + 1)];
int outLen = encryptionCipher.update(data.data(), data.size() + 1, encData);
int fLen = encryptionCipher.final(encData + outLen);
CHECK(data != std::string(encData));
char decData[decryptionCipher.getMinimumBufLength(outLen + fLen)];
outLen = decryptionCipher.update(encData, outLen + fLen, decData);
decryptionCipher.final(decData + outLen);
CHECK(data == std::string(decData));
}
Thanks in advance
EDIT: I am just wondering if there was a need for supplementary code because of the "continuous" aspect of the Cipher.
I wrote the following code that should return a signature of the provided std::string signed using an EC private key.
std::string msg = "test";
size_t messageLength = msg.length();
size_t encMessageLength;
unsigned char* encMessage;
signMessage(msg, evp_private_key, messageLength, &encMessageLength, &encMessage);
bool signMessage(std::string msg, EVP_PKEY *&key, size_t messageLength, size_t *encMessageLength, unsigned char** encMessage) {
unsigned char * u_msg = (unsigned char*) msg.c_str();
EVP_MD_CTX* signCtx = EVP_MD_CTX_new();
if (EVP_DigestSignInit(signCtx,NULL, EVP_sha256(), NULL, key) <= 0) {
return NULL;
}
if (EVP_DigestSignUpdate(signCtx, u_msg, messageLength) <= 0) {
return NULL;
}
if (EVP_DigestSignFinal(signCtx, NULL, encMessageLength) <= 0) {
return NULL;
}
*encMessage = (unsigned char*)malloc(*encMessageLength);
if (EVP_DigestSignFinal(signCtx, *encMessage, encMessageLength) <= 0) {
return NULL;
}
EVP_MD_CTX_free(signCtx);
return true;
}
*encMessage is freed after the function call.
The length of encMessage varies greatly between 3 and 139.
An example output casted and printed as char* as well as hex looks like this:
�D�b���w�x�VS:������dƀ7�#����v�B%M�X2�ky���!�h�};J>�!���h�ħ�n����/�j�U���aL����z�X���>�2�>
Length: 138
hex: 30818702414fa9b7d8cac465525add0451784bc751544702edd0e24bdb0dca44f362fc80a11b3777e78316788e56533a91c0a1eb058bf1a564c68037900640cc13b9aca776c4024201254dd55832a16b799ad2f021f468a07d3b4a3e801321bba284688fc4a7c0156e86da1e84952f8c6ab755da1dd3ec614cec10bea1bc7aac58affa9c3efb32990f3e
Another function call:
msg: 0��B
Length: 5
hex: 3081880242
What am I doing wrong?
a question: Vendor says that for some encryption purpose uses PKCS#1 V2.1 OAEP with SHA-256... Is that even possible?
I have checked and re-checked openssl and all they have is RSA public key encrypt with OAEP padding which is supposed to be PKCS#1 V2.1 with SHA1
So what can I do? How can I use SHA256 in RSA PUBLIC KEY encryption?
IS it even possible?
Best regards,
EDITED: ANSWER HOW TO USE RSA ENCRYPTION USING OPENSSL OAEP PADDING AND SHA256 DIGEST
#include "openssl/rsa.h"
#include <openssl/err.h>
#define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1 154
int RSA_padding_add_PKCS1_OAEP_mgf1_SHA256(unsigned char *to, int tlen,
const unsigned char *from, int flen,
const unsigned char *param, int plen,
const EVP_MD *md, const EVP_MD *mgf1md)
{
int i, emlen = tlen - 1;
unsigned char *db, *seed;
unsigned char *dbmask, seedmask[EVP_MAX_MD_SIZE];
int mdlen;
if (md == NULL)
md = EVP_sha256(); //HERE IS THE ACTUAL USE OF SHAR256 digest!
if (mgf1md == NULL)
mgf1md = md;
mdlen = EVP_MD_size(md);
if (flen > emlen - 2 * mdlen - 1)
{
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1,
RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return 0;
}
if (emlen < 2 * mdlen + 1)
{
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, RSA_R_KEY_SIZE_TOO_SMALL);
return 0;
}
to[0] = 0;
seed = to + 1;
db = to + mdlen + 1;
if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL))
return 0;
memset(db + mdlen, 0,
emlen - flen - 2 * mdlen - 1);
db[emlen - flen - mdlen - 1] = 0x01;
memcpy(db + emlen - flen - mdlen, from, (unsigned int)flen);
if (RAND_bytes(seed, mdlen) <= 0)
return 0;
#ifdef PKCS_TESTVECT
memcpy(seed,
"\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f",
20);
#endif
dbmask = (unsigned char*)OPENSSL_malloc(emlen - mdlen);
if (dbmask == NULL)
{
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE);
return 0;
}
if (PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md) < 0)
return 0;
for (i = 0; i < emlen - mdlen; i++)
db[i] ^= dbmask[i];
if (PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md) < 0)
return 0;
for (i = 0; i < mdlen; i++)
seed[i] ^= seedmask[i];
OPENSSL_free(dbmask);
return 1;
}
int RSA_padding_add_PKCS1_OAEP_SHA256(unsigned char *to, int tlen,
const unsigned char *from, int flen,
const unsigned char *param, int plen)
{
return RSA_padding_add_PKCS1_OAEP_mgf1_SHA256(to, tlen, from, flen,
param, plen, NULL, NULL);
}
static int RSA_eay_public_encrypt_SHA256(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
BIGNUM *f, *ret;
int i, j, k, num = 0, r = -1;
unsigned char *buf = NULL;
BN_CTX *ctx = NULL;
#ifdef OPENSSL_FIPS
if (FIPS_selftest_failed())
{
FIPSerr(FIPS_F_RSA_EAY_PUBLIC_ENCRYPT, FIPS_R_FIPS_SELFTEST_FAILED);
goto err;
}
if (FIPS_module_mode() && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW)
&& (BN_num_bits(rsa->n) < OPENSSL_RSA_FIPS_MIN_MODULUS_BITS))
{
RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_KEY_SIZE_TOO_SMALL);
return -1;
}
#endif
if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS)
{
RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_MODULUS_TOO_LARGE);
return -1;
}
if (BN_ucmp(rsa->n, rsa->e) <= 0)
{
RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE);
return -1;
}
/* for large moduli, enforce exponent limit */
if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS)
{
if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS)
{
RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE);
return -1;
}
}
if ((ctx = BN_CTX_new()) == NULL) goto err;
BN_CTX_start(ctx);
f = BN_CTX_get(ctx);
ret = BN_CTX_get(ctx);
num = BN_num_bytes(rsa->n);
buf = (unsigned char*)OPENSSL_malloc(num);
if (!f || !ret || !buf)
{
RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, ERR_R_MALLOC_FAILURE);
goto err;
}
switch (padding)
{
case RSA_PKCS1_PADDING:
i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen);
break;
#ifndef OPENSSL_NO_SHA
case RSA_PKCS1_OAEP_PADDING:
i = RSA_padding_add_PKCS1_OAEP_SHA256(buf, num, from, flen, NULL, 0);
break;
#endif
case RSA_SSLV23_PADDING:
i = RSA_padding_add_SSLv23(buf, num, from, flen);
break;
case RSA_NO_PADDING:
i = RSA_padding_add_none(buf, num, from, flen);
break;
default:
RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
if (i <= 0) goto err;
if (BN_bin2bn(buf, num, f) == NULL) goto err;
if (BN_ucmp(f, rsa->n) >= 0)
{
/* usually the padding functions would catch this */
RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
}
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
goto err;
if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx,
rsa->_method_mod_n)) goto err;
/* put in leading 0 bytes if the number is less than the
* length of the modulus */
j = BN_num_bytes(ret);
i = BN_bn2bin(ret, &(to[num - j]));
for (k = 0; k<(num - i); k++)
to[k] = 0;
r = num;
err:
if (ctx != NULL)
{
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
if (buf != NULL)
{
OPENSSL_cleanse(buf, num);
OPENSSL_free(buf);
}
return(r);
}
int RSA_public_encrypt_sha256(int flen, const unsigned char *from, unsigned char *to,
RSA *rsa, int padding)
{
return(RSA_eay_public_encrypt_SHA256(flen, from, to, rsa, padding));
}
Just add these few functions and call RSA_public_encrypt_sha256 instead of RSA_public_encrypt and voila you have RSA_OAEP_SHA256
Well i know this is abusing the openssl code, but this is a solution if you cannot compile openssl lib yourself, like i cannot because i received this as a part of an ARM platform
All thanks go to JARIQ in the answer below!
Thank you!
I am not sure about the OpenSSL API but in PKCS#11 API when you are using RSA encryption with OAEP padding you can specify message digest algorithm and also a mask generation function as you can see in my code sample (take a look at _03_EncryptAndDecryptSinglePartOaepTest() method) . It is written in C# but I believe it should be easily understandable. However I have never tried anything else than SHA1.
More information can be found in RFC 3447 and PKCS#11 specification (chapter 12.1.7 and chapter 12.1.8).
EDIT for OpenSSL:
In OpenSSL RSA encryption with public key and OAEP padding is performed in this order:
you need to pass RSA_PKCS1_OAEP_PADDING flag to function RSA_public_encrypt() implemented in rsa_crpt.c
RSA_public_encrypt() then calls function RSA_eay_public_encrypt() implemented in rsa_eay.c (unless you are using some cryptographic hardware device via ENGINE)
RSA_eay_public_encrypt() then calls function RSA_padding_add_PKCS1_OAEP() implemented in rsa_oaep.c
This uses SHA1 which seems to be currently the only option implemented in OpenSSL but I believe it should be possible to slightly modify code in rsa_oaep.c file to achieve what you need.
I'm trying to encrypt a file using AES from OpenSSL and then write the output to a file. But I'm getting messy outputs, sometimes decipherable and sometimes not.
The main code is based from here: https://github.com/shanet/Crypto-Example/blob/master/crypto-example.cpp
Here's the code:
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 calling like this:
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...
Thanks.
I'm actually the author of the example you've based your code off of. As WhozCraig pointed out in the comments above, you are using a stringstream to write the encrypted message to a file. The problem with this is that encrypted messages are not regular ASCII strings. They are binary data (values greater than 127, hence the need for an unsigned char array) and binary data cannot be treated the same as ASCII strings.
I'm not much of a C++ person, so I would write the data to a file the C way with fwrite, but if you want to do it the C++ way, I think you're looking for ifstream rather than stringstream.
Side note, I'm betting this is just for debugging, but I'll point it out anyway just to make sure: Hardcoding your AES key and IV (strncpy((char*)aesKey, (const char*)"B374A26A71490437AA024E4FADD5B4AA", AES_KEYLEN/8)) completely defeats the purpose of encryption. If you want to avoid the PBKDF (EVP_BytesToKey) you can just use RAND_Bytes to get random data for your AES key.