私はクライアント証明書の問題に苦しんでおり、ここの誰かが私を助けてくれることを願っています. ブーストasioを使用してクライアント/サーバーのペアを開発していますが、具体的でないようにします。私はWindowsを使用しており、openssl 1.0.1eを使用しています
基本的に、クライアント証明書を使用してクライアント認証を行いたいと考えています。サーバーは、自分の CA によって署名された証明書を持つクライアントのみを受け入れます。そのため、自己署名 CA をセットアップしました。これにより、さらに 2 つの証明書が発行されました。1 つはクライアント用、もう 1 つはサーバー用です。どちらも CA によって署名されています。私はそれをかなりの回数行ってきましたが、私はそれを手に入れたと確信しています。
私のサーバー側も正常に動作します。クライアント証明書を要求し、s_client を使用していてそれらの証明書を与えると、すべてが機能します。また、ブラウザーを使用していて、ルート CA を信頼できるものとしてインストールしてから、クライアント証明書をインポートした場合。
私が仕事に就けないのは、libssl クライアントだけです。ハンドシェイク中に常に失敗し、私が見る限り、クライアント証明書を送信しません。
$ openssl.exe s_server -servername localhost -bugs -CAfile myca.crt -cert server.crt
-cert2 server.crt -key private/server.key -key2 private/server.key -accept 8887 -www
-state -Verify 5
verify depth is 5, must return a certificate
Setting secondary ctx parameters
Using default temp DH parameters
Using default temp ECDH parameters
ACCEPT
SSL_accept:before/accept initialization
SSL_accept:SSLv3 read client hello A
SSL_accept:SSLv3 write server hello A
SSL_accept:SSLv3 write certificate A
SSL_accept:SSLv3 write key exchange A
SSL_accept:SSLv3 write certificate request A
SSL_accept:SSLv3 flush data
SSL3 alert read:warning:no certificate
SSL3 alert write:fatal:handshake failure
SSL_accept:error in SSLv3 read client certificate B
SSL_accept:error in SSLv3 read client certificate B
2675716:error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not return a
certificate:s3_srvr.c:3193:
ACCEPT
この s_server をデバッグ ツールとして使用していますが、実際のサーバーに対して同じことが起こります。s_client は同じ証明書で正常に動作します。また、サーバーで「-Verify」を無効にすると、接続が機能します。したがって、クライアントが証明書の送信を拒否しただけのようです。その理由は何ですか?
ブースト asio を SSL ラッパーとして使用しているため、コードは次のようになります。
m_ssl_context.set_verify_mode( asio::ssl::context::verify_peer );
m_ssl_context.load_verify_file( "myca.crt" );
m_ssl_context.use_certificate_file( "testclient.crt", asio::ssl::context::pem );
m_ssl_context.use_private_key_file( "testclient.key", asio::ssl::context::pem );
また、次のように言って、asio をバイパスし、SSL コンテキストに直接アクセスしようとしました。
SSL_CTX *ctx = m_ssl_context.impl();
SSL *ssl = m_ssl_socket.impl()->ssl;
int res = 0;
res = SSL_CTX_use_certificate_chain_file(ctx, "myca.crt");
if (res <= 0) {
// handle error
}
res = SSL_CTX_use_certificate_file(ctx, "testclient.crt", SSL_FILETYPE_PEM);
if (res <= 0) {
// handle error
}
res = SSL_CTX_use_PrivateKey_file(ctx, "testclient.key", SSL_FILETYPE_PEM);
if (res <= 0) {
// handle error
}
動作に違いは見られません。更新できない非常に古いブースト1.43 asioを使用していることに言及する必要がありますが、関連するすべての呼び出しは多かれ少なかれ直接OpenSSLに送信され、サーバーはそのバージョンで正常に動作するため、除外できると思います。
クライアントとサーバーを特定のバージョンに強制し始めると、エラー メッセージは変わりますが、動作せず、常に s_client テストで動作します。現在は TLSv1 に設定されています
たとえば、TLSv1に切り替えると、クライアントとサーバーの間でより多くのおしゃべりがあり、最終的にエラーが発生します:
...
SSL_accept:SSLv3 read client key exchange A
<<< TLS 1.0 ChangeCipherSpec [length 0001]
01
<<< TLS 1.0 Handshake [length 0010], Finished
14 00 00 0c f4 71 28 4d ab e3 dd f2 46 e8 8b ed
>>> TLS 1.0 Alert [length 0002], fatal unexpected_message
02 0a
SSL3 alert write:fatal:unexpected_message
SSL_accept:failed in SSLv3 read certificate verify B
2675716:error:140880AE:SSL routines:SSL3_GET_CERT_VERIFY:missing verify
message:s3_srvr.c:2951:
2675716:error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake failure:s3_pkt.c:989:
ACCEPT
これを参照している openssl メーリング リストに投稿された古いバグ エントリを見つけました。明らかに、2 年前に修正されたハンドシェイクの間違った CRLF です。それともありますか?
私はこれをほぼ1週間デバッグしてきましたが、本当に行き詰まっています。何を試すべきかについて誰か提案がありますか?私はアイデアがありません...
乾杯、ステファン
PS: s_client と同じ証明書を使用した場合の上記の s_server デバッグ アウトは次のとおりです。
$ openssl s_client -CAfile ca.crt -cert testclient.crt -key private/testclient.key -verify 2 -connect myhost:8887
ACCEPT
SSL_accept:before/accept initialization
SSL_accept:SSLv3 read client hello A
SSL_accept:SSLv3 write server hello A
SSL_accept:SSLv3 write certificate A
SSL_accept:SSLv3 write key exchange A
SSL_accept:SSLv3 write certificate request A
SSL_accept:SSLv3 flush data
depth=1 C = DE, // further info
verify return:1
depth=0 C = DE, // further info
verify return:1
SSL_accept:SSLv3 read client certificate A
SSL_accept:SSLv3 read client key exchange A
SSL_accept:SSLv3 read certificate verify A
SSL_accept:SSLv3 read finished A
SSL_accept:SSLv3 write session ticket A
SSL_accept:SSLv3 write change cipher spec A
SSL_accept:SSLv3 write finished A
SSL_accept:SSLv3 flush data
ACCEPT
... ハンドシェイクが完了し、データが転送されます。