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.

Исключения

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

Требования к криптографически стойкому генератору описаны в статье Википедии «Криптографически стойкий генератор псевдослучайных чисел (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: Теперь принимается записываемый объект, подобный bytes.

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

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» необходимо использовать время по Гринвичу (RFC 5280).

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

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

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

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

Изменено в версии 3.5: Версия SSL по умолчанию 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 задаёт назначение сертификата в виде набора OID или ровно 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

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

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

ssl.VERIFY_DEFAULT

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

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

ssl.VERIFY_CRL_CHECK_LEAF

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

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

ssl.VERIFY_CRL_CHECK_CHAIN

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

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

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

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

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. Этот параметр установлен по умолчанию. Он не обязательно задает те же флаги, что и константа SSL_OP_ALL в OpenSSL.

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

Коллекция enum.IntFlag констант 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 согласование протокола на уровне приложения, описанного в 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 встроенную поддержку расширения индикация имени сервера (определенного в RFC 6066).

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

ssl.HAS_NPN

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

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

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

class ssl.AlertDescription

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

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

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

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

class ssl.TLSVersion

Коллекция enum.IntEnum версий 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
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-сокеты предоставляют следующие методы объекта Socket Objects:

  • 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: OpenSSL сопоставляет имя хоста или IP-адрес во время рукопожатия. Функция match_hostname() больше не используется. Если OpenSSL отклоняет имя хоста или IP-адрес, рукопожатие досрочно прерывается, а другой стороне отправляется TLS-сообщение-предупреждение.

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 и URI OCSP.

Изменено в версии 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-label ("xn--pythn-mua.org"), а не форма U-label ("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. Для TLS 1.3 нет отдельной константы PROTOCOL.

См. также

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 может быть функцией, вызываемой для получения пароля, необходимого для расшифровки закрытого ключа. Она будет вызвана, только если закрытый ключ зашифрован и требуется пароль. Функция вызывается без аргументов и должна возвращать строку, bytes или bytearray. Если возвращаемое значение является строкой, перед использованием для расшифровки ключа оно будет закодировано в UTF-8. Также непосредственно в качестве аргумента password можно передать значение типа string, bytes или bytearray. Оно игнорируется, если закрытый ключ не зашифрован и пароль не нужен.

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

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

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

SSLContext.load_default_certs(purpose=Purpose.SERVER_AUTH)

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

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

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

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

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

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

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

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

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

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

SSLContext.get_ca_certs(binary_form=False)

Получает список загруженных сертификатов удостоверяющих центров (CA). Если параметр 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()

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

Если HAS_ALPN имеет значение False, этот метод возбуждает исключение NotImplementedError.

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

SSLContext.set_npn_protocols(protocols)

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

Если HAS_NPN имеет значение False, этот метод возбуждает исключение NotImplementedError.

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

Устарело с версии 3.10: NPN вытеснен ALPN

SSLContext.sni_callback

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

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

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

Типичное применение этого обработчика — изменение атрибута SSLSocket.context объекта ssl.SSLSocket на новый объект типа 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.

Если при сборке библиотеки OpenSSL была определена константа OPENSSL_NO_TLSEXT, этот метод возбуждает исключение NotImplementedError.

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

SSLContext.set_servername_callback(server_name_callback)

Это устаревший API, сохранённый для обратной совместимости. По возможности следует использовать sni_callback. Указанный server_name_callback похож на sni_callback, однако, если имя хоста сервера является доменным именем в кодировке IDN, server_name_callback получает декодированную U-label ("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_side имеет значение true, указание server_hostname вызовет исключение ValueError.

Параметр 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 — см. 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 в файл журнала ключей при каждом создании или получении ключевого материала. Файл журнала ключей предназначен только для отладки. Формат файла определён 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, объединив их побитовой операцией ИЛИ.

Изменено в версии 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, можно объединять побитовой операцией ИЛИ. По умолчанию 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) — это представление в кодировке base64, заключённое между строкой заголовка и строкой окончания:

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

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

Если требуется проверять сертификат другой стороны соединения, необходимо предоставить файл «сертификатов ЦС», содержащий цепочки сертификатов для каждого издателя, которому вы готовы доверять. И этот файл просто содержит объединённые цепочки. Для проверки 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 проверяют сертификат сервера: проверяется, что сертификат сервера подписан одним из сертификатов ЦС, что подпись корректна, а также другие свойства, например срок действия и соответствие имени узла:

>>> 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-рукопожатие будет неблокирующим: метод 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-рукопожатие асинхронно.

Поддержка Memory BIO

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

С момента появления модуля SSL в Python 2.6 класс SSLSocket предоставляет две связанные, но отдельные группы возможностей:

  • Обработка протокола SSL
  • Сетевой ввод-вывод

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

Совместное использование обработки протокола SSL и сетевого ввода-вывода обычно работает хорошо, но в некоторых случаях возникают проблемы. Например, асинхронные фреймворки ввода-вывода могут использовать другую модель мультиплексирования ввода-вывода, а не модель «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.
  • В отличие от SSL-сокета, вызов метода unwrap() ничего не возвращает: для SSL-сокета этот метод возвращает базовый сокет.
  • В качестве первого параметра обратный вызов server_name_callback, переданный в SSLContext.set_servername_callback(), получит экземпляр SSLObject, а не экземпляр SSLSocket.

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

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

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

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

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

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

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

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

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

RFC 1422: Повышение конфиденциальности электронной почты в Интернете. Часть II: Управление ключами на основе сертификатов

Стив Кент

RFC 4086: Требования к случайности для обеспечения безопасности

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

RFC 5280: Профиль сертификатов и списков отзыва сертификатов (CRL) инфраструктуры открытых ключей Internet X.509

Д. Купер

RFC 5246: Протокол защиты транспортного уровня (TLS), версия 1.2

Т. Диркс и др.

RFC 6066: Расширения протокола защиты транспортного уровня (TLS)

Д. Истлейк

IANA TLS: параметры протокола защиты транспортного уровня (TLS)

IANA

RFC 7525: Рекомендации по безопасному использованию протокола защиты транспортного уровня (TLS) и протокола защиты транспортного уровня для дейтаграмм (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