Клиент Python - SSL lib - проверка сертификата не выполнена
Я пытаюсь сделать небольшой безопасный клиент HTTPS для обучения и посмотреть, как все механики SSL работают на более высоком уровне, поэтому я пытаюсь преобразовать простой сокет в ssl через ssl.wrap_socket.
Я, вероятно, получил всю концепцию назад, но вот что я делаю:
s.connect((host, port))
if port == 443:
f = open('cacerts.txt', 'r')
calist = f.read()
f.close()
ca = ssl.get_server_certificate((host, port), ssl_version=ssl.PROTOCOL_SSLv3|ssl.PROTOCOL_TLSv1)
if not ca in calist:
f = open('cacerts.txt', 'a')
f.write(ca)
f.close()
s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv3|ssl.PROTOCOL_TLSv1, cert_reqs=ssl.CERT_REQUIRED, ca_certs="cacerts.txt")
s.do_handshake()
И когда я вызываю do_handshake(), я получаю следующее:
Traceback (most recent call last):
File "SSL_test.py", line 84, in Requester
s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv3|ssl.PROTOCOL_TLSv1, cert_reqs=ssl.CERT_REQUIRED, ca_certs="cacerts.txt")
File "C:\Python26\lib\ssl.py", line 338, in wrap_socket
suppress_ragged_eofs=suppress_ragged_eofs)
File "C:\Python26\lib\ssl.py", line 120, in __init__
self.do_handshake()
File "C:\Python26\lib\ssl.py", line 279, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [Errno 1] _ssl.c:490: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
Я искал вокруг какое-то время и пытался найти что-то, что было бы близко к тому, что я делаю, но все указывают на PyOpenSSL или Twisted, и я предпочел бы, если бы я мог остаться вне этих библиотек, главным образом потому, что позже я планирую привести его в острую производственную среду, где мне разрешено использовать встроенные библиотеки Python2.6.
Любая помощь будет полезна!
Ответы
Ответ 1
Проблема заключается в том, что вы не можете проверить сертификат самостоятельно (это то, что вы пытаетесь сделать), если оно самоподписано и имеет бит CA. Вы должны добавить настоящий сертификат CA веб-сайта в файл cacerts.txt
. Другая альтернатива (что-то вроде "connect anyway" в веб-браузере) заключается в том, чтобы отбросить cert_reqs
до ssl.CERT_NONE
после получения такого исключения и понять, что в середине может быть человек. Это не проблема модуля ssl
, так работает SSL/X.509.
Ответ 2
Если вы просто учитесь, вы также можете использовать "Анонимный Диффи-Хеллман" , то есть сервер вообще не имеет сертификата, и ваш клиент не хочет его проверять.
Ниже представлен простой (и небезопасный) тест.
Сервер тестирования, любезно предоставленный openssl
пакет:
openssl s_server -nocert -cipher "ALL:aNULL:eNULL"
Проверить клиент в Python
:
...
ssl.wrap_socket(..., ciphers="ALL:aNULL:eNULL")
...
-
Если вы хотите играть с сертификатами, пакет openssl
может генерировать то, что вы хотите, но это немного сложно сделать правильно. Хороший инструмент графического интерфейса TinyCA
, он написан на Perl и использует команды openssl, но предлагает вам достойную структуру для создания собственных центров сертификации, подписывать собственные сертификаты и т.д.
Если вы спешите, просто установите apache, запустите его, ваш дистрибутив (linux или wamp), скорее всего, создаст самозаверяющий сертификат, чтобы вы начали. Настройте apache до точки, где вы можете подключиться к https://localhost
с помощью браузера. Затем используйте этот сервер для подключения, я думаю, вы получите, если вы добавите самозаверяющий сервер CA в список/файл CA вашего клиента.