#python #python-3.x #ssl #openssl #tls1.2
#python #python-3.x #ssl #openssl #tls1.2
Вопрос:
Запуск Python3.6.
У меня есть пакет сертификатов в формате pem, то есть сертификат сервера и его CA-сертификат. контекст ssl load_cert_chain(‘aws-bundle.pem’) выдает ошибку SSL. У других библиотек, таких как urllib, возникают проблемы с проверкой сертификата из транзакции HTTPS.
Вот как выглядит этот файл пакета (с пропущенными строками):
-----BEGIN CERTIFICATE-----
MIIESTCCAzGgAwIBAgITBn UV4WH6Kx33rJTMlu8mYtWDTANBgkqhkiG9w0BAQsF
. . .
yLyKQXhw2W2Xs0qLeC1etA jTGDK4UfLeC0SF7FSi8o5LL21L8IzApar2pR/
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgITBn USionzfP6wq4rAfkI7rnExjANBgkqhkiG9w0BAQsF
. . .
akcjMS9cmvqtmg5iUaQqqcT5NJ0hGA==
-----END CERTIFICATE-----
Вот выдержки из моей расшифровки ipython:
In [33]: import ssl
In [34]: context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
In [35]: context.load_cert_chain('aws-bundle.pem')
---------------------------------------------------------------------------
SSLError Traceback (most recent call last)
<ipython-input-38-c955611be04f> in <module>
----> 1 context.load_cert_chain('aws-bundle.pem')
SSLError: [SSL] PEM lib (_ssl.c:3520)
Кстати, инструмент командной строки openssl может отлично работать с этими метаданными bundle — dump в виде текста.
Кстати, я также был бы готов поспорить, что библиотека запросов справится с моими потребностями, но я имею дело с контекстом, в котором было бы более желательно не устанавливать дополнительные пакеты.
Ответ №1:
Вероятно, вам нужно использовать load_verify_locations
вместо load_cert_chain
.
Посмотрите документацию:
SSLContext.load_cert_chain(certfile, keyfile=None, password=None)
Загрузите закрытый ключ и соответствующий сертификат. Строка certfile должна быть путем к одному файлу в формате PEM
, содержащему сертификат, а также любое количество сертификатов CA
, необходимых для установления подлинности сертификата. Строка ключевого
файла, если она присутствует, должна указывать на файл, содержащий закрытый ключ
. В противном случае закрытый ключ также будет взят из certfile. См
. Обсуждение сертификатов для получения дополнительной информации о том, как
сертификат хранится в файле сертификата.
Внимательно обратите внимание на: Загрузите закрытый ключ и соответствующий сертификат.
Вы не предоставляете ключ в своем вызове, поэтому он будет искать его внутри вашего файла «certificate» и, не найдя его, он заблеет, для более длинных объяснений, которые я написал ниже, прежде чем понял, что вы не использовали соответствующий метод.
Кстати, возможно, вы на самом деле смешиваете load_cert_chain
load_verify_locations
. load_cert_chain
для загрузки ВАШЕГО сертификата (с прикрепленными к нему дополнительными сертификатами CA) и связанного с ним закрытого ключа, А НЕ для загрузки сертификатов CA / intermediate, это делается с load_verify_locations
помощью .
Ваш «пакет» либо не является вашим сертификатом, либо не содержит закрытого ключа. Судя по названию, я полагаю, что на самом деле это сертификаты CA / intermediate, а не ваш сертификат, поэтому я думаю, что вы смешали два разных метода.
Предыдущая диагностика внутри _ssl.c
, чтобы понять ошибку
Просматривая исходные тексты Python 3.6.8, строка 3520 из _ssl.c
(https://github.com/python/cpython/blob/3c6b436a57893dd1fae4e072768f41a199076252/Modules/_ssl.c ) идеально соответствует ошибке:
_setSSLError(NULL, 0, __FILE__, __LINE__);
(почему это сделано так загадочно без каких-либо подробностей, просто ускользает от меня).
Если вы дважды проверите, вы, скорее всего, находитесь в соответствующем месте относительно вашего вызова, поскольку функция, в которой это появляется, является _ssl__SSLContext_load_cert_chain_impl
.
Теперь, если вы изучите приведенный выше код, который приводит к этой строке, вы придете к:
r = SSL_CTX_use_PrivateKey_file(self->ctx,
PyBytes_AS_STRING(keyfile ? keyfile_bytes : certfile_bytes), SSL_FILETYPE_PEM);
И здесь что-то не удалось. Так что, судя по названию it ( SSL_CTX_use_PrivateKey_file
), я полагаю, проблема связана с вашим закрытым ключом, прикрепленным к сертификату, поэтому вы можете перестать просматривать содержимое пакета сертификатов!
К сожалению, я понятия не имею, в чем может быть проблема с закрытым ключом, но я думаю, вы могли бы начать очевидный путь проверки:
- путь к нему в порядке
- все ли разрешения для файла в порядке
- содержимое в порядке
Почему это делается там? Вероятно, потому, что код позже делает:
r = SSL_CTX_check_private_key(self->ctx);
следовательно, он гарантирует, что закрытый ключ соответствует вашему сертификату.
И если у вас действительно возникла проблема с файлом пакета, это сделано выше:
r = SSL_CTX_use_certificate_chain_file(self->ctx, PyBytes_AS_STRING(certfile_bytes));
Если это не удастся, это вызовет ошибку в строке 3499, и, следовательно, вы, вероятно, будете иметь вместо этого в stacktrace:
SSLError: [SSL] PEM lib (_ssl.c:3499)
Опять же, мне совершенно непонятно, почему разработчики этих библиотек и оболочек поверх библиотек просто решают создавать такие загадочные сообщения об ошибках, кроме как причинять страдания всем пользователям. В принципе, без изучения исходного кода невозможно понять, что происходит…
И даже в этом случае в исходном коде нет абсолютно никаких комментариев, но, возможно, в некоторых частях он все равно был автоматически сгенерирован.
Комментарии:
1. Спасибо за вашу помощь. Отличная детективная работа! И мне нравится ваша критика сообщения об ошибке!
2. Могу ли я загрузить файл как текст, а не как фактический файл? пожалуйста, посоветуйте, как
3. @shareef вы имеете в виду использование встроенной функции
open()
?