草庐IT

c++ - Boost Asio HTTPS 请求给出 'certificate verify failed' 错误

coder 2024-02-09 原文

我正在尝试使用 C++ 应用程序中的 Boost.Asio 通过 HTTPS 连接读取数据。我正在解决一个类似的 SO 问题 ( HTTPS request with Boost.Asio and OpenSSL ),但我仍然收到“证书验证失败”错误。

我稍微更新了代码 - 使用 Google 代替,因为 www.mtgox.com 网站已经更改并且给我浏览器关于自签名证书的警告。我想 Google 的证书链不会有这些问题。

我已经下载了颁发者证书并从命令行确认它工作正常:

openssl s_client -showcerts  -CApath ./certs -connect google.com:443

给我:

CONNECTED(00000003)
depth=2 C = US, O = Equifax, OU = Equifax Secure Certificate Authority
verify return:1
depth=1 C = US, O = Google Inc, CN = Google Internet Authority
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google Inc, CN = *.google.com
verify return:1
---
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com
   i:/C=US/O=Google Inc/CN=Google Internet Authority
-----BEGIN CERTIFICATE-----
MIIF/DCCBWWgAwIBAgIKHN4TOQAAAAB/azANBgkqhkiG9w0BAQUFADBGMQswCQYD
VQQGEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzEiMCAGA1UEAxMZR29vZ2xlIElu
dGVybmV0IEF1dGhvcml0eTAeFw0xMzAzMDcxNDI0MDFaFw0xMzA2MDcxOTQzMjda
MGYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1N
b3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgSW5jMRUwEwYDVQQDFAwqLmdv
b2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANVtYuy195QvNel7
trGWR58HJwAZ+ePoaDQgb2tBFllwxpNZDWSAeUi+L2FHDla/L7DEig62yWvR2xgJ
Fg0w9XZkm5uyKIi4olF9ahjWDdlzRJNwYp8cEfReW2d7buBbRIRx7QHywR3FSi9B
uY7BEwIne/Sppz/j8RttVSDXYGNJAgMBAAGjggPPMIIDyzAdBgNVHSUEFjAUBggr
BgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFDeOUXJygXLBA10KGrRYrS7UX19J
MB8GA1UdIwQYMBaAFL/AMOv1QxE+Z7qekfv8atrjaxIkMFsGA1UdHwRUMFIwUKBO
oEyGSmh0dHA6Ly93d3cuZ3N0YXRpYy5jb20vR29vZ2xlSW50ZXJuZXRBdXRob3Jp
dHkvR29vZ2xlSW50ZXJuZXRBdXRob3JpdHkuY3JsMGYGCCsGAQUFBwEBBFowWDBW
BggrBgEFBQcwAoZKaHR0cDovL3d3dy5nc3RhdGljLmNvbS9Hb29nbGVJbnRlcm5l
dEF1dGhvcml0eS9Hb29nbGVJbnRlcm5ldEF1dGhvcml0eS5jcnQwDAYDVR0TAQH/
BAIwADCCApUGA1UdEQSCAowwggKIggwqLmdvb2dsZS5jb22CDSouYW5kcm9pZC5j
b22CFiouYXBwZW5naW5lLmdvb2dsZS5jb22CEiouY2xvdWQuZ29vZ2xlLmNvbYIW
Ki5nb29nbGUtYW5hbHl0aWNzLmNvbYILKi5nb29nbGUuY2GCCyouZ29vZ2xlLmNs
gg4qLmdvb2dsZS5jby5pboIOKi5nb29nbGUuY28uanCCDiouZ29vZ2xlLmNvLnVr
gg8qLmdvb2dsZS5jb20uYXKCDyouZ29vZ2xlLmNvbS5hdYIPKi5nb29nbGUuY29t
LmJygg8qLmdvb2dsZS5jb20uY2+CDyouZ29vZ2xlLmNvbS5teIIPKi5nb29nbGUu
Y29tLnRygg8qLmdvb2dsZS5jb20udm6CCyouZ29vZ2xlLmRlggsqLmdvb2dsZS5l
c4ILKi5nb29nbGUuZnKCCyouZ29vZ2xlLmh1ggsqLmdvb2dsZS5pdIILKi5nb29n
bGUubmyCCyouZ29vZ2xlLnBsggsqLmdvb2dsZS5wdIIPKi5nb29nbGVhcGlzLmNu
ghQqLmdvb2dsZWNvbW1lcmNlLmNvbYINKi5nc3RhdGljLmNvbYIMKi51cmNoaW4u
Y29tghAqLnVybC5nb29nbGUuY29tghYqLnlvdXR1YmUtbm9jb29raWUuY29tgg0q
LnlvdXR1YmUuY29tggsqLnl0aW1nLmNvbYILYW5kcm9pZC5jb22CBGcuY2+CBmdv
by5nbIIUZ29vZ2xlLWFuYWx5dGljcy5jb22CCmdvb2dsZS5jb22CEmdvb2dsZWNv
bW1lcmNlLmNvbYIKdXJjaGluLmNvbYIIeW91dHUuYmWCC3lvdXR1YmUuY29tMA0G
CSqGSIb3DQEBBQUAA4GBAFnvOnn7rF3Tj94qGAPl09lYFYZxoObOYvqQg5H2tEr6
JZk1OEn/743r3yyTllwk8E6zyyerXMzNPXI9dOtkdNwGUcEaWw19eDAWUiZOi7EI
wIRY2VPT5+7BPIwFgcydtyqcDJz39HdNNHtIkOXHzgEnwnFiqJT2cjeX27DWyqwl
-----END CERTIFICATE-----
 1 s:/C=US/O=Google Inc/CN=Google Internet Authority
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
-----BEGIN CERTIFICATE-----
MIICsDCCAhmgAwIBAgIDC2dxMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0
aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkwNjA4MjA0MzI3WhcNMTMwNjA3MTk0MzI3
WjBGMQswCQYDVQQGEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzEiMCAGA1UEAxMZ
R29vZ2xlIEludGVybmV0IEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
gYkCgYEAye23pIucV+eEPkB9hPSP0XFjU5nneXQUr0SZMyCSjXvlKAy6rWxJfoNf
NFlOCnowzdDXxFdF7dWq1nMmzq0yE7jXDx07393cCDaob1FEm8rWIFJztyaHNWrb
qeXUWaUr/GcZOfqTGBhs3t0lig4zFEfC7wFQeeT9adGnwKziV28CAwEAAaOBozCB
oDAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFL/AMOv1QxE+Z7qekfv8atrjaxIk
MB8GA1UdIwQYMBaAFEjmaPkr0rKV10fYIyAQTzOYkJ/UMBIGA1UdEwEB/wQIMAYB
Af8CAQAwOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20v
Y3Jscy9zZWN1cmVjYS5jcmwwDQYJKoZIhvcNAQEFBQADgYEAuIojxkiWsRF8YHde
BZqrocb6ghwYB8TrgbCoZutJqOkM0ymt9e8kTP3kS8p/XmOrmSfLnzYhLLkQYGfN
0rTw8Ktx5YtaiScRhKqOv5nwnQkhClIZmloJ0pC3+gz4fniisIWvXEyZ2VxVKfml
UUIuOss4jHg7y/j7lYe8vJD5UDI=
-----END CERTIFICATE-----
---
Server certificate
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com
issuer=/C=US/O=Google Inc/CN=Google Internet Authority
---
No client certificate CA names sent
---
SSL handshake has read 2744 bytes and written 348 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-RC4-SHA
Server public key is 1024 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.1
    Cipher    : ECDHE-RSA-RC4-SHA
    Session-ID: A69DDC4E1D33F3D03603AED0CC9F101CC1A49BEE76D61AC0508A780D9E2AF06A
    Session-ID-ctx: 
    Master-Key: 8B08C4A8FB1332EE278F037B115EB4E3E6EF51BCE464B05F8B0652A2773FD34FC2F769B2AB51DCC57CF9844A8B747F97
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 100800 (seconds)
    TLS session ticket:
    0000 - 1f 6b 71 a9 3c 1f 83 b0-ad 45 ee 74 5f bb d6 3f   .kq.<....E.t_..?
    0010 - 06 a3 01 3a a6 00 53 da-b2 72 9b 16 d5 5f 54 75   ...:..S..r..._Tu
    0020 - 7e 35 10 1d c8 7e 6e 9e-29 dc f1 67 97 aa 94 77   ~5...~n.)..g...w
    0030 - 81 f5 a4 6c 25 29 61 13-12 6b d3 13 86 40 95 ae   ...l%)a..k...@..
    0040 - d0 6b d9 1f 9e 62 a4 09-68 8a fb 7b 6a b0 34 74   .k...b..h..{j.4t
    0050 - 57 0e 2f 45 d8 e9 9c 10-af 43 dc 83 b7 bd 8f 63   W./E.....C.....c
    0060 - 5e 84 d4 e1 bd 8a 18 55-de 4b a7 58 1e 9d b1 bf   ^......U.K.X....
    0070 - 84 de bb 0b 4a 9b 46 7f-cf 94 8b e3 48 53 54 49   ....J.F.....HSTI
    0080 - 1a 3b f9 41 4b 08 fc ac-b6 09 f0 5b 65 bf e3 cd   .;.AK......[e...
    0090 - 62 7b ad e4                                       b{..

    Start Time: 1363898770
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)

如果我然后输入

GET

我得到了 Google 主页的 html/javascript 代码,这是我所期望的。

但是,我的代码仍然失败。 (我尽量让它尽可能短):

#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_peer);
    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 HTTP/1.1\r\n";
      request_ << "Host: google.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("www.google.com", "443");
    boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
    boost::asio::ssl::context context(boost::asio::ssl::context::sslv23);
    context.add_verify_path("/home/mint/workspace/BoostExamples/certs");
    client c(io_service, context, iterator);
    io_service.run();
  }catch (std::exception& e){
    std::cerr << "Exception: " << e.what() << "\n";
  }

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

出现以下错误:

Connection OK!
Verifying:
/C=US/O=Google Inc/CN=Google Internet Authority
Handshake failed: certificate verify failed

我认为我正在正确加载证书,但我不确定,而且我不清楚如何从 Boost 中获取更多信息以进一步阐明问题。我在 Linux Mint 上,所以我不知道 Debian 的 SSL 3 问题是否也开始发挥作用。广泛搜索和阅读 Boost.Asio 文档也无济于事。有很多引用资料,但解释不多。

任何关于我做错了什么的建议,或者如何找出导致问题的原因,我们将不胜感激。

最佳答案

OpenSSL 可能会为您完成这项工作:

int main(int argc, char* argv[]) {
    ...
    boost::asio::ssl::context context(boost::asio::ssl::context::sslv23);
    context.set_default_verify_paths();
    ...
}

Boost 在底层使用 OpenSSL SSL_CTX_set_default_verify_paths()

来自 boost 文档:

Configures the context to use the default directories for finding certification authority certificates.

另见 http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/reference/ssl__context/set_default_verify_paths.html

关于c++ - Boost Asio HTTPS 请求给出 'certificate verify failed' 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15558177/

有关c++ - Boost Asio HTTPS 请求给出 'certificate verify failed' 错误的更多相关文章

  1. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  2. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  3. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  4. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  5. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  6. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  7. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  8. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

  9. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  10. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

    我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

随机推荐