Klien https dapatkan dengan cpp-netlib menggunakan sertifikat dan kata sandi klien

Saya mencoba menggunakan cppnetlib, atau bahkan perpustakaan asio boost untuk terhubung untuk melakukan pengambilan url sederhana dan menarik halaman yang dihasilkan ke bawah.

Saya telah membuatnya berfungsi dengan http, dan bahkan https menggunakan cppnetlib tetapi saya perlu memberikan sertifikat klien yang memerlukan kata sandi.. Sayangnya saya harus menggunakan cppnetlib v0.10 yang lebih lama.

Apakah ini mungkin dilakukan. Saya pikir jawabannya adalah membuat _io_service saya sendiri dan mengkonfigurasinya secara khusus untuk permintaan https dengan sertifikat dan kata sandi dan kemudian menyediakannya ke konstruktor boost::network::http:client. Di bawah ini berfungsi di http, dan akan berfungsi untuk https tanpa persyaratan sertifikat.

std::string url = "http://www.boost.org";
std::string certFile = "C:\\cert\\mycert.p12";
std::string password = "MyPassWord";
try {
        http::client client;
        http::client::request request(url);
        http::client::response response = client->get(request);

        std::string resultText = static_cast<std::string>(body(response));
        std::cout << resultText << std::endl;
        delete client;
    }
    catch (std::exception &e) {
        std::cerr << "Caught something connecting " << e.what() << std::endl;
    }

person Jim    schedule 23.03.2017    source sumber
comment
Saya juga akan menggunakan asio secara langsung untuk get https yang menggunakan file p12 dan kata sandi sebagai sertifikat klien   -  person Jim    schedule 28.03.2017
comment
Ternyata tidak bisa dilakukan dengan cppnetlib v0.10, saya akan menerima solusi menggunakan file PEM standar menggunakan asio dari boost 1.49   -  person Jim    schedule 30.03.2017


Jawaban (1)


v0.10 cppnetlib tidak secara langsung mendukung sertifikasi klien. Karena Anda menggunakan cppnetleb, Anda dapat menggunakan boost asio dengan boost 1.49

Berikut adalah contoh kode yang melakukan sebagian besar pekerjaan asio https://github.com/alexandruc/SimpleHttpsClient/blob/master/https_client.cpp

Kode itu sangat mirip dengan http://www.boost.org/doc/libs/1_49_0/doc/html/boost_asio/example/ssl/client.cpp

Saya menempatkan keduanya jika tautannya putus. Itu menangani koneksi https untuk melakukan sertifikasi klien, Anda perlu menambahkan baris berikut ke fungsi utama sebelum membuat klien:

        std::string tempString = "test.pem"; //this is a pem file that contains a private key and a certificate. 

        boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23_client);
        ctx.set_options(boost::asio::ssl::context::default_workarounds
                                    | boost::asio::ssl::context::no_sslv2
                                    | boost::asio::ssl::context::no_sslv3);
        ctx.set_default_verify_paths();

        ctx.use_certificate_file(tempFileStr.c_str(), boost::asio::ssl::context_base::pem);
        ctx.use_private_key_file(tempFileStr.c_str(), boost::asio::ssl::context_base::pem);

Namun dalam contoh ini Anda tidak memiliki file PEM melainkan file p12, (format pkcs12). openssl dapat digunakan untuk mendekripsi dan membuat file pem yang diinginkan. Saya mengadaptasi kode di bawah ini dari Cara memuat file PKCS#12 di OpenSSL secara terprogram? Sayangnya versi boost ini tidak mendukung sertifikat di memori sehingga harus ditulis, dienkripsi ke file. Saya meletakkan ini di direktori sementara, dan mungkin pada akhirnya akan dihapus.

std::string _certFile = "C:\\cert\\mycert.p12";
std::string password = "_certPassword";
boost::filesystem::path tempFile = boost::filesystem::temp_directory_path() / "temp.pem";
std::string tempFileStr = tempFile.generic_string();
std::cout<<"Using temp file " << tempFileStr<<std::endl;
try
    {

        //read in the pksc12 file, decode it and write a PEM file
        FILE *fp;
        EVP_PKEY *pkey;
        X509 *cert;
        STACK_OF(X509) *ca = NULL;
        PKCS12 *p12;
        int i;

        OpenSSL_add_all_algorithms();
        ERR_load_crypto_strings();
        if (!(fp = fopen(_certFile.c_str(), "rb"))) {
            fprintf(stderr, "Error opening file %s\n", _certFile);
            return false;       
        }
        p12 = d2i_PKCS12_fp(fp, NULL);
        fclose (fp);
        if (!p12) {
            fprintf(stderr, "Error reading PKCS#12 file\n");
            ERR_print_errors_fp(stderr);
            return false; 
        }
        if (!PKCS12_parse(p12, _certpPassword.c_str(), &pkey, &cert, &ca)) {
            fprintf(stderr, "Error parsing PKCS#12 file\n");
            ERR_print_errors_fp(stderr);
            return false; 

        }
        PKCS12_free(p12);
        if (!(fp = fopen(tempFileStr.c_str(), "w"))) {
            fprintf(stderr, "Error opening file %s\n", tempFileStr.c_str());
            return false; 
        }

        if (pkey) {
            fprintf(fp, "***Private Key***\n");
            PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL);
        }
        if (cert) {
            fprintf(fp, "***User Certificate***\n");
            PEM_write_X509(fp, cert);
        }
        if (ca && sk_X509_num(ca)) {
            fprintf(fp, "***Other Certificates***\n");

            for (i = 0; i < sk_X509_num(ca); i++) 
            {
                PEM_write_X509(fp, sk_X509_value(ca, i));
            }

        }

        sk_X509_pop_free(ca, X509_free);
        X509_free(cert);
        EVP_PKEY_free(pkey);    
        fclose(fp);

    }
    catch (std::exception &e) {
        retVal = false;
        std::cout <<"Error parsing/decrypting pkcs12 file into PEM or writing temporary pem file" << e.what() << std::endl;        
    }

Berikut adalah penyertaan yang saya gunakan

//for ssl connection
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/asio/ssl/context_base.hpp>

//for parsing key file
#include <openssl/pkcs12.h>
person Jim    schedule 03.04.2017