create a c++ openssl function that can decrypt the data that have been encrypted with this function

it will need to try multiple times by removing the prependstr and guessing the possible password and salt sizes


/*
	The password and salt is generated inside the function with a random size of 3, 6, or 9.
	
    The encrypted data is returned as:
    [prependStr][password][salt][data]
	prependStr:         random string with length between 6 and 11.
    password:   as base64 => when decoding the password:  must be decoded from base64
	salt:       as base64 => when decoding the salt:      is used AS base64
*/
inline bool weakEncrypt2(QByteArray& data)
{  
    VMSTART // VM_C205_M

    if (data.isEmpty())
        return false;

    // Generate the password
    unsigned char random_byte;
    RAND_bytes(&random_byte, 1);
    int passwordSize = 3 + (random_byte % 3) * 3; // Random size of 3, 6, or 9.
    std::vector<unsigned char> password(passwordSize);
    RAND_bytes(password.data(), passwordSize);
    
	// Encode the password as base64
    BIO* bio = BIO_push(BIO_new(BIO_f_base64()), BIO_new(BIO_s_mem()));    
    BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
    BIO_write(bio, password.data(), passwordSize);    
    BUF_MEM* bptr;
    BIO_get_mem_ptr(bio, &bptr);
    std::vector<unsigned char> b64Password(bptr->length);
    memcpy(b64Password.data(), bptr->data, bptr->length);    
    OPENSSL_cleanse(bptr->data, bptr->length);
    OPENSSL_cleanse(bptr, sizeof(*bptr));
    BIO_free_all(bio);

	// Generate a random salt  
    RAND_bytes(&random_byte, 1);
    int saltSize = 3 + (random_byte % 3) * 3; // Random size of 3, 6, or 9.
    std::vector<unsigned char> salt(saltSize);
    RAND_bytes(salt.data(), saltSize);

	// Encode the salt as base64
	bio = BIO_push(BIO_new(BIO_f_base64()), BIO_new(BIO_s_mem()));
	BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
	BIO_write(bio, salt.data(), saltSize);
	BIO_get_mem_ptr(bio, &bptr);
	std::vector<unsigned char> b64Salt(bptr->length);
	memcpy(b64Salt.data(), bptr->data, bptr->length);	
	OPENSSL_cleanse(salt.data(), saltSize);
    OPENSSL_cleanse(bptr->data, bptr->length);
	OPENSSL_cleanse(bptr, sizeof(*bptr));
	BIO_free_all(bio);

	// SHA256 the salt and password
	int b64SaltSize = b64Salt.size();
    unsigned char keyHash[SHA256_DIGEST_LENGTH];
    unsigned char ivHash[SHA256_DIGEST_LENGTH];
    SHA256(password.data(), passwordSize, keyHash);
    SHA256(b64Salt.data(),  b64SaltSize,  ivHash);

    OPENSSL_cleanse(password.data(), passwordSize);

    std::vector<unsigned char> hashedKey(16);
    std::vector<unsigned char> hashedIv(16);

    bio = BIO_push(BIO_new(BIO_f_base64()), BIO_new(BIO_s_mem()));    
    BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
    if (BIO_write(bio, keyHash, SHA256_DIGEST_LENGTH) != SHA256_DIGEST_LENGTH ||
        BIO_flush(bio) != 1) 
    {
        BIO_free_all(bio);
        return false;
    }

    BIO_get_mem_ptr(bio, &bptr);
    std::memcpy(hashedKey.data(), bptr->data, 16);

    BIO_reset(bio);
    if (BIO_write(bio, ivHash, SHA256_DIGEST_LENGTH) != SHA256_DIGEST_LENGTH ||
        BIO_flush(bio) != 1)
    {
        BIO_free_all(bio);
        return false;
    }

    BIO_get_mem_ptr(bio, &bptr);
    std::memcpy(hashedIv.data(), bptr->data, 16);

    BIO_free_all(bio);

    OPENSSL_cleanse(keyHash, sizeof(keyHash));
    OPENSSL_cleanse(ivHash, sizeof(ivHash));

    std::vector<unsigned char> cipherBuf(data.size() + EVP_MAX_BLOCK_LENGTH);
    const EVP_CIPHER* cipherType = EVP_aes_128_cbc();
    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    
    if (!ctx)
        return false;

    if (EVP_EncryptInit_ex(ctx, cipherType, NULL, hashedKey.data(), hashedIv.data()) != 1) 
    {
		OPENSSL_cleanse(data.data(), data.size());
        data.clear();
        EVP_CIPHER_CTX_free(ctx);
        return false;
    }

    OPENSSL_cleanse(hashedKey.data(), hashedKey.size());
    OPENSSL_cleanse(hashedIv.data(), hashedIv.size());

    int outLength1 = 0;
    if (EVP_EncryptUpdate(ctx, cipherBuf.data(), &outLength1, 
                          reinterpret_cast<unsigned char*>(data.data()), data.size()) != 1)
    {
        OPENSSL_cleanse(data.data(), data.size());
        data.clear();
        EVP_CIPHER_CTX_free(ctx);
        return false;
    }

    int outLength2 = 0;
    if (EVP_EncryptFinal_ex(ctx, cipherBuf.data() + outLength1, &outLength2) != 1)
    {
        OPENSSL_cleanse(data.data(), data.size());
        data.clear();
        EVP_CIPHER_CTX_free(ctx);
        return false;
    }

    EVP_CIPHER_CTX_free(ctx);

    // Base64 encode the result
    BIO* b64_encode = BIO_new(BIO_f_base64());
    BIO* mem        = BIO_new(BIO_s_mem());
    BIO_push(b64_encode, mem);
    BIO_set_flags(b64_encode, BIO_FLAGS_BASE64_NO_NL);

    // Generate random string to prepend
    unsigned char randomByte;
    RAND_bytes(&randomByte, 1);
    int prependStrSize = 6 + (randomByte % 6); // Random size between 6 and 11
    std::vector<unsigned char> prependStr(prependStrSize);
    RAND_bytes(prependStr.data(), prependStrSize);
	BIO_write(b64_encode, prependStr.data(), prependStrSize);

	OPENSSL_cleanse(prependStr.data(), prependStr.size());

    // Write the password
	BIO_write(b64_encode, b64Password.data(), b64Password.size());
    OPENSSL_cleanse(b64Password.data(),       b64Password.size());

    // Write the salt
    BIO_write(b64_encode, b64Salt.data(), b64SaltSize);
    OPENSSL_cleanse(b64Salt.data(),       b64SaltSize);

    // Write the ciphertext
    BIO_write(b64_encode, cipherBuf.data(), outLength1 + outLength2);
    BIO_flush(b64_encode);
    BUF_MEM* bptr_result;
    BIO_get_mem_ptr(mem, &bptr_result);
    
    OPENSSL_cleanse(cipherBuf.data(), cipherBuf.size());
    OPENSSL_cleanse(data.data(), data.size());

    data = QByteArray(bptr_result->data, bptr_result->length);

    OPENSSL_cleanse(bptr_result->data, bptr_result->length);
    BIO_free_all(b64_encode); 

    VMEND // VM_C205_M

    return true;
}