I'm trying to make implementation of python AES data decrypting function using c++ openssl. Is it possible? If so, what I'm doing wrong?
python code:
def decrypt(data, key):
# data will be in hexadecimal representation of binary
try:
print(data)
#b'v10|\x80K\x11$\xbf\x8b\xc7\x8bOz\xafc\[some_data]de\x172\xdf\xe8k]\r\xcfm\xf9\x95\xdac'
# length is 121
iv = data[3:15]
data= data[15:]
aes = AES.new(encryption_key, AES.MODE_GCM, iv)
return aes.decrypt(data)[:-16].decode()
except:
print('err')
How c++ code should work in my opinion:
- First get key in raw format (main()): key: eRx×LŘé7R¬[some_key]ReÜüś˘o,
- Get data for decrypt() (main()): v10|ÇK$┐őăő[data]»c╚Á╔ßЧ│Ů2▀Ŕk]
- Convert it to hexadecimal representation of binary to perform substr(), (other way substr() won't work the same way as in python code). This will be the converted data: v10|\x80K\x11$\xbf\x8b\xc7\x8bOz\xafc\x04[some_data]\xb5\xc9\xe1\xd1\xf5\xb3\xde\x172\xdf\xe8k]\r\xcfm\xf9\x95\xdac
- Then perform substr() to extract iv and e_data from the string.
- Then convert it back, so that we get raw binary data, which is necessary for final decryption
- Perform decryption
I tried the code below in various modifications (including completelyt not using function with converting), but it keeps returning "ERR: FINAL". Why?
c++ code:
#include <iostream>
#include <fstream>
#include <string>
#include <windows.h>
#include <wincrypt.h>
#include <openssl/evp.h>
#include <sstream>
#include <iomanip>
#include <regex>
std::string convert(const std::string& input) {
std::ostringstream oss;
for (char ch : input) {
if (ch >= 32 && ch <= 126) {
oss << ch;
} else if (ch == '\r') {
oss << "\\r";
} else {
oss << "\\x" << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(static_cast<unsigned char>(ch));
}
}
return oss.str();
}
std::string frm(const std::string& pybyte) {
std::string result;
for (size_t i = 0; i < pybyte.size(); ++i) {
if (pybyte[i] == '\\' && i + 1 < pybyte.size() && pybyte[i + 1] == 'x') {
std::string hexValue = pybyte.substr(i + 2, 2);
char ch = static_cast<char>(std::stoi(hexValue, nullptr, 16));
result += ch;
i += 3;
} else {
result += pybyte[i];
}
}
return result;
}
std::string rev(const std::string& pybyte) {
std::ostringstream oss;
std::string formed = frm(pybyte);
for (char ch : formed) {
oss << ch;
}
return oss.str();
}
std::string decrypt(const std::string& data, const std::string& key) {
try {
std::string cvdat = convert(data);
std::cout << "encrypted: " << data << std::endl;
std::cout << "encrypted_conv: " << cvdat << std::endl;
std::cout << "encrypted_reconv: " << rev(cvdat) << std::endl;
std::string iv = cvdat.substr(3, 33);
std::string e_data = cvdat.substr(36);
std::cout << "iv: " << iv << std::endl;
std::cout << "edata: " << e_data << std::endl;
iv = rev(iv);
e_data = rev(e_data);
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
if (!ctx) {
std::cout << "ERR: CTX";
return "";
}
if (EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), nullptr, nullptr, nullptr) != 1) {
std::cout << "ERR: INIT SET";
EVP_CIPHER_CTX_free(ctx);
return "";
}
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size(), nullptr) != 1) {
std::cout << "ERR: IVLEN";
EVP_CIPHER_CTX_free(ctx);
return "";
}
if (EVP_DecryptInit_ex(ctx, nullptr, nullptr, reinterpret_cast<const unsigned char*>(key.c_str()), reinterpret_cast<const unsigned char*>(iv.c_str())) != 1) {
std::cout << "ERR: KEY, IV" << std::endl;
EVP_CIPHER_CTX_free(ctx);
return "";
}
std::string decryptedtext(e_data.size(), '\0');
int decryptedtext_len = 0;
if (EVP_DecryptUpdate(ctx, reinterpret_cast<unsigned char*>(&decryptedtext[0]), &decryptedtext_len, reinterpret_cast<const unsigned char*>(e_data.c_str()), e_data.size()) != 1) {
std::cout << "ERR: UPDATE";
EVP_CIPHER_CTX_free(ctx);
return "";
}
int final_len = 0;
if (EVP_DecryptFinal_ex(ctx, reinterpret_cast<unsigned char*>(&decryptedtext[decryptedtext_len]), &final_len) != 1) {
std::cout << "ERR: FINAL";
EVP_CIPHER_CTX_free(ctx);
return "";
}
EVP_CIPHER_CTX_free(ctx);
decryptedtext_len += final_len;
decryptedtext.resize(decryptedtext_len);
return decryptedtext;
} catch (...) {
std::cout << "ERR";
return "";
}
}
int main() {
std::string data = "v10|ÇK$┐őă[data]┌6ńW╚Á╔ßЧ│Ů2▀Ŕk]";
std::string key = "eRx×LŘé7R¬[some_key]ReÜüś˘o,";
res = decrypt(data, key);
std::cout << res;
return 0;
}