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

Источник: Lib/ssl.py


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

Примечание

Некоторое поведение может зависеть от платформы, поскольку выполняются вызовы API сокетов операционной системы. Установленная версия OpenSSL также может быть причиной различий в поведении. Например, TLSv1.3 поставляется с OpenSSL версии 1.1.1.

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

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

Availability: не WASI.

Этот модуль не работает или недоступен на WebAssembly. Дополнительную информацию см. в разделе Платформы WebAssembly.

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

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

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

Изменено в версии 3.5.3: Обновлено для поддержки связывания с OpenSSL 1.1.0

Изменено в версии 3.6: OpenSSL 0.9.8, 1.0.0 и 1.0.1 устарели и больше не поддерживаются. В будущем модуль ssl будет требовать как минимум OpenSSL 1.0.2 или 1.1.0.

Изменено в версии 3.10: PEP 644 был реализован. Для работы модуля ssl требуется OpenSSL 1.1.1 или более новая версия.

Использование устаревших констант и функций приводит к предупреждениям об устаревании.

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

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

Экземпляры SSLSocket должны быть созданы с помощью метода SSLContext.wrap_socket(). Вспомогательная функция create_default_context() возвращает новый контекст с безопасными настройками по умолчанию.

Пример клиентского сокета с контекстом по умолчанию и двойным стеком IPv4/IPv6:

import socket
import ssl

hostname = 'www.python.org'
context = ssl.create_default_context()

with socket.create_connection((hostname, 443)) as sock:
    with context.wrap_socket(sock, server_hostname=hostname) as ssock:
        print(ssock.version())

Пример клиентского сокета с пользовательским контекстом и IPv4:

hostname = 'www.python.org'
# PROTOCOL_TLS_CLIENT requires valid cert chain and hostname
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.load_verify_locations('path/to/cabundle.pem')

with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock:
    with context.wrap_socket(sock, server_hostname=hostname) as ssock:
        print(ssock.version())

Серверный сокет example прослушивает localhost IPv4:

context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain('/path/to/certchain.pem', '/path/to/private.key')

with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock:
    sock.bind(('127.0.0.1', 8443))
    sock.listen(5)
    with context.wrap_socket(sock, server_side=True) as ssock:
        conn, addr = ssock.accept()
        ...

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

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

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

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

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

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

Если поддерживается keylog_filename и установлена переменная окружения SSLKEYLOGFILE, create_default_context() включает регистрацию ключей.

Настройки по умолчанию для этого контекста включают VERIFY_X509_PARTIAL_CHAIN и VERIFY_X509_STRICT. Они заставляют базовую реализацию OpenSSL вести себя более похоже на соответствующую реализацию RFC 5280, в обмен на небольшую несовместимость со старыми сертификатами X.509.

Примечание

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

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

Примечание

Если при попытке подключения некоторых старых клиентов или серверов с помощью SSLContext, созданного этой функцией, возникает ошибка «Protocol or cipher suite mismatch», возможно, они поддерживают только SSL3.0, который эта функция исключает с помощью OP_NO_SSLv3. Широко распространено мнение, что SSL3.0 - это completely broken. Если вы все еще хотите продолжать использовать эту функцию, но при этом разрешать соединения SSL 3.0, вы можете снова включить их, используя:

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

Примечание

По умолчанию этот контекст включает VERIFY_X509_STRICT, который может отклонить предварительные:rfc:5280 или неправильно оформленные сертификаты, которые базовая реализация OpenSSL в противном случае приняла бы. Хотя отключать это не рекомендуется, вы можете сделать это с помощью:

ctx = ssl.create_default_context()
ctx.verify_flags &= ~ssl.VERIFY_X509_STRICT

Added in version 3.4.

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

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

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

Изменено в версии 3.8: Добавлена поддержка регистрации ключей в SSLKEYLOGFILE.

Изменено в версии 3.10: Теперь контекст использует протокол PROTOCOL_TLS_CLIENT или PROTOCOL_TLS_SERVER вместо стандартного PROTOCOL_TLS.

Изменено в версии 3.13: Теперь контекст использует VERIFY_X509_PARTIAL_CHAIN и VERIFY_X509_STRICT в своих флагах проверки по умолчанию.

Исключения

exception ssl.SSLError

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

Изменено в версии 3.3: Раньше SSLError был подтипом socket.error.

library

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

Added in version 3.3.

reason

Строковая мнемоника, обозначающая причину возникновения ошибки, например CERTIFICATE_VERIFY_FAILED. Диапазон возможных значений зависит от версии OpenSSL.

Added in version 3.3.

exception ssl.SSLZeroReturnError

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

Added in version 3.3.

exception ssl.SSLWantReadError

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

Added in version 3.3.

exception ssl.SSLWantWriteError

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

Added in version 3.3.

exception ssl.SSLSyscallError

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

Added in version 3.3.

exception ssl.SSLEOFError

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

Added in version 3.3.

exception ssl.SSLCertVerificationError

Подкласс SSLError, возникающий при неудачной проверке сертификата.

Added in version 3.7.

verify_code

Числовой номер ошибки, обозначающий ошибку верификации.

verify_message

Человекочитаемая строка ошибки проверки.

exception ssl.CertificateError

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

Изменено в версии 3.7: Исключение теперь является псевдонимом для SSLCertVerificationError.

Случайная генерация

ssl.RAND_bytes(num)

Возвращает num криптографически стойких псевдослучайных байтов. Вызывает ошибку SSLError, если ГПСЧ не был засеян достаточным количеством данных или если операция не поддерживается текущим методом RAND. RAND_status() может использоваться для проверки состояния ГПСЧ, а RAND_add() может использоваться для засева ГПСЧ.

Почти для всех приложений предпочтительнее os.urandom().

Прочитайте статью Cryptographically secure pseudorandom number generator (CSPRNG) в Википедии, чтобы узнать требования к криптографически сильному генератору.

Added in version 3.3.

ssl.RAND_status()

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

ssl.RAND_add(bytes, entropy)

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

Изменено в версии 3.5: Записываемый bytes-like object теперь принимается.

Работа с сертификатами

ssl.cert_time_to_seconds(cert_time)

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

Вот пример:

>>> 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).

Изменено в версии 3.5: Интерпретирует введенное время как время в UTC, указанное в строке ввода часовым поясом „GMT“. Ранее использовался локальный часовой пояс. Возвращает целое число (без долей секунды во входном формате)

ssl.get_server_certificate(addr, ssl_version=PROTOCOL_TLS_CLIENT, ca_certs=None[, timeout])

Если указан адрес addr SSL-защищенного сервера в виде пары (имя хоста, номер порта), получает сертификат сервера и возвращает его в виде PEM-кодированной строки. Если указано ssl_version, то для попытки подключения к серверу используется данная версия протокола SSL. Если указан параметр ca_certs, то это должен быть файл, содержащий список корневых сертификатов, в том же формате, что и параметр cafile в SSLContext.load_verify_locations(). Вызов попытается проверить сертификат сервера на соответствие этому набору корневых сертификатов и завершится неудачей, если попытка проверки окажется неудачной. С помощью параметра timeout можно указать тайм-аут.

Изменено в версии 3.3: Эта функция теперь совместима с IPv6.

Изменено в версии 3.5: Значение ssl_version по умолчанию изменено с PROTOCOL_SSLv3 на PROTOCOL_TLS для максимальной совместимости с современными серверами.

Изменено в версии 3.10: Был добавлен параметр timeout.

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()

Возвращает именованный кортеж с путями к стандартным cafile и capath OpenSSL. Пути те же, что используются в SSLContext.set_default_verify_paths(). Возвращаемое значение - named tuple DefaultVerifyPaths:

  • cafile - разрешенный путь к cafile или None, если файл не существует,

  • capath - разрешенный путь к capath или None, если каталог не существует,

  • openssl_cafile_env - Ключ окружения OpenSSL, указывающий на cafile,

  • openssl_cafile - жестко закодированный путь к кафайлу,

  • openssl_capath_env - Ключ окружения OpenSSL, указывающий на капчу,

  • openssl_capath - жестко закодированный путь к директории capath

Added in version 3.4.

ssl.enum_certificates(store_name)

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

Функция возвращает список кортежей (cert_bytes, encoding_type, trust). Тип_кодировки задает кодировку 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)]

Availability: Windows.

Added in version 3.4.

ssl.enum_crls(store_name)

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

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

Availability: Windows.

Added in version 3.4.

Константы

Все константы теперь являются коллекциями enum.IntEnum или enum.IntFlag.

Added in version 3.6.

ssl.CERT_NONE

Возможное значение для SSLContext.verify_mode. За исключением PROTOCOL_TLS_CLIENT, это режим по умолчанию. При использовании сокетов на стороне клиента принимается практически любой сертификат. Ошибки проверки, такие как недоверенный или просроченный сертификат, игнорируются и не прерывают рукопожатие TLS/SSL.

В режиме сервера сертификат у клиента не запрашивается, поэтому клиент не отправляет сертификат для проверки подлинности.

См. обсуждение Соображения безопасности ниже.

ssl.CERT_OPTIONAL

Возможное значение для SSLContext.verify_mode. В клиентском режиме CERT_OPTIONAL имеет то же значение, что и CERT_REQUIRED. Рекомендуется использовать CERT_REQUIRED для сокетов на стороне клиента.

В режиме сервера клиенту отправляется запрос на сертификат клиента. Клиент может либо проигнорировать запрос, либо отправить сертификат, чтобы выполнить аутентификацию с помощью сертификата клиента TLS. Если клиент решает отправить сертификат, он проверяется. Любая ошибка проверки немедленно прерывает рукопожатие TLS.

Для использования этого параметра необходимо, чтобы в SSLContext.load_verify_locations() был передан действительный набор сертификатов ЦС.

ssl.CERT_REQUIRED

Возможное значение для SSLContext.verify_mode. В этом режиме сертификаты требуются с другой стороны сокетного соединения; если сертификат не предоставлен или его проверка не удалась, будет выдан сигнал SSLError. Этот режим не достаточен для проверки сертификата в режиме клиента, так как он не соответствует именам хостов. check_hostname также должен быть включен для проверки подлинности сертификата. PROTOCOL_TLS_CLIENT использует CERT_REQUIRED и включает check_hostname по умолчанию.

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

Для использования этого параметра необходимо, чтобы в SSLContext.load_verify_locations() был передан действительный набор сертификатов ЦС.

class ssl.VerifyMode

enum.IntEnum коллекция констант CERT_*.

Added in version 3.6.

ssl.VERIFY_DEFAULT

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

Added in version 3.4.

ssl.VERIFY_CRL_CHECK_LEAF

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

Added in version 3.4.

ssl.VERIFY_CRL_CHECK_CHAIN

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

Added in version 3.4.

ssl.VERIFY_X509_STRICT

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

Added in version 3.4.

ssl.VERIFY_ALLOW_PROXY_CERTS

Возможное значение SSLContext.verify_flags для включения проверки сертификата прокси-сервера.

Added in version 3.10.

ssl.VERIFY_X509_TRUSTED_FIRST

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

Added in version 3.4.4.

ssl.VERIFY_X509_PARTIAL_CHAIN

Возможное значение для SSLContext.verify_flags. Указывает OpenSSL принимать промежуточные УЦ в хранилище доверия в качестве якорей доверия, так же как и самоподписанные сертификаты корневых УЦ. Это позволяет доверять сертификатам, выданным промежуточным ЦС, без необходимости доверять его предку - корневому ЦС.

Added in version 3.10.

class ssl.VerifyFlags

enum.IntFlag коллекция констант VERIFY_*.

Added in version 3.6.

ssl.PROTOCOL_TLS

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

Added in version 3.6.

Не рекомендуется, начиная с версии 3.10: Клиенты и серверы TLS требуют разных настроек по умолчанию для безопасной связи. Общая константа протокола TLS устарела в пользу PROTOCOL_TLS_CLIENT и PROTOCOL_TLS_SERVER.

ssl.PROTOCOL_TLS_CLIENT

Автоматическое определение наивысшей версии протокола, которую поддерживают клиент и сервер, и настройка контекстных соединений на стороне клиента. По умолчанию протокол включает CERT_REQUIRED и check_hostname.

Added in version 3.6.

ssl.PROTOCOL_TLS_SERVER

Автоматически определяйте самую высокую версию протокола, которую поддерживают клиент и сервер, и настраивайте контекстные соединения на стороне сервера.

Added in version 3.6.

ssl.PROTOCOL_SSLv23

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

Не рекомендуется, начиная с версии 3.6: Вместо этого используйте PROTOCOL_TLS.

ssl.PROTOCOL_SSLv3

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

Этот протокол недоступен, если OpenSSL скомпилирован с опцией no-ssl3.

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

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

Не рекомендуется, начиная с версии 3.6: В OpenSSL устарели все протоколы, зависящие от версии. Вместо протокола по умолчанию PROTOCOL_TLS_SERVER или PROTOCOL_TLS_CLIENT используйте протоколы SSLContext.minimum_version и SSLContext.maximum_version.

ssl.PROTOCOL_TLSv1

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

Не рекомендуется, начиная с версии 3.6: OpenSSL отказался от всех протоколов, специфичных для конкретной версии.

ssl.PROTOCOL_TLSv1_1

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

Added in version 3.4.

Не рекомендуется, начиная с версии 3.6: OpenSSL отказался от всех протоколов, специфичных для конкретной версии.

ssl.PROTOCOL_TLSv1_2

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

Added in version 3.4.

Не рекомендуется, начиная с версии 3.6: OpenSSL отказался от всех протоколов, специфичных для конкретной версии.

ssl.OP_ALL

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

Added in version 3.2.

ssl.OP_NO_SSLv2

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

Added in version 3.2.

Не рекомендуется, начиная с версии 3.6: SSLv2 устарел

ssl.OP_NO_SSLv3

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

Added in version 3.2.

Не рекомендуется, начиная с версии 3.6: SSLv3 устарел

ssl.OP_NO_TLSv1

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

Added in version 3.2.

Не рекомендуется, начиная с версии 3.7: Опция устарела с версии OpenSSL 1.1.0, вместо нее используйте новые SSLContext.minimum_version и SSLContext.maximum_version.

ssl.OP_NO_TLSv1_1

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

Added in version 3.4.

Не рекомендуется, начиная с версии 3.7: Эта опция устарела с версии OpenSSL 1.1.0.

ssl.OP_NO_TLSv1_2

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

Added in version 3.4.

Не рекомендуется, начиная с версии 3.7: Эта опция устарела с версии OpenSSL 1.1.0.

ssl.OP_NO_TLSv1_3

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

Added in version 3.6.3.

Не рекомендуется, начиная с версии 3.7: Опция устарела с версии OpenSSL 1.1.0. Она была добавлена в версии 2.7.15 и 3.6.3 для обратной совместимости с OpenSSL 1.0.2.

ssl.OP_NO_RENEGOTIATION

Отключите все повторные переговоры в TLSv1.2 и более ранних версиях. Не отправляйте сообщения HelloRequest и игнорируйте запросы на повторное согласование через ClientHello.

Эта опция доступна только в OpenSSL 1.1.0h и более поздних версиях.

Added in version 3.7.

ssl.OP_CIPHER_SERVER_PREFERENCE

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

Added in version 3.3.

ssl.OP_SINGLE_DH_USE

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

Added in version 3.3.

ssl.OP_SINGLE_ECDH_USE

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

Added in version 3.3.

ssl.OP_ENABLE_MIDDLEBOX_COMPAT

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

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

Added in version 3.8.

ssl.OP_NO_COMPRESSION

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

Added in version 3.3.

class ssl.Options

enum.IntFlag коллекция констант OP_*.

ssl.OP_NO_TICKET

Запрещает стороне клиента запрашивать билет сессии.

Added in version 3.6.

ssl.OP_IGNORE_UNEXPECTED_EOF

Игнорируйте неожиданное завершение TLS-соединений.

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

Added in version 3.10.

ssl.OP_ENABLE_KTLS

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

Обратите внимание, что при включенном TLS ядра некоторые криптографические операции выполняются ядром напрямую, а не через доступные провайдеры OpenSSL. Это может быть нежелательно, если, например, приложение требует, чтобы все криптографические операции выполнялись провайдером FIPS.

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

Added in version 3.12.

ssl.OP_LEGACY_SERVER_CONNECT

Разрешите унаследованное небезопасное пересогласование между OpenSSL и непропатченными серверами только.

Added in version 3.12.

ssl.HAS_ALPN

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

Added in version 3.5.

ssl.HAS_NEVER_CHECK_COMMON_NAME

Имеет ли библиотека OpenSSL встроенную поддержку, не проверяющую общее имя субъекта, а SSLContext.hostname_checks_common_name - возможность записи.

Added in version 3.7.

ssl.HAS_ECDH

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

Added in version 3.3.

ssl.HAS_SNI

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

Added in version 3.2.

ssl.HAS_NPN

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

Added in version 3.3.

ssl.HAS_SSLv2

Имеется ли в библиотеке OpenSSL встроенная поддержка протокола SSL 2.0.

Added in version 3.7.

ssl.HAS_SSLv3

Имеется ли в библиотеке OpenSSL встроенная поддержка протокола SSL 3.0.

Added in version 3.7.

ssl.HAS_TLSv1

Имеется ли в библиотеке OpenSSL встроенная поддержка протокола TLS 1.0.

Added in version 3.7.

ssl.HAS_TLSv1_1

Имеется ли в библиотеке OpenSSL встроенная поддержка протокола TLS 1.1.

Added in version 3.7.

ssl.HAS_TLSv1_2

Имеется ли в библиотеке OpenSSL встроенная поддержка протокола TLS 1.2.

Added in version 3.7.

ssl.HAS_TLSv1_3

Имеется ли в библиотеке OpenSSL встроенная поддержка протокола TLS 1.3.

Added in version 3.7.

ssl.HAS_PSK

Имеет ли библиотека OpenSSL встроенную поддержку TLS-PSK.

Added in version 3.13.

ssl.CHANNEL_BINDING_TYPES

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

Added in version 3.3.

ssl.OPENSSL_VERSION

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

>>> ssl.OPENSSL_VERSION
'OpenSSL 1.0.2k  26 Jan 2017'

Added in version 3.2.

ssl.OPENSSL_VERSION_INFO

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

>>> ssl.OPENSSL_VERSION_INFO
(1, 0, 2, 11, 15)

Added in version 3.2.

ssl.OPENSSL_VERSION_NUMBER

Необработанный номер версии библиотеки OpenSSL в виде одного целого числа:

>>> ssl.OPENSSL_VERSION_NUMBER
268443839
>>> hex(ssl.OPENSSL_VERSION_NUMBER)
'0x100020bf'

Added in version 3.2.

ssl.ALERT_DESCRIPTION_HANDSHAKE_FAILURE
ssl.ALERT_DESCRIPTION_INTERNAL_ERROR
ALERT_DESCRIPTION_*

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

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

Added in version 3.4.

class ssl.AlertDescription

enum.IntEnum коллекция констант ALERT_DESCRIPTION_*.

Added in version 3.6.

Purpose.SERVER_AUTH

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

Added in version 3.4.

Purpose.CLIENT_AUTH

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

Added in version 3.4.

class ssl.SSLErrorNumber

enum.IntEnum коллекция констант SSL_ERROR_*.

Added in version 3.6.

class ssl.TLSVersion

enum.IntEnum коллекция версий SSL и TLS для SSLContext.maximum_version и SSLContext.minimum_version.

Added in version 3.7.

TLSVersion.MINIMUM_SUPPORTED
TLSVersion.MAXIMUM_SUPPORTED

Минимальная или максимальная поддерживаемая версия SSL или TLS. Это магические константы. Их значения не отражают минимальную и максимальную доступные версии TLS/SSL.

TLSVersion.SSLv3
TLSVersion.TLSv1
TLSVersion.TLSv1_1
TLSVersion.TLSv1_2
TLSVersion.TLSv1_3

От SSL 3.0 до TLS 1.3.

Не рекомендуется, начиная с версии 3.10: Все члены TLSVersion, кроме TLSVersion.TLSv1_2 и TLSVersion.TLSv1_3, устарели.

Сокеты SSL

class ssl.SSLSocket(socket.socket)

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

Однако, поскольку протокол SSL (и TLS) имеет собственное обрамление поверх TCP, абстракция сокетов SSL может в некоторых аспектах отличаться от спецификации обычных сокетов уровня ОС. См. особенно notes on non-blocking sockets.

Экземпляры SSLSocket должны быть созданы с помощью метода SSLContext.wrap_socket().

Изменено в версии 3.5: Был добавлен метод sendfile().

Изменено в версии 3.5: Значение shutdown() не сбрасывает таймаут сокета при каждом получении или отправке байтов. Таймаут сокета теперь равен максимальной общей продолжительности отключения.

Не рекомендуется, начиная с версии 3.6: Создание экземпляра SSLSocket напрямую устарело, используйте SSLContext.wrap_socket(), чтобы обернуть сокет.

Изменено в версии 3.7: Экземпляры SSLSocket должны создаваться с помощью wrap_socket(). В более ранних версиях можно было создавать экземпляры напрямую. Это никогда не документировалось и официально не поддерживалось.

Изменено в версии 3.10: Теперь Python использует внутренние значения SSL_read_ex и SSL_write_ex. Функции поддерживают чтение и запись данных размером более 2 ГБ. Запись данных нулевой длины больше не приводит к ошибке нарушения протокола.

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

SSLSocket.read(len=1024, buffer=None)

Считывает до len байт данных из сокета SSL и возвращает результат в виде экземпляра bytes. Если указан buffer, то вместо этого считывается в буфер и возвращается количество считанных байт.

Поднимите SSLWantReadError или SSLWantWriteError, если сокет равен non-blocking и чтение будет заблокировано.

Поскольку в любой момент возможно повторное согласование, обращение к read() также может вызвать операцию записи.

Изменено в версии 3.5: Таймаут сокета больше не сбрасывается каждый раз при получении или отправке байтов. Теперь таймаут сокета - это максимальная общая продолжительность чтения до len байт.

Не рекомендуется, начиная с версии 3.6: Используйте recv() вместо read().

SSLSocket.write(buf)

Записывает buf в сокет SSL и возвращает количество записанных байт. Аргумент buf должен быть объектом, поддерживающим интерфейс буфера.

Поднимите SSLWantReadError или SSLWantWriteError, если сокет имеет значение non-blocking и запись будет заблокирована.

Поскольку в любой момент возможно повторное согласование, обращение к write() также может вызвать операции чтения.

Изменено в версии 3.5: Таймаут сокета больше не сбрасывается каждый раз при получении или отправке байтов. Теперь таймаут сокета - это максимальная общая продолжительность записи buf.

Не рекомендуется, начиная с версии 3.6: Используйте send() вместо write().

Примечание

Методы read() и write() - это низкоуровневые методы, которые считывают и записывают незашифрованные данные на уровне приложения и расшифровывают/зашифровывают их в зашифрованные данные на уровне провода. Эти методы требуют активного SSL-соединения, т. е. рукопожатие было завершено и SSLSocket.unwrap() не вызывался.

Обычно вместо этих методов следует использовать методы API сокета, такие как recv() и send().

SSLSocket.do_handshake()

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

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

Изменено в версии 3.5: Таймаут сокета больше не сбрасывается каждый раз при получении или отправке байтов. Таймаут сокета теперь равен максимальной общей продолжительности рукопожатия.

Изменено в версии 3.7: Имя хоста или IP-адрес сопоставляются OpenSSL во время рукопожатия. Функция match_hostname() больше не используется. Если OpenSSL отказывает в имени хоста или IP-адресе, рукопожатие прерывается раньше времени, и пиру отправляется сообщение TLS alert.

SSLSocket.getpeercert(binary_form=False)

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

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

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

{'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}

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

  • для клиентского SSL-сокета, сервер всегда будет предоставлять сертификат, независимо от того, требовалась ли проверка;

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

См. также SSLContext.check_hostname.

Изменено в версии 3.2: Возвращаемый словарь включает дополнительные элементы, такие как issuer и notBefore.

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

Изменено в версии 3.9: Строки адресов IPv6 больше не содержат завершающей новой строки.

SSLSocket.get_verified_chain()

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

Added in version 3.13.

SSLSocket.get_unverified_chain()

Возвращает цепочку необработанных сертификатов, предоставленную другим участником SSL-канала, в виде списка байтов в DER-кодировке.

Added in version 3.13.

SSLSocket.cipher()

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

SSLSocket.shared_ciphers()

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

Added in version 3.5.

SSLSocket.compression()

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

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

Added in version 3.3.

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

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

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

Added in version 3.3.

SSLSocket.selected_alpn_protocol()

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

Added in version 3.5.

SSLSocket.selected_npn_protocol()

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

Added in version 3.3.

Не рекомендуется, начиная с версии 3.10: NPN был заменен на ALPN

SSLSocket.unwrap()

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

SSLSocket.verify_client_post_handshake()

Запрашивает аутентификацию после рукопожатия (PHA) у клиента TLS 1.3. PHA может быть инициирована только для соединения TLS 1.3 из сокета на стороне сервера, после начального рукопожатия TLS и с включенной PHA на обеих сторонах, см. SSLContext.post_handshake_auth.

Метод не выполняет обмен сертификатами немедленно. Серверная сторона отправляет CertificateRequest во время следующего события записи и ожидает, что клиент ответит сертификатом на следующее событие чтения.

Если какое-либо предварительное условие не выполняется (например, не TLS 1.3, PHA не включена), выдается сообщение SSLError.

Примечание

Доступен только при использовании OpenSSL 1.1.1 и поддержке TLS 1.3. Без поддержки TLS 1.3 метод вызывает ошибку NotImplementedError.

Added in version 3.8.

SSLSocket.version()

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

Added in version 3.5.

SSLSocket.pending()

Возвращает количество уже расшифрованных байтов, доступных для чтения и ожидающих соединения.

SSLSocket.context

Объект SSLContext, к которому привязан данный SSL-сокет.

Added in version 3.2.

SSLSocket.server_side

Булево значение, которое равно True для сокетов на стороне сервера и False для сокетов на стороне клиента.

Added in version 3.2.

SSLSocket.server_hostname

Имя хоста сервера: Тип str, или None для серверного сокета, или если имя хоста не было указано в конструкторе.

Added in version 3.2.

Изменено в версии 3.7: Теперь этот атрибут всегда является ASCII-текстом. Когда server_hostname является интернационализированным доменным именем (IDN), этот атрибут теперь хранит форму A-метки ("xn--pythn-mua.org"), а не форму U-метки ("pythön.org").

SSLSocket.session

Сеанс SSLSession для данного SSL-соединения. Сессия доступна для сокетов на стороне клиента и сервера после выполнения рукопожатия TLS. Для клиентских сокетов сессия может быть установлена до вызова do_handshake(), чтобы повторно использовать сессию.

Added in version 3.6.

SSLSocket.session_reused

Added in version 3.6.

Контексты SSL

Added in version 3.2.

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

class ssl.SSLContext(protocol=None)

Создание нового SSL-контекста. Вы можете передать protocol, который должен быть одной из констант PROTOCOL_*, определенных в этом модуле. Параметр указывает, какую версию протокола SSL следует использовать. Как правило, сервер выбирает определенную версию протокола, а клиент должен приспособиться к выбору сервера. Большинство версий несовместимы с другими версиями. Если параметр не указан, по умолчанию используется PROTOCOL_TLS; он обеспечивает наибольшую совместимость с другими версиями.

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

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

SSLv2

SSLv3

ТЛС [3]

TLSv1

TLSv1.1

TLSv1.2

SSLv2

да

нет

нет [1]

нет

нет

нет

SSLv3

нет

да

нет [2]

нет

нет

нет

TLS (SSLv23) [3]

нет [1]

нет [2]

да

да

да

да

TLSv1.

нет

нет

да

да

нет

нет

TLSv1.1.

нет

нет

да

нет

да

нет

TLSv1.2.

нет

нет

да

нет

нет

да

Сноски

См.также

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

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

Не рекомендуется, начиная с версии 3.10: SSLContext без аргумента протокола является устаревшим. В будущем класс контекста будет требовать протокол PROTOCOL_TLS_CLIENT или PROTOCOL_TLS_SERVER.

Изменено в версии 3.10: В наборы шифров по умолчанию теперь входят только безопасные шифры AES и ChaCha20 с прямой секретностью и уровнем безопасности 2. Запрещены ключи RSA и DH длиной менее 2048 бит и ключи ECC длиной менее 224 бит. PROTOCOL_TLS, PROTOCOL_TLS_CLIENT и PROTOCOL_TLS_SERVER используют TLS 1.2 в качестве минимальной версии TLS.

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

SSLContext.cert_store_stats()

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

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

>>> context.cert_store_stats()
{'crl': 0, 'x509_ca': 1, 'x509': 2}

Added in version 3.4.

SSLContext.load_cert_chain(certfile, keyfile=None, password=None)

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

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

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

Если закрытый ключ не совпадает с сертификатом, выдается сообщение SSLError.

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

SSLContext.load_default_certs(purpose=Purpose.SERVER_AUTH)

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

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

Added in version 3.4.

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

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

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

Строка cafile (если присутствует) - это путь к файлу со скомпонованными сертификатами ЦС в формате PEM. Дополнительные сведения о том, как расположить сертификаты в этом файле, см. в разделе Сертификаты.

Строка capath, если она присутствует, представляет собой путь к директории, содержащей несколько сертификатов CA в формате PEM, следующий за OpenSSL specific layout.

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

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

SSLContext.get_ca_certs(binary_form=False)

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

Примечание

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

Added in version 3.4.

SSLContext.get_ciphers()

Получить список включенных шифров. Список располагается в порядке приоритета шифров. См. SSLContext.set_ciphers().

Пример:

>>> ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
>>> ctx.set_ciphers('ECDHE+AESGCM:!ECDSA')
>>> ctx.get_ciphers()
[{'aead': True,
  'alg_bits': 256,
  'auth': 'auth-rsa',
  'description': 'ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH     Au=RSA  '
                 'Enc=AESGCM(256) Mac=AEAD',
  'digest': None,
  'id': 50380848,
  'kea': 'kx-ecdhe',
  'name': 'ECDHE-RSA-AES256-GCM-SHA384',
  'protocol': 'TLSv1.2',
  'strength_bits': 256,
  'symmetric': 'aes-256-gcm'},
 {'aead': True,
  'alg_bits': 128,
  'auth': 'auth-rsa',
  'description': 'ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH     Au=RSA  '
                 'Enc=AESGCM(128) Mac=AEAD',
  'digest': None,
  'id': 50380847,
  'kea': 'kx-ecdhe',
  'name': 'ECDHE-RSA-AES128-GCM-SHA256',
  'protocol': 'TLSv1.2',
  'strength_bits': 128,
  'symmetric': 'aes-128-gcm'}]

Added in version 3.6.

SSLContext.set_default_verify_paths()

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

SSLContext.set_ciphers(ciphers)

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

Примечание

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

Шифр-сюиты 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.

Added in version 3.5.

SSLContext.set_npn_protocols(protocols)

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

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

Added in version 3.3.

Не рекомендуется, начиная с версии 3.10: NPN был заменен на ALPN

SSLContext.sni_callback

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

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

Функция обратного вызова будет вызвана с тремя аргументами: первый - ssl.SSLSocket, второй - строка, представляющая имя сервера, с которым клиент намерен установить связь (или None, если приветствие клиента TLS не содержит имени сервера), и третий аргумент - исходный SSLContext. Аргумент «имя сервера» является текстовым. Для интернационализированного доменного имени имя сервера является IDN A-меткой ("xn--pythn-mua.org").

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

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

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

Если из функции sni_callback будет вызвано исключение, то TLS-соединение прервется с выдачей фатального TLS-сообщения ALERT_DESCRIPTION_HANDSHAKE_FAILURE.

Этот метод поднимет NotImplementedError, если при сборке библиотеки OpenSSL было определено OPENSSL_NO_TLSEXT.

Added in version 3.7.

SSLContext.set_servername_callback(server_name_callback)

Это устаревший API, сохраненный для обратной совместимости. По возможности вместо него следует использовать sni_callback. Данный server_name_callback аналогичен sni_callback, за исключением того, что когда имя хоста сервера является интернационализированным доменным именем в кодировке IDN, server_name_callback получает декодированную U-метку ("pythön.org").

Если произошла ошибка декодирования имени сервера, TLS-соединение будет прервано с выдачей клиенту сообщения ALERT_DESCRIPTION_INTERNAL_ERROR fatal TLS alert.

Added in version 3.4.

SSLContext.load_dh_params(dhfile)

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

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

Added in version 3.3.

SSLContext.set_ecdh_curve(curve_name)

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

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

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

Added in version 3.3.

См.также

SSL/TLS & Perfect Forward Secrecy

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

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

Оберните существующий сокет Python sock и верните экземпляр SSLContext.sslsocket_class (по умолчанию SSLSocket). Возвращаемый SSL-сокет привязан к контексту, его настройкам и сертификатам. sock должен быть сокетом SOCK_STREAM; другие типы сокетов не поддерживаются.

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

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

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

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

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

сессия, см. session.

Чтобы завернуть SSLSocket в другой SSLSocket, используйте SSLContext.wrap_bio().

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

Изменено в версии 3.6: Был добавлен аргумент session.

Изменено в версии 3.7: Метод возвращает экземпляр SSLContext.sslsocket_class вместо жестко закодированного SSLSocket.

SSLContext.sslsocket_class

Тип возврата SSLContext.wrap_socket(), по умолчанию SSLSocket. Атрибут может быть переопределен для экземпляра класса, чтобы вернуть пользовательский подкласс SSLSocket.

Added in version 3.7.

SSLContext.wrap_bio(incoming, outgoing, server_side=False, server_hostname=None, session=None)

Оберните объекты BIO входящий и исходящий и верните экземпляр SSLContext.sslobject_class (по умолчанию SSLObject). Подпрограммы SSL будут считывать входные данные из входящего BIO и записывать данные в исходящий BIO.

Параметры server_side, server_hostname и session имеют то же значение, что и в SSLContext.wrap_socket().

Изменено в версии 3.6: Был добавлен аргумент session.

Изменено в версии 3.7: Метод возвращает экземпляр SSLContext.sslobject_class вместо жестко закодированного SSLObject.

SSLContext.sslobject_class

Тип возврата SSLContext.wrap_bio(), по умолчанию SSLObject. Атрибут может быть переопределен для экземпляра класса, чтобы вернуть пользовательский подкласс SSLObject.

Added in version 3.7.

SSLContext.session_stats()

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

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

Нужно ли сопоставлять имя хоста сертификата-аналога в SSLSocket.do_handshake(). Для контекста verify_mode должно быть установлено значение CERT_OPTIONAL или CERT_REQUIRED, а в wrap_socket() необходимо передать server_hostname, чтобы имя хоста совпало. Включение проверки имени хоста автоматически переводит verify_mode из CERT_NONE в CERT_REQUIRED. Пока включена проверка имени хоста, его нельзя вернуть в значение CERT_NONE. Протокол PROTOCOL_TLS_CLIENT включает проверку имени хоста по умолчанию. В других протоколах проверка имени хоста должна быть включена явно.

Пример:

import socket, ssl

context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
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))

Added in version 3.4.

Изменено в версии 3.7: verify_mode теперь автоматически меняется на CERT_REQUIRED, когда включена проверка имени хоста, а verify_mode становится CERT_NONE. Ранее та же операция завершилась бы неудачей при значении ValueError.

SSLContext.keylog_filename

Запись ключей TLS в файл keylog при генерации или получении ключевого материала. Файл keylog предназначен только для отладки. Формат файла определен NSS и используется многими анализаторами трафика, такими как Wireshark. Файл журнала открывается только в режиме добавления. Записи синхронизируются между потоками, но не между процессами.

Added in version 3.8.

SSLContext.maximum_version

Член перечисления TLSVersion, представляющий наивысшую поддерживаемую версию TLS. По умолчанию используется значение TLSVersion.MAXIMUM_SUPPORTED. Атрибут доступен только для чтения для протоколов, отличных от PROTOCOL_TLS, PROTOCOL_TLS_CLIENT и PROTOCOL_TLS_SERVER.

Атрибуты maximum_version, minimum_version и SSLContext.options влияют на поддерживаемые версии SSL и TLS контекста. Реализация не предотвращает недопустимые комбинации. Например, контекст с OP_NO_TLSv1_2 в options и maximum_version, установленным в TLSVersion.TLSv1_2, не сможет установить соединение TLS 1.2.

Added in version 3.7.

SSLContext.minimum_version

Как и SSLContext.maximum_version, за исключением наименьшей поддерживаемой версии или TLSVersion.MINIMUM_SUPPORTED.

Added in version 3.7.

SSLContext.num_tickets

Управление количеством билетов сеанса TLS 1.3 для контекста PROTOCOL_TLS_SERVER. Настройка не влияет на соединения TLS 1.0 - 1.2.

Added in version 3.8.

SSLContext.options

Целое число, представляющее набор опций SSL, включенных в данном контексте. По умолчанию используется значение OP_ALL, но вы можете указать другие опции, например OP_NO_SSLv2, объединив их в OR.

Изменено в версии 3.6: SSLContext.options возвращает флаги Options:

>>> ssl.create_default_context().options  
<Options.OP_ALL|OP_NO_SSLv3|OP_NO_SSLv2|OP_NO_COMPRESSION: 2197947391>

Не рекомендуется, начиная с версии 3.7: Все опции OP_NO_SSL* и OP_NO_TLS* были устаревшими, начиная с Python 3.7. Вместо них используйте SSLContext.minimum_version и SSLContext.maximum_version.

SSLContext.post_handshake_auth

Включите аутентификацию клиента TLS 1.3 после рукопожатия. По умолчанию аутентификация после квитирования отключена, и сервер может запрашивать сертификат клиента TLS только во время начального квитирования. Если эта функция включена, сервер может запрашивать сертификат клиента TLS в любое время после рукопожатия.

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

При включении на серверных сокетах SSLContext.verify_mode также должен быть установлен в CERT_OPTIONAL или CERT_REQUIRED. Фактический обмен клиентскими cert откладывается до вызова SSLSocket.verify_client_post_handshake() и выполнения некоторых операций ввода-вывода.

Added in version 3.8.

SSLContext.protocol

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

SSLContext.hostname_checks_common_name

Будет ли check_hostname возвращаться к проверке общего имени субъекта сертификата при отсутствии расширения альтернативного имени субъекта (по умолчанию: true).

Added in version 3.7.

Изменено в версии 3.10: Флаг не действует в OpenSSL до версии 1.1.1l. Python 3.8.9, 3.9.3 и 3.10 содержат обходные пути для предыдущих версий.

SSLContext.security_level

Целое число, представляющее security level для контекста. Этот атрибут доступен только для чтения.

Added in version 3.10.

SSLContext.verify_flags

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

Added in version 3.4.

Изменено в версии 3.6: SSLContext.verify_flags возвращает флаги VerifyFlags:

>>> ssl.create_default_context().verify_flags  
<VerifyFlags.VERIFY_X509_TRUSTED_FIRST: 32768>
SSLContext.verify_mode

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

Изменено в версии 3.6: SSLContext.verify_mode возвращает VerifyMode перечисление:

>>> ssl.create_default_context().verify_mode  
<VerifyMode.CERT_REQUIRED: 2>
SSLContext.set_psk_client_callback(callback)

Включает аутентификацию TLS-PSK (предварительный общий ключ) при соединении на стороне клиента.

В общем случае следует предпочесть аутентификацию на основе сертификатов этому методу.

Параметр callback - это вызываемый объект с сигнатурой: def callback(hint: str | None) -> tuple[str | None, bytes]. Параметр hint - необязательная подсказка идентификатора, передаваемая сервером. Возвращаемое значение - кортеж в форме (client-identity, psk). Идентификатор клиента - это необязательная строка, которая может быть использована сервером для выбора соответствующего PSK для клиента. Строка должна быть меньше или равна 256 октетов в кодировке UTF-8. PSK - это bytes-like object, представляющий собой ключ с предварительным разделением. Возврат PSK нулевой длины означает отказ в соединении.

Установка callback в None удаляет все существующие обратные вызовы.

Примечание

При использовании TLS 1.3:

  • параметр hint всегда равен None.

  • client-identity должна быть непустой строкой.

Пример использования:

context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
context.maximum_version = ssl.TLSVersion.TLSv1_2
context.set_ciphers('PSK')

# A simple lambda:
psk = bytes.fromhex('c0ffee')
context.set_psk_client_callback(lambda hint: (None, psk))

# A table using the hint from the server:
psk_table = { 'ServerId_1': bytes.fromhex('c0ffee'),
              'ServerId_2': bytes.fromhex('facade')
}
def callback(hint):
    return 'ClientId_1', psk_table.get(hint, b'')
context.set_psk_client_callback(callback)

Этот метод поднимет значение NotImplementedError, если HAS_PSK равно False.

Added in version 3.13.

SSLContext.set_psk_server_callback(callback, identity_hint=None)

Включает аутентификацию TLS-PSK (предварительный общий ключ) при подключении на стороне сервера.

В общем случае следует предпочесть аутентификацию на основе сертификатов этому методу.

Параметр callback - это вызываемый объект с сигнатурой: def callback(identity: str | None) -> bytes. Параметр identity - это необязательный идентификатор, отправленный клиентом, который может быть использован для выбора соответствующего PSK. Возвращаемое значение - bytes-like object, представляющее собой предварительно распределенный ключ. Возврат PSK нулевой длины означает отказ в соединении.

Установка callback в None удаляет все существующие обратные вызовы.

Параметр identity_hint - это необязательная строка подсказки идентификатора, передаваемая клиенту. Строка должна быть меньше или равна 256 октетов в кодировке UTF-8.

Примечание

При использовании TLS 1.3 параметр identity_hint не передается клиенту.

Пример использования:

context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.maximum_version = ssl.TLSVersion.TLSv1_2
context.set_ciphers('PSK')

# A simple lambda:
psk = bytes.fromhex('c0ffee')
context.set_psk_server_callback(lambda identity: psk)

# A table using the identity of the client:
psk_table = { 'ClientId_1': bytes.fromhex('c0ffee'),
              'ClientId_2': bytes.fromhex('facade')
}
def callback(identity):
    return psk_table.get(identity, b'')
context.set_psk_server_callback(callback, 'ServerId_1')

Этот метод поднимет значение NotImplementedError, если HAS_PSK равно False.

Added in version 3.13.

Сертификаты

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

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

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

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

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

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

Файлы 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-----

Сертификаты ЦС

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

Комбинированный ключ и сертификат

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

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

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

Если вы собираетесь создать сервер, предоставляющий услуги 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
%

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

Примеры

Тестирование на поддержку SSL

Чтобы проверить наличие поддержки SSL в установке Python, пользовательский код должен использовать следующую идиому:

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

Работа на стороне клиента

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

>>> context = ssl.create_default_context()

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

>>> context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
>>> context.load_verify_locations("/etc/ssl/certs/ca-bundle.crt")

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

Протокол PROTOCOL_TLS_CLIENT настраивает контекст для проверки сертификата и имени хоста. Для протокола verify_mode устанавливается значение CERT_REQUIRED, а для check_hostname - True. Все остальные протоколы создают SSL-контексты с небезопасными настройками по умолчанию.

Когда вы используете контекст для подключения к серверу, CERT_REQUIRED и check_hostname проверяют сертификат сервера: удостоверяются, что сертификат сервера был подписан одним из сертификатов 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.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'']

См. обсуждение Соображения безопасности ниже.

Работа на стороне сервера

Для работы с сервером обычно требуется сертификат сервера и закрытый ключ, каждый из которых хранится в отдельном файле. Сначала вы создадите контекст, содержащий ключ и сертификат, чтобы клиенты могли проверить вашу подлинность. Затем вы откроете сокет, привяжете его к порту, вызовете на нем 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.example.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.recv(1024)
    # empty 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.recv(1024)
    # finished with client

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

Заметки о неблокирующих сокетах

В неблокирующем режиме SSL-сокеты ведут себя несколько иначе, чем обычные сокеты. Поэтому при работе с неблокирующими сокетами необходимо знать несколько моментов:

  • Большинство методов SSLSocket будут вызывать либо SSLWantWriteError, либо SSLWantReadError, а не BlockingIOError, если операция ввода-вывода будет заблокирована. SSLWantReadError будет поднят, если необходима операция чтения на базовом сокете, и SSLWantWriteError для операции записи на базовом сокете. Обратите внимание, что попытки записи в SSL-сокет могут потребовать сначала чтения из базового сокета, а попытки чтения из SSL-сокета могут потребовать предварительной записи в базовый сокет.

    Изменено в версии 3.5: В ранних версиях Python метод SSLSocket.send() возвращал ноль, а не поднимал SSLWantWriteError или SSLWantReadError.

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

  • И наоборот, поскольку уровень SSL имеет собственное обрамление, на сокете SSL могут оставаться данные, доступные для чтения, и select() об этом не знает. Поэтому сначала следует вызвать SSLSocket.recv(), чтобы слить все потенциально доступные данные, а затем блокировать вызов select(), если это все еще необходимо.

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

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

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

См.также

Модуль asyncio поддерживает non-blocking SSL sockets и предоставляет API более высокого уровня. Он опрашивает события с помощью модуля selectors и обрабатывает исключения SSLWantWriteError, SSLWantReadError и BlockingIOError. Он также асинхронно выполняет рукопожатие SSL.

Поддержка БИО памяти

Added in version 3.5.

С тех пор как в Python 2.6 появился модуль SSL, класс SSLSocket предоставляет две связанные, но разные области функциональности:

  • Работа с протоколом SSL

  • Сеть IO

API сетевого ввода-вывода идентичен тому, что предоставляет socket.socket, от которого также унаследован SSLSocket. Это позволяет использовать SSL-сокет в качестве замены обычного сокета, что значительно упрощает добавление поддержки SSL в существующее приложение.

Сочетание обработки протоколов SSL и сетевого ввода-вывода обычно работает хорошо, но есть случаи, когда это не так. Примером могут служить фреймворки асинхронного ввода-вывода, которые хотят использовать модель мультиплексирования ввода-вывода, отличную от модели «выбор/опрос по дескриптору файла» (основанной на готовности), которая используется в socket.socket и во внутренних подпрограммах ввода-вывода сокетов OpenSSL. Это особенно актуально для платформ вроде Windows, где такая модель неэффективна. Для этой цели предусмотрен вариант SSLSocket с уменьшенной областью применения, называемый SSLObject.

class ssl.SSLObject

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

Этот класс реализует интерфейс поверх низкоуровневого объекта SSL, реализованного в OpenSSL. Этот объект фиксирует состояние SSL-соединения, но сам не предоставляет никаких сетевых операций ввода-вывода. Ввод-вывод должен осуществляться через отдельные объекты «BIO», которые являются уровнем абстракции ввода-вывода OpenSSL.

У этого класса нет публичного конструктора. Экземпляр SSLObject должен быть создан с помощью метода wrap_bio(). Этот метод создаст экземпляр SSLObject и свяжет его с парой BIO. Входящий BIO используется для передачи данных из Python в экземпляр протокола SSL, а исходящий BIO используется для передачи данных в обратном направлении.

Доступны следующие методы:

По сравнению с SSLSocket этот объект не обладает следующими характеристиками:

  • Любая форма сетевого ввода-вывода; recv() и send() читают и записывают только в базовые буферы MemoryBIO.

  • Механизм do_handshake_on_connect отсутствует. Вы всегда должны вручную вызывать do_handshake(), чтобы начать рукопожатие.

  • Обработка suppress_ragged_eofs отсутствует. Все условия конца файла, нарушающие протокол, сообщаются через исключение SSLEOFError.

  • Вызов метода unwrap() ничего не возвращает, в отличие от сокета SSL, где он возвращает базовый сокет.

  • Обратный вызов server_name_callback, переданный в SSLContext.set_servername_callback(), получит в качестве первого параметра экземпляр SSLObject, а не экземпляр SSLSocket.

Некоторые замечания, связанные с использованием SSLObject:

  • Все операции ввода-вывода на SSLObject равны non-blocking. Это означает, что, например, read() вызовет SSLWantReadError, если ему потребуется больше данных, чем доступно входящему BIO.

Изменено в версии 3.7: Экземпляры SSLObject должны быть созданы с помощью wrap_bio(). В более ранних версиях можно было создавать экземпляры напрямую. Это никогда не документировалось и официально не поддерживалось.

Объект SSLO взаимодействует с внешним миром с помощью буферов памяти. Класс MemoryBIO предоставляет буфер памяти, который может быть использован для этой цели. Он оборачивает объект BIO (Basic IO) памяти OpenSSL:

class ssl.MemoryBIO

Буфер памяти, который можно использовать для передачи данных между Python и экземпляром протокола SSL.

pending

Возвращает количество байт, находящихся в буфере памяти.

eof

Булево значение, указывающее, является ли память BIO текущей в позиции конца файла.

read(n=-1)

Считывание до n байт из буфера памяти. Если n не задано или отрицательно, возвращаются все байты.

write(buf)

Запись байтов из buf в память BIO. Аргумент buf должен быть объектом, поддерживающим буферный протокол.

Возвращаемое значение - количество записанных байт, которое всегда равно длине buf.

write_eof()

Запись маркера EOF в память BIO. После вызова этого метода вызов write() запрещен. Атрибут eof станет истинным после того, как все данные, находящиеся в буфере, будут прочитаны.

SSL-сессия

Added in version 3.6.

class ssl.SSLSession

Объект сессии, используемый session.

id
time
timeout
ticket_lifetime_hint
has_ticket

Соображения безопасности

Лучшие настройки по умолчанию

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

Например, вот как можно использовать класс smtplib.SMTP для создания надежного, безопасного соединения с SMTP-сервером:

>>> import ssl, smtplib
>>> smtp = smtplib.SMTP("mail.python.org", port=587)
>>> context = ssl.create_default_context()
>>> smtp.starttls(context=context)
(220, b'2.0.0 Ready to start TLS')

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

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

Ручные настройки

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

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

Изменено в версии 3.7: Сверка имен хостов теперь выполняется OpenSSL. Python больше не использует match_hostname().

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

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

Версии SSL 2 и 3 считаются небезопасными, поэтому использовать их опасно. Если вы хотите добиться максимальной совместимости между клиентами и серверами, рекомендуется использовать в качестве версии протокола PROTOCOL_TLS_CLIENT или PROTOCOL_TLS_SERVER. По умолчанию SSLv2 и SSLv3 отключены.

>>> client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
>>> client_context.minimum_version = ssl.TLSVersion.TLSv1_3
>>> client_context.maximum_version = ssl.TLSVersion.TLSv1_3

Созданный выше SSL-контекст будет разрешать только TLSv1.3 и более поздние версии (если они поддерживаются вашей системой) соединения с сервером. PROTOCOL_TLS_CLIENT по умолчанию подразумевает проверку сертификатов и проверку имени хоста. Вам необходимо загрузить сертификаты в контекст.

Выбор шифра

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

Многопроцессорная обработка

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

TLS 1.3

Added in version 3.7.

Протокол TLS 1.3 ведет себя несколько иначе, чем предыдущая версия TLS/SSL. Некоторые новые функции TLS 1.3 пока недоступны.

  • В TLS 1.3 используется разрозненный набор шифр-сюитов. По умолчанию включены все шифры AES-GCM и ChaCha20. Метод SSLContext.set_ciphers() пока не может включить или отключить ни один из шифров TLS 1.3, но SSLContext.get_ciphers() возвращает их.

  • Билеты сеанса больше не передаются как часть начального рукопожатия и обрабатываются по-другому. SSLSocket.session и SSLSession не совместимы с TLS 1.3.

  • Сертификаты на стороне клиента также больше не проверяются во время начального рукопожатия. Сервер может запросить сертификат в любое время. Клиенты обрабатывают запросы сертификатов во время отправки или получения данных приложения от сервера.

  • Такие функции TLS 1.3, как ранние данные, отложенный запрос сертификата клиента TLS, настройка алгоритма подписи и повторный ключ, пока не поддерживаются.