OpenSSLで安全なネットワークプログラム


OpenSSLが提供するライブラリを使うと簡単に暗号化された 通信を行うことができます。 OpenSSLについては私は詳しくは知らないので他をあたってください。 しかし、私が理解した程度で作ったSSLによる通信プログラムを用意しましたので 参考にして下さい。


SSLのサーバーを動かす前の準備

SSLは公開鍵暗号方式のためサーバー側で公開鍵と秘密鍵のファイルを 事前に用意しておかなければなりません。それには openssl コマンドを 以下のようにして実行します。

openssl req -new -x509 -nodes -out public.key -keyout private.key
いろいろ尋ねられますが、全部無視してリターンだけでも大丈夫です。 終ると公開鍵ファイル public.key と秘密鍵ファイル private.key が出来ています。


SSLのサーバー

SSLのサーバー側のプログラムの雛型は以下のようになります。 名前は ssltcps.cc です。
SSLのserver : ssltcps.cc のソースintegnet.h のソース

// OpenSSL で暗号化した TCP/IP 通信プログラムの雛型 (サーバー側) #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <openssl/ssl.h> #include "integnet.h" // 接続のポート #define PORT 12345 int main( void ) { // INET で STREAM なソケットの作成 int sb = socket( AF_INET, SOCK_STREAM, 0 ); // 接続の目印の指定 sockaddr_in addr = SOCKADDR_IN_INIT( AF_INET, htons(PORT), InAddr(htonl(INADDR_ANY)) ); // 目印の公開 if( bind( sb, (sockaddr*)&addr, sizeof(addr) ) < 0 ){ perror("bind"); exit(1); } // 接続要求の受信開始(同時に1回線まで接続可とする) listen( sb, 1 ); // 接続要求の受信 int s = accept( sb, NULL, NULL ); // SSLの初期化 SSL_library_init(); SSL_CTX* ctx = SSL_CTX_new( SSLv2_server_method() ); SSL* ssl = SSL_new( ctx ); SSL_set_fd( ssl, s ); // SSLの公開鍵と秘密鍵の読みだし SSL_use_certificate_file( ssl, "public.key", SSL_FILETYPE_PEM ); SSL_use_PrivateKey_file( ssl, "private.key", SSL_FILETYPE_PEM ); // SSL通信の開始 SSL_accept(ssl); char msg[64]; SSL_read( ssl, msg, sizeof(msg) ); printf("Server received : %s\n", msg ); // SSLの終了 SSL_shutdown(ssl); SSL_free(ssl); SSL_CTX_free(ctx); // ソケットの廃止 close(s); close(sb); return 0; }

このプログラムをコンパイルするには SSL のライブラリを連結するために -lssl -lcryptoのオプションが必要です。


SSLのクライアント

SSLのクライアント側のプログラムの雛型は以下のようになります。 名前は ssltcpc.cc です。
SSLのclient : ssltcpc.cc のソースintegnet.h のソース

// OpenSSL で暗号化した TCP/IP 通信プログラムの雛型 (クライアント側) #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <openssl/ssl.h> #include "integnet.h" // 接続のポート #define PORT 12345 #define HOST "127.0.0.1" int main( void ) { // INET で STREAM なソケットの作成 int s = socket( AF_INET, SOCK_STREAM, 0 ); // 接続の目印の指定 sockaddr_in addr = SOCKADDR_IN_INIT( AF_INET, htons(PORT), InAddr(HOST) ); if( h_errno ){ herror("gethostbyname"); exit(1); } // ソケットの回線への接続 if( connect( s, (sockaddr*)&addr, sizeof(addr) ) < 0 ){ perror("connect"); exit(1); } // SSLの初期化 SSL_library_init(); SSL_CTX* ctx = SSL_CTX_new( SSLv2_client_method() ); SSL* ssl = SSL_new( ctx ); // SSL通信の開始 SSL_set_fd( ssl, s ); SSL_connect( ssl ); char msg[64] = "This is client."; SSL_write( ssl, msg, strlen(msg) ); // SSLの終了 SSL_shutdown(ssl); SSL_free(ssl); SSL_CTX_free(ctx); // 回線の切断 close(s); return 0; }

このプログラムをコンパイルするには SSL のライブラリを連結するために -lssl -lcryptoのオプションが必要です。

さて果たして通信できるでしょうか? OpenSSLについてより深く知りたい人は各自で頑張って下さい。


目次

Copyright(C) by Naoki Watanabe. Jan 1st, 2001.
渡辺尚貴 naoki@cms.phys.s.u-tokyo.ac.jp