Что такое boost :: asio :: ssl :: context :: load_verify_file и как с ним работать? - PullRequest
7 голосов
/ 06 сентября 2011

Theare - небольшое количество повышения :: asio :: ssl небольшая база образовательных кодов C ++ онлайн.Еще меньше на boost :: asio :: ssl :: context :: load_verify_file Так что я нашел один из здесь кода с минимальными изменениями - компилируется и запускается с boost 1.47.0:

#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <istream>
#include <ostream>
#include <string>


class client
{
public:
    client(boost::asio::io_service& io_service, boost::asio::ssl::context& context, boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
        : socket_(io_service, context)
    {
        socket_.set_verify_mode(boost::asio::ssl::context::verify_none);
        socket_.set_verify_callback(boost::bind(&client::verify_certificate, this, _1, _2));

        boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator, boost::bind(&client::handle_connect, this, boost::asio::placeholders::error));
    }

    bool verify_certificate(bool preverified, boost::asio::ssl::verify_context& ctx)
    {
        char subject_name[256];
        X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
        X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
        std::cout << "Verifying:\n" << subject_name << std::endl;

        return preverified;
    }

    void handle_connect(const boost::system::error_code& error)
    {
        if(!error){
            std::cout << "Connection OK!" << std::endl;
            socket_.async_handshake(boost::asio::ssl::stream_base::client, boost::bind(&client::handle_handshake, this, boost::asio::placeholders::error));
        }else{
            std::cout << "Connect failed: " << error.message() << std::endl;
        }
    }

    void handle_handshake(const boost::system::error_code& error)
    {
        if(!error){
            std::cout << "Sending request: " << std::endl;

            std::stringstream request_;

            request_ << "GET /api/0/data/ticker.php HTTP/1.1\r\n";
            request_ << "Host: mtgox.com\r\n";
            request_ << "Accept-Encoding: *\r\n";
            request_ << "\r\n";

            std::cout << request_.str() << std::endl;

            boost::asio::async_write(socket_, boost::asio::buffer(request_.str()), boost::bind(&client::handle_write, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
        }else{
            std::cout << "Handshake failed: " << error.message() << std::endl;
        }
    }

    void handle_write(const boost::system::error_code& error, size_t bytes_transferred)
    {
        if (!error){
            std::cout << "Sending request OK!" << std::endl;
            boost::asio::async_read(socket_, boost::asio::buffer(reply_, bytes_transferred), boost::bind(&client::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
        }else{
            std::cout << "Write failed: " << error.message() << std::endl;
        }
    }

    void handle_read(const boost::system::error_code& error, size_t bytes_transferred)
    {
        if (!error){
            std::cout << "Reply: ";
            std::cout.write(reply_, bytes_transferred);
            std::cout << "\n";
        }else{
            std::cout << "Read failed: " << error.message() << std::endl;
        }
    }

private:
    boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
    char reply_[0x1 << 16];
};

int main(int argc, char* argv[])
{
    try{
        boost::asio::io_service io_service;

        boost::asio::ip::tcp::resolver resolver(io_service);
        boost::asio::ip::tcp::resolver::query query("mtgox.com", "443");
        boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);

        boost::asio::ssl::context context(boost::asio::ssl::context::sslv23);
        //context.load_verify_file("key.pem"); // uncomment this line

        client c(io_service, context, iterator);

        io_service.run();
    }catch (std::exception& e){
        std::cerr << "Exception: " << e.what() << "\n";
    }

    std::cin.get();
    return 0;
}

Вот одна действительно любопытная строка: context.load_verify_file("key.pem"); Итак, у меня есть несколько вопросов по этому поводу:

  1. Что это значит для меня как http-клиента?
  2. Отправляется ли он на сервер?
  3. Как создать такой файл?
  4. Для чего он вообще нужен?
  5. Код компилируется и работает без него.Это нормально?Безопасно ли наше соединение с сервером, если key.pem?
  6. Я хочу использовать Google или другой большой хост ssl.Что мне делать?

1 Ответ

6 голосов
/ 06 сентября 2011

Проще говоря:

Файл .pem может содержать сертификат (открытый ключ), либо закрытый ключ, либо их комбинацию.PEM - это способ кодирования данных, а сертифицированные X509 обычно используются с PEM.Например, сервер читает файл .pem и отправляет сертификат клиенту, чтобы клиент мог проверить его перед подключением.

Сервер с самозаверяющим сертификатом выдает предупреждение в современных браузерах, в котором говорится, что этоне является доверенным (если только он не подписан CA , а браузеры имеют базу данных подписанных CA, которую они используют для проверки того, является ли сертификат «действительным» или нет), и вы можете проверить детали сертификата и решить,Вы хотите доверять этому сайту или нет.Хорошим примером является ссылка IETF.org , поскольку срок действия их сертификата истек не так давно:)

  1. Как клиент, это может что-то значить, но это не такнужно, если вам это не нужно.То есть, если сервер отправляет сертификат, ваш клиент может захочет проверить его, прежде чем продолжить, и в этом случае вам понадобится информация от CA, подписавшего сертификат сервера, который можно загрузить изФайл .pem, содержащий информацию CA.Если ваш клиент не заботится о проверке, тогда он не нуждается в этом.

    В основном функция load_verify_file() загружает информацию CA для проверки сертификата, отправленного сервером.

    Вы можете создать свой собственный файл CA и подписать собственный сертификат сервера, а затем использовать свой собственный файл CA с клиентом, чтобы убедиться, что вы подключаетесь к своему собственному серверу.

  2. читать 1. Нет, клиент не отправляет его.

  3. Если вы хотите узнать больше, вот руководство прямо из duckduckgo.

  4. Прочитайте 3 и начало этого сообщения.

  5. Если клиент принимает сертификат сервера просто отлично и не отклоняет его, так как он не можетпроверьте это, тогда все в порядке.Легко проверить, включить только ssl-подключение к / с сервера и посмотреть, будет ли клиент подключаться и выполнять работу, которую он должен, или просто анализировать трафик и искать его.

  6. Не уверенчто ты имеешь ввиду там.Покупаете хост SSL?Если это так, проблема все еще будет с вашим клиентом, если он хочет принять соединение или нет.

...