Boardy Boardy - 2 months ago 13
C++ Question

Converting C# Encryption to C++ encryption

I am currently learning C++ and looking into using it for a project but I need to be able to encrypt and decrypt string.

I have conversion code in various languages such as C#, Java and PHP and they can work together, for example, C# and/or/ Java and/or PHP can write an encrypted string to a database and any of those languages can read in the value from the database and decrypt it.

Below is the C# code as an example:

public static string encrypt(string encryptionString)
{
byte[] clearTextBytes = Encoding.UTF8.GetBytes(encryptionString);

SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();

MemoryStream ms = new MemoryStream();
byte[] rgbIV = Encoding.ASCII.GetBytes("ryojvlzmdalyglrj");

byte[] key = Encoding.ASCII.GetBytes("hcxilkqbbhczfeultgbskdmaunivmfuo");
CryptoStream cs = new CryptoStream(ms, rijn.CreateEncryptor(key, rgbIV), CryptoStreamMode.Write);

cs.Write(clearTextBytes, 0, clearTextBytes.Length);

cs.Close();

return Convert.ToBase64String(ms.ToArray());
}


I have tried the following in C++

void Encryption::encryptString(string stringToEncrypt)
{
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);

//string key = "hcxilkqbbhczfeultgbskdmaunivmfuo";
//string iv = "ryojvlzmdalyglrj";

unsigned char key[33] = "hcxilkqbbhczfeultgbskdmaunivmfuo";
unsigned char iv[17] = "ryojvlzmdalyglrj";



vector<unsigned char> encrypted;
size_t max_output_len = stringToEncrypt.length() + 16 - (stringToEncrypt.length() % 16);
//size_t max_output_len = 16 - (stringToEncrypt.length() % 16);
encrypted.resize(max_output_len);

EVP_CipherInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, iv, 1);

// EVP_CipherUpdate can encrypt all your data at once, or you can do
// small chunks at a time.
int actual_size = 0;
EVP_CipherUpdate(&ctx,
&encrypted[0], &actual_size,
reinterpret_cast<unsigned char *>(&stringToEncrypt[0]), stringToEncrypt.size());

// EVP_CipherFinal_ex is what applies the padding. If your data is
// a multiple of the block size, you'll get an extra AES block filled
// with nothing but padding.
int final_size;
EVP_CipherFinal_ex(&ctx, &encrypted[actual_size], &final_size);
actual_size += final_size;

encrypted.resize(actual_size);

for (size_t index = 0; index < encrypted.size(); ++index)
{
std::cout << std::hex << std::setw(2) << std::setfill('0') <<
static_cast<unsigned int>(encrypted[index]);
}
std::cout << "\n";

EVP_CIPHER_CTX_cleanup(&ctx);
}


Although the code runs, I get a completely different response.

For example in C++ I get
bb5ef912a40cb9f16b91b3a7fccc2bc8
whereas if I encrypt
Hello
in any of the other languages I have I get
u175EqQMufFrkbOn/MwryA==


I have linked the project to the openssl libraries

Thanks for any help you can provide.

UPDATE

I was a bit of a numpty, didn't notice the string was converted to hex and I wasn't 100% sure whether or not the openssl encryptor does the base 64 encoding or not.

So I am now trying to convert what has been encrypted into a base 64 string.

Below is the C++ encoding code that does the encoding:

string HelperMethods::base64Encode(const char* buffer, int in_len)
{
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];

while (in_len--) {
char_array_3[i++] = *(buffer++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;

for (i = 0; (i < 4); i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}

if (i)
{
for (j = i; j < 3; j++)
char_array_3[j] = '\0';

char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;

for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];

while ((i++ < 3))
ret += '=';

}

return ret;
}


When I am encrypting the string
Hello
I am expectin the base 64 encoded string to be
u175EqQMufFrkbOn/MwryA==
but when I run it in the C++ code I am getting the following:

u175EqQMufFrkbOn/MwryADNzc3Nzc3Nzc3Nzc3Nzc39/f39NjQAAA==


As you can see, I'm more a less there, except its for some reason a lot bigger than I was expecting,
NZc3
seems to keep repeating itself for some reason.

I am calling the encoder as follows from the encryption function

char * buff_str = (char*)malloc(encrypted.size() * 2 + 1);
char * buff_ptr = buff_str;


for (size_t index = 0; index < encrypted.size(); ++index)
{
buff_ptr += sprintf(buff_ptr, "%c", encrypted[index]);

}
string encryptedString = buff_str;


HelperMethods helperMethods;
string converted = helperMethods.base64Encode(encryptedString.c_str(), sizeof(encryptedString));
cout << "Converted: " << converted << endl;


Thanks

Answer

Simply: the result of the encryption is the same, they are just in different encodings. bb5ef912a40cb9f16b91b3a7fccc2bc8 is hexadecimal encoded and u175EqQMufFrkbOn/MwryA== is Base64 encoded. They are the same value.

Comments