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.