私はEJPの回答に同意しますが、別の回答を受け入れたので、自己署名証明書の問題についてさらに詳しく説明します。
サーバーで自己署名証明書を使用することができます。この証明書を信頼するために、すべての潜在的なクライアントを構成する必要があります。これは、証明書を(秘密鍵なしで)各マシンの信頼できるストアにインポートするか、ブラウザーの信頼できる証明書リポジトリ内にインポートすることで実行できます(たとえば、Firefoxは、実行しているOSに関係なく独自の証明書を使用します)。ここでの自己署名サーバー証明書は、主にカスタムCA証明書の特殊なケースであり、各クライアントは使用する可能性のある各サーバーについて知る必要があります(自己署名証明書を取り消すことができないという欠点があります)。これは問題ありませんが、実際には、マシンの数が少ない場合、これはすぐに問題になる可能性があります。
主な問題は、クライアント証明書としての自己署名証明書に関するものです。
クライアント証明書認証はサーバーによって開始され、サーバーはTLS証明書要求メッセージをクライアントに送信します。このメッセージには、受け入れても構わないと思っている認証局の名前のリストが含まれています。次に、クライアントはこのリストを使用して、送信する証明書を選択します。クライアントは、このCAリストの名前の1つと一致する発行者DNを持つ証明書(秘密鍵を持っている)を探します(中間CAの場合は、証明書チェーンを使用することもできます)。このCAリストにある発行者DNへのリンクを作成するには、証明書が必要です)。
ほとんどのクライアントは、これらの条件に一致する証明書が見つからない場合、クライアント証明書をまったく送信しません。これは、自己署名クライアント証明書を使用しようとする場合の最大の問題になります。
この問題を回避する方法は、サーバーに空のリストを送信させることです。これにより、どの証明書を選択するかについてクライアントにより多くの自由が与えられます(それを受け入れるかどうかを選択するのはサーバー次第ですが、とにかく常にそうなります)。これはTLS1.1で明示的に許可されており、以前のバージョン(SSLv3 / TLS 1.0)はこのトピックについては言及していませんが、実際には、私が知る限り、ほとんどのSSLv3 /TLS1.0スタックでも正常に機能します。(これは、たとえば、ブラウザによって自動証明書選択が行われる場合でも、その自動選択を正しく行うことが困難になるため、不格好な相互作用につながる可能性があります。)
Javaは、TLS証明書要求メッセージで空のCAリストを返すX509TrustManager
ようにカスタマイズできます。getAcceptedIssuers()
私の知る限り、C#/。Netでは、SslStream
'sRemoteCertificateValidationCallback
には同等のものがありません。私の知る限り、このリストは、IIS/を使用する場合のマシンの信頼できる証明書リストから作成されますSslStream
。(これは証明書の検証自体とは無関係であることに注意してください。サーバーがどの証明書を受け入れるかをアドバタイズするだけです。)
さらに、自己署名証明書でクライアント証明書認証を使用する場合は、この認証を実行するためにサーバーに独自の検証コールバックを実装する必要があります。簡単な例は、取得した証明書から公開鍵を抽出し、それをサーバーが持っている事前定義されたリストと比較して、その事前定義されたリストにあるユーザー名を使用することです。自己署名証明書の内容を自分が知っているものと照合する明示的な方法がない限り、自己署名証明書の内容を信頼することはできません。ただ言うコールバックを実装するreturn true;
すべての認証を実行するわけではありません。誰でも同じ名前または属性と異なるキーで証明書を作成できます。(サーバーの信頼できる証明書ストアで各client-certを明示的に信頼することをお勧めしますが、TLS証明書要求メッセージでCAリストが長くなる可能性があります。)
商用CAに依存したくない場合は、独自のCAを構築してください。少し手間がかかる場合がありますが(ほとんどの場合、管理)、少なくとも、よりクリーンな結果のシステムが得られます。そのCA証明書を使用してクライアントとサーバーを構成することにより、変更を加えずに、より多くのクライアントとサーバーに拡張できるようになります。また、クライアント証明書が要求されたときの通常のCAリストの動作を利用できるようになります。