简体   繁体   English

使用带有 SSL (HTTPS) 的 Boost-Beast (Asio) http 客户端

[英]Using Boost-Beast (Asio) http client with SSL (HTTPS)

I am new to SSL and the Boost-Beast library, and also C++, but that's a different story.我是 SSL 和 Boost-Beast 库以及 C++ 的新手,但这是另一回事。 I have a question regarding using HTTPS (SSL) with Beast.我有一个关于在 Beast 中使用 HTTPS (SSL) 的问题。 I am going to use the library to connect to a REST service and post JSON to a server where I do not control the certificates, the API etc.我将使用该库连接到 REST 服务并将 JSON 发布到我不控制证书、API 等的服务器。

And it kind of works.它有点工作。 The thing is that I do not clearly understand HOW it works.问题是我不清楚它是如何工作的。 In the example that comes with Beast it is referenced to a file example/common/root_certificates.hpp where it is two certificates in base64 format or something like that.在 Beast 附带的示例中,它被引用到一个文件example/common/root_certificates.hpp ,其中它是两个 base64 格式或类似格式的证书。

When I tried the example, I got it to work with POST a JSON string to a server, let's call it "exampleserver.com".当我尝试这个例子时,我让它可以使用 POST 一个 JSON 字符串到服务器,我们称之为“exampleserver.com”。 Connected to both port 80 and 443. Even though I commented out the line where it calls the root certificate function, load_root_certificates(ctx);连接到端口 80 和 443。即使我注释掉了它调用根证书函数的行, load_root_certificates(ctx); . . No errors from handshaking or anything else showed up.没有出现握手或其他任何错误。 And the server responded correctly.并且服务器响应正确。

So, my questions are then:那么,我的问题是:

1) Did the Beast library get the certificate from exampleserver.com or did I already have it installed and that's why it worked? 1) Beast 库是从exampleserver.com获得证书还是我已经安装了它,这就是它工作的原因? If so what happens when it expires?如果是这样,当它到期时会发生什么? Do I have to reinstall a new one on every client that uses my application?我是否必须在使用我的应用程序的每个客户端上重新安装一个新的? I would prefer to not have any hardcoded certificates in my code to check it upon.我宁愿在我的代码中没有任何硬编码证书来检查它。 The certificate says DigiCert Global Root CA -> DigiCert SHA2 Secure Server CA is that a standard certificate maybe that comes with the browser?证书说DigiCert Global Root CA -> DigiCert SHA2 Secure Server CA是浏览器附带的标准证书吗?

2) Did it just use plain HTTP over port 443 (no SSL)? 2)它是否只是在端口 443 上使用了普通 HTTP(无 SSL)? Don know if this is possible at all...不知道这是否可能......

Even though I commented out the line where it calls the root certificate funtion, "load_root_certificates(ctx);"即使我注释掉了它调用根证书功能的行,“load_root_certificates(ctx);”

In that case, openssl uses the systemwide default certificate store (eg on linux /etc/ssl/certs), so the "usual" authorities will be trusted (just like eg your browser does).在这种情况下,openssl 使用系统范围的默认证书存储(例如在 linux /etc/ssl/certs 上),因此将信任“通常”权限(就像您的浏览器一样)。

1) Did the Beast library get the certificate from "exampleserver.com" or did I already have it installed and thats why it worked? 1) Beast 库是从“exampleserver.com”获得证书还是我已经安装了它,这就是它工作的原因?

Yes.是的。

If so what happens when it expires?如果是这样,当它到期时会发生什么?

It will fail to verify.它将无法验证。 Test it, if you want: https://expired.badssl.com/测试它,如果你想: https : //expired.badssl.com/

That site has many excellent SSL tests ( https://badssl.com )该站点有许多出色的 SSL 测试( https://badssl.com

The certificate says "DigiCert Global Root CA -> DigiCert SHA2 Secure Server CA" is that a standard certificate maybe that comes with the browser?证书上写着“DigiCert Global Root CA -> DigiCert SHA2 Secure Server CA”是浏览器附带的标准证书吗?

The browser's trusted certificates aren't relevant (you're not using the browser).浏览器的可信证书不相关(您没有使用浏览器)。 However, you can see openssl's (see above), or you can test using something like但是,您可以看到 openssl(见上文),或者您可以使用类似的东西进行测试

openssl s_client  -connect exampleserver.com:443 -verify -showcerts 

Which prints something similar to打印出类似于

verify depth is 0
CONNECTED(00000003)
depth=3 C = SE, O = AddTrust AB, OU = AddTrust External TTP Network, CN = AddTrust External CA Root
verify return:1
depth=2 C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO RSA Certification Authority
verify return:1
depth=1 C = US, ST = TX, L = Houston, O = "cPanel, Inc.", CN = "cPanel, Inc. Certification Authority"
verify return:1
depth=0 CN = tradingfleet.com
verify return:1
---
Certificate chain
 0 s:/CN=tradingfleet.com
   i:/C=US/ST=TX/L=Houston/O=cPanel, Inc./CN=cPanel, Inc. Certification Authority
 1 s:/C=US/ST=TX/L=Houston/O=cPanel, Inc./CN=cPanel, Inc. Certification Authority
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
 2 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
   i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFUjCCBDqgAwIBAgIQPI9I0oyjgNMrudesOYyqgDANBgkqhkiG9w0BAQsFADBy
MQswCQYDVQQGEwJVUzELMAkGA1UECBMCVFgxEDAOBgNVBAcTB0hvdXN0b24xFTAT
BgNVBAoTDGNQYW5lbCwgSW5jLjEtMCsGA1UEAxMkY1BhbmVsLCBJbmMuIENlcnRp
ZmljYXRpb24gQXV0aG9yaXR5MB4XDTE4MDIxODAwMDAwMFoXDTE4MDUxOTIzNTk1
OVowGzEZMBcGA1UEAxMQdHJhZGluZ2ZsZWV0LmNvbTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBANe5zu81biDwwIloBMFHWc2OvoiGTNBr2aya8auWrzRm
rmbOfugZOaIAms79jnINCQ7jy0Qk2xwblgCifCg7y/UfSXvv7IWUWcEDywsAoyz/
sUc9myvQbot+kD1DaxVoyN85LnDehaYF5+myDznJISQe1ei01n/aIF8gwOz4k3Gn
R07Zh0sDRBjIiRsAL6ZljrPRk47cul2+8pD0qNJHHN0QX6hz/KPOugTiivI1+ymo
onSeeN29oh5oTtCHP2yj9+RNsCNcPAnbDawy0RAgFi2W5GyHiIo/NkUxBXN8tQxH
2xrPnY+MQJHUcKXJd//DTX6tWoQqo4xisN6Q9iZ3+R8CAwEAAaOCAjkwggI1MB8G
A1UdIwQYMBaAFH4DWmVBa6d+CuG4nQjqHY4dasdlMB0GA1UdDgQWBBQKTFmhmBNx
pS9uBbXjqE1ZjCOiFjAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0TAQH/BAIwADAdBgNV
HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwTwYDVR0gBEgwRjA6BgsrBgEEAbIx
AQICNDArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21vZG8uY29tL0NQ
UzAIBgZngQwBAgEwTAYDVR0fBEUwQzBBoD+gPYY7aHR0cDovL2NybC5jb21vZG9j
YS5jb20vY1BhbmVsSW5jQ2VydGlmaWNhdGlvbkF1dGhvcml0eS5jcmwwfQYIKwYB
BQUHAQEEcTBvMEcGCCsGAQUFBzAChjtodHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9j
UGFuZWxJbmNDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNydDAkBggrBgEFBQcwAYYY
aHR0cDovL29jc3AuY29tb2RvY2EuY29tMIGXBgNVHREEgY8wgYyCEHRyYWRpbmdm
bGVldC5jb22CF2NwYW5lbC50cmFkaW5nZmxlZXQuY29tghVtYWlsLnRyYWRpbmdm
bGVldC5jb22CGHdlYmRpc2sudHJhZGluZ2ZsZWV0LmNvbYIYd2VibWFpbC50cmFk
aW5nZmxlZXQuY29tghR3d3cudHJhZGluZ2ZsZWV0LmNvbTANBgkqhkiG9w0BAQsF
AAOCAQEAPFIZv1oHXm79+uoLnP9Sya2qEghOn/uPpNtappgUSrh2Pb0MueX84C0P
4HRS4yHRO1TD9ZOfCuPsguzXhl+RUB7Asl2iAhwthoZGMLhv6uaUnAUHZbpdkJY3
r/quuWHXDGNoe2quAOxGLPDO7WMvrDh1hFi7x7AGshkRSZ4DREBnCS7iprKzKL6H
BaNqtAlWgoXcSSg1RpnbU2o4bWIv8mZG0ATr7Cc8VSf04SjBLZnLTNeqo6Z+ALQ3
yrFsAytim6857FB231V5NEvLh+iZjSOuBG9xv+4Nw46bVz9z8QxB3czAodrDGXbB
lgH1s5f486lRq45dRn/hGY+DZjJXgg==
-----END CERTIFICATE-----
subject=/CN=tradingfleet.com
issuer=/C=US/ST=TX/L=Houston/O=cPanel, Inc./CN=cPanel, Inc. Certification Authority
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 4988 bytes and written 431 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: 24CB439538212A23E0391887F856E369858AB6864B25DA5F1FD618550C41EB92
    Session-ID-ctx: 
    Master-Key: 1B8A3028923478527196B429D10F3584C5FA5DE4175C834CBBEF9EB19013FBFE58E7668CED9C0877E15F4F214A61F80C
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - ca 83 5a 76 c2 51 7b c7-68 15 12 a7 cb c9 f5 35   ..Zv.Q{.h......5
    0010 - 0a dc c1 2a 90 fd 61 69-0a d9 89 09 f0 c4 b3 40   ...*..ai.......@
    0020 - 79 dc 97 8a c5 0d a1 67-85 5e b4 25 47 94 ed 23   y......g.^.%G..#
    0030 - 42 df b2 99 25 ec b1 fa-d7 3e 3e 24 37 ef 67 ef   B...%....>>$7.g.
    0040 - 56 f4 d2 57 cd 47 48 bd-d7 86 b1 2f b5 76 d6 db   V..W.GH..../.v..
    0050 - 12 9d 7a d3 94 b0 58 bf-c5 c4 3e 7d 05 98 75 1d   ..z...X...>}..u.
    0060 - 31 bc 9b 23 4f a7 ce 37-af 77 8a 96 89 20 20 64   1..#O..7.w...  d
    0070 - 3d bf de 25 b2 09 02 20-49 09 b5 57 a1 c3 75 ed   =..%... I..W..u.
    0080 - 97 ec 51 d2 46 f7 c6 b7-4a d8 b2 db 95 eb ac d6   ..Q.F...J.......
    0090 - be 76 14 80 ca 08 dc b7-b6 cb e9 c9 cc 8b 45 bd   .v............E.
    00a0 - d7 1d a7 88 9b a4 91 33-aa 23 fe 23 65 b8 e1 d9   .......3.#.#e...
    00b0 - 98 f6 55 1e 25 32 97 b5-22 ac d0 58 01 a6 42 60   ..U.%2.."..X..B`

    Start Time: 1522150150
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
^C

2) Did it just use plain http over port 443 (no SSL)? 2)它是否只是在端口 443 上使用了普通的 http(没有 SSL)? Don know if this is possible at all...不知道这是否可能......

No it didn't.不,它没有。

It's possible only given a whacky server config, but usually if your server connects https from a browser, it will be impossible to connect plain:可能只提供了一个糟糕的服务器配置,但通常如果您的服务器从浏览器连接 https,则无法连接普通:

As suggested by Vinnie Falco, in the file example/common/root_certificates.hpp , use the following header only library https://github.com/djarek/certify正如 Vinnie Falco 所建议的,在文件example/common/root_certificates.hpp ,使用以下仅标头库https://github.com/djarek/certify

In your code add the following includes在您的代码中添加以下包括

#include <boost/certify/extensions.hpp>
#include <boost/certify/https_verification.hpp>

And replace the initial code:并替换初始代码:

    // This holds the root certificate used for verification
    load_root_certificates(ctx);

    // Verify the remote server's certificate
    ctx.set_verify_mode(ssl::verify_peer);

by this:通过这个:

    ctx.set_verify_mode(ssl::context::verify_peer );
    boost::certify::enable_native_https_server_verification(ctx);

Tested quickly with site badssl.com and sites with good ssl certificate.使用网站 badssl.com 和具有良好 ssl 证书的网站进行了快速测试。 And it's work like a charm.它的工作就像一个魅力。

Possibly, you already figured it out by now.可能,你现在已经想通了。

I tried the same beast sample (Boost libraries 1.70) and had to make the following change to the ctor of session (I did it there it may be possible to make the change at some other place in code as well):我尝试了相同的野兽示例(Boost 库 1.70),并且必须对会话的构造函数进行以下更改(我在那里进行了更改,可能也可以在代码的其他位置进行更改):

    ws_.next_layer().set_verify_mode(boost::asio::ssl::verify_peer);
    ws_.next_layer().set_verify_callback(std::bind(&session::verify_certificate, this, _1, _2));

and added a method (that I copied as is from the Asio client sample):并添加了一个方法(我从 Asio 客户端示例中按原样复制了该方法):

bool verify_certificate(bool pverified_ok, 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 " << subject_name << std::endl;

    return pverified_ok;
}

This change causes the verification to fail (I had removed the hard-coded certificates since I did not want to use those).此更改导致验证失败(我已删除硬编码证书,因为我不想使用它们)。 The callback assists in logging that the server certificate was actually being verified.回调有助于记录服务器证书实际上正在被验证。

Just like the Asio sample adding a CA certificate to the ssl::context eg就像 Asio 示例将 CA 证书添加到 ssl::context 例如

    boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
    ctx.load_verify_file("ca.pem"); // CA certificate

Causes the verification to pass.导致验证通过。

You need to create the self-signed CA certificate and server certificate signed by it and place it in the server code (again from Asio sample) eg您需要创建自签名 CA 证书和由它签名的服务器证书,并将其放置在服务器代码中(同样来自 Asio 示例)例如

    context_.use_certificate_chain_file("..\\sample-server1.pem");
    context_.use_private_key_file("..\\sample-server1-key.pem", boost::asio::ssl::context::pem);
    context_.use_tmp_dh_file("..\\dh2048.pem");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM