0

I'm implementing encrypt/decrypt code with c++/c# I referred to this post and referred to answers.z`

But c++/c# encrypted code was not matched.

Here are my codes.

C++

// base64 encode part
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";


static inline bool is_base64(BYTE c) {
    return (isalnum(c) || (c == '+') || (c == '/'));
}

std::string base64_encode(BYTE const* buf, unsigned int bufLen) {
    std::string ret;
    int i = 0;
    int j = 0;
    BYTE char_array_3[3];
    BYTE char_array_4[4];

    while (bufLen--) {
        char_array_3[i++] = *(buf++);
        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;
}

//start encrypt
std::string key = "01286567891233460123456789a12345";
std::string iv = "0123456789123456";
std::string encrypt(const std::string& str_in)
{
    std::string str_out;
    std::string str_out2;

    byte* keybyte = (byte*)key.c_str();
    
    CryptoPP::AES::Encryption aesEncryption((byte*)key.c_str(), CryptoPP::AES::MAX_KEYLENGTH);
    CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, (byte*)iv.c_str());

    StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(str_out));
    stfEncryptor.Put(reinterpret_cast<const unsigned char*>(str_in.c_str()), str_in.length() + 1);
    stfEncryptor.MessageEnd();

    str_out2 = base64_encode(reinterpret_cast<const unsigned char*>(str_out.c_str()), strlen(str_out.c_str()));

    return str_out2;
}
std::string decrypt(const std::string& cipher_text)
{
    std::string str_out;
//need to insert code of decrypt base64
    CryptoPP::AES::Decryption aesDecryption((byte*)key.c_str(), CryptoPP::AES::MAX_KEYLENGTH);
    CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, (byte*)iv.c_str());

    CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(str_out));
    stfDecryptor.Put(reinterpret_cast<const unsigned char*>(cipher_text.c_str()), cipher_text.size());
    stfDecryptor.MessageEnd();

    return str_out;
}

c#

public string Encrypt(string testCode)
{
    string clearText = testCode;
    byte[] clearBytes = Encoding.Default.GetBytes(clearText);

    using (Aes encryptor = Aes.Create("AES"))
    {
        //encryptor.BlockSize = 128;
        encryptor.Padding = PaddingMode.Zeros;
        encryptor.KeySize = 128;
        encryptor.Mode = CipherMode.CBC;
        encryptor.Key = Encoding.Default.GetBytes("01286567891233460123456789a12345");
        encryptor.IV = Encoding.Default.GetBytes("0123456789123456");
        using (MemoryStream ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
            {
                cs.Write(clearBytes, 0, clearBytes.Length);
                cs.Close();
            }
            byte[] bt = ms.ToArray();
            clearText = Convert.ToBase64String(bt); //clearText = Encoding.Default.GetString(bt); 
        }
    }
    return clearText; //Return the encrypted command
}

public string Decrypt(string cipherText)
{
    byte[] clearBytes = Convert.FromBase64String(cipherText);

    using (Aes decryptor = Aes.Create("AES"))
    {
        // decryptor.BlockSize = 128;
        decryptor.Padding = PaddingMode.Zeros;
        decryptor.KeySize = 128;
        decryptor.Mode = CipherMode.CBC;
        decryptor.Key = Encoding.Default.GetBytes("01286567891233460123456789a12345");
        decryptor.IV = Encoding.Default.GetBytes("0123456789123456");
        using (MemoryStream ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, decryptor.CreateDecryptor(), CryptoStreamMode.Write))
            {
                cs.Write(clearBytes, 0, clearBytes.Length);
                cs.Close();
            }
            byte[] bt = ms.ToArray();
            cipherText = Encoding.Default.GetString(bt);
        }
    }

    return cipherText; //Return the decrypted text
}

c++ result

encrypted code : ks8zzu20w6zURkuZMgbx8g==
decrypted code : test

c# result

encrypted code : nsWRYBylyjVaJ5Yckk+SRw==
decrypted code : test

I tested with test word both of C++/C# however encrypted code was not matched.

Also, I tested after remove base64 encode code but pure encrypted code was not matched as well.

Could anyone please share your knowledge?

EDIT1

I tried to copy encrypted code by c++ and pasted to c# decrypt code like below

string testcode = "ks8zzu20w6zURkuZMgbx8g=="
Decrypt(testcode)

//result - test↗↗↗↗↗

As you can see, the results look very similar, but there is something weird. This symbol is added after the word test. I could not found out why result like this. Is there something I missed?

Solved

std::string encrypt(const std::string& str_in)
{
    std::string str_out;
    std::string str_out2;

    byte* keybyte = (byte*)key.c_str();
    
    CryptoPP::AES::Encryption aesEncryption((byte*)key.c_str(), CryptoPP::AES::MAX_KEYLENGTH);
    CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, (byte*)iv.c_str());

    StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(str_out));
// 'str_in.length() + 1' in the line below makes the encryption code different from c# code.
    /*stfEncryptor.Put(reinterpret_cast<const unsigned char*>(str_in.c_str()), str_in.length() + 1);*/
    stfEncryptor.Put(reinterpret_cast<const unsigned char*>(str_in.c_str()), str_in.length());
    stfEncryptor.MessageEnd();
    str_out2 = cryptobase64_encode(str_out);
    
    return str_out2;
}

As I commented, str_in.length() + 1 makes the encrypted code different from C# code.

And I changed C# padding options from Zeros to PKCS7 for matching c++ encrypted code. But I don't know why I need to set this option. I think I need to study this. Anyway, It works well. Special thanks to @jdweng.

takeyourcode
  • 375
  • 4
  • 17
  • 2
    Try changing the padding mode in c# – jdweng Jun 08 '21 at 03:00
  • Very similar questions have been asked here many times over the years. Have you searched for one? – Eric J. Jun 08 '21 at 03:13
  • @jdweng Thank you for your answer. I tried it but all options showed different results – takeyourcode Jun 08 '21 at 04:07
  • @EricJ. Sure, I found similar things and applied to my code. I think that the code I posted is simplest code I've ever seen, so I applied it my code and tried to running it. But I didn't get the same result when I encrypt in c++/c#. – takeyourcode Jun 08 '21 at 04:13
  • @jdweng Thank you! I missed that I only tried change padding mode in `encrypt` function.. I've changed padding mode in `decrypt` function as well, and it work perfectly! – takeyourcode Jun 08 '21 at 04:42
  • maybe this can be moved to Code Review on StackExchange - how to flag question for this? – ivan.ukr Jun 08 '21 at 06:29
  • No @ivan.ukr, broken code is [not ready for review](//codereview.stackexchange.com/help/dont-ask) until it's fixed. – Toby Speight Jun 08 '21 at 07:39

0 Answers0