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;
}
