【问题标题】:What is boost::asio::ssl::context::load_verify_file and how to work with it?什么是 boost::asio::ssl::context::load_verify_file 以及如何使用它?
【发布时间】:2011-09-06 18:26:55
【问题描述】:

这里有少量的 boost::asio::ssl 在线小型 C++ 教育代码库。在boost::asio::ssl::context::load_verify_file 上甚至更少所以我从here 代码中找到了一个修改最少的代码 - 使用 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 主机。我该怎么办?

【问题讨论】:

    标签: c++ boost ssl https boost-asio


    【解决方案1】:

    简单来说:

    .pem 文件可以包含证书(公钥)或私钥,或两者的组合。 PEM 是一种对数据进行编码的方式,X509 认证通常与 PEM 一起使用。例如,服务器读取 .pem 文件并将证书发送给客户端,以便客户端可以在连接之前对其进行验证。

    具有自签名证书的服务器会在当今的浏览器上弹出一条警告,指出它不受信任(除非由 CA 签名,并且浏览器有一个签名 CA 的数据库,他们使用该数据库来验证证书是否是否“有效”),您可以检查证书详细信息并决定是否要信任该站点。一个很好的例子是 IETF.org 链接,因为他们的证书不久前过期:)

    1. 作为客户,它可能意味着什么,但除非你需要它,否则它并不需要。也就是说,如果服务器发送证书,您的客户端可能想要在继续​​之前对其进行验证,在这种情况下,您需要来自签署服务器证书的 CA 的信息,这些信息可以加载来自包含 CA 信息的 .pem 文件。如果您的客户不关心验证,那么它就不需要它。

      基本上load_verify_file() 函数会加载 CA 信息,以便对服务器发送的证书进行验证。

      您可以创建自己的 CA 文件并签署自己的服务器证书,然后将您自己的 CA 文件用于客户端,以验证您是否连接到自己的服务器。

    2. 读取1.不,客户端不发送。

    3. 如果你想了解更多,这里是直接来自 duckduckgo 的guide

    4. 阅读 3 和这篇文章的开头。

    5. 如果客户端接受服务器证书就好了并且没有拒绝它,因为它无法验证它,那么它很好。易于检查,仅启用与服务器的 ssl 连接,并查看客户端是否会连接并执行它应该执行的工作,或者只是嗅探流量并进行查找。

    6. 不确定你的意思。购买ssl主机?如果是这样,问题仍然存在于您的客户端是否要接受连接。

    【讨论】:

    • Grate!)顺便说一句,是否有任何开放和免费的 key.pem 密钥集合?
    • (就像一个谷歌浏览器可能会使用?)
    • 从未使用过完整的集合。由于我使用的是 firefox,因此在选项中有一个选项可以导出当前受信任的 CA。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 2015-03-13
    • 2013-10-25
    • 2014-11-19
    • 1970-01-01
    相关资源
    最近更新 更多