SSL в Python: почему он не отправляет сертификат на сервер?

Я пишу какое-то программное обеспечение, которое должно получать информацию с веб-страницы, защищенной SSL. Ниже приведен фрагмент кода, который я использую для подключения к серверу.

s = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.wrap_socket (
    s,
    ca_certs = '/home/stilz/Desktop/Certyfikaty/GLOWNE_CA.cer',
    cert_reqs = ssl.CERT_REQUIRED,
    ssl_version = ssl.PROTOCOL_SSLv3,
)
ssl_sock.connect ((HOST, PORT))

Однако это не работает. Он выдает исключение с сообщением «Ошибка оповещения о рукопожатии». Я перехватил несколько TCP-пакетов, исходящих из моего скрипта, а также соответствующие пакеты из Internet Explorer и выяснил, что мой скрипт вообще не отправляет сертификат (сервер возвращает что-то вроде «Неустранимая ошибка: сертификат не предоставлен»), в то время как IE отправляет его нормально. Насколько я знаю, файл ca.cer является сертификатом x509 (начинается с "-----BEGIN CERTIFICATE-----").

Пожалуйста, помогите мне и скажите, что я делаю неправильно. Если я предоставил мало информации, пожалуйста, дайте мне знать.

С Уважением


person stilz    schedule 25.06.2011    source источник
comment
Добро пожаловать в СО. Вы можете обновить свой вопрос, отредактировав его. Вы можете голосовать за вопросы (голосовать за или против), и если вы получите ответ, который удовлетворяет ваши потребности и отвечает на ваш вопрос, вы можете пометить его как ответ   -  person Eugene Mayevski 'Callback    schedule 25.06.2011
comment
Согласен с @Eugene. Вы могли бы сказать в вопросе, что речь идет об использовании сертификата/закрытого ключа, который находится на смарт-карте, под Windows (если он под Windows? ... /home/stilz/Desktop/ не похоже).   -  person Bruno    schedule 25.06.2011


Ответы (2)


Прежде всего, вам нужно определить, нужно ли вам аутентифицировать себя на сервере (сертификат отправляется на сервер только в этом случае) или вам нужно проверять подлинность сервера (в этом случае сертификат не отправляется на сервер).

Теперь о проблемах в вашем коде:

Случай 1: вам не нужно проходить аутентификацию на сервере. В этом случае вам не нужно указывать свой сертификат, и на сервер ничего не отправляется.

Случай 2: вам нужно аутентифицировать себя на сервере. В этом случае вам необходимо указать свой сертификат и файл закрытого ключа в параметрах keyfile и certfile. Только после этого ваш сертификат отправляется на сервер (и при рукопожатии используется закрытый ключ).

Я предполагаю, что у вас есть случай 1 на самом деле. Итак, прежде всего вам нужно проверить, предоставляет ли сервер действительный сертификат, подключившись к нему с помощью веб-браузера и проверив цепочку сертификатов сайта. Может случиться так, что сайт отправляет свой сертификат, но пропускает промежуточные сертификаты CA.

В любом случае я хотел бы напомнить о обсуждении сертификатов в документации по Python. который я предлагаю вам перечитать.

person Eugene Mayevski 'Callback    schedule 25.06.2011
comment
Видимо, я не читал тот раздел, который вы указали. Это объясняет, как все работает. Теперь мне нужно получить закрытый ключ (и файл сертификата, и открытый/закрытый ключи находятся на смарт-карте). Помощь будет оценена по достоинству (см. комментарии ниже следующего поста). заранее спасибо - person stilz; 25.06.2011

Если сервер запрашивает (и требует) сертификат для отправки клиентом, вам необходимо указать ssl.wrap_socket путь к вашему сертификату (certfile) и соответствующий ему закрытый ключ (keyfile). Параметр ca_certs используется только для того, чтобы клиент сверял сертификат сервера с известными сертификатами ЦС, он не имеет ничего общего с отправкой клиентского сертификата.

Возможно, вам потребуется экспортировать сертификат клиента и закрытый ключ из IE (а затем преобразовать их в формат PEM).

person Bruno    schedule 25.06.2011
comment
IE использует смарт-карту для получения ключа. Это публичное или частное? Насколько я знаю, невозможно получить закрытый ключ из смарт-карты. Я прав? В любом случае, что я могу сделать, чтобы экспортировать эти вещи из IE? Заранее спасибо. - person stilz; 25.06.2011
comment
Смарт-карта, вероятно, предоставит как сертификат, так и закрытый ключ. Однако, скорее всего, в него будут встроены криптографические возможности, так что закрытый ключ не должен (или не может) покидать смарт-карту. Вы, вероятно, не сможете получить закрытый ключ в формате PEM для использования ssl.ssl_wrap. В зависимости от интерфейса, используемого смарт-картой, возможно, стоит поискать PKCS#11 в Python (или в любом другом формате смарт-карты). - person Bruno; 25.06.2011
comment
Я пробовал инструменты OpenSC (как pkcs11, так и pkcs15), но, по-видимому, они не могут перечислить ключи. Если IE может это сделать, что я должен сделать то же самое? Я пробовал нюхать USB (это USB-ридер), но не заметил никакого трафика. - person stilz; 25.06.2011
comment
Возможно, ваша карта несовместима с PKCS#11. Попробуйте узнать, какие драйвера используются под Windows. - person Bruno; 25.06.2011
comment
@stilz Это может быть невозможность OpenSC получить доступ к карте (это происходит с некоторыми устройствами). Есть ли какая-то особая причина для использования Python в Windows? Что-то более подходящее для Windows (например, .NET) сможет получить доступ к смарт-карте через CryptoAPI (именно так работает IE). - person Eugene Mayevski 'Callback; 25.06.2011