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

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


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

Примечание

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

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

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

В этом разделе описаны объекты и функции модуля 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 или новее.

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

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

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

Начиная с Python 3.2 и 2.7.9, рекомендуется использовать SSLContext.wrap_socket() экземпляра SSLContext, чтобы обернуть сокеты как объекты SSLSocket. Вспомогательные функции create_default_context() возвращают новый контекст с безопасными настройками по умолчанию. Старая функция wrap_socket() устарела, поскольку она неэффективна и не поддерживает указание имени сервера (SNI) и сопоставление имен хостов.

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

import socket
import ssl

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Примечание

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

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

Примечание

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

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

Добавлено в версии 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, вызываемый non-blocking SSL socket при попытке чтения или записи данных, но для выполнения запроса необходимо получить больше данных на базовом транспорте TCP.

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

exception ssl.SSLWantWriteError

Подкласс SSLError, вызываемый non-blocking SSL socket при попытке чтения или записи данных, но перед выполнением запроса необходимо отправить больше данных по базовому транспорту 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_pseudo_bytes(num)

Return (bytes, is_cryptographic): bytes - num псевдослучайных байтов, is_cryptographic равно True, если сгенерированные байты криптографически стойкие. Вызывает ошибку SSLError, если операция не поддерживается текущим методом RAND.

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

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

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

Не рекомендуется, начиная с версии 3.6: OpenSSL устарел ssl.RAND_pseudo_bytes(), вместо него используйте ssl.RAND_bytes().

ssl.RAND_status()

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

ssl.RAND_add(bytes, entropy)

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

Изменено в версии 3.5: Теперь допускается запись bytes-like object.

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

ssl.match_hostname(cert, hostname)

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

CertificateError is raised on failure. On success, the function returns nothing:

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

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

Изменено в версии 3.3.3: Функция теперь следует RFC 6125, раздел 6.4.3, и не сопоставляет ни множественные подстановочные знаки (например, *.*.com или *a*.example.org), ни подстановочный знак внутри фрагмента интернационализированных доменных имен (IDN). А-маркировки ИДИ, такие как www*.xn--pthon-kva.org, по-прежнему поддерживаются, но x*.python.org больше не соответствует xn--tda.python.org.

Изменено в версии 3.5: Теперь поддерживается сопоставление IP-адресов, если они присутствуют в поле subjectAltName сертификата.

Изменено в версии 3.7: Функция больше не используется для TLS-соединений. Сопоставление имен хостов теперь выполняется OpenSSL.

Разрешить подстановочный знак, если он является самым левым и единственным символом в данном сегменте. Частичные подстановочные знаки типа www*.example.com больше не поддерживаются.

Не рекомендуется, начиная с версии 3.7.

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-защитой в виде пары (hostname, port-number), получает сертификат сервера и возвращает его в виде PEM-кодированной строки. Если указано ssl_version, используется данная версия протокола SSL для попытки соединения с сервером. Если указано ca_certs, то это должен быть файл, содержащий список корневых сертификатов, в том же формате, который используется для того же параметра в SSLContext.wrap_socket(). Вызов попытается проверить сертификат сервера на соответствие этому набору корневых сертификатов и завершится неудачей, если попытка проверки окажется неудачной. С помощью параметра timeout можно указать тайм-аут.

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

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

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

ssl.DER_cert_to_PEM_cert(DER_cert_bytes)

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

ssl.PEM_cert_to_DER_cert(PEM_cert_string)

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

ssl.get_default_verify_paths()

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

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

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

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

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

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

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

Availability: LibreSSL игнорирует переменные окружения openssl_cafile_env и openssl_capath_env.

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

ssl.enum_certificates(store_name)

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

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

Пример:

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

Availability: Windows.

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

ssl.enum_crls(store_name)

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

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

Availability: Windows.

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

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

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

Внутри функция создает SSLContext с протоколом ssl_version и SSLContext.options, установленным в cert_reqs. Если заданы параметры keyfile, certfile, ca_certs или ciphers, то их значения передаются в SSLContext.load_cert_chain(), SSLContext.load_verify_locations() и SSLContext.set_ciphers().

Аргументы server_side, do_handshake_on_connect и suppress_ragged_eofs имеют то же значение, что и SSLContext.wrap_socket().

Не рекомендуется, начиная с версии 3.7: Начиная с Python 3.2 и 2.7.9, рекомендуется использовать SSLContext.wrap_socket() вместо wrap_socket(). Функция верхнего уровня ограничена и создает небезопасный клиентский сокет без указания имени сервера или сопоставления имени хоста.

Константы

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

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

ssl.CERT_NONE

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

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

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

ssl.CERT_OPTIONAL

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

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

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

ssl.CERT_REQUIRED

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

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

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

class ssl.VerifyMode

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

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

ssl.VERIFY_DEFAULT

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

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

ssl.VERIFY_CRL_CHECK_LEAF

P […] […] […]

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

ssl.VERIFY_CRL_CHECK_CHAIN

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

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

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

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

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

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

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

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

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

Не рекомендуется, начиная с версии 3.7: Эта опция устарела с версии OpenSSL 1.1.0. Она была добавлена в версии 2.7.15, 3.6.3 и 3.7.0 для обратной совместимости с 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.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 встроенную поддержку обмена ключами Diffie-Hellman на основе эллиптической кривой. Это должно быть верно, если только эта функция не была явно отключена распространителем.

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

ssl.HAS_SNI

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

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

ssl.HAS_NPN

Имеет ли библиотека OpenSSL встроенную поддержку Next Protocol Negotiation, как описано в Application Layer Protocol Negotiation. Если true, вы можете использовать метод 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 и других. В IANA TLS Alert Registry содержится этот список и ссылки на 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 предоставляют следующие методы Объекты сокетов:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

SSLSocket.write(buf)

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

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

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

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

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

Примечание

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

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

SSLSocket.do_handshake()

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

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

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

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

SSLSocket.getpeercert(binary_form=False)

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

Если параметр binary_form равен False, и сертификат был получен от сверстника, этот метод возвращает экземпляр dict. Если сертификат не был подтвержден, dict будет пустым. Если сертификат был подтвержден, то возвращается 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}

Примечание

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

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

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

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

Изменено в версии 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')

Получить данные привязки канала для текущего соединения в виде объекта байтов. Возвращает 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-сокет. Если SSL-сокет был создан с помощью устаревшей функции wrap_socket() (а не SSLContext.wrap_socket()), то это объект пользовательского контекста, созданный для этого 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 (кроме PROTOCOL_SSLv2) и OP_NO_SSLv3 (кроме PROTOCOL_SSLv3). Начальный список наборов шифров содержит только шифры HIGH, без шифров NULL и без шифров MD5 (кроме PROTOCOL_SSLv2).

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

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

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

SSLContext.cert_store_stats()

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

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

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

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

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

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

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

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

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

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

SSLContext.load_default_certs(purpose=Purpose.SERVER_AUTH)

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

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

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

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

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

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

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

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

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

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

SSLContext.get_ca_certs(binary_form=False)

Получение списка загруженных сертификатов «центра сертификации» (ЦС). Если параметр binary_form имеет значение False, то каждая запись списка представляет собой дикту, подобно выводу 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 cipher list format. Если ни один шифр не может быть выбран (потому что опции времени компиляции или другая конфигурация запрещают использование всех указанных шифров), будет выдано предупреждение SSLError.

Примечание

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

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

SSLContext.set_alpn_protocols(protocols)

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

Этот метод вызовет ошибку NotImplementedError, если HAS_ALPN будет False.

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

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

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

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

Типичным использованием этого обратного вызова является изменение атрибута ssl.SSLSocket 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-соединение будет прервано с сообщением ALERT_DESCRIPTION_INTERNAL_ERROR фатального TLS-предупреждения для клиента.

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

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

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

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

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

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

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

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

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

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

Изменено в версии 3.5: Всегда разрешайте передавать имя_хоста сервера, даже если 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-сессиях, созданных или управляемых данным контекстом. Возвращается словарь, в котором имена каждого piece of information сопоставлены с их числовыми значениями. Например, вот общее количество обращений и промахов в кэше сессий с момента создания контекста:

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

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

Пример:

import socket, ssl

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

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

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

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

SSLContext.keylog_filename

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

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

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

SSLContext.protocol

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

SSLContext.hostname_checks_common_name

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

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

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

SSLContext.security_level

Целое число, представляющее 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 certs», заполненный цепочками сертификатов для каждого эмитента, которому вы готовы доверять. Опять же, этот файл просто содержит эти цепочки, скомпонованные вместе. Для проверки Python будет использовать первую цепочку, которую найдет в файле. Файл сертификатов платформы можно использовать, вызвав SSLContext.load_default_certs(), это делается автоматически с помощью create_default_context().

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

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

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

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

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

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

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

Примеры

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

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

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

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

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

>>> context = ssl.create_default_context()

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

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

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

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

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

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

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

>>> cert = conn.getpeercert()

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

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

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

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

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

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

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

import socket, ssl

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

См.также

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

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

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

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

  • Обработка протокола SSL

  • Сетевой IO

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

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

class ssl.SSLObject

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

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

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

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

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

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

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

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

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

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

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

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

  • Вызов wrap_bio() на уровне модуля отсутствует, как в случае с wrap_socket(). SSLObject всегда создается через SSLContext.

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

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

Выбор шифра

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

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

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

Вернуться на верх