SSL
SSL (Secure Sockets Layer) は公開鍵暗号、
共通鍵暗号、電子署名、
公開鍵証明書などの技術を組み合わせ、暗号化による
盗聴防止、改ざん・破損の検出、通信相手の証明などを一度に実現している通信技術です。
TCP/IP のセッション層とトランスポート層の間で機能するため、アプリケーションは
ソケットのオープン時以外に SSL かどうかを意識する必要がないという利点があります。
また特定のプロトコル固有の暗号化技術ではないため、HTTP や FTP、POP3 などさまざまな
プロトコルで使用することができます。
SSL サーバ認証の概要
概略的な説明ですのでプロトコルの詳細はなどを参照してください。
まず SSL を利用するためにはクライアントとサーバそれぞれに必要な証明書を配布します。
- サーバの管理者は鍵ペアを作成し、CA に公開鍵と CSR (証明書署名要求;
Certification Signing Request) を提出してサーバ証明書と呼ばれる証明書を
発行してもらいます。サーバ証明書には CSR で提出した身元情報が記載されており、
その内容と公開鍵が CA によって証明されている事を表す
電子署名が付けられています。
- クライアントには、そのクライアントが信頼する CA の公開鍵証明書をあらかじめ
インストールしておきます (一般的なブラウザや Java には VeriSign などの有名どころの
CA 証明書がデフォルトでインストールされています)。
サーバ認証の概要
プロトコル自体の詳細は省略して鍵や証明書の流れを概略的に。
公開鍵方式による暗号は負荷が高いため、通信の最初に共通鍵をやり取りするためだけ
に使用されます。
- サーバは SSL 接続を受け付けるとサーバ証明書 (証明書チェーン) を送り返します。
- クライアントは証明書チェーンの中に自分が信頼している CA が含まれていること
を確認し、一連の証明書を検証します。サーバ証明書が正しいことが確認できれば証明
書の内容と公開鍵が CA に提出されたものと同じであることが保障されます。
- クライアントは新しくプレマスターシークレット (共通鍵を生成する元の情報)
を生成してサーバの公開鍵で暗号化して送り返します。
- サーバは自分の持つ秘密鍵で暗号を解除してプレマスターシークレットを取り出
します。以後はクライアントとサーバの双方でプレマスターシークレットから作成した
共通鍵 (セッション鍵) で暗号化通信を行います。
暗号化通信までに必要なこの一連の流れはハンドシェイクプロトコルを呼ばれます。
悪意的な中継者が居たとしてもクライアントに渡されるサーバ証明書を偽造することは
できません (クライアントで検証すればすぐに分かります)。暗号化されたプレマスター
シークレットは秘密鍵を持つサーバでしか解読できません。
しかし、なりすましではなく中継者自身の「本物の」証明書を用いた場合、利用者が
証明書の内容確認を怠れば意味がないのは明白です。
クライアント認証の概要
サーバ側からも通信相手が本当に意図したクライアントである事を確認できるように
SSL のハンドシェイクでクライアントに証明書を要求することができます。クライアント
証明書 (個人証明書) から行う認証はクライアント認証と呼ばれます。
- サーバはサーバ証明書を送信するときにクライアント証明書を要求します。
- クライアントは自分の秘密鍵を用いて Hello メッセージから電子署名を生成し、
クライアント証明書とともに送り返します。
- サーバはクライアント証明書の公開鍵を使用して電子署名を検証します。署名が
正しければ証明書が通信相手のものであることが保障できるため、その記載内容から意図
した相手かどうかを判断します。
Java による SSL 通信
J2SE 1.4 から JSSE
(Java Secure Socket Extension) が標準となり SSL を使用したソケット通信が可能に
なっています。
単純な SSL クライアントソケットはデフォルトの
SSLSocketFactory
から参照することができます。
Java
// SSL ソケットのオープン (例外省略)
SocketFactory factory = SSLSocketFactory.getDefault();
Socket socket = factory.createSocket("www.keisan.nta.go.jp", 443);
// ...
クライアント認証用の秘密鍵 (署名用) と証明書を指定する場合は
クライアント証明書を使用してより安全性を高めたり、アプリケーション固有の信頼済み
CA 証明書を持っている場合。
Java
// SSL ソケットのオープン (例外省略)
SocketFactory factory = SSLSocketFactory.getDefault();
Socket socket = factory.createSocket("www.keisan.nta.go.jp", 443);
// ...