Spec-Zone.ru › Python 2.7

ssl — Обёртка TLS/SSL для сокетов

Новая в версии 2.6.

Исходный код: Lib/ssl.py

Этот модуль предоставляет доступ к шифрованию Transport Layer Security (часто называемому «Secure Sockets Layer») и средствам проверки подлинности узлов для сетевых сокетов, как для клиентской, так и для серверной стороны. Этот модуль использует библиотеку OpenSSL. Он доступен на всех современных Unix-системах, Windows, Mac OS X и, вероятно, на дополнительных платформах, при условии установки OpenSSL на этой платформе.

Изменено в версии 2.7.13: Обновлено для поддержки подключения с OpenSSL 1.1.0

Примечание

Некоторые особенности могут зависеть от платформы, так как вызовы осуществляются к API сокетов операционной системы. Установленная версия OpenSSL также может вызывать изменения в поведении. Например, TLSv1.1 и TLSv1.2 поставляются с openssl версии 1.0.1.

Предупреждение

Не используйте этот модуль без прочтения Разъяснения по безопасности. Это может привести к ложному ощущению безопасности, так как настройки по умолчанию модуля ssl не обязательно подходят для вашего приложения.

В этом разделе документируются объекты и функции в модуле ssl; для получения более общей информации о TLS, SSL и сертификатах, читатель обращается к документации в разделе «См. также» внизу.

Этот модуль предоставляет класс ssl.SSLSocket, который происходит от типа socket.socket и обеспечивает сокет-подобную обёртку, которая также шифрует и расшифровывает данные, передаваемые по сокету с использованием SSL. Он поддерживает дополнительные методы, такие как getpeercert(), который извлекает сертификат другой стороны соединения, и cipher(), который извлекает шифр, используемый для защищённого соединения.

Для более сложных приложений класс ssl.SSLContext помогает управлять настройками и сертификатами, которые затем могут быть унаследованы сокетами SSL, созданными через метод SSLContext.wrap_socket().

1. Функции, константы и исключения

exception ssl.SSLError

Выбрасывается для сигнализации об ошибке из базовой реализации SSL (в настоящее время предоставляемой библиотекой OpenSSL). Это указывает на какую-то проблему в более высоком уровне шифрования и проверки подлинности, наложенном поверх базового сетевого соединения. Эта ошибка является подтипом socket.error, которая, в свою очередь, является подтипом IOError. Код ошибки и сообщение экземпляров SSLError предоставляются библиотекой OpenSSL.

library

Мемонический строковый идентификатор подмодуля OpenSSL, в котором произошла ошибка, например SSL, PEM или X509. Диапазон возможных значений зависит от версии OpenSSL.

Новая в версии 2.7.9.

reason

Мемонический строковый идентификатор причины возникновения этой ошибки, например CERTIFICATE_VERIFY_FAILED. Диапазон возможных значений зависит от версии OpenSSL.

Новая в версии 2.7.9.

exception ssl.SSLZeroReturnError

Подкласс SSLError, выбрасываемый при попытке чтения или записи, когда SSL-соединение было закрыто корректно. Обратите внимание, что это не означает, что базовый транспорт (например, TCP) был закрыт.

Новая в версии 2.7.9.

exception ssl.SSLWantReadError

Подкласс SSLError, выбрасываемый для неблокирующего SSL-сокета при попытке чтения или записи данных, но для выполнения запроса необходимо получить больше данных по базовому TCP-транспорту.

Новая в версии 2.7.9.

exception ssl.SSLWantWriteError

Подкласс SSLError, выбрасываемый для неблокирующего SSL-сокета при попытке чтения или записи данных, но для выполнения запроса необходимо отправить больше данных по базовому TCP-транспорту.

Новая в версии 2.7.9.

exception ssl.SSLSyscallError

Подкласс SSLError, выбрасываемый, когда при выполнении операции с SSL-сокетом возникла системная ошибка. К сожалению, нет простого способа проверить исходное значение errno.

Новая в версии 2.7.9.

exception ssl.SSLEOFError

Подкласс SSLError, выбрасываемый, когда SSL-соединение было прервано внезапно. Как правило, не следует пытаться повторно использовать базовый транспорт, когда встречается эта ошибка.

Новая в версии 2.7.9.

exception ssl.CertificateError

Выбрасывается для сигнализации об ошибке с сертификатом (например, несоответствие имени хоста). Ошибки сертификатов, обнаруженные OpenSSL, однако, вызывают SSLError.

1.1. Создание сокета

Следующая функция позволяет создавать автономные сокеты. Начиная с Python 2.7.9, использование SSLContext.wrap_socket() может быть более гибким.

ssl.wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version={see docs}, ca_certs=None, do_handshake_on_connect=True, suppress_ragged_eofs=True, ciphers=None)

Принимает экземпляр sock socket.socket и возвращает экземпляр ssl.SSLSocket, подтип socket.socket, который оборачивает базовый сокет в контекст SSL. sock должен быть сокетом SOCK_STREAM; другие типы сокетов не поддерживаются.

Для сокетов стороны клиента создание контекста отложенно; если базовый сокет ещё не подключен, создание контекста будет выполнено после вызова connect() на сокете. Для сокетов стороны сервера, если у сокета нет удалённого партнёра, предполагается, что это сокет прослушивания, и оборачивание SSL для серверной стороны автоматически выполняется при подключении клиентов через метод accept(). wrap_socket() может генерировать исключение SSLError.

Параметры keyfile и certfile задают необязательные файлы, содержащие сертификат, используемый для идентификации локальной стороны соединения. Подробнее о том, как сертификат хранится в certfile, см. обсуждение Сертификатов.

Параметр server_side — это булево значение, определяющее, требуется ли поведение сокета для серверной или клиентской стороны.

Параметр cert_reqs указывает, требуется ли сертификат от другой стороны соединения и будет ли он проверен при наличии. Он должен иметь одно из трёх значений CERT_NONE (сертификаты игнорируются), CERT_OPTIONAL (не требуется, но проверяется, если предоставлен) или CERT_REQUIRED (требуется и проверяется). Если значение этого параметра не CERT_NONE, то параметр ca_certs должен указывать на файл сертификатов CA.

Файл ca_certs содержит набор конкатенированных сертификатов «центра сертификации», которые используются для проверки сертификатов, переданных с другой стороны соединения. Подробнее о том, как организовать сертификаты в этом файле, см. обсуждение Сертификатов.

Параметр ssl_version определяет, какую версию протокола SSL использовать. Как правило, сервер выбирает определённую версию протокола, а клиент должен адаптироваться к выбору сервера. Большинство версий несовместимы друг с другом. Если не указано, по умолчанию используется PROTOCOL_SSLv23; он обеспечивает наибольшую совместимость с другими версиями.

Ниже приведена таблица, показывающая, с какими версиями на сервере (по горизонтали) могут соединяться какие версии на клиенте (по вертикали):

клиент / сервер

SSLv2

SSLv3

SSLv23

TLSv1

TLSv1.1

TLSv1.2

SSLv2

да

нет

да

нет

нет

нет

SSLv3

нет

да

да

нет

нет

нет

SSLv23 1

нет

да

да

да

да

да

TLSv1

нет

нет

да

да

нет

нет

TLSv1.1

нет

нет

да

нет

да

нет

TLSv1.2

нет

нет

да

нет

нет

да

Примечания

1

Протокол TLS 1.3 будет доступен с PROTOCOL_SSLv23 в OpenSSL >= 1.1.1. Нет отдельной константы PROTOCOL только для TLS 1.3.

Примечание

Успешные соединения будут различаться в зависимости от версии OpenSSL. Например, до OpenSSL 1.0.0 клиент SSLv23 всегда пытался соединиться с SSLv2.

Параметр ciphers устанавливает доступные шифры для данного объекта SSL. Он должен быть строкой в формате списка шифров OpenSSL .

Параметр do_handshake_on_connect определяет, необходимо ли автоматически выполнить рукопожатие SSL после выполнения socket.connect(), или приложение должно вызвать его явно, вызвав метод SSLSocket.do_handshake(). Явное вызов SSLSocket.do_handshake() даёт программе контроль над поведением блокировки операций ввода/вывода сокета, участвующих в рукопожатии.

Параметр suppress_ragged_eofs определяет, как метод SSLSocket.read() должен обрабатывать неожиданное завершение файла (EOF) с другой стороны соединения. Если задано True (по умолчанию), он возвращает обычное EOF (пустой байтовый объект) в ответ на неожиданные ошибки EOF, возбуждённые базовым сокетом; если False, он возбуждает исключения в вызывающую сторону.

Изменено в версии 2.7: Новый необязательный аргумент ciphers.

1.2. Создание контекста

Функция-удобство помогает создавать объекты SSLContext для общих целей.

ssl.create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None, capath=None, cadata=None)

Возвращает новый объект SSLContext с параметрами по умолчанию для заданного purpose. Параметры выбираются модулем ssl и обычно представляют более высокий уровень безопасности, чем при прямом вызове конструктора SSLContext.

cafile, capath, cadata представляют необязательные сертификаты CA для доверенных сертификатов проверки сертификата, как в SSLContext.load_verify_locations(). Если все три параметра равны None, эта функция может выбрать доверие к сертификатам CA по умолчанию системы.

Параметры: PROTOCOL_SSLv23, OP_NO_SSLv2 и OP_NO_SSLv3 с высокозащищёнными шифрами без RC4 и без неавторизованных шифров. Передача SERVER_AUTH в качестве purpose устанавливает verify_mode в значение CERT_REQUIRED и загружает сертификаты CA (если задан хотя бы один из параметров cafile, capath или cadata) или использует SSLContext.load_default_certs() для загрузки сертификатов CA по умолчанию.

Примечание

Протокол, параметры, шифры и другие параметры могут быть изменены на более жёсткие значения в любое время без предварительного предупреждения. Значения представляют собой разумный баланс между совместимостью и безопасностью.

Если вашему приложению требуются определённые настройки, создайте объект SSLContext и настройте его самостоятельно.

Примечание

Если вы обнаружите, что при попытке подключения некоторых старых клиентов или серверов с объектом SSLContext, созданным этой функцией, возникает ошибка, сообщающая о «несовпадении протокола или набора шифров», возможно, они поддерживают только SSL3.0, что исключается этой функцией с помощью OP_NO_SSLv3. SSL3.0 широко считается полностью небезопасным. Если вы всё же хотите продолжить использование этой функции, но разрешить подключения SSL 3.0, вы можете снова включить их с помощью:

ctx = ssl.create_default_context(Purpose.CLIENT_AUTH)
ctx.options &= ~ssl.OP_NO_SSLv3

Введено в версии 2.7.9.

Изменено в версии 2.7.10: RC4 был исключён из строки шифров по умолчанию.

Изменено в версии 2.7.13: ChaCha20/Poly1305 был добавлен в строку шифров по умолчанию.

3DES был исключён из строки шифров по умолчанию.

ssl._https_verify_certificates(enable=True)

Указывает, будут ли проверятся сертификаты сервера при создании клиентских соединений HTTPS без указания конкретного контекста SSL.

Начиная с Python 2.7.9, httplib и модули, которые его используют, например, urllib2 и xmlrpclib, по умолчанию проверяют сертификаты удалённых серверов, получаемые при установлении клиентских соединений HTTPS. Эта проверка по умолчанию проверяет, подписан ли сертификат центром сертификации, присутствующим в хранилище доверенных сертификатов системы, и совпадает ли общее имя (или альтернативное имя субъекта) представленного сертификата с запрошенным хостом.

Установка enable в True гарантирует, что это поведение по умолчанию будет активным.

Установка enable в False возвращает обработку сертификатов HTTPS к поведению Python 2.7.8 и более ранних версий, что позволяет устанавливать соединения с серверами, использующими самозаверяющие сертификаты, сертификаты, подписанные центром сертификации, отсутствующим в хранилище доверенных сертификатов системы, и серверами, где имя хоста не совпадает с представленным сертификатом сервера.

Ведущая нижняя черта в этой функции указывает на то, что её намеренно нет в реализации Python 3 и она может отсутствовать во всех реализациях Python 2.7. Портативный подход к обходу проверок сертификатов или хранилища доверенных сертификатов системы, когда это необходимо, заключается в том, чтобы инструменты включали его в каждом конкретном случае, явно передавая соответствующим образом настроенный контекст SSL, а не отменяя поведение по умолчанию клиентских модулей стандартной библиотеки.

Добавлена в версии 2.7.12.

См. также

  • CVE-2014-9365 – атака «человек посередине» HTTPS на клиентские приложения Python, использующие настройки по умолчанию
  • PEP 476 – Включение проверки сертификатов по умолчанию для HTTPS
  • PEP 493 – Инструменты миграции проверки HTTPS для Python 2.7

1.3. Генерация случайных чисел

Устаревшая начиная с версии 2.7.13: OpenSSL устарел ssl.RAND_pseudo_bytes(), используйте ssl.RAND_bytes() вместо этого.

ssl.RAND_status()

Возвращает True если генератор псевдослучайных чисел SSL был запущен с достаточным количеством случайности, и False в противном случае. Вы можете использовать ssl.RAND_egd() и ssl.RAND_add() для увеличения случайности генератора псевдослучайных чисел.

ssl.RAND_egd(path)

Если у вас запущен демон сбора энтропии (EGD) где-то, и path — путь к сокету соединения с ним, это прочитает 256 байт случайности из сокета и добавит его в генератор псевдослучайных чисел SSL, чтобы повысить безопасность сгенерированных секретных ключей. Это обычно необходимо только на системах без лучших источников случайности.

См. http://egd.sourceforge.net/ или http://prngd.sourceforge.net/ для источников демонов сбора энтропии.

Доступность: недоступен с LibreSSL и OpenSSL > 1.1.0

ssl.RAND_add(bytes, entropy)

Смешивает заданные байты в генератор псевдослучайных чисел SSL. Параметр entropy (вещественное число) — это нижняя граница энтропии, содержащейся в строке (поэтому вы всегда можете использовать 0.0). См. RFC 1750 для получения дополнительной информации о источниках энтропии.

1.4. Обработка сертификатов

ssl.match_hostname(cert, hostname)

Проверьте, что cert (в декодированном формате, как возвращается SSLSocket.getpeercert()) соответствует заданному hostname. Применяемые правила аналогичны правилам проверки подлинности серверов HTTPS, изложенным в RFC 2818 и RFC 6125, за исключением того, что в настоящее время IP-адреса не поддерживаются. Помимо HTTPS, эта функция должна подходить для проверки подлинности серверов в различных протоколах на основе SSL, таких как FTPS, IMAPS, POPS и других.

CertificateError генерируется при ошибке. При успешном выполнении функция ничего не возвращает:

>>> cert = {'subject': ((('commonName', 'example.com'),),)}
>>> ssl.match_hostname(cert, "example.com")
>>> ssl.match_hostname(cert, "example.org")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/py3k/Lib/ssl.py", line 130, in match_hostname
ssl.CertificateError: hostname 'example.org' doesn't match 'example.com'

Добавлена в версии 2.7.9.

ssl.cert_time_to_seconds(cert_time)

Возвращает время в секундах с момента эпохи, учитывая строку cert_time , представляющую дату «notBefore» или «notAfter» из сертификата в формате "%b %d %H:%M:%S %Y %Z" strptime (C locale).

Вот пример:

>>> import ssl
>>> timestamp = ssl.cert_time_to_seconds("Jan  5 09:34:43 2018 GMT")
>>> timestamp
1515144883
>>> from datetime import datetime
>>> print(datetime.utcfromtimestamp(timestamp))
2018-01-05 09:34:43

Даты «notBefore» или «notAfter» должны использовать GMT (RFC 5280).

Изменено в версии 2.7.9: Вводное время интерпретируется как время в UTC, как указано в строке ввода с помощью часового пояса 'GMT'. Предыдущие версии использовали местный часовой пояс. Возвращается целое число (нет дробных секунд в формате ввода)

ssl.get_server_certificate(addr, ssl_version=PROTOCOL_SSLv23, ca_certs=None)

Принимая адрес addr защищенного SSL сервера в виде пары (hostname, номер_порта), извлекает сертификат сервера и возвращает его как строку в формате PEM. Если ssl_version задан, используется указанная версия протокола SSL для попытки подключения к серверу. Если ca_certs задан, он должен содержать список корневых сертификатов в формате, аналогичном формату параметра в wrap_socket(). Вызов будет пытаться валидировать сертификат сервера по отношению к этому набору корневых сертификатов и потерпит неудачу, если попытка проверки не увенчается успехом.

Изменено в версии 2.7.9: Эта функция теперь совместима с IPv6, а значение по умолчанию ssl_version изменено с PROTOCOL_SSLv3 на PROTOCOL_SSLv23 для максимальной совместимости с современными серверами.

ssl.DER_cert_to_PEM_cert(DER_cert_bytes)

Принимая сертификат в виде DER-кодированного блока байтов, возвращает строку PEM-кодированного формата того же сертификата.

ssl.PEM_cert_to_DER_cert(PEM_cert_string)

Принимая сертификат в виде ASCII-строки PEM, возвращает DER-кодированную последовательность байтов для этого же сертификата.

ssl.get_default_verify_paths()

Возвращает кортеж с именами путей к файлу и каталогу по умолчанию для сертификатов авторитетов OpenSSL. Пути такие же, как у SSLContext.set_default_verify_paths(). Возвращаемое значение — кортеж именованный кортеж DefaultVerifyPaths.

  • cafile — разрешенный путь к файлу cafile или None в случае, если файла не существует,
  • capath — разрешенный путь к каталогу capath или None в случае, если каталог не существует,
  • openssl_cafile_env — переменная окружения OpenSSL, указывающая на файл cafile,
  • openssl_cafile — жёстко заданный путь к файлу cafile,
  • openssl_capath_env — переменная окружения OpenSSL, указывающая на каталог capath,
  • openssl_capath — жёстко заданный путь к каталогу capath

Доступность: LibreSSL игнорирует переменные среды openssl_cafile_env и openssl_capath_env

Добавлена в версии 2.7.9.

ssl.enum_certificates(store_name)

Получение сертификатов из хранилища системных сертификатов Windows. store_name может быть одним из CA, ROOT или MY. Windows также может предоставлять дополнительные хранилища сертификатов.

Функция возвращает список кортежей (cert_bytes, encoding_type, trust). encoding_type указывает кодировку cert_bytes. Она может быть x509_asn для данных X.509 ASN.1 или pkcs_7_asn для данных PKCS#7 ASN.1. Trust указывает назначение сертификата как набора OIDS или точно True если сертификат надёжен для всех целей.

Пример:

>>> ssl.enum_certificates("CA")
[(b'data...', 'x509_asn', {'1.3.6.1.5.5.7.3.1', '1.3.6.1.5.5.7.3.2'}),
 (b'data...', 'x509_asn', True)]

Доступность: Windows.

Добавлена в версии 2.7.9.

ssl.enum_crls(store_name)

Получение списков выданных сертификатов (CRLs) из системного хранилища сертификатов Windows. store_name может быть одним из CA, ROOT или MY. Windows может предоставлять и дополнительные хранилища сертификатов.

Функция возвращает список кортежей (cert_bytes, encoding_type, trust). Encoding_type указывает кодировку cert_bytes. Это либо x509_asn для данных X.509 ASN.1, либо pkcs_7_asn для данных PKCS#7 ASN.1.

Доступность: Windows.

Добавлена в версии 2.7.9.

1.5. Константы

ssl.CERT_NONE

Возможные значения для SSLContext.verify_mode или параметра cert_reqs к wrap_socket(). В этом режиме (по умолчанию) сертификаты не требуются от другой стороны сокет-соединения. Если сертификат получен от другой стороны, он не проверяется.

См. обсуждение Учитывание безопасности ниже.

ssl.CERT_OPTIONAL

Возможные значения для SSLContext.verify_mode или параметра cert_reqs к wrap_socket(). В этом режиме сертификаты не требуются от другой стороны сокет-соединения; но если они предоставлены, будет попытка проверки, и при ошибке будет возбуждено исключение SSLError.

Использование этого параметра требует наличия действительного набора сертификатов CA, передаваемого либо в SSLContext.load_verify_locations(), либо как значение параметра ca_certs к wrap_socket().

ssl.CERT_REQUIRED

Возможные значения для SSLContext.verify_mode или параметра cert_reqs к wrap_socket(). В этом режиме сертификаты требуются от другой стороны сокет-соединения; будет возбуждено исключение SSLError если сертификат не предоставлен или его проверка завершилась неудачей.

Использование этого параметра требует наличия действительного набора сертификатов CA, передаваемого либо в SSLContext.load_verify_locations(), либо как значение параметра ca_certs к wrap_socket().

ssl.VERIFY_DEFAULT

Возможные значения для SSLContext.verify_flags. В этом режиме списки выданных сертификатов (CRLs) не проверяются. По умолчанию OpenSSL не требует и не проверяет CRLs.

Добавлена в версии 2.7.9.

ssl.VERIFY_CRL_CHECK_LEAF

Возможные значения для SSLContext.verify_flags. В этом режиме проверяется только сертификат участника, но не промежуточные сертификаты CA. Режим требует действительного CRL, подписанного эмитентом сертификата участника (его непосредственным предком CA). Если соответствующий CRL не загружен с помощью SSLContext.load_verify_locations, проверка завершится неудачей.

Добавлена в версии 2.7.9.

ssl.VERIFY_CRL_CHECK_CHAIN

Возможные значения для SSLContext.verify_flags. В этом режиме проверяются CRLs всех сертификатов в цепочке сертификатов участника.

Добавлена в версии 2.7.9.

ssl.VERIFY_X509_STRICT

Возможные значения для SSLContext.verify_flags для отключения решений для некорректных сертификатов X.509.

Добавлена в версии 2.7.9.

ssl.VERIFY_X509_TRUSTED_FIRST

Возможные значения для SSLContext.verify_flags. Оно указывает OpenSSL предпочесть доверенные сертификаты при построении цепочки доверия для проверки сертификата. Этот флаг включён по умолчанию.

Добавлена в версии 2.7.10.

ssl.PROTOCOL_TLS

Выбирает наивысшую версию протокола, поддерживаемую как клиентом, так и сервером. Несмотря на название, этот параметр может выбирать как протоколы TLS, так и SSL.

Добавлена в версии 2.7.13.

ssl.PROTOCOL_SSLv23

Псевдоним для PROTOCOL_TLS.

Устарело начиная с версии 2.7.13: Используйте PROTOCOL_TLS вместо этого.

ssl.PROTOCOL_SSLv2

Выбирает SSL версии 2 в качестве протокола шифрования канала.

Этот протокол недоступен, если OpenSSL скомпилирован с флагом OPENSSL_NO_SSL2.

Предупреждение

SSL версии 2 небезопасен. Его использование настоятельно не рекомендуется.

Устарело начиная с версии 2.7.13: Поддержка SSLv2 удалена из OpenSSL.

ssl.PROTOCOL_SSLv3

Выбирает SSL версии 3 в качестве протокола шифрования канала.

Этот протокол недоступен, если OpenSSL скомпилирован с флагом OPENSSL_NO_SSLv3.

Предупреждение

SSL версии 3 небезопасен. Его использование настоятельно не рекомендуется.

Устарело начиная с версии 2.7.13: OpenSSL устарел все версии протоколов. Используйте протокол по умолчанию с флагами, такими как OP_NO_SSLv3.

ssl.PROTOCOL_TLSv1

Выбирает TLS версии 1.0 в качестве протокола шифрования канала.

Устарело начиная с версии 2.7.13: OpenSSL устарел все версии протоколов. Используйте протокол по умолчанию с флагами, такими как OP_NO_SSLv3.

ssl.PROTOCOL_TLSv1_1

Выбирает TLS версии 1.1 в качестве протокола шифрования канала. Доступно только с openssl версии 1.0.1+.

Добавлена в версии 2.7.9.

Устарело начиная с версии 2.7.13: OpenSSL устарел все версии протоколов. Используйте протокол по умолчанию с флагами, такими как OP_NO_SSLv3.

ssl.PROTOCOL_TLSv1_2

Выбирает TLS версии 1.2 в качестве протокола шифрования канала. Это самая современная версия, и, вероятно, лучший выбор для максимальной защиты, если обе стороны ее поддерживают. Доступно только с openssl версии 1.0.1+.

Добавлена в версии 2.7.9.

Устарело начиная с версии 2.7.13: OpenSSL устарел все версии протоколов. Используйте протокол по умолчанию с флагами, такими как OP_NO_SSLv3.

ssl.OP_ALL

Включает решения для различных ошибок, присутствующих в других реализациях SSL. Этот параметр установлен по умолчанию. Он не обязательно устанавливает те же флаги, что и константа SSL_OP_ALL OpenSSL.

Добавлена в версии 2.7.9.

ssl.OP_NO_SSLv2

Запрещает подключение SSLv2. Этот параметр применим только в сочетании с PROTOCOL_SSLv23. Он запрещает выбор SSLv2 в качестве версии протокола.

Добавлена в версии 2.7.9.

ssl.OP_NO_SSLv3

Запрещает подключение SSLv3. Этот параметр применим только в сочетании с PROTOCOL_SSLv23. Он запрещает выбор SSLv3 в качестве версии протокола.

Добавлена в версии 2.7.9.

ssl.OP_NO_TLSv1

Запрещает подключение TLSv1. Этот параметр применим только в сочетании с PROTOCOL_SSLv23. Он запрещает выбор TLSv1 в качестве версии протокола.

Добавлена в версии 2.7.9.

END_OF_DOCUMENT_MARKER
ssl.OP_NO_TLSv1_1

Предотвращает подключение TLSv1.1. Этот параметр применим только в сочетании с PROTOCOL_SSLv23. Он препятствует выбору протокола версии TLSv1.1 со стороны узлов. Доступно только с версией openssl 1.0.1+.

Новое в версии 2.7.9.

ssl.OP_NO_TLSv1_2

Предотвращает подключение TLSv1.2. Этот параметр применим только в сочетании с PROTOCOL_SSLv23. Он препятствует выбору протокола версии TLSv1.2 со стороны узлов. Доступно только с версией openssl 1.0.1+.

Новое в версии 2.7.9.

ssl.OP_NO_TLSv1_3

Предотвращает подключение TLSv1.3. Этот параметр применим только в сочетании с PROTOCOL_TLS. Он препятствует выбору протокола версии TLSv1.3 со стороны узлов. TLS 1.3 доступен с OpenSSL 1.1.1 или более поздней версии. Если Python скомпилирован с более ранней версией OpenSSL, флаг по умолчанию равен 0.

Новое в версии 2.7.15.

ssl.OP_CIPHER_SERVER_PREFERENCE

Используйте предпочтение порядка шифров сервера вместо предпочтения клиента. Этот параметр не влияет на сокеты клиентов и серверные сокеты SSLv2.

Новое в версии 2.7.9.

ssl.OP_SINGLE_DH_USE

Препятствует повторному использованию одного и того же ключа DH для различных сессий SSL. Это повышает секретность вперёд, но требует больше вычислительных ресурсов. Этот параметр применим только к серверным сокетам.

Новое в версии 2.7.9.

ssl.OP_SINGLE_ECDH_USE

Препятствует повторному использованию одного и того же ключа ECDH для различных сессий SSL. Это повышает секретность вперёд, но требует больше вычислительных ресурсов. Этот параметр применим только к серверным сокетам.

Новое в версии 2.7.9.

ssl.OP_ENABLE_MIDDLEBOX_COMPAT

Отправлять фиктивные сообщения Change Cipher Spec (CCS) в рукопожатии TLS 1.3, чтобы подключение TLS 1.3 выглядело более похожим на подключение TLS 1.2.

Этот параметр доступен только с OpenSSL 1.1.1 и более поздними версиями.

Новое в версии 2.7.16.

ssl.OP_NO_COMPRESSION

Отключить сжатие на канале SSL. Это полезно, если протокол приложения поддерживает свою собственную схему сжатия.

Этот параметр доступен только с OpenSSL 1.0.0 и более поздними версиями.

Новое в версии 2.7.9.

ssl.HAS_ALPN

Поддерживает ли библиотека OpenSSL встроенную поддержку расширения TLS Application-Layer Protocol Negotiation, как описано в RFC 7301.

Новое в версии 2.7.10.

ssl.HAS_ECDH

Поддерживает ли библиотека OpenSSL встроенную поддержку обмена ключами Diffie-Hellman на основе эллиптических кривых. Это должно быть истинно, если функция не была явно отключена дистрибутором.

Новое в версии 2.7.9.

ssl.HAS_SNI

Поддерживает ли библиотека OpenSSL встроенную поддержку расширения Server Name Indication (как определено в RFC 4366).

Новое в версии 2.7.9.

ssl.HAS_NPN

Поддерживает ли библиотека OpenSSL встроенную поддержку Next Protocol Negotiation, как описано в спецификации черновика NPN. Если значение true, вы можете использовать метод SSLContext.set_npn_protocols() для объявления поддерживаемых протоколов.

Новое в версии 2.7.9.

ssl.HAS_TLSv1_3

Поддерживает ли библиотека OpenSSL встроенную поддержку протокола TLS 1.3.

Новое в версии 2.7.15.

ssl.CHANNEL_BINDING_TYPES

Список поддерживаемых типов привязных каналов TLS. Строки в этом списке могут быть использованы в качестве аргументов для SSLSocket.get_channel_binding().

Новое в версии 2.7.9.

ssl.OPENSSL_VERSION

Строка версии библиотеки OpenSSL, загруженной интерпретатором:

>>> ssl.OPENSSL_VERSION
'OpenSSL 0.9.8k 25 Mar 2009'

Новое в версии 2.7.

ssl.OPENSSL_VERSION_INFO

Кортеж из пяти целых чисел, представляющих информацию о версии библиотеки OpenSSL:

>>> ssl.OPENSSL_VERSION_INFO
(0, 9, 8, 11, 15)

Новое в версии 2.7.

ssl.OPENSSL_VERSION_NUMBER

Чистое число версии библиотеки OpenSSL, как одно целое число:

>>> ssl.OPENSSL_VERSION_NUMBER
9470143L
>>> hex(ssl.OPENSSL_VERSION_NUMBER)
'0x9080bfL'

Новое в версии 2.7.

ssl.ALERT_DESCRIPTION_HANDSHAKE_FAILURE
ssl.ALERT_DESCRIPTION_INTERNAL_ERROR
ALERT_DESCRIPTION_*

Описания оповещений из RFC 5246 и других. Реестр оповещений TLS IANA содержит этот список и ссылки на RFC, где определено их значение.

Используется в качестве возвращаемого значения функции обратного вызова в SSLContext.set_servername_callback().

Новое в версии 2.7.9.

Purpose.SERVER_AUTH

Параметр для create_default_context() и SSLContext.load_default_certs(). Это значение указывает, что контекст может быть использован для аутентификации веб-серверов (следовательно, он будет использоваться для создания клиентских сокетов).

Новое в версии 2.7.9.

Purpose.CLIENT_AUTH

Параметр для create_default_context() и SSLContext.load_default_certs(). Это значение указывает, что контекст может быть использован для аутентификации веб-клиентов (следовательно, он будет использоваться для создания серверных сокетов).

Новое в версии 2.7.9.

2. SSL-сокеты

SSL-сокеты предоставляют следующие методы Объектов сокета:

  • accept()
  • bind()
  • close()
  • connect()
  • fileno()
  • getpeername(), getsockname()
  • getsockopt(), setsockopt()
  • gettimeout(), settimeout(), setblocking()
  • listen()
  • makefile()
  • recv(), recv_into() (но передача аргумента flags отличного от нуля не допускается)
  • send(), sendall() (с тем же ограничением)
  • shutdown()

Однако, поскольку протокол SSL (и TLS) имеет свою собственную структуру поверх TCP, абстракция SSL-сокет может в некоторых отношениях отличаться от спецификации обычных сокетов операционной системы. См. особенно примечания о неблокирующих сокетах.

SSL-сокеты также имеют следующие дополнительные методы и атрибуты:

SSLSocket.do_handshake()

Выполнить начальную рукопожатие SSL.

Изменено в версии 2.7.9: Метод рукопожатия также выполняет match_hostname(), когда атрибут check_hostname сокета context имеет значение True.

SSLSocket.getpeercert(binary_form=False)

Если на другом конце соединения нет сертификата для удалённого узла, возвращает None. Если рукопожатие SSL ещё не выполнено, генерируется исключение ValueError.

Если параметр binary_form равен False, и сертификат был получен от удалённого узла, этот метод возвращает экземпляр dict. Если сертификат не был проверен, словарь пуст. Если сертификат был проверен, возвращается словарь с несколькими ключами, среди них subject (субъект, которому выдан сертификат) и issuer (субъект, выпустивший сертификат). Если сертификат содержит экземпляр расширения Subject Alternative Name (см. RFC 3280), в словаре также будет ключ subjectAltName.

Поля subject и issuer являются кортежами, содержащими последовательность относительных отличительных имён (RDNs), заданных в структуре данных сертификата для соответствующих полей, и каждое RDN является последовательностью пар имя-значение. Вот пример из реальной жизни:

{'issuer': ((('countryName', 'IL'),),
            (('organizationName', 'StartCom Ltd.'),),
            (('organizationalUnitName',
              'Secure Digital Certificate Signing'),),
            (('commonName',
              'StartCom Class 2 Primary Intermediate Server CA'),)),
 'notAfter': 'Nov 22 08:15:19 2013 GMT',
 'notBefore': 'Nov 21 03:09:52 2011 GMT',
 'serialNumber': '95F0',
 'subject': ((('description', '571208-SLe257oHY9fVQ07Z'),),
             (('countryName', 'US'),),
             (('stateOrProvinceName', 'California'),),
             (('localityName', 'San Francisco'),),
             (('organizationName', 'Electronic Frontier Foundation, Inc.'),),
             (('commonName', '*.eff.org'),),
             (('emailAddress', 'hostmaster@eff.org'),)),
 'subjectAltName': (('DNS', '*.eff.org'), ('DNS', 'eff.org')),
 'version': 3}

Примечание

Для проверки сертификата конкретной службы можно использовать функцию match_hostname().

Если параметр binary_form равен True, и был предоставлен сертификат, этот метод возвращает DER-кодированную форму всего сертификата как последовательность байтов или None, если удалённый узел не предоставил сертификат. Предоставление сертификата удалённым узлом зависит от роли SSL-сокета:

  • для SSL-сокета клиента сервер всегда предоставит сертификат, независимо от того, потребовалась ли проверка;
  • для SSL-сокета сервера клиент предоставит сертификат только по запросу сервера; следовательно, getpeercert() вернёт None, если вы использовали CERT_NONE (а не CERT_OPTIONAL или CERT_REQUIRED).

Изменено в версии 2.7.9: Возвращаемый словарь включает дополнительные элементы, такие как issuer и notBefore. Дополнительно генерируется исключение ValueError, если рукопожатие не завершено. Возвращаемый словарь включает дополнительные элементы расширений X509v3, такие как crlDistributionPoints, caIssuers и OCSP URI.

SSLSocket.cipher()

Возвращает кортеж из трёх значений: имя используемого шифра, версия протокола SSL, определяющая его использование, и количество используемых секретных битов. Если соединение не установлено, возвращает None.

SSLSocket.compression()

Возвращает используемый алгоритм сжатия в виде строки или None если сжатие не используется.

Если протокол более высокого уровня поддерживает свой собственный механизм сжатия, вы можете использовать OP_NO_COMPRESSION для отключения сжатия на уровне SSL.

Добавлена в версии 2.7.9.

SSLSocket.get_channel_binding(cb_type="tls-unique")

Получить данные канальной привязки для текущего соединения в виде объекта bytes. Возвращает None если соединение не установлено или рукопожатие не завершено.

Параметр cb_type позволяет выбрать желаемый тип канальной привязки. Допустимые типы канальной привязки перечислены в списке CHANNEL_BINDING_TYPES. В настоящее время поддерживается только канальная привязка «tls-unique», определённая в RFC 5929. Если запрошен неподдерживаемый тип канальной привязки, будет вызвано исключение ValueError.

Добавлена в версии 2.7.9.

SSLSocket.selected_alpn_protocol()

Возвращает протокол, выбранный во время рукопожатия TLS. Если SSLContext.set_alpn_protocols() не был вызван, если другая сторона не поддерживает ALPN, если этот сокет не поддерживает ни один из предложенных клиентом протоколов, или если рукопожатие ещё не произошло, возвращается None.

Добавлена в версии 2.7.10.

SSLSocket.selected_npn_protocol()

Возвращает протокол более высокого уровня, выбранный во время рукопожатия TLS/SSL. Если SSLContext.set_npn_protocols() не был вызван, или если другая сторона не поддерживает NPN, или если рукопожатие ещё не произошло, возвращается None.

Добавлена в версии 2.7.9.

SSLSocket.unwrap()

Выполняет рукопожатие закрытия SSL, удаляет слой TLS из базового сокета и возвращает базовый объект сокета. Это можно использовать, чтобы перейти от шифрованного к нешифрованному режиму работы по подключению. Возвращённый сокет всегда должен использоваться для дальнейшего общения с другой стороной соединения, а не оригинальный сокет.

SSLSocket.version()

Возвращает фактическую версию протокола SSL, согласованную соединением, в виде строки, или None , если безопасное соединение не установлено. На данный момент возможные значения включают "SSLv2", "SSLv3", "TLSv1", "TLSv1.1" и "TLSv1.2". Более новые версии OpenSSL могут определять больше значений.

Добавлена в версии 2.7.9.

SSLSocket.context

Объект SSLContext, к которому привязан этот сокет SSL. Если сокет SSL был создан с помощью функции верхнего уровня wrap_socket() (а не SSLContext.wrap_socket()), это пользовательский объект контекста, созданный для этого сокета SSL.

Добавлена в версии 2.7.9.

3. Контексты SSL

Добавлена в версии 2.7.9.

Контекст SSL хранит различные данные, имеющие больший срок жизни, чем отдельные соединения SSL, такие как параметры конфигурации SSL, сертификат(ы) и закрытый ключ(и). Он также управляет кэшем сессий SSL для сокетов на стороне сервера, чтобы ускорить повторные соединения от одних и тех же клиентов.

class ssl.SSLContext(protocol)

Создает новый контекст SSL. Необходимо передать protocol, которое должно быть одним из PROTOCOL_* констант, определенных в этом модуле. PROTOCOL_SSLv23 в настоящее время рекомендуется для максимальной совместимости.

См. также

create_default_context() позволяет модулю ssl выбирать параметры безопасности для заданной цели.

Изменено в версии 2.7.16: Контекст создается со значениями по умолчанию по умолчанию. Параметры OP_NO_COMPRESSION, OP_CIPHER_SERVER_PREFERENCE, OP_SINGLE_DH_USE, OP_SINGLE_ECDH_USE, OP_NO_SSLv2 (кроме PROTOCOL_SSLv2), и OP_NO_SSLv3 (кроме PROTOCOL_SSLv3) устанавливаются по умолчанию. Изначальный список наборов шифров содержит только HIGH шифры, не NULL шифры и не MD5 шифры (кроме PROTOCOL_SSLv2).

Объекты SSLContext имеют следующие методы и атрибуты:

SSLContext.cert_store_stats()

Получение статистики о количестве загруженных сертификатов X.509, количестве сертификатов X.509, помеченных как сертификаты CA, и списках отзыва сертификатов в виде словаря.

Пример для контекста с одним сертификатом CA и одним другим сертификатом:

>>> context.cert_store_stats()
{'crl': 0, 'x509_ca': 1, 'x509': 2}
SSLContext.load_cert_chain(certfile, keyfile=None, password=None)

Загрузка закрытого ключа и соответствующего сертификата. Строка certfile должна содержать путь к одному файлу в формате PEM, содержащему сертификат, а также любое количество сертификатов CA, необходимых для установления подлинности сертификата. Строка keyfile, если она присутствует, должна указывать на файл, содержащий закрытый ключ в. В противном случае закрытый ключ будет взят из certfile также. См. обсуждение Сертификаты для получения дополнительной информации о том, как сертификат хранится в certfile.

Аргумент password может быть функцией для получения пароля для расшифровки закрытого ключа. Он будет вызван только в том случае, если закрытый ключ зашифрован и необходим пароль. Он будет вызван без аргументов и должен вернуть строку, байты или массив байтов. Если возвращаемое значение является строкой, оно будет закодировано в UTF-8 перед использованием для расшифровки ключа. В качестве альтернативы можно указать строку, байты или массив байтов непосредственно как аргумент password. Он будет проигнорирован, если закрытый ключ не зашифрован и пароль не нужен.

Если аргумент password не указан и пароль необходим, будет использован встроенный механизм запроса пароля OpenSSL для интерактивного запроса пароля у пользователя.

Исключение SSLError возникает, если закрытый ключ не соответствует сертификату.

SSLContext.load_default_certs(purpose=Purpose.SERVER_AUTH)

Загрузка набора сертификатов «уполномоченного центра сертификации» (CA) из стандартных расположений. В Windows он загружает сертификаты CA из хранилищ системы CA и ROOT. В других системах он вызывает SSLContext.set_default_verify_paths(). В будущем метод может загружать сертификаты CA и из других мест.

Флаг purpose указывает, какие сертификаты CA загружаются. Параметры по умолчанию Purpose.SERVER_AUTH загружает сертификаты, помеченные и доверенные для аутентификации веб-сервера TLS (клиентские сокеты). Purpose.CLIENT_AUTH загружает сертификаты CA для проверки сертификатов клиента на стороне сервера.

SSLContext.load_verify_locations(cafile=None, capath=None, cadata=None)

Загрузка набора сертификатов «уполномоченного центра сертификации» (CA), используемых для проверки сертификатов других узлов, когда verify_mode отличается от CERT_NONE. Должен быть указан хотя бы один из cafile или capath.

Этот метод также может загружать списки отзыва сертификатов (CRL) в форматах PEM или DER. Для использования CRL необходимо правильно настроить SSLContext.verify_flags.

Строка cafile, если присутствует, является путём к файлу, содержащему конкатенированные сертификаты CA в формате PEM. См. обсуждение Сертификаты для получения дополнительной информации о том, как организовать сертификаты в этом файле.

Строка capath, если присутствует, — это путь к каталогу, содержащему несколько сертификатов CA в формате PEM, следуя специфичной для OpenSSL структуре расположения.

Объект cadata, если он присутствует, — это строка ASCII с одним или несколькими сертификатами в формате PEM или похожий на байты объект с сертификатами в формате DER. Как и в случае с capath, дополнительные строки вокруг PEM-закодированных сертификатов игнорируются, но должен быть присутствовать хотя бы один сертификат.

SSLContext.get_ca_certs(binary_form=False)

Возвращает список загруженных сертификатов «уполномоченного центра сертификации» (CA). Если параметр binary_form равен False, каждый элемент списка — это словарь, подобный выводу из SSLSocket.getpeercert(). В противном случае метод возвращает список DER-закодированных сертификатов. Список, возвращаемый методом, не содержит сертификатов из capath, если сертификат не был запрошен и загружен соединением SSL.

Примечание

Сертификаты в каталоге capath не загружаются, пока не будут использованы хотя бы один раз.

SSLContext.set_default_verify_paths()

Загружает набор стандартных сертификатов «уполномоченного центра сертификации» (CA) из пути к файловой системе, определённого при построении библиотеки OpenSSL. К сожалению, нет простого способа узнать, удалось ли выполнить этот метод: ошибка не возвращается, если сертификаты не найдены. Однако, если библиотека OpenSSL предоставляется в качестве части операционной системы, она, вероятно, настроена правильно.

SSLContext.set_ciphers(ciphers)

Устанавливает доступные шифры для сокетов, созданных с помощью данного контекста. Это должна быть строка в формате списка шифров OpenSSL . Если ни один шифр не может быть выбран (потому что опции времени компиляции или другая конфигурация запрещает использование всех указанных шифров), будет возбуждено исключение SSLError.

Примечание

при подключении метод SSLSocket.cipher() сокетов SSL вернёт текущий выбранный шифр.

OpenSSL 1.1.1 имеет наборы шифров TLS 1.3, включённые по умолчанию. Эти наборы не могут быть отключены с помощью set_ciphers().

SSLContext.set_alpn_protocols(protocols)

Укажите протоколы, которые сокет должен рекламировать во время рукопожатия SSL/TLS. Это должен быть список ASCII-строк, например, ['http/1.1', 'spdy/2'], упорядоченных по предпочтению. Выбор протокола произойдёт во время рукопожатия и будет выполняться в соответствии с RFC 7301. После успешного рукопожатия метод SSLSocket.selected_alpn_protocol() вернёт согласованный протокол.

Этот метод вызовет NotImplementedError, если HAS_ALPN имеет значение False.

OpenSSL 1.1.0 до 1.1.0e прервёт рукопожатие и вызовет SSLError, когда обе стороны поддерживают ALPN, но не могут договориться о протоколе. Версии 1.1.0f+ ведут себя как 1.0.2, SSLSocket.selected_alpn_protocol() возвращает None.

Новое в версии 2.7.10.

SSLContext.set_npn_protocols(protocols)

Укажите протоколы, которые сокет должен рекламировать во время рукопожатия SSL/TLS. Это должен быть список строк, например, ['http/1.1', 'spdy/2'], упорядоченных по предпочтению. Выбор протокола произойдёт во время рукопожатия, в соответствии со спецификацией черновика NPN. После успешного рукопожатия метод SSLSocket.selected_npn_protocol() вернёт согласованный протокол.

Этот метод вызовет NotImplementedError, если HAS_NPN имеет значение False.

SSLContext.set_servername_callback(server_name_callback)

Регистрирует функцию обратного вызова, которая будет вызвана после получения сообщения рукопожатия TLS Client Hello сервером SSL/TLS, когда клиент TLS указывает указание имени сервера. Механизм указания имени сервера описан в RFC 6066 разделе 3 — Указание имени сервера.

Только один обратный вызов может быть установлен для SSLContext. Если server_name_callback равно None, обратный вызов отключён. Вызов этой функции в последующий раз отключит ранее зарегистрированный обратный вызов.

Функция обратного вызова server_name_callback будет вызвана с тремя аргументами: первый — ssl.SSLSocket, второй — строка, представляющая имя сервера, с которым клиент намеревается общаться (или None, если TLS Client Hello не содержит имя сервера), и третий — исходный SSLContext. Аргумент имени сервера — это имя сервера, декодированное по IDNA.

Типичное использование этого обратного вызова — изменение атрибута ssl.SSLSocket’s SSLSocket.context на новый объект типа SSLContext, представляющий цепочку сертификатов, соответствующую имени сервера.

Из-за ранней фазы согласования подключения TLS доступны только ограниченные методы и атрибуты, такие как SSLSocket.selected_alpn_protocol() и SSLSocket.context. Методы SSLSocket.getpeercert(), SSLSocket.getpeercert(), SSLSocket.cipher() и SSLSocket.compress() требуют, чтобы подключение TLS продвинулось за пределы TLS Client Hello, поэтому они не содержат значимых значений и не могут вызываться безопасно.

Функция server_name_callback должна возвращать None, чтобы продолжить переговоры TLS. Если требуется ошибка TLS, можно вернуть константу ALERT_DESCRIPTION_*. Другие возвращаемые значения приведут к ошибке TLS с ALERT_DESCRIPTION_INTERNAL_ERROR.

В случае ошибки декодирования имени сервера по IDNA подключение TLS завершится с фатальным предупреждением TLS ALERT_DESCRIPTION_INTERNAL_ERROR для клиента.

Если при выполнении функции server_name_callback произойдёт исключение, подключение TLS завершится с фатальным предупреждением TLS ALERT_DESCRIPTION_HANDSHAKE_FAILURE.

Этот метод вызовет NotImplementedError, если в библиотеке OpenSSL при её компиляции была определена OPENSSL_NO_TLSEXT.

SSLContext.load_dh_params(dhfile)

Загружает параметры генерации ключей для обмена ключами Диффи-Хеллмана (DH). Использование обмена ключами DH повышает конфиденциальность вперёд, но за счёт вычислительных ресурсов (как на сервере, так и на клиенте). Параметр dhfile должен содержать путь к файлу с параметрами DH в формате PEM.

Это значение не применяется к сокетам клиентов. Вы также можете использовать опцию OP_SINGLE_DH_USE для повышения безопасности.

SSLContext.set_ecdh_curve(curve_name)

Устанавливает имя кривой для обмена ключами Диффи-Хеллмана на основе эллиптических кривых (ECDH). ECDH значительно быстрее обычного DH, и, по мнению многих, столь же безопасен. Параметр curve_name должен содержать строку с описанием известной эллиптической кривой, например, prime256v1 для широко поддерживаемой кривой.

Это значение не применяется к сокетам клиентов. Вы также можете использовать опцию OP_SINGLE_ECDH_USE для повышения безопасности.

Этот метод недоступен, если HAS_ECDH имеет значение False.

См. также

SSL/TLS & Perfect Forward Secrecy

Винсент Бернат.

SSLContext.wrap_socket(sock, server_side=False, do_handshake_on_connect=True, suppress_ragged_eofs=True, server_hostname=None)

Оборачивает существующий сокет Python sock и возвращает объект SSLSocket. sock должен быть сокетом SOCK_STREAM; другие типы сокетов не поддерживаются.

Возвращаемый сокет SSL привязан к контексту, его настройкам и сертификатам. Параметры server_side, do_handshake_on_connect и suppress_ragged_eofs имеют такое же значение, как и в функции верхнего уровня wrap_socket().

При подключениях клиентов необязательный параметр server_hostname указывает имя хоста сервиса, к которому мы подключаемся. Это позволяет одному серверу размещать несколько служб SSL с разными сертификатами, очень похоже на виртуальные хосты HTTP. Указание server_hostname вызовет ValueError, если server_side имеет значение true.

Изменено в версии 2.7.9: Всегда разрешается передавать server_hostname, даже если в OpenSSL нет SNI.

SSLContext.session_stats()

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

>>> stats = context.session_stats()
>>> stats['hits'], stats['misses']
(0, 0)
SSLContext.check_hostname

Нужно ли сопоставлять имя хоста сертификата клиента с match_hostname() в SSLSocket.do_handshake(). Атрибут контекста verify_mode должен быть установлен в CERT_OPTIONAL или CERT_REQUIRED, и вы должны передать server_hostname в wrap_socket() для проверки имени хоста.

Пример:

import socket, ssl

context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
context.load_default_certs()

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = context.wrap_socket(s, server_hostname='www.verisign.com')
ssl_sock.connect(('www.verisign.com', 443))

Примечание

Эта функция требует OpenSSL 0.9.8f или более поздней версии.

SSLContext.options

Целое число, представляющее набор включённых SSL-параметров в данном контексте. Значение по умолчанию — OP_ALL, но можно указать и другие параметры, например, OP_NO_SSLv2, используя побитовое ИЛИ.

Примечание

В версиях OpenSSL, более ранних, чем 0.9.8m, можно только устанавливать параметры, а не сбрасывать их. Попытка сбросить параметр (сбросив соответствующие биты) приведёт к исключению ValueError.

SSLContext.protocol

Версия протокола, выбранная при создании контекста. Этот атрибут является только для чтения.

SSLContext.verify_flags

Флаги для операций проверки сертификатов. Можно задавать флаги, например, VERIFY_CRL_CHECK_LEAF, используя побитовое ИЛИ. По умолчанию OpenSSL не требует и не проверяет списки отозванных сертификатов (CRL). Доступно только с версией openssl 0.9.8+.

SSLContext.verify_mode

Требуется ли проверка сертификатов других участников и как вести себя в случае неудачи. Этот атрибут должен быть одним из CERT_NONE, CERT_OPTIONAL или CERT_REQUIRED.

4. Сертификаты

В целом, сертификаты являются частью системы с открытым и закрытым ключом. В этой системе каждому субъекту (который может быть компьютером, человеком или организацией) присваивается уникальный двухкомпонентный криптографический ключ. Одна часть ключа является открытой, и называется открытым ключом; другая часть является секретной, и называется закрытым ключом. Эти две части взаимосвязаны: если вы зашифруете сообщение одной из частей, вы сможете расшифровать его только другой частью.

Сертификат содержит информацию о двух субъектах. Он содержит имя субъекта и открытый ключ субъекта. Он также содержит утверждение второго субъекта, выдающего органа, о том, что субъект является тем, за кого себя выдает, и что это действительно открытый ключ субъекта. Утверждение выдающего органа подписано закрытым ключом выдающего органа, который известен только ему. Однако любой может проверить утверждение выдающего органа, найдя его открытый ключ, расшифровав утверждение с помощью него и сравнив его с другой информацией в сертификате. Сертификат также содержит информацию о периоде его действия. Это выражается двумя полями, называемыми «notBefore» и «notAfter».

При использовании сертификатов в Python клиент или сервер может использовать сертификат для подтверждения своей личности. Другая сторона сетевого соединения также может быть обязана предоставить сертификат, который может быть проверен клиентом или сервером, требующим такой проверки. Попытка подключения может быть настроена на вызов исключения, если проверка завершится неудачей. Проверка выполняется автоматически, с помощью базового фреймворка OpenSSL; приложение не должно беспокоиться об его механике. Но приложение обычно должно предоставлять наборы сертификатов, чтобы позволить этому процессу произойти.

Python использует файлы для хранения сертификатов. Они должны быть отформатированы в формате «PEM» (см. RFC 1422), который представляет собой кодировку base-64, обернутую заголовком и подвалом:

-----BEGIN CERTIFICATE-----
... (certificate in base64 PEM encoding) ...
-----END CERTIFICATE-----

4.1. Цепочки сертификатов

Файлы Python, содержащие сертификаты, могут содержать последовательность сертификатов, иногда называемую цепочкой сертификатов. Эта цепочка должна начинаться с конкретного сертификата субъекта, представляющего собой клиента или сервер, затем с сертификата выдающего органа этого сертификата, а затем с сертификата выдающего органа этого сертификата и так далее до тех пор, пока не дойдёте до самоподписанного сертификата, то есть сертификата, у которого субъект и выдающий орган совпадают, иногда называемого корневым сертификатом. Сертификаты должны быть просто объединены в файле сертификата. Например, предположим, что у нас есть цепочка из трёх сертификатов, от сертификата нашего сервера до сертификата центра сертификации, который подписал наш сертификат сервера, до корневого сертификата организации, выпустившей сертификат центра сертификации:

-----BEGIN CERTIFICATE-----
... (certificate for your server)...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (the certificate for the CA)...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (the root certificate for the CA's issuer)...
-----END CERTIFICATE-----

4.2. Сертификаты центров сертификации

Если требуется проверка сертификата другой стороны подключения, необходимо предоставить файл «CA certs», заполненный цепочками сертификатов для каждого органа сертификации, которому вы доверяете. Опять же, этот файл просто содержит эти цепочки, объединённые вместе. Для проверки Python будет использовать первую цепочку в файле, которая совпадает. Файл сертификатов платформы можно использовать, вызвав SSLContext.load_default_certs(), это делается автоматически с помощью create_default_context().

4.3. Объединённый ключ и сертификат

Часто закрытый ключ хранится в том же файле, что и сертификат; в этом случае необходимо передать только параметр certfile функции SSLContext.load_cert_chain() и wrap_socket(). Если закрытый ключ хранится вместе с сертификатом, он должен предшествовать первому сертификату в цепочке сертификатов:

-----BEGIN RSA PRIVATE KEY-----
... (private key in base64 encoding) ...
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
... (certificate in base64 PEM encoding) ...
-----END CERTIFICATE-----

4.4. Самоподписанные сертификаты

Если вы собираетесь создать сервер, предоставляющий SSL-защищённые подключения, вам необходимо получить сертификат для этого сервиса. Существует множество способов получения соответствующих сертификатов, таких как покупка сертификата у центра сертификации. Ещё одним распространённым подходом является создание самоподписанного сертификата. Самый простой способ сделать это — с помощью пакета OpenSSL, используя что-то вроде следующего:

% openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem
Generating a 1024 bit RSA private key
.......++++++
.............................++++++
writing new private key to 'cert.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:MyState
Locality Name (eg, city) []:Some City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Organization, Inc.
Organizational Unit Name (eg, section) []:My Group
Common Name (eg, YOUR name) []:myserver.mygroup.myorganization.com
Email Address []:ops@myserver.mygroup.myorganization.com
%

Недостатком самоподписанного сертификата является то, что он является собственным корневым сертификатом, и никто другой не будет иметь его в своём кэше известных (и доверенных) корневых сертификатов.

5. Примеры

5.1. Проверка поддержки SSL

Для проверки наличия поддержки SSL в установке Python пользовательский код должен использовать следующий фрагмент:

try:
    import ssl
except ImportError:
    pass
else:
    ...  # do something that requires SSL support

5.2. Клиентская операция

Этот пример создаёт SSL-контекст с рекомендуемыми настройками безопасности для клиентских сокетов, включая автоматическую проверку сертификатов:

>>> context = ssl.create_default_context()

Если вы предпочитаете настраивать настройки безопасности самостоятельно, вы можете создать контекст с нуля (но имейте в виду, что вы можете неправильно указать настройки):

>>> context = ssl.SSLContext(ssl.PROTOCOL_TLS)
>>> context.verify_mode = ssl.CERT_REQUIRED
>>> context.check_hostname = True
>>> context.load_verify_locations("/etc/ssl/certs/ca-bundle.crt")

(Этот фрагмент предполагает, что ваша операционная система размещает набор всех сертификатов CA в /etc/ssl/certs/ca-bundle.crt; если нет, вы получите ошибку и должны будете скорректировать расположение)

При использовании контекста для подключения к серверу, CERT_REQUIRED проверяет серверный сертификат: убеждается, что серверный сертификат был подписан одним из сертификатов CA, и проверяет корректность подписи:

>>> conn = context.wrap_socket(socket.socket(socket.AF_INET),
...                            server_hostname="www.python.org")
>>> conn.connect(("www.python.org", 443))

Затем вы можете получить сертификат:

>>> cert = conn.getpeercert()

Визуальный осмотр показывает, что сертификат идентифицирует требуемый сервис (то есть хост HTTPS www.python.org):

>>> pprint.pprint(cert)
{'OCSP': ('http://ocsp.digicert.com',),
 'caIssuers': ('http://cacerts.digicert.com/DigiCertSHA2ExtendedValidationServerCA.crt',),
 'crlDistributionPoints': ('http://crl3.digicert.com/sha2-ev-server-g1.crl',
                           'http://crl4.digicert.com/sha2-ev-server-g1.crl'),
 'issuer': ((('countryName', 'US'),),
            (('organizationName', 'DigiCert Inc'),),
            (('organizationalUnitName', 'www.digicert.com'),),
            (('commonName', 'DigiCert SHA2 Extended Validation Server CA'),)),
 'notAfter': 'Sep  9 12:00:00 2016 GMT',
 'notBefore': 'Sep  5 00:00:00 2014 GMT',
 'serialNumber': '01BB6F00122B177F36CAB49CEA8B6B26',
 'subject': ((('businessCategory', 'Private Organization'),),
             (('1.3.6.1.4.1.311.60.2.1.3', 'US'),),
             (('1.3.6.1.4.1.311.60.2.1.2', 'Delaware'),),
             (('serialNumber', '3359300'),),
             (('streetAddress', '16 Allen Rd'),),
             (('postalCode', '03894-4801'),),
             (('countryName', 'US'),),
             (('stateOrProvinceName', 'NH'),),
             (('localityName', 'Wolfeboro,'),),
             (('organizationName', 'Python Software Foundation'),),
             (('commonName', 'www.python.org'),)),
 'subjectAltName': (('DNS', 'www.python.org'),
                    ('DNS', 'python.org'),
                    ('DNS', 'pypi.org'),
                    ('DNS', 'docs.python.org'),
                    ('DNS', 'testpypi.python.org'),
                    ('DNS', 'bugs.python.org'),
                    ('DNS', 'wiki.python.org'),
                    ('DNS', 'hg.python.org'),
                    ('DNS', 'mail.python.org'),
                    ('DNS', 'packaging.python.org'),
                    ('DNS', 'pythonhosted.org'),
                    ('DNS', 'www.pythonhosted.org'),
                    ('DNS', 'test.pythonhosted.org'),
                    ('DNS', 'us.pycon.org'),
                    ('DNS', 'id.python.org')),
 'version': 3}

Теперь SSL-канал установлен и сертификат проверен, вы можете продолжить общение с сервером:

>>> conn.sendall(b"HEAD / HTTP/1.0\r\nHost: linuxfr.org\r\n\r\n")
>>> pprint.pprint(conn.recv(1024).split(b"\r\n"))
[b'HTTP/1.1 200 OK',
 b'Date: Sat, 18 Oct 2014 18:27:20 GMT',
 b'Server: nginx',
 b'Content-Type: text/html; charset=utf-8',
 b'X-Frame-Options: SAMEORIGIN',
 b'Content-Length: 45679',
 b'Accept-Ranges: bytes',
 b'Via: 1.1 varnish',
 b'Age: 2188',
 b'X-Served-By: cache-lcy1134-LCY',
 b'X-Cache: HIT',
 b'X-Cache-Hits: 11',
 b'Vary: Cookie',
 b'Strict-Transport-Security: max-age=63072000; includeSubDomains',
 b'Connection: close',
 b'',
 b'']

См. обсуждение Рекомендаций по безопасности ниже.

5.3. Операция на стороне сервера

Для серверной операции обычно требуется серверный сертификат и закрытый ключ, каждый в отдельном файле. Сначала вы создадите контекст, содержащий ключ и сертификат, чтобы клиенты могли проверить вашу подлинность. Затем вы откроете сокет, привяжете его к порту, вызовете listen() на нём и начнёте ждать подключения клиентов:

import socket, ssl

context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile="mycertfile", keyfile="mykeyfile")

bindsocket = socket.socket()
bindsocket.bind(('myaddr.mydomain.com', 10023))
bindsocket.listen(5)

Когда клиент подключится, вы вызовете accept() на сокете, чтобы получить новый сокет от другой стороны, и используете метод SSLContext.wrap_socket() контекста для создания серверного SSL-сокета для подключения:

while True:
    newsocket, fromaddr = bindsocket.accept()
    connstream = context.wrap_socket(newsocket, server_side=True)
    try:
        deal_with_client(connstream)
    finally:
        connstream.shutdown(socket.SHUT_RDWR)
        connstream.close()

Затем вы будете читать данные из connstream и делать с ними что-то, пока не закончите с клиентом (или клиент не закончит с вами):

def deal_with_client(connstream):
    data = connstream.read()
    # null data means the client is finished with us
    while data:
        if not do_something(connstream, data):
            # we'll assume do_something returns False
            # when we're finished with client
            break
        data = connstream.read()
    # finished with client

И вернётесь к прослушиванию новых подключений клиентов (конечно, реальный сервер, вероятно, обработает каждое подключение клиента в отдельной потоке или поместит сокеты в режим без блокировки и будет использовать цикл событий).

6. Примечания по сокетам без блокировки

При работе с сокетами без блокировки необходимо учитывать несколько моментов:

  • Вызов select() указывает, что сокет на уровне ОС можно читать (или писать), но это не подразумевает наличия достаточных данных на верхнем уровне SSL. Например, может прибыть только часть кадра SSL. Поэтому необходимо быть готовым к обработке ошибок SSLSocket.recv() и SSLSocket.send(), и повторить попытку после другого вызова select().
  • Напротив, поскольку у SSL-слоя есть собственное форматирование, сокет SSL может по-прежнему иметь доступные данные для чтения, не зная об этом select(). Поэтому сначала следует вызвать SSLSocket.recv() для сброса потенциально доступных данных, а затем блокироваться при вызове select(), если это по-прежнему необходимо.

    (конечно, аналогичные меры применяются при использовании других примитивов, таких как poll(), или тех, что в модуле selectors)

  • Сам SSL-handshake будет асинхронным: метод SSLSocket.do_handshake() должен повторяться до тех пор, пока он не вернётся успешно. Вот синопсис с использованием select() для ожидания готовности сокета:

    while True:
        try:
            sock.do_handshake()
            break
        except ssl.SSLWantReadError:
            select.select([sock], [], [])
        except ssl.SSLWantWriteError:
            select.select([], [sock], [])
    

7. Рассмотрение вопросов безопасности

7.1. Лучшие значения по умолчанию

Для клиентского использования, если у вас нет особых требований к вашей политике безопасности, настоятельно рекомендуется использовать функцию create_default_context() для создания вашего контекста SSL. Она загрузит доверенные сертификаты CA системы, включит проверку сертификатов и проверку имени хоста и попытается выбрать разумные безопасные настройки протокола и шифрования.

Если для подключения необходим сертификат клиента, его можно добавить с помощью SSLContext.load_cert_chain().

Напротив, если вы создаёте контекст SSL, вызывая конструктор SSLContext самостоятельно, он не будет иметь проверки сертификатов или проверки имени хоста по умолчанию. Если вы это делаете, прочитайте следующие параграфы, чтобы достичь хорошего уровня безопасности.

7.2. Настройки вручную

7.2.1. Проверка сертификатов

При непосредственном вызове конструктора SSLContext, CERT_NONE является значением по умолчанию. Поскольку он не аутентифицирует другого участника, он может быть небезопасным, особенно в режиме клиента, где большинство времени вы хотите гарантировать подлинность сервера, с которым взаимодействуете. Поэтому в режиме клиента настоятельно рекомендуется использовать CERT_REQUIRED. Однако этого недостаточно; также необходимо проверить, что сертификат сервера, который можно получить, вызвав SSLSocket.getpeercert(), соответствует нужному сервису. Для многих протоколов и приложений сервис можно идентифицировать по имени хоста; в этом случае можно использовать функцию match_hostname(). Эта распространённая проверка автоматически выполняется при включении SSLContext.check_hostname.

В режиме сервера, если вы хотите аутентифицировать своих клиентов с помощью SSL-слоя (вместо использования механизма аутентификации более высокого уровня), вы также должны указать CERT_REQUIRED и аналогично проверить сертификат клиента.

Примечание

В режиме клиента, CERT_OPTIONAL и CERT_REQUIRED эквивалентны, если не включены анонимные шифры (они отключены по умолчанию).

7.2.2. Версии протоколов

SSL-версии 2 и 3 считаются небезопасными и поэтому их использование опасно. Если вы хотите максимальную совместимость между клиентами и серверами, рекомендуется использовать PROTOCOL_SSLv23 в качестве версии протокола, а затем отключить SSLv2 и SSLv3 явно с помощью атрибута SSLContext.options:

context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.options |= ssl.OP_NO_SSLv2
context.options |= ssl.OP_NO_SSLv3

Созданный выше контекст SSL позволит только подключениям TLSv1 и более поздним (если это поддерживается вашей системой).

7.2.3. Выбор шифров

Если у вас есть продвинутые требования к безопасности, то точная настройка шифров, включённых при переговорах SSL-сессии, возможна через метод SSLContext.set_ciphers(). Начиная с Python 2.7.9, модуль ssl отключает определённые слабые шифры по умолчанию, но вы можете ещё больше ограничить выбор шифра. Убедитесь, что вы прочитали документацию OpenSSL о формате списка шифров cipher list format. Если вы хотите проверить, какие шифры включены заданным списком шифров, используйте команду openssl ciphers на вашей системе.

7.3. Мультипроцессирование

Если вы используете этот модуль в многопроцессном приложении (например, с использованием модулей multiprocessing или concurrent.futures), имейте в виду, что внутренний генератор случайных чисел OpenSSL не обрабатывает должным образом разветвлённые процессы. Приложения должны изменить состояние PRNG родительского процесса, если они используют любую функцию SSL с os.fork(). Любой успешный вызов RAND_add(), RAND_bytes() или RAND_pseudo_bytes() достаточно.

8. Поддержка LibreSSL

LibreSSL — это ветвь OpenSSL 1.0.1. Модуль ssl имеет ограниченную поддержку LibreSSL. Некоторые функции недоступны, когда модуль ssl скомпилирован с LibreSSL.

  • LibreSSL >= 2.6.1 больше не поддерживает NPN. Методы SSLContext.set_npn_protocols() и SSLSocket.selected_npn_protocol() недоступны.
  • SSLContext.set_default_verify_paths() игнорирует переменные среды SSL_CERT_FILE и SSL_CERT_PATH, хотя get_default_verify_paths() всё ещё их сообщает.

См. также

Class socket.socket

Документация базового класса socket

SSL/TLS Strong Encryption: An Introduction

Введение из документации веб-сервера Apache

RFC 1422: Privacy Enhancement for Internet Electronic Mail: Part II: Certificate-Based Key Management

Steve Kent

RFC 1750: Randomness Recommendations for Security

D. Eastlake et. al.

RFC 3280: Internet X.509 Public Key Infrastructure Certificate and CRL Profile

Housley et. al.

RFC 4366: Transport Layer Security (TLS) Extensions

Blake-Wilson et. al.

RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2

T. Dierks et. al.

RFC 6066: Transport Layer Security (TLS) Extensions

D. Eastlake

IANA TLS: Transport Layer Security (TLS) Parameters

IANA

RFC 7525: Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)

IETF

Mozilla’s Server Side TLS recommendations

Mozilla

© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/2.7/library/ssl.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API