Spec-Zone.ru › Python 3.12

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 не обязательно подходят для вашего приложения.

Доступность: не Emscripten, не WASI.

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

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

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

Для более сложных приложений класс 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())

Пример сокета сервера, прослушивающего на 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 с настройками по умолчанию для заданной цели purpose. Настройки выбираются модулем ssl и обычно представляют более высокий уровень безопасности, чем при непосредственном вызове конструктора SSLContext.

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

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

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

Примечание

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

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

Примечание

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

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

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

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

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

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

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

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

END_OF_DOCUMENT_MARKER

Исключения

exception ssl.SSLError

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

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

library

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

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

reason

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

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

exception ssl.SSLZeroReturnError

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

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

exception ssl.SSLWantReadError

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

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

exception ssl.SSLWantWriteError

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

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

exception ssl.SSLSyscallError

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

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

exception ssl.SSLEOFError

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

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

exception ssl.SSLCertVerificationError

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

Добавлен в версии 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), чтобы ознакомиться с требованиями к криптографически сильному генератору.

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

ssl.RAND_status()

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

ssl.RAND_add(bytes, entropy)

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

Изменено в версии 3.5: Теперь принимается изменяемый объект-подобный байтам.

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

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(). Результат — именованный кортеж DefaultVerifyPaths:

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

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

ssl.enum_certificates(store_name)

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

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

Пример:

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

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

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

ssl.enum_crls(store_name)

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

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

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

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

Константы

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

Добавлен в версии 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-соединение.

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

ssl.CERT_REQUIRED

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

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

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

class ssl.VerifyMode

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

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

ssl.VERIFY_DEFAULT

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

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

ssl.VERIFY_CRL_CHECK_LEAF

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

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

ssl.VERIFY_CRL_CHECK_CHAIN

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

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

ssl.VERIFY_X509_STRICT

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

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

ssl.VERIFY_ALLOW_PROXY_CERTS

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

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

ssl.VERIFY_X509_TRUSTED_FIRST

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

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

ssl.VERIFY_X509_PARTIAL_CHAIN

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

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

class ssl.VerifyFlags

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

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

ssl.PROTOCOL_TLS

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

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

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

ssl.PROTOCOL_TLS_CLIENT

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

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

ssl.PROTOCOL_TLS_SERVER

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

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

ssl.PROTOCOL_SSLv23

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

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

END_OF_DOCUMENT_MARKER
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+.

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

Устарело начиная с версии 3.6: OpenSSL устарел все протоколы, зависящие от версии.

ssl.PROTOCOL_TLSv1_2

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

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

Устарело начиная с версии 3.6: OpenSSL устарел все протоколы, зависящие от версии.

ssl.OP_ALL

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

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

ssl.OP_NO_SSLv2

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

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

Устарело начиная с версии 3.6: SSLv2 устарел

ssl.OP_NO_SSLv3

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

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

Устарело начиная с версии 3.6: SSLv3 устарел

ssl.OP_NO_TLSv1

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

Добавлен в версии 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+.

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

Устарело начиная с версии 3.7: Опция устарела начиная с OpenSSL 1.1.0.

ssl.OP_NO_TLSv1_2

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

Добавлен в версии 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.

Добавлен в версии 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 и более поздними версиями.

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

ssl.OP_CIPHER_SERVER_PREFERENCE

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

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

ssl.OP_SINGLE_DH_USE

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

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

ssl.OP_SINGLE_ECDH_USE

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

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

ssl.OP_ENABLE_MIDDLEBOX_COMPAT

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

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

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

ssl.OP_NO_COMPRESSION

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

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

class ssl.Options

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

ssl.OP_NO_TICKET

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

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

ssl.OP_IGNORE_UNEXPECTED_EOF

Игнорировать неожиданное завершение подключений TLS.

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

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

ssl.OP_ENABLE_KTLS

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

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

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

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

ssl.OP_LEGACY_SERVER_CONNECT

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

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

ssl.HAS_ALPN

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

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

ssl.HAS_NEVER_CHECK_COMMON_NAME

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

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

ssl.HAS_ECDH

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

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

ssl.HAS_SNI

Есть ли в библиотеке OpenSSL встроенная поддержка расширения Server Name Indication (определенного в RFC 6066).

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

ssl.HAS_NPN

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

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

ssl.HAS_SSLv2

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

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

ssl.HAS_SSLv3

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

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

ssl.HAS_TLSv1

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

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

ssl.HAS_TLSv1_1

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

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

ssl.HAS_TLSv1_2

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

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

ssl.HAS_TLSv1_3

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

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

ssl.CHANNEL_BINDING_TYPES

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

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

ssl.OPENSSL_VERSION

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

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

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

ssl.OPENSSL_VERSION_INFO

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

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

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

ssl.OPENSSL_VERSION_NUMBER

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

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

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

ssl.ALERT_DESCRIPTION_HANDSHAKE_FAILURE
ssl.ALERT_DESCRIPTION_INTERNAL_ERROR
ALERT_DESCRIPTION_*

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

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

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

class ssl.AlertDescription

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

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

Purpose.SERVER_AUTH

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

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

Purpose.CLIENT_AUTH

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

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

class ssl.SSLErrorNumber

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

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

class ssl.TLSVersion

Коллекция констант SSL и TLS версий для SSLContext.maximum_version и SSLContext.minimum_version.

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

TLSVersion.MINIMUM_SUPPORTED
TLSVersion.MAXIMUM_SUPPORTED

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

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

Протоколы SSL 3.0 до TLS 1.3.

Устарело начиная с версии 3.10: Все члены TLSVersion за исключением TLSVersion.TLSv1_2 и TLSVersion.TLSv1_3 устарели.

SSL Soкеты

class ssl.SSLSocket(socket.socket)

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

  • accept()
  • bind()
  • close()
  • connect()
  • detach()
  • fileno()
  • getpeername(), getsockname()
  • getsockopt(), setsockopt()
  • gettimeout(), settimeout(), setblocking()
  • listen()
  • makefile()
  • recv(), recv_into() (но передача ненулевого flags аргумента запрещена)
  • send(), sendall() (с тем же ограничением)
  • sendfile() (но os.sendfile будет использоваться только для текстовых сокетов, в противном случае send() будет использоваться)
  • shutdown()

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

Экземпляры 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, если сокет неблокирующий, и чтение заблокирует выполнение.

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

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

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

SSLSocket.write(buf)

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

Возбуждает SSLWantReadError или SSLWantWriteError, если сокет неблокирующий, и запись заблокирует выполнение.

Поскольку в любое время возможно переподключение, вызов 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 имеет значение true.

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

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

SSLSocket.getpeercert(binary_form=False)

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

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

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

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

Если параметр 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.cipher()

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

SSLSocket.shared_ciphers()

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

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

SSLSocket.compression()

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

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

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

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

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

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

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

SSLSocket.selected_alpn_protocol()

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

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

SSLSocket.selected_npn_protocol()

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

Добавлена в версии 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.

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

SSLSocket.version()

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

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

SSLSocket.pending()

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

SSLSocket.context

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

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

SSLSocket.server_side

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

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

SSLSocket.server_hostname

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

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

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

SSLSocket.session

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

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

SSLSocket.session_reused

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

SSL-контексты

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

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

class ssl.SSLContext(protocol=None)

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

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

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

SSLv2

SSLv3

TLS [3]

TLSv1

TLSv1.1

TLSv1.2

SSLv2

да

нет

нет [1]

нет

нет

нет

SSLv3

нет

да

нет [2]

нет

нет

нет

TLS (SSLv23) [3]

нет [1]

нет [2]

да

да

да

да

TLSv1

нет

нет

да

да

нет

нет

TLSv1.1

нет

нет

да

нет

да

нет

TLSv1.2

нет

нет

да

нет

нет

да

Примечания

[1] (1,2)

SSLContext отключает SSLv2 по умолчанию с помощью OP_NO_SSLv2.

[2] (1,2)

SSLContext отключает SSLv3 по умолчанию с помощью OP_NO_SSLv3.

[3] (1,2)

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

См. также

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 устарело. В будущем класс контекста будет либо требовать 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 поддерживает только ограниченное изменение после его использования в соединении. Добавление новых сертификатов во внутренний хранилище доверия разрешено, но изменение шифров, настроек проверки или сертификатов mTLS может привести к неожиданному поведению.

Примечание

SSLContext предназначен для совместного использования и использования несколькими соединениями. Таким образом, он потокобезопасен, пока не переконфигурирован после использования в соединении.

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

SSLContext.cert_store_stats()

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

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

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

Добавлен в версии 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: Новый необязательный аргумент password.

END_OF_DOCUMENT_MARKER
SSLContext.load_default_certs(purpose=Purpose.SERVER_AUTH)

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

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

Добавлена в версии 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, если присутствует, — это путь к каталогу, содержащему несколько сертификатов ЦС в формате PEM, следуя специфичному для OpenSSL расположению.

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

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

SSLContext.get_ca_certs(binary_form=False)

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

Примечание

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

Добавлена в версии 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'}]

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

SSLContext.set_default_verify_paths()

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

SSLContext.set_ciphers(ciphers)

Установка доступных шифров для сокетов, созданных с этим контекстом. Должно быть строкой в формате списка шифров OpenSSL. Если ни один шифр не может быть выбран (потому что параметры времени компиляции или другая конфигурация запрещают использование всех указанных шифров), будет возбуждено исключение 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.

Добавлена в версии 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.

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

Устарело начиная с версии 3.10: NPN устарел, его заменил ALPN

SSLContext.sni_callback

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

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

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

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

Из-за ранней фазы согласования TLS, только ограниченное количество методов и атрибутов применимо, например, SSLSocket.selected_alpn_protocol() и SSLSocket.context. Методы SSLSocket.getpeercert(), 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.

Добавлен в версии 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 завершится с сообщением об ошибке TLS ALERT_DESCRIPTION_INTERNAL_ERROR для клиента.

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

SSLContext.load_dh_params(dhfile)

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

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

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

SSLContext.set_ecdh_curve(curve_name)

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

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

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

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

См. также

SSL/TLS и Совершенная конфиденциальность в будущем

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

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, вызов метода с server_side равным True вызовет ValueError.

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

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

session, см. session.

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

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

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

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

SSLContext.sslsocket_class

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

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

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

Оборачивает объекты BIO incoming и outgoing и возвращает экземпляр 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.

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

SSLContext.session_stats()

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

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

Требовать соответствия имени хоста в сертификате удалённого узла в SSLSocket.do_handshake(). Контекст должен иметь verify_mode установленным в CERT_OPTIONAL или CERT_REQUIRED, и вы должны передать server_hostname в wrap_socket(), чтобы сопоставить имя хоста. Включение проверки имени хоста автоматически устанавливает 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))

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

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

SSLContext.keylog_filename

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

Записи синхронизируются между потоками, но не между процессами.

Добавлен в версии 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.

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

SSLContext.minimum_version

Аналогично SSLContext.maximum_version, но это наименьшая поддерживаемая версия или TLSVersion.MINIMUM_SUPPORTED.

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

SSLContext.num_tickets

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

Добавлен в версии 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. Фактический обмен сертификатом клиента откладывается до вызова SSLSocket.verify_client_post_handshake() и выполнения некоторых операций ввода-вывода.

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

SSLContext.protocol

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

SSLContext.hostname_checks_common_name

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

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

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

SSLContext.security_level

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

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

SSLContext.verify_flags

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

Добавлен в версии 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>

Сертификаты

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

Сертификат содержит информацию о двух субъектах. Он содержит имя субъекта и открытый ключ субъекта. Он также содержит утверждение второго субъекта, эмитента, о том, что субъект является тем, за кого себя выдает, и что это действительно открытый ключ субъекта. Утверждение эмитента подписано закрытым ключом эмитента, который известен только эмитенту. Однако любой может проверить утверждение эмитента, найдя открытый ключ эмитента, расшифровав утверждение с его помощью и сравнив его с другой информацией в сертификате. Сертификат также содержит информацию о периоде времени, в течение которого он действителен. Это выражается в двух полях, называемых «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

Если вы хотите выполнить проверку сертификата другой стороны соединения, вам нужно предоставить файл «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")

(в этом фрагменте предполагается, что ваша операционная система размещает пакет всех сертификатов CA в /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

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

Примечания по неблокирующим сокетам

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-handshake будет неблокирующим: метод SSLSocket.do_handshake() должен быть повторен до тех пор, пока он не вернётся успешно. Вот краткий обзор использования select() для ожидания готовности сокета:

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

См. также

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

Поддержка BIO для памяти

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

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

  • Обработка протокола SSL
  • Сеть IO

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

Комбинирование обработки протокола SSL и сети IO обычно работает хорошо, но существуют случаи, когда это не так. Например, в фреймворках асинхронного ввода-вывода, которые хотят использовать другую модель мультиплексирования ввода-вывода, отличную от модели «select/poll по дескриптору файла» (основанной на готовности), используемой классом 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 — для передачи данных в обратном направлении.

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

  • context
  • server_side
  • server_hostname
  • session
  • session_reused
  • read()
  • write()
  • getpeercert()
  • selected_alpn_protocol()
  • selected_npn_protocol()
  • cipher()
  • shared_ciphers()
  • compression()
  • pending()
  • do_handshake()
  • verify_client_post_handshake()
  • unwrap()
  • get_channel_binding()
  • version()

По сравнению с 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 является неблокирующим. Это означает, что, например, read() вызовет исключение SSLWantReadError, если ему потребуется больше данных, чем доступно в объекте входящего BIO.

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

Объект SSLObject взаимодействует с внешним миром с использованием буферов памяти. Класс 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 станет истинным после прочтения всех данных, в настоящее время находящихся в буфере.

END_OF_DOCUMENT_MARKER

Сессия SSL

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

class ssl.SSLSession

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

id
time
timeout
ticket_lifetime_hint
has_ticket

Рекомендации по безопасности

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

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

Например, вот как вы можете использовать класс 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 по формату списка шифров. Если вы хотите проверить, какие шифры включены в заданном списке шифров, используйте SSLContext.get_ciphers() или команду openssl ciphers на вашей системе.

Многопроцессорность

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

TLS 1.3

Добавлена в версии 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-сертификата клиента, настройка алгоритмов подписи и переключение ключей, пока не поддерживаются.

См. также

Class socket.socket

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

SSL/TLS Strong Encryption: An Introduction

Введение из документации Apache HTTP Server

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

Стив Кент

RFC 4086: Randomness Requirements for Security

Дональд Е., Джеффри И. Шилер

RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile

Д. Купер

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

Т. Диеркс и др.

RFC 6066: Transport Layer Security (TLS) Extensions

Д. Истлейк

IANA TLS: Transport Layer Security (TLS) Parameters

IANA

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

IETF

Рекомендации Mozilla по TLS на стороне сервера

Mozilla

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

Spec-Zone.ru

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