ไคลเอ็นต์ https รับ cpp-netlib โดยใช้ใบรับรองไคลเอ็นต์และรหัสผ่าน

ฉันกำลังพยายามใช้ cppnetlib หรือแม้แต่ boost asio libraries เพื่อเชื่อมต่อเพื่อรับ url แบบง่าย ๆ และดึงหน้าผลลัพธ์ลง

ฉันทำให้มันใช้งานได้กับ http และแม้แต่ https usign cppnetlib แต่ฉันต้องระบุใบรับรองไคลเอนต์ที่ใช้รหัสผ่าน .. บังเอิญฉันจำเป็นต้องใช้ cppnetlib v0.10 รุ่นเก่ากว่า

เป็นไปได้ไหมที่จะทำ. ฉันคิดว่าคำตอบคือสร้าง _io_service ของตัวเองและกำหนดค่าเองสำหรับคำขอ https ด้วยใบรับรองและรหัสผ่าน จากนั้นจัดหาสิ่งนั้นให้กับตัวสร้าง boost::network::http:client ข้อมูลด้านล่างนี้ใช้ได้กับ http และจะใช้ได้กับ https โดยไม่ต้องมีใบรับรอง

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 แหล่งที่มา
comment
ฉันจะยกเว้นการใช้ asio โดยตรงเพื่อรับ https ที่ใช้ไฟล์ p12 และรหัสผ่านเป็นใบรับรองไคลเอ็นต์   -  person Jim    schedule 28.03.2017
comment
ปรากฎว่าไม่สามารถทำได้ด้วย cppnetlib v0.10 ฉันจะยอมรับวิธีแก้ปัญหาโดยใช้ไฟล์ PEM มาตรฐานโดยใช้ asio จากการเพิ่ม 1.49   -  person Jim    schedule 30.03.2017


คำตอบ (1)


v0.10 cppnetlib ไม่รองรับการรับรองไคลเอ็นต์โดยตรง เนื่องจากคุณใช้ cppnetleb คุณสามารถใช้ boost asio พร้อม boost 1.49 ได้

นี่คือโค้ดตัวอย่างที่ ASIO ส่วนใหญ่ใช้งานได้ https://github.com/alexandruc/SimpleHttpsClient/blob/master/https_client.cpp

โค้ดนั้นคล้ายกับ http://www.boost.org/doc/libs/1_49_0/doc/html/boost_asio/example/ssl/client.cpp

ฉันกำลังใส่ทั้งสองอย่างในกรณีที่ลิงก์เสียหาย ที่จัดการการเชื่อมต่อ https เพื่อทำการรับรองไคลเอนต์ คุณต้องเพิ่มบรรทัดต่อไปนี้ในฟังก์ชันหลักก่อนที่จะสร้างไคลเอนต์:

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

อย่างไรก็ตาม ในตัวอย่างนี้ คุณไม่มีไฟล์ PEM แต่เป็นไฟล์ p12 (รูปแบบ pkcs12) openssl สามารถใช้เพื่อถอดรหัสและสร้างไฟล์ pem ที่ถูก deisred ฉันดัดแปลงโค้ดด้านล่างจาก วิธีโหลดไฟล์ PKCS#12 ใน OpenSSL โดยทางโปรแกรมใช่ไหม น่าเสียดายที่การบูสต์เวอร์ชันนี้ไม่รองรับใบรับรองในหน่วยความจำ ดังนั้นจึงจำเป็นต้องเขียนและถอดรหัสลงในไฟล์ ฉันใส่สิ่งนี้ลงใน temp dir และน่าจะถูกลบทิ้งในตอนท้าย

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

นี่คือสิ่งที่ฉันใช้

//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