Requests: SSLError "不正なハンドシェイク:エラー([( 'SSLルーチン'、 'tls_process_server_certificate'、 '証明書の検証に失敗しました')]、)自己署名証明書

作成日 2017年11月10日  ·  12コメント  ·  ソース: psf/requests

こんにちは。 httpsでサーバーに接続しようとしています。 検証パラメータに含まれている自己署名証明書である証明書がありますが、結果は「証明書の検証に失敗しました」というエラーになります。 証明書が(Microsoft IISによって)自己署名されていることに関係しているのではないかと思っていましたが、curlを使用すると機能します。
前もって感謝します!

これはopensslの出力です。

openssl s_client -showcerts -connect server:44300
CONNECTED(00000003)
depth=0 CN = server
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = server
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/CN=server
   i:/CN=server
-----BEGIN CERTIFICATE-----
<certificate data here>
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=server
issuer=/CN=server
---
No client certificate CA names sent
Peer signing digest: SHA1
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 1477 bytes and written 431 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: CC4A000083B1E03B446416C9C0B16CBEAB79949E3CF5C936A309A6F92FA01364
    Session-ID-ctx:
    Master-Key: 798A570B0EC2A0CBB7C4C4DE6167E7579A92239942D869CD794B8BEBEA6EB5E492394634AD32665A8BB829DE1F3858D2
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1510329948
    Timeout   : 300 (sec)
    Verify return code: 21 (unable to verify the first certificate)
---

期待される結果

証明書がverifyパラメーターに含まれているため、接続が失敗しないことを期待しています。 Pythonの外でcurlを使って同じことを試してみると、うまくいきます。

curl https://server:44300 --cacert /usr/share/ca-certificates/server.crt
 HTTP/1.1 403 Forbidden
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Content-Length: 1158
Content-Type: text/html
Server: Microsoft-IIS/10.0
X-Frame-Options: SAMEORIGIN
P3P: CP=None
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS
Access-Control-Allow-Headers: X-Requested-With,Content-Type
Access-Control-Allow-Credentials: true
Date: Fri, 10 Nov 2017 16:02:26 GMT

(失敗しますが、証明書の問題が原因ではありません)

実結果

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "xxxxx/TestVirtualEnv/local/lib/python2.7/site-packages/requests/api.py", line 72, in get
    return request('get', url, params=params, **kwargs)
  File "xxxxx/TestVirtualEnv/local/lib/python2.7/site-packages/requests/api.py", line 58, in request
    return session.request(method=method, url=url, **kwargs)
  File "xxxxx/TestVirtualEnv/local/lib/python2.7/site-packages/requests/sessions.py", line 508, in request
    resp = self.send(prep, **send_kwargs)
  File "xxxxx/TestVirtualEnv/local/lib/python2.7/site-packages/requests/sessions.py", line 618, in send
    r = adapter.send(request, **kwargs)
  File "xxxxx/TestVirtualEnv/local/lib/python2.7/site-packages/requests/adapters.py", line 506, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='nlybstqvp4nb75n.code1.emi.philips.com', port=44300): Max retries exceeded with url: / (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')],)",),))

複製手順

import requests
requests.get('https://server:44300', verify='/usr/share/ca-certificates/server.crt')

システムインフォメーション

$ python -m requests.help
{
  "chardet": {
    "version": "3.0.4"
  },
  "cryptography": {
    "version": "2.1.3"
  },
  "idna": {
    "version": "2.6"
  },
  "implementation": {
    "name": "CPython",
    "version": "2.7.12"
  },
  "platform": {
    "release": "4.10.0-38-generic",
    "system": "Linux"
  },
  "pyOpenSSL": {
    "openssl_version": "1010007f",
    "version": "17.3.0"
  },
  "requests": {
    "version": "2.18.4"
  },
  "system_ssl": {
    "version": "1000207f"
  },
  "urllib3": {
    "version": "1.22"
  },
  "using_pyopenssl": true
}

このコマンドは、Requestsv2.16.4以降でのみ使用できます。 さもないと、
システムに関する基本的な情報をいくつか提供してください(Pythonバージョン、
オペレーティングシステム、&c)。

最も参考になるコメント

Python requestsモジュールの初心者で、安全なサイトへのアクセスが必要な作業を行いたい場合は、このエラーによって運命づけられる可能性が高くなります- Certificate verify failedそしてすべての初心者プログラマーのようにauth = session.post( mysecureurl, verify=false)を使用したくなるでしょう

しかし、これは非常に悪い習慣であり、多くのSO投稿では推奨されていませんが、エラーを修正するのが非常に難しいため、初心者はこれを誤用します。
この問題に光を当ててみましょう。
Python(pip)とConda、およびPythonベースのソフトウェアはすべて、すべてのブラウザと同じように個別の証明書ストアを使用します。 Python Requestsライブラリは、デフォルトで独自のCAファイルを使用するか、インストールされている場合はcertifiパッケージの証明書バンドルを使用します。 また、pipはcurlとは異なり、システム証明書を使用しません。
したがって、 requestsの場合は、condaまたはpipを使用して証明書ストアを手動で指定する必要があります。

Tldr;

  1. ここに表示されているこのすばらしいブログに従って、ブラウザを使用してすべての.cerエンコードされた証明書チェーンをエクスポートします。 ブログはcondacertstoreではなくgitcertstoreに関するものであり、ルートをエクスポートするように指示されているだけですが、すべての証明書チェーンを別々のファイルにエクスポートしたことに注意してください。
  2. 次に、コマンドpip install certifi $を使用してcertifiをインストールします
  3. condaまたはpythonの証明書ストアのデフォルトパスを確認します。

import ssl
ssl.get_default_verify_paths()または
import certifi
certifi.where()

  1. デフォルトのcacert.pemファイルを見つけたら、これを(できればNotepad ++で)開き、ファイルの最後にすべての証明書を追加します。 (証明書の境界-----BEGIN CERTIFICATE----------END CERTIFICATE-----に注意してください)。 ファイルを保存すると、それだけです。
    または、condaを使用している場合は、condaコマンドを使用します。
    conda config --set ssl_verify <pathToYourFile>.crt
    (このコマンドがC:\Users\johndoe\.condarcのものを更新することに気づきました)

  2. 以下のコードを使用して確認します。
    import certifi
    auth = session.post('https://mysecuresite.com/', cert=());

また、Linuxを使用している場合は、このリンクを使用して、カスタムcacertをシステム全体またはユーザープロファイル( .bashrcまたは.bash_profile )にエクスポートできます。

全てのコメント12件

ところで、これはUbuntu16.04です

このエラーは、証明書自体が何らかの形で無効であるためにほぼ確実に発生します。 PEMでエンコードされた証明書自体を提供できますか?

やあ。 迅速な回答をありがとう。 これは証明書です:
-----証明書の開始-----
MIID3TCCAsWgAwIBAgIIU / nMdlbWojMwDQYJKoZIhvcNAQELBQAwMDEuMCwGA1UE
AwwlTkxZQlNUUVZQNE5CNzVOLmNvZGUxLmVtaS5waGlsaXBzLmNvbTAeFw0xNzEx
MTAwMDAwMDBaFw0yNzExMTAwMDAwMDBaMDAxLjAsBgNVBAMMJU5MWUJTVFFWUDRO
Qjc1Ti5jb2RlMS5lbWkucGhpbGlwcy5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQC3mzWep6k1 / FbkzzoyZ8QBy / tE8adfwKvw80zaLL + car1bBZ9U
VIXs4es3babtjD3QJWP5 / mwoBdIp8gvQkjA1X7RBNJZXbPz6hGR4eqaeRQLrFV9Y
TtB92MA9CDpCXfalCvzzO1jw3zvP1BHUdnTQEwSnnwtf / Ryaud + e7TDxGq8LThmc
glZgO8d2zaYpIjwWx92bXDF / qlqWBkH5mtKIkWOw6Y71xz0Di62cFrMAPEGBjK3c
szpBa5Ttb9 + SFtl16t2xDyCbiPFkoMW / 4u3Husy / i18hLhEuQwZMHnWsocm + etZ4
8fDt5Bqhab8zC + LKS + Ll7qZdqMHzobeB6j5JAgMBAAGjgfowgfcwXwYDVR0jBFgw
VoAUGdJ3os9nPtTubuwcy1ugtDMdSMChNKQyMDAxLjAsBgNVBAMMJU5MWUJTVFFW
UDROQjc1Ti5jb2RlMS5lbWkucGhpbGlwcy5jb22CCFP5zHZW1qIzMB0GA1UdDgQW
BBQZ0neiz2c + 1O5u7BzLW6C0Mx1IwDAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIE
sDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwOwYDVR0RBDQwMoIlTkxZ
QlNUUVZQNE5CNzVOLmNvZGUxLmVtaS5waGlsaXBzLmNvbYIJbG9jYWxob3N0MA0G
CSqGSIb3DQEBCwUAA4IBAQC0MtflowNB4LTLKD1MW3w0QIY5ale3 / sEhNCQgHGN5
iNZJptFuFt5jgPGmFjy0Pb5vLMS / Ag1RF3UgTeZzFnaSgyB4mTnwj1gLdwQidVcr
2SlL7TffCj0m / bYjtNbwExRqXE4pQKb5RKwYwpruZaX / G3oHWOG9 + 2X9Pw5C42zB
OFE4KvYUwOV + noabXvil8LERIdKYxR / 2B6qBiwm47IcioqM07zTYLHJ + WDTEMO2k
Qy51yXwFmeOEr5MIBElYCQ0j2AfI4RCXr + 2cyUym7tjEr3 / I8EsZ5Crvdf ++ Gwaz
2A05ScPMr + 5yfVXygZCenMTwNAyUY1yN9zVj8 / n94Psa
-----証明書の終了-----
私は完全に有効ではないことを知っています。 しかし、どういうわけかカールはそれを受け入れることができます。 なぜリクエストが同じことをしないのか疑問に思いました。 どちらもopensslを使用して証明書を検証すると想定しました。

これに関する更新はありますか? また、Pythonリクエストライブラリの自己署名認定サイトで問題が発生しています。

以下のエラーが発生します。

requests.get( 'https://10.10.24.20'、verify =' / etc / ssl / certs / certSIGN_ROOT_CA.pem ')
トレースバック(最後の最後の呼び出し):
ファイル ""、1行目、
ファイル "/usr/local/lib/python2.7/dist-packages/requests/api.py"、72行目、get
return request( 'get'、url、params = params、 * kwargs)ファイル "/usr/local/lib/python2.7/dist-packages/requests/api.py"、58行目、リクエストsession.request(method = method、url = url、* kwargs)を返します
ファイル "/usr/local/lib/python2.7/dist-packages/requests/sessions.py"、行508、リクエスト
resp = self.send(prep、 * send_kwargs)ファイル "/usr/local/lib/python2.7/dist-packages/requests/sessions.py"、行618、送信r = adapter.send(request、* kwargs)
ファイル "/usr/local/lib/python2.7/dist-packages/requests/adapters.py"、行506、送信
SSLError(e、request = request)を発生させます
requests.exceptions.SSLError:HTTPSConnectionPool(host = '10 .10.24.20 '、port = 443):URLで最大再試行回数を超えました:/(SSLError(SSLError( "bad handshake:Error([(' SSLroutines '、' tls_process_server_certificate '、'証明書の検証に失敗しました ')]、) "、)、))

Falseを検証し続けると機能しますが、verify = Trueでそれが必要です

これは前に見たことがなかったので、新しい号を開きました。申し訳ありません。 しかし、私は同じ問題に直面しています。 私の場合、verify = Falseでも「request」は失敗します。

$ python
Python 2.7.13(デフォルト、2017年1月19日、14:48:08)
[GCC 6.3.0 20170118] linux2で
詳細については、「help」、「copyright」、「credits」、または「license」と入力してください。

インポートリクエスト
requests.get( "https:// localhost:9000 / getcpuinfo"、verify = False)
トレースバック(最後の最後の呼び出し):
ファイル ""、1行目、
ファイル "/usr/lib/python2.7/dist-packages/requests/api.py"、行70、get
return request( 'get'、url、params = params、 * kwargs)ファイル "/usr/lib/python2.7/dist-packages/requests/api.py"、56行目、リクエストsession.request(method = method、url = url、* kwargs)を返します
ファイル "/usr/lib/python2.7/dist-packages/requests/sessions.py"、行488、リクエスト
resp = self.send(prep、 * send_kwargs)ファイル "/usr/lib/python2.7/dist-packages/requests/sessions.py"、行609、送信r = adapter.send(request、* kwargs)
ファイル "/usr/lib/python2.7/dist-packages/requests/adapters.py"、行497、送信
SSLError(e、request = request)を発生させます
requests.exceptions.SSLError :( "不正なハンドシェイク:SysCallError(-1、 '予期しないEOF')"、)

私のローカル証明書情報は、

$ openssl s_client -showcerts -connect localhost:9000
CONNECTED(00000003)
depth=0 CN = localhost
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = localhost
verify return:1
write:errno=0
---
Certificate chain
 0 s:/CN=localhost
   i:/CN=localhost
-----BEGIN CERTIFICATE-----
MIIC/jCCAeagAwIBAgIJAKATu2AY/QT4MA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
BAMMCWxvY2FsaG9zdDAeFw0xNzExMDkyMTQ1NTBaFw0xNzEyMDkyMTQ1NTBaMBQx
EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAJTPk5nao0wG/EDFGnq7BvXMkEZ5oUVq7PAUxWi+E/byJk924l7Z5kACgWBa
zQL0lLXLpdMk97EFGWMblz5Ehtqh7U8HaE9OZ6x/pesDTka+REnpXecklRrdZHX7
lfFnNIU58grPpB2GyUXrRdOtcPlaKXUo+VTd7PgwMtYVtt8pyTWxSB2MMYrqJGT8
78KX6trRzQLm7tas3U0jD59+R8j7gxU6FyFaNJBrkJ5T9kHGKOsAzSqZdCgRBjl5
i7xcXJfOAAnZ3jhGlY5DQht+HZDHhjkLG9kcZZhFDYteFk8drzbd3lBw96nLq+8A
Sy92FtQL4GiYSwZ0WVAmwmTCGjUCAwEAAaNTMFEwHQYDVR0OBBYEFLYjwGKbcV9h
sYHxe8l9UvXVivByMB8GA1UdIwQYMBaAFLYjwGKbcV9hsYHxe8l9UvXVivByMA8G
A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHl7okBCJlms+cwfzLhs
sbyyuX2wgngxyvjy497zBmeh1TiueGPhOx9u/sfJSZmoUaeRd/zPGkp2DcPQ+Lo2
EHYrXMPE1Ecgpu/15JZ8jNuE+FwZb9lllULLwzq8pDkdbdsSRltdV/rFlZ2YkscB
c+xvVaCltw5KpKnY6AWHoqwoDcd8TZKzyKXLSuluKbHNC1lvg8cMzs6hFA9P92Ae
9P08AKLAIOGJ7QzRrXQIsAO4p9rHheeZeYQZyNiRrXPQUoWos4+OjynaNs+FabhN
XBtSl/GGPRRRfU/D9v4iKfQx15CEvs1AKn1Z6mIPF05pSqbgIoz2mJBV6UM7e+hz
TRs=
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=localhost
issuer=/CN=localhost
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 1198 bytes and written 302 bytes
Verification error: self signed certificate
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: 
    Session-ID-ctx: 
    Master-Key: 5311B8500C8AF327083E1465FE1E1A6A98E0996B4791150A01D6B130C7F0549909A4BDCDED388E9EDE124BB6C50E150A
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1510599077
    Timeout   : 7200 (sec)
    Verify return code: 18 (self signed certificate)
    Extended master secret: no
---

この問題を乗っ取らないでください。 一般に、これらの質問をするためにStack Overflowを使用する必要があります。リクエストで問題をオーバーロードすると、私はそれを閉じようとします。

@ sg77証明書にはCA=FALSEのマークが付いているため、証明書を発行する資格がありません。 curlは、この証明書をルートCAとしてではなく、ピンとして使用するようにコードをカスタマイズしていると思われます。 要求はそれを行いません。この証明書はルートCAになることができないため、検証されません。

CA=TRUEを使用して新しい証明書を作成するか、BasicConstraintsを完全に省略することをお勧めします。

@ ashwini-kaklij証明書が表示されないため、検証が失敗する理由がわかりません。 ここに投稿しないでください:代わりにStackOverflowに質問を送信してください。

@uttampawarエラーは、サーバーが何らかの理由でTLSハンドシェイクを好まないことが原因で発生します。 詳細がないので、理由を特定できません。 もう一度、StackOverflowに質問してください。

@Lukasa私は問題をハイジャックするつもりはありませんでした。 これは間違った場所かもしれません。 似たような性質のものを見たので、コメントと観察を追加しました。 フィードバックをいただければ幸いです。 stackoverflowについてお聞きします。 ありがとう。

この問題を乗っ取らないでください。 一般に、これらの質問をするためにStack Overflowを使用する必要があります。リクエストで問題をオーバーロードすると、私はそれを閉じようとします。

@ sg77証明書にはCA=FALSEのマークが付いているため、証明書を発行する資格がありません。 curlは、この証明書をルートCAとしてではなく、ピンとして使用するようにコードをカスタマイズしていると思われます。 要求はそれを行いません。この証明書はルートCAになることができないため、検証されません。

CA=TRUEを使用して新しい証明書を作成するか、BasicConstraintsを完全に省略することをお勧めします。

@ ashwini-kaklij証明書が表示されないため、検証が失敗する理由がわかりません。 _ここに投稿しないでください_:代わりにStackOverflowに質問を送信してください。

@uttampawarエラーは、サーバーが何らかの理由でTLSハンドシェイクを好まないことが原因で発生します。 詳細がないので、理由を特定できません。 もう一度、StackOverflowに質問してください。

こんにちはルカサ-あなたの返事を見たところです。 @ sg77に「証明書にはCA=FALSEのマークが付いています」と返信しました。

これが間違っていることをどのように判断し、どこで/どのようにこれをTRUEに戻すことができますか?

ありがとう。

証明書キーをオンラインで投稿することは、パスワードを投稿することに似ています

@Synida

証明書キーをオンラインで投稿することは、パスワードを投稿することに似ています

うーん、いや。 証明書の秘密鍵を投稿することは、パスワードと同じです。

ビジネスのすべてのCAは、すべての主流のOSとブラウザに証明書を持っています。 彼らはみんなにパスワードを渡していますか?

https://en.wikipedia.org/wiki/Public-key_cryptography

このエラーは、証明書自体が何らかの形で無効であるためにほぼ確実に発生します。 PEMでエンコードされた証明書自体を提供できますか?

この証明書にアクセスするにはどうすればよいですか?

Python requestsモジュールの初心者で、安全なサイトへのアクセスが必要な作業を行いたい場合は、このエラーによって運命づけられる可能性が高くなります- Certificate verify failedそしてすべての初心者プログラマーのようにauth = session.post( mysecureurl, verify=false)を使用したくなるでしょう

しかし、これは非常に悪い習慣であり、多くのSO投稿では推奨されていませんが、エラーを修正するのが非常に難しいため、初心者はこれを誤用します。
この問題に光を当ててみましょう。
Python(pip)とConda、およびPythonベースのソフトウェアはすべて、すべてのブラウザと同じように個別の証明書ストアを使用します。 Python Requestsライブラリは、デフォルトで独自のCAファイルを使用するか、インストールされている場合はcertifiパッケージの証明書バンドルを使用します。 また、pipはcurlとは異なり、システム証明書を使用しません。
したがって、 requestsの場合は、condaまたはpipを使用して証明書ストアを手動で指定する必要があります。

Tldr;

  1. ここに表示されているこのすばらしいブログに従って、ブラウザを使用してすべての.cerエンコードされた証明書チェーンをエクスポートします。 ブログはcondacertstoreではなくgitcertstoreに関するものであり、ルートをエクスポートするように指示されているだけですが、すべての証明書チェーンを別々のファイルにエクスポートしたことに注意してください。
  2. 次に、コマンドpip install certifi $を使用してcertifiをインストールします
  3. condaまたはpythonの証明書ストアのデフォルトパスを確認します。

import ssl
ssl.get_default_verify_paths()または
import certifi
certifi.where()

  1. デフォルトのcacert.pemファイルを見つけたら、これを(できればNotepad ++で)開き、ファイルの最後にすべての証明書を追加します。 (証明書の境界-----BEGIN CERTIFICATE----------END CERTIFICATE-----に注意してください)。 ファイルを保存すると、それだけです。
    または、condaを使用している場合は、condaコマンドを使用します。
    conda config --set ssl_verify <pathToYourFile>.crt
    (このコマンドがC:\Users\johndoe\.condarcのものを更新することに気づきました)

  2. 以下のコードを使用して確認します。
    import certifi
    auth = session.post('https://mysecuresite.com/', cert=());

また、Linuxを使用している場合は、このリンクを使用して、カスタムcacertをシステム全体またはユーザープロファイル( .bashrcまたは.bash_profile )にエクスポートできます。

このページは役に立ちましたか?
0 / 5 - 0 評価