web-dev-qa-db-ja.com

SSLが失敗したことを示すアラート「SSL3_READ_BYTES:sslv3 alert bad certificate」

以下のコマンドを実行している間、openssl s_client -Host example.xyz -port 9093

次のエラーが発生します。

_139810559764296:error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate:s3_pkt.c:1259:SSL alert number 42
39810559764296:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:184:
_

しかし、最後に"Verify return code: 0 (ok)"メッセージが表示されます。

私の質問は、上記のアラートが何を意味するか、およびSSLが実際に成功したかどうかです。よろしくお願いいたします。

_SSL handshake has read 6648 bytes and written 354 bytes
New, TLSv1/SSLv3, Cipher is AES128-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol  : TLSv1.2
Cipher    : AES128-SHA
Session-ID: xx
Session-ID-ctx:
Master-Key: xx
Key-Arg   : None
Krb5 Principal: None
PSK identity: None
PSK identity hint: None
Start Time: 1475096098
Timeout   : 300 (sec)
**Verify return code: 0 (ok)**
_
17
kris433

「ハンドシェイクの失敗」とは、ハンドシェイクが失敗し、SSL/TLS接続がないことを意味します。 opensslはシェル(またはCMDなど)に存在し、入力データがサーバーに送信されるのを待たないことがわかります。 「戻りコード0を確認する」は、サーバーの証明書にfoundの問題がなかったことを意味します。これは、まったく確認されなかったか、または確認されて問題がなかったためです。 OpenSSLのチェックはすべてを網羅していません。この場合、プロトコルを知ることで、後者のケースを推測できます。

アラートの受信_bad certificate_(コード42)サーバーが認証を要求することを意味します証明書を使用していないため、ハンドシェイクが失敗しました。 _SSL handshake has read ... and written ..._行の前の数行には、通常_Acceptable client certificate CA names_の後にCAを識別する複数の行が続き、おそらく_Client Certificate Types_で始まる行が続き、_Requested Signature Algorithms_に依存する行もあるはずです。 OpenSSLバージョンとネゴシエートされたプロトコル。

証明書を検索「受諾可能」リストにあるCAによって発行された場合、またはそれが空の場合は、サーバー上のドキュメントまたはサーバーに関するドキュメントを探して、信頼するCAを確認するか、サーバーのオペレーターまたは所有者に連絡してそれらを確認します。 および対応する秘密鍵、両方ともPEM形式、およびそれらを指定 with _-cert $file -key $file_; PEMで可能なように1つのファイルに両方がある場合は、_-cert $file_を使用します。それらが別の形式である場合は、それを指定するか、ここで検索して、おそらくスーパーユーザーとsecurity.SXを探します。さまざまな証明書と秘密鍵のフォーマットの変換に関するQ&Aはすでにたくさんあります。サーバーの構成方法に応じてパブリックCA(社内のものではない)からの証明書の場合によくあるように、証明書に「チェーン」または「中間」証明書(または複数)を検証する必要がある場合、 _s_client_にはトリックが必要です。チェーン証明書をシステムのトラストストアに追加するか、サーバーを検証するために必要なCA証明書を含むローカル/一時トラストストアを作成し、さらにチェーン証明書を追加します。送信する必要があります。

そのような証明書がない場合は、証明書を取得する必要があります。これは、答えるのにはるかに詳細が必要な別の質問であるか、証明書認証を使用せずにサーバーに接続する方法を見つける必要があります。もう一度ドキュメントを確認するか、オペレーター/所有者に問い合わせてください。

編集:コメントから、Javaにクライアントキーと証明書チェーン、およびサーバーアンカーがある可能性があります。チェックすると、そのケースを完全にカバーする適切な既存の回答が見つからないため、これはおそらくうまく検索されませんが:

_# Assume Java keystore is type JKS (the default but not only possibility)
# named key.jks and the privatekey entry is named mykey (ditto)
# and the verify certs are in trust.jks in entries named trust1 trust2 etc.

# convert Java key entry to PKCS12 then PKCS12 to PEM files
keytool -importkeystore -srckeystore key.jks -destkeystore key.p12 -deststoretype pkcs12 -srcalias mykey 
openssl pkcs12 -in key.p12 -nocerts -out key.pem
openssl pkcs12 -in key.p12 -nokeys -clcerts -out cert.pem
openssl pkcs12 -in key.p12 -nokeys -cacerts -out chain.pem
# extract verify certs to individual PEM files
# (or if you 'uploaded' PEM files and still have them just use those)
keytool -keystore trust.jks -export -alias trust1 -rfc -file trust1.pem
keytool -keystore trust.jks -export -alias trust2 -rfc -file trust2.pem
... more if needed ...
# combine for s_client 
cat chain.pem trust*.pem >combined.pem
openssl s_client -connect Host:port -key key.pem -cert cert.pem -CAfile combined.pem
_
27

私の場合、秘密鍵が証明書と一致しなかったときにこのエラーが発生しました。私が失効したときに証明書を更新し、新しい秘密鍵を作成する必要がありました。しかし、私はそれを自分のアプリで参照するのを忘れていました。新しい秘密鍵をポイントすると、このエラーはなくなりました。

1
Blake