web-dev-qa-db-ja.com

クライアント証明書を使用しようとしたときのsslv3アラートハンドシェイクエラーの解決

認証に証明書が必要なサービスに接続しようとしています。プロセスは、サービスにCSRファイルを送信することです。サービスはCSRに署名し、接続に使用する証明書を送信します。

  1. 次のコマンドラインでCSRを生成しました。

    openssl req -new -nodes -newkey rsa:2048 -keyout cert.key -out cert.csr
    
  2. Cert.csrの内容を受け取って送信しました。クライアント証明書が生成され、PEMファイルが返されました。

  3. Curl()のSSLCERTで証明書ファイルを使用して接続し、cert.keyの秘密鍵をCURLOPT_SSLKEYとして提供しようとしています(ステップ1で取得しました)。

  4. 次で失敗します:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure

このプロセスで何が間違っていますか?

動作しますサービスから秘密鍵を含むテスト証明書(自己署名証明書)を受け取って試してみると。しかし、CSRから生成された証明書を使用し、秘密キーをキーとして使用すると、ハンドシェイクエラーでエラーが発生します。

だから私はそれがopenssl/curlがv3/TLSなどをサポートしていないこととは関係がないことを知っています.

私が実行するものは次のとおりです。

  curl -i -v --request POST https://service.com/ --cert clientcert.pem --key private_key.pem --cert-type pem --tlsv1.1 --insecure
* Connected to service.com (1xx.xxx.xxx.xx) port 443 (#0)
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Request CERT (13):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS handshake, CERT verify (15):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS alert, Server hello (2):
* error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
* Closing connection 0

以下のバージョンの実行:curl 7.35.0(x86_64-pc-linux-gnu)libcurl/7.35.0 OpenSSL/1.0.1f zlib/1.2.8 libidn/1.28 librtmp/2.3

11
Karem

明確な答えではありませんが、コメントに収めるには多すぎます。

間違った発行者(ただし、サーバーcouldはより具体的なアラートコードを使用しますが)または間違ったサブジェクトを持っている証明書を与えたと仮定します。 curlopenssl clientの両方が不一致を訴えることなくペアになっているため、証明書がプライベートキーと一致することがわかります。ただし、curlはopensslを使用し、SSLクライアントはopensslを使用するため、設定されたクライアント証明書がcertreq.CAと一致することを強制しないため、実際に目的のCAと一致することはわかりません。

動作するテストP12の証明書でopenssl x509 <clientcert.pem -noout -subject -issuerと同じ操作を行います。 openssl s_clientを実行(または実行したものを確認)し、Acceptable client certificate CA namesの下を確認します。そこの名前またはそれらの1つが、証明書の発行者と(正確に!)一致する必要があります。そうでない場合、それがあなたの問題である可能性が高く、CSRを正しい場所に正しい方法で提出したことを確認する必要があります。おそらく、彼らは異なる地域、またはビジネスライン、テスト対製品、またはアクティブ対保留中などに異なる体制を持っています。

証明書の発行者が希望のCAと一致する場合、そのサブジェクトを実際の(テストP12)CAと比較します。それらは同様の形式ですか?動作しているコンポーネントにコンポーネントがありませんか?許可されている場合は、test-P12のサブジェクト名とまったく同じサブジェクト名、または取得できる限り近いサブジェクト名を使用して新しいCSRを生成および送信してみてください。 (これを行うために新しいkeyを生成する必要はありませんが、選択する場合は、どの証明書がどのキーと一致するかを追跡し、混同しないようにします。) KeyUsage、ExtendedKeyUsage、多分Policy、Constraints、または非標準的なものなど、サブジェクトの承認に合理的に関連する可能性のある違いについては、openssl x509 <cert -noout -textを使用して証明書の拡張子を調べるのは助けになりません。

他のすべてが失敗した場合は、サーバーオペレーターに問題についてログに何が記載されているか、またはログを自分でアクセスできるかどうかを尋ねます。

4

どのSSL秘密鍵をクライアント証明書とともに送信する必要がありますか?

そのなかで何も :)

クライアント証明書の魅力的な点の1つは、秘密(パスワードなど)をサーバーにプレーンテキスト(HTTP basic_auth)で送信するなど、愚かなことをしないことです。パスワードは引き続きクライアント証明書のキーのロック解除に使用されますが、クライアントの交換やtp認証中に直接使用されることはありません。

代わりに、クライアントはそのセッション用の一時的なランダムキーを選択します。次に、クライアントは証明書を使用して一時的なランダムキーに署名し、サーバーに送信します(一部の手は放棄します)。悪者が何かを傍受した場合、それはランダムなので、将来使用することはできません。サーバーは新しいランダムな値も選択するため、サーバーでのプロトコルの2回目の実行にも使用できません。


次のエラーで失敗します:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure

TLS 1.0以降を使用します。そして Server Name Indication を使用します。

あなたはコードを提供していないので、何をすべきかをどのように伝えるかは私には明確ではありません。代わりに、テスト用のOpenSSLコマンドラインを次に示します。

openssl s_client -connect www.example.com:443 -tls1 -servername www.example.com \
    -cert mycert.pem -key mykey.pem -CAfile <certificate-authority-for-service>.pem

-CAfileを使用して、「verify error:num = 20」を回避することもできます。たとえば、 gateway.sandbox.Push.Apple.comへの接続時の「verify error:num = 20」 を参照してください。

5
jww