int rsa_sign( rsa_ctx *ctx, int h_len, const uchar *hash, uchar *sig )
{
    int ret = 0;
    int nb_pad = 0, olen = 0;
    uchar *p = sig;

    /* ---------------- */
    /* init             */
    /* ---------------- */    
    olen = ctx->len;
    *p++ = 0;
    *p++ = RSA_SIGN;    

    /* ---------------- */    
    /* PKCS 1.5         */
    /* ---------------- */   
    nb_pad = olen - 3 - h_len; 

    if( nb_pad < 8 )
    {
        ret = E_RSA_BAD_INPUT_DATA;
        goto _err;
    }

    memset( p, MASK, nb_pad );
    p = p + nb_pad;
    *p++ = 0;

    /* ---------------- */
    /* RAW padding      */
    /* ---------------- */    
    memcpy( p, hash, h_len );

    /* ---------------- */
    /* private key      */
    /* ---------------- */    
    return rsa_pri( ctx, sig, sig );

_err: 

    return ret;
}
bool http_proxy_server_config::load_config(const std::string& config_data)
{
    bool rollback = true;
    std::shared_ptr<bool> auto_rollback(&rollback, [this](bool* rollback) {
        if (*rollback) {
            this->config_map.clear();
            authentication::get_instance().remove_all_users();
        }
    });

    jsonxx::Object json_obj;
    if (!json_obj.parse(config_data)) {
        std::cerr << "Failed to parse config" << std::endl;
        return false;
    }
    if (json_obj.has<jsonxx::String>("bind_address")) {
        this->config_map["bind_address"] = std::string(json_obj.get<jsonxx::String>("bind_address"));
    }
    else {
        this->config_map["bind_address"] = std::string("0.0.0.0");
    }
    if (json_obj.has<jsonxx::Number>("listen_port")) {
        this->config_map["listen_port"] = static_cast<unsigned short>(json_obj.get<jsonxx::Number>("listen_port"));
    }
    else {
        this->config_map["listen_port"] = static_cast<unsigned short>(8090);
    }
    if (!json_obj.has<jsonxx::String>("rsa_private_key")) {
        std::cerr << "Could not find \"rsa_private_key\" in config or it's value is not a string" << std::endl;
        return false;
    }
    const std::string& rsa_private_key = json_obj.get<jsonxx::String>("rsa_private_key");
    try {
        rsa rsa_pri(rsa_private_key);
        if (rsa_pri.modulus_size() < 128) {
            std::cerr << "Must use RSA keys of at least 1024 bits" << std::endl;
            return false;
        }
    }
    catch (const std::exception&) {
        std::cerr << "The value of rsa_private_key is bad" << std::endl;
        return false;
    }
    this->config_map["rsa_private_key"] = rsa_private_key;
    if (json_obj.has<jsonxx::Number>("timeout")) {
        int timeout = static_cast<int>(json_obj.get<jsonxx::Number>("timeout"));
        this->config_map["timeout"] = static_cast<unsigned int>(timeout < 30 ? 30 : timeout);
    }
    else {
        this->config_map["timeout"] = 240u;
    }
    if (json_obj.has<jsonxx::Number>("workers")) {
        int threads = static_cast<int>(json_obj.get<jsonxx::Number>("workers"));
        this->config_map["workers"] = static_cast<unsigned int>(threads < 1 ? 1 : (threads > 16 ? 16 : threads));
    }
    else {
        this->config_map["workers"] = 4u;
    }
    if (json_obj.has<jsonxx::Boolean>("auth")) {
        this->config_map["auth"] = json_obj.get<jsonxx::Boolean>("auth");
        if (!json_obj.has<jsonxx::Array>("users")) {
            std::cerr << "Could not find \"users\" in config or it's value is not a array" << std::endl;
            return false;
        }
        const jsonxx::Array& users_array = json_obj.get<jsonxx::Array>("users");
        for (size_t i = 0; i < users_array.size(); ++i) {
            if (!users_array.has<jsonxx::Object>(i) || !users_array.get<jsonxx::Object>(i).has<jsonxx::String>("username") || !users_array.get<jsonxx::Object>(i).has<jsonxx::String>("username")) {
                std::cerr << "The value of \"users\" contains unexpected element" << std::endl;
                return false;
            }
            authentication::get_instance().add_user(users_array.get<jsonxx::Object>(i).get<jsonxx::String>("username"),
                users_array.get<jsonxx::Object>(i).get<jsonxx::String>("password"));
        }
    }
    else {
        this->config_map["auth"] = false;
    }

    rollback = false;
    return true;
}