[SSL認証、証明書] SSL双方向認証Java Combat、証明書を作成するkeytool

記事ディレクトリ


関連記事:
//-----------Java SSL はじめます----------------------
【SSL認証・証明書】SSL 2- way認証 SSL片方向認証との違い(概念図)
【ssl認証、証明書】 Javaのssl構文 API記述(SSLContext)、keytoolツールとの接続
【ssl認証、証明書】 SSL双方向認証 java実戦、keytool証明書を作成するには
[SSL 認証、証明書] Wireshark パケット キャプチャ分析
[SSL 証明書、証明書] キーストア ファイルの内容を表示します
//-----------Java SSL 終了------ ---------- ----------

//----------以下は CA 証明書と openssl に関する知識です---------------
[SSL 証明書、証明書] TLS/SSL 双方向証明書概念、openssl genrsa 例
[ssl 証明書、証明書] openssl genrsa コマンド詳細説明
[ssl 証明書、証明書] SSL 証明書の基本概念、証明書の形式、openssl と keytool の違い

概要

keytoolコマンド、バージョンが違うので注意[SSL証明書、証明書] keytool genkeyとgenkeypairの違いと接続

この記事のコード例の原理については、「【SSL認証・証明書】JavaのSSL接続とkeytool」を参照して合わせてご覧ください。

キーツールの例

シミュレーション シナリオ:
サーバーとクライアント間の通信には承認と ID 検証が必要です。つまり、クライアントはサーバーからのメッセージのみを受け入れることができ、サーバーはクライアントからのメッセージのみを受け入れることができます。

実装テクノロジ:
JSSE (Java Security Socket Extension) は、
インターネット上のセキュリティ通信を解決するために Sun が開始したソリューションです。SSL および TSL (Transport Layer Security) プロトコルを実装します。JSSE には、データ暗号化、サーバー認証、メッセージ整合性、クライアント認証などのテクノロジーが含まれています。JSSE を使用すると、開発者は TCP/IP プロトコル経由でクライアントとサーバー間でデータを安全に送信できます。

メッセージ認証を実装するため。
サーバーのニーズ:
1) KeyStore: サーバーの秘密キーを保存する
2) Trust KeyStore: クライアントの認可証明書を保存する
同様に、クライアントのニーズ:
1) KeyStore: クライアントの秘密キーを保存する
2) Trust KeyStore: サーバーの認可証明書のコピーを保存するリストは、ピアが送信した証明書が正当であるかどうかを判断するために使用され、tks 証明書のみが有効で、それ以外の場合は接続が直接拒否されます。

Java に付属の keytool コマンドを使用して、このような情報ファイルを生成できます。
1) サーバーの秘密キーを生成し、サーバーの KeyStore ファイルにインポートします。

厳密に言えば、この時点で生成されるのはキー ペアです。つまり、秘密キーと公開キーの両方がこのファイル内にあり、インポートを通じて証明書をエクスポートできます (証明書には公開キーが含まれます)。

keytool -genkey -alias serverkey -keystore kserver.keystore

プロセス中に、これらを個別に入力し、必要に応じて自分で設定する必要があります
キーストアのパスワード: 123456
名前と姓: stone
組織単位名: eulic
組織名: eulic
市または地域の名前: HZ
州または県の名前: ZJ
国コード: CN
サーバーキー秘密キー パスワード、キーストアと同じパスワードを入力しないでください: 123456
kserver.keystore ファイルを生成します
。 server.keystore はサーバー用であり、独自の秘密キーを保存します。

2) 秘密キーに従って、サーバー証明書 (公開キーを含む) をエクスポートします。

これが、kserver.keystore に公開鍵情報が含まれていると言われる理由です。

keytool -export -alias serverkey -keystore kserver.keystore -file server.crt

server.crt はサーバーの証明書です。

3) サーバー証明書をクライアントの信頼キーストアにインポートします。

keytool -import -alias serverkey -file server.crt -keystore tclient.keystore

tclient.keystore はクライアント用であり、信頼された証明書を保存します。

同じ方法を使用して、クライアントの秘密キーとクライアントの証明書を生成し、サーバーの信頼キーストアにインポートします。

1)keytool -genkey -alias clientkey -keystore kclient.keystore
2)keytool -export -alias clientkey -keystore kclient.keystore -file client.crt
3)keytool -import -alias clientkey -file client.crt -keystore tserver.keystore

このように、生成されたファイルは、
サーバーストレージ: kserver.keystore tserver.keystore
クライアントストレージ: kclient.keystore tclient.kyestore の2 つのグループに分けられます。

次に、JSSE を使用して SSLServerSocket と SSLSocket をそれぞれ生成します。

サーバー側で、SSLServerSocket コードを生成します。

SSLContext ctx = SSLContext.getInstance("SSL");

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");

KeyStore ks = KeyStore.getInstance("JKS");
KeyStore tks = KeyStore.getInstance("JKS");

ks.load(new FileInputStream("data/kserver.keystore"), SERVER_KEY_STORE_PASSWORD.toCharArray());
tks.load(new FileInputStream("data/tserver.keystore"), SERVER_TRUST_KEY_STORE_PASSWORD.toCharArray());

kmf.init(ks, SERVER_KEY_STORE_PASSWORD.toCharArray());
tmf.init(tks);

ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

serverSocket = (SSLServerSocket) ctx.getServerSocketFactory().createServerSocket(DEFAULT_PORT);
serverSocket.setNeedClientAuth(true);

注: サーバー側では、setNeedClientAuth(true)双方向認証を有効にするように設定する必要があります。そうでない場合は、基本的に一方向認証になります。

クライアント側では、SSLSocket を生成するコードは似ていますが、若干の違いがあります。

SSLContext ctx = SSLContext.getInstance("SSL");

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");

KeyStore ks = KeyStore.getInstance("JKS");
KeyStore tks = KeyStore.getInstance("JKS");

ks.load(new FileInputStream("data/kclient.keystore"), CLIENT_KEY_STORE_PASSWORD.toCharArray());
tks.load(new FileInputStream("data/tclient.keystore"), CLIENT_TRUST_KEY_STORE_PASSWORD.toCharArray());

kmf.init(ks, CLIENT_KEY_STORE_PASSWORD.toCharArray());
tmf.init(tks);

ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

return (SSLSocket) ctx.getSocketFactory().createSocket(DEFAULT_HOST, DEFAULT_PORT);

このようにして、サーバーとクライアント間の認証ベースの対話が完了します。

クライアントは、kclient.keystore の clientkey 秘密キーを使用してデータを暗号化し、サーバーに送信します。
サーバーは、tserver.keystore の client.crt 証明書 (clientkey の公開キーを含む) を使用してデータを復号します。成功した場合、メッセージがクライアントから送信されたことが証明されます。ロジック処理

サーバーは、kserver.keystore 内のserverkey 秘密鍵を使用してデータを暗号化し、クライアントに送信します。クライアントは、
tclient.keystore 内のserver.crt 証明書 (serverkey 公開鍵を含む) を使用してデータを復号化します。復号化が成功した場合は、 、メッセージがサーバーから送信されたことを証明します。ロジック処理

プロセス中に復号化に失敗した場合、メッセージの送信元が間違っていることがわかります。ロジック処理は実行されません。これで双方向認証が完了します。

サーバーを起動するとき:

  • 最初に Telnet 127.0.0.1 7777 を使用して CMD で接続すると、接続が成功したことがわかりますが、メッセージの送信後、この時点ではクライアントに証明書がないため、接続はすぐに切断されます。
  • クライアント プログラムを再起動すると、接続が正常でメッセージを交換できることがわかります。

完全な例については、study-ssl を参照してください。

参考

SSL双方向認証のJava実装

おすすめ

転載: blog.csdn.net/m0_45406092/article/details/129790663