The most important thing in HTTPS is SSL handshake. SSL handshake is used to negotiate the secret key and encryption suite. The overall process is as follows:
- The client tells the server to use HTTPS protocol;
- The server returns its certificate and public key to the client;
- Client verifies the validity of public key and certificate;
- After passing the verification, the client generates a random encryption secret key and sends it to the server using the server public key encryption;
- After receiving the encryption key, the server decrypts the session key with the private key;
- The server and the client use the generated random secret key for data encryption transmission;
Use Asio and OpenSSL to demonstrate the code as follows:
#include <iostream> #include <string> #include <boost/asio.hpp> #include <boost/asio/ssl.hpp> using namespace boost::asio; int main() { typedef ssl::stream<ip::tcp::socket> ssl_socket; try { io_service srv{}; ip::tcp::resolver resolver{srv}; ip::tcp::resolver::query query{"www.baidu.com", "https"}; ip::tcp::resolver::iterator iterator{resolver.resolve(query)}; ssl::context ctx{ssl::context::sslv23}; ctx.set_default_verify_paths(); ssl_socket socket{srv, ctx}; socket.set_verify_mode(ssl::verify_peer); socket.set_verify_callback([=](bool preverified, ssl::verify_context& vctx) -> bool { char subject_name[256]{}; X509* cert = X509_STORE_CTX_get_current_cert(vctx.native_handle()); X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256); std::cout << "Verifying => " << subject_name << std::endl; return preverified; }); connect(socket.lowest_layer(), iterator); socket.lowest_layer().set_option(ip::tcp::no_delay{true}); socket.handshake(ssl_socket::client); streambuf request{}; std::ostream request_stream{&request}; request_stream << "GET / HTTP/1.1\r\n"; request_stream << "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)\r\n"; request_stream << "Host: www.baidu.com\r\n\r\n"; write(socket, request); streambuf response{}; read_until(socket, response, "\r\n"); std::istream response_stream{&response}; std::string http_version{}; response_stream >> http_version; unsigned int status_code{}; response_stream >> status_code; std::string status_message{}; std::getline(response_stream, status_message); std::cout << "HTTP Version => " << http_version << std::endl; std::cout << "Status Code => " << status_code << std::endl; std::cout << "Status Message => " << status_message << std::endl; return 0; } catch (std::exception& e) { std::cout << "Exception: " << e.what() << std::endl; return 1; } }