boost::asioで簡単SSL通信
OSI参照モデルとIP、TCPのパケット構成を知ってたらSSLは簡単
IPパケットの構成:IPヘッダー+TCPパケット
TCPパケットの構成:TCPヘッダー+上位層で作られたデータ
上位層で作られたデータっちゅうのは、
HTTPとかFTPでクライアントがサーバーにデータを送信する例やと
コマンドのことやと思ってもらったらええかな。
普通はアプリケーション層で作られたデータを指すわけやけど、
SSL通信やとアプリケーション層とトランスポート層の間にある
セッション層でデータを暗号化するだけ。
つまり、
(非SSL)TCPパケットの構成:TCPヘッダー+上位層で作られたデータ
(SSL)TCPパケットの構成:TCPヘッダー+上位層で作られたデータを暗号化したもの
これだけの話。
さて本題
boost::asioでSSLクライアントを実装してみる。
どんな時に使えるかっちゅうと、ブラウザみたいなHTTPクライアントを作る時とか、
メーラーを作る時とか、FTPクライアントを作る時とかに、SSL通信に対応させたい場合。
いわゆるHTTPSとか、SMTP over SSLとか、FTPSってやつ。
まずはboost::asioでHTTP通信
#include <iostream> #include <boost/asio.hpp> int main() { try { // ネットワークI/O用 boost::asio::io_service io_service; // ネームサーバーに問い合わせて名前解決してくれる boost::asio::ip::tcp::resolver resolver( io_service ); // リゾルバにお願いする内容 boost::asio::ip::tcp::resolver::query query( "xxx.com", "http" ); // リゾルバにお願いして見つかったホスト(複数あるかも) boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve( query ); // EOFみたいなやつ boost::asio::ip::tcp::resolver::iterator end; // エラーの内容("ホストが見つからんかった"で初期化) boost::system::error_code error = boost::asio::error::host_not_found; // リゾルバにお願いして見つかったホストに接続 boost::asio::ip::tcp::socket socket( io_service ); while( error && endpoint_iterator != end ) { socket.close(); // ちゃんと繋がったらerrorはNULLになる socket.connect( *endpoint_iterator++, error ); } // 繋がったホストに送信するリクエストの内容 boost::asio::streambuf request; std::ostream request_stream( &request ); request_stream << "GET /index.html HTTP/1.0\r\n"; request_stream << "Host: xxx.com\r\n"; request_stream << "\r\n"; // ソケットに書き込み boost::asio::write( socket, request ); // 受信したレスポンスの内容 boost::asio::streambuf response; while( boost::asio::read( socket, response, boost::asio::transfer_at_least( 1 ), error ) ) { std::cout << &response; } // 受信時にエラーが発生したらthrow if( error != boost::asio::error::eof ) { throw boost::system::system_error( error ); } } catch( std::exception& e ) { std::cout << "Exception: " << e.what() << std::endl; } return 0; }
長くなってもたから
続き(boost::asio::ssl)は次回。