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


Данный модуль обеспечивает доступ к средствам шифрования Безопасности транспортного уровня (Transport Layer Security, TLS) (часто называемому «Уровень защищенных сокетов (Secure Sockets Layer, SSL)») и одноранговой аутентификации для сетевых сокетов, как на стороне клиента, так и на стороне сервера. Данный модуль использует библиотеку OpenSSL. Он доступен на всех современных системах Unix, Windows, Mac OS X и, возможно, на дополнительных платформах, если на этой платформе установлен OpenSSL.

Примечание

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

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

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

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

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

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

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

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

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

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

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

import socket
import ssl

hostname = 'digitology.tech'
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 = 'digitology.tech'
# PROTOCOL_TLS_CLIENT требуется действительная цепочка сертификатов и имя хоста
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())

Пример сокета сервера, прослушивающего IPv4 на локальном хосте:

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

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

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

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

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

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

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

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

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

Примечание

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

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

Примечание

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

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

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

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

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

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

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

Исключения

exception ssl.SSLError

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

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

library

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

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

reason

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

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

exception ssl.SSLZeroReturnError

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

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

exception ssl.SSLWantReadError

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

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

exception ssl.SSLWantWriteError

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

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

exception ssl.SSLSyscallError

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

Добавлено в версии 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, если PRNG не заполнен достаточным количеством данных или если операция не поддерживается текущим методом RAND. Можно использовать RAND_status() для проверки состояния PRNG, а RAND_add() можно использовать для заполнения PRNG.

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

Прочитайте статью в Википедии про Криптографически защищённый генератор псевдослучайных чисел (CSPRNG), чтобы узнать о требованиях к криптографическому генератору.

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

ssl.RAND_pseudo_bytes(num)

Возвращает (байты, is_cryptographic): байты — это псевдослучайные байты 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_egd(path)

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

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

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

ssl.RAND_add(bytes, entropy)

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

Изменено в версии 3.5: Доступен для записи байтоподобный объект.

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

ssl.match_hostname(cert, hostname)

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

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

>>> cert = {'subject': ((('commonName', 'digitology.tech'),),)}
>>> ssl.match_hostname(cert, "digitology.tech")
>>> ssl.match_hostname(cert, "digitology.int")
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 'digitology.int' doesn't match 'digitology.tech'

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

Изменено в версии 3.3.3: Теперь функция следует RFC 6125, раздел 6.4.3, и не соответствует ни нескольким подстановочным знакам (например, *.*.com или *a*.digitology.tech), ни подстановочным знакам внутри фрагмента интернационализированных доменных имён (IDN). A-метки IDN, такие как www*.xn--digitology.tech, по-прежнему поддерживаются, но x*.digitology.tech больше не соответствует xn--tda.digitology.tech.

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

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

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

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

ssl.cert_time_to_seconds(cert_time)

Возвращает время в секундах с начала эпохи, учитывая строку cert_time, представляющую дату «notBefore» или «notAfter» из сертификата в формате strptime "%b %d %H:%M:%S %Y %Z" (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, ca_certs=None)

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

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

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

ssl.DER_cert_to_PEM_cert(DER_cert_bytes)

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

ssl.PEM_cert_to_DER_cert(PEM_cert_string)

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

ssl.get_default_verify_paths()

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

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

Доступность: 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). encoding_type указывает кодировку cert_bytes. Это либо x509_asn для данных X.509 ASN.1, либо pkcs_7_asn для данных PKCS#7 ASN.1. Доверие указывает назначение сертификата как множество OIDS или точно True, если сертификат заслуживает доверия для всех целей.

Пример:

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

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

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

ssl.enum_crls(store_name)

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

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

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

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

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.

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

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

ssl.CERT_OPTIONAL

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

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

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

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

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

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

ssl.VERIFY_CRL_CHECK_CHAIN

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

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

ssl.VERIFY_X509_STRICT

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

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

ssl.VERIFY_X509_TRUSTED_FIRST

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

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

class ssl.VerifyFlags

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

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

ssl.PROTOCOL_TLS

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

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

ssl.PROTOCOL_TLS_CLIENT

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

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

ssl.PROTOCOL_TLS_SERVER

Автоматическое согласование самой высокой версии протокола, например PROTOCOL_TLS, но поддержка только серверных подключений SSLSocket.

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

ssl.PROTOCOL_SSLv23

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

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

ssl.PROTOCOL_SSLv2

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

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

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

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

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

ssl.PROTOCOL_SSLv3

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

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

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

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

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

ssl.PROTOCOL_TLSv1

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

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

ssl.PROTOCOL_TLSv1_1

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

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

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

ssl.PROTOCOL_TLSv1_2

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

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

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

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

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

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

class ssl.Options

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

ssl.OP_NO_TICKET

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

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

ssl.HAS_ALPN

Есть ли у библиотеки OpenSSL встроенная поддержка расширения TLS Согласования протокола прикладного уровня, как приведено в RFC 7301.

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

ssl.HAS_NEVER_CHECK_COMMON_NAME

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

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

ssl.HAS_ECDH

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

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

ssl.HAS_SNI

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

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

ssl.HAS_NPN

Есть ли у библиотеки OpenSSL встроенная поддержка Следующего согласования протокола, как приведено в Согласовании протокола прикладного уровня. Когда это значение истинно, вы можете использовать метод SSLContext.set_npn_protocols(), чтобы объявить, какие протоколы вы хотите поддерживать.

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

ssl.HAS_SSLv2

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

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

ssl.HAS_SSLv3

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

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

ssl.HAS_TLSv1

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

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

ssl.HAS_TLSv1_1

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

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

ssl.HAS_TLSv1_2

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

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

ssl.HAS_TLSv1_3

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

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

ssl.CHANNEL_BINDING_TYPES

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

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

ssl.OPENSSL_VERSION

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

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

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

ssl.OPENSSL_VERSION_INFO

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

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

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

ssl.OPENSSL_VERSION_NUMBER

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

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

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

ssl.ALERT_DESCRIPTION_HANDSHAKE_FAILURE
ssl.ALERT_DESCRIPTION_INTERNAL_ERROR
ALERT_DESCRIPTION_*

Описания предупреждений из RFC 5246 и других. Реестр предупреждений IANA TLS содержит данный список и ссылки на 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.

SSL-сокеты

class ssl.SSLSocket(socket.socket)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

SSLSocket.write(buf)

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

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

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

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

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

Примечание

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

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

SSLSocket.do_handshake()

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

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

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

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

SSLSocket.getpeercert(binary_form=False)

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

Если параметр binary_form равен False, и сертификат был получен от однорангового узла, данный метод возвращает экземпляр dict. Если сертификат не был проверен, словарь пуст. Если сертификат был проверен, он возвращает словарь с несколькими ключами, среди которых subject (принципал, получавший сертификат) и issuer (принципал, выдавший сертификат). Если сертификат содержит экземпляр расширения Альтернативного имени субъекта (см. 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', '*.eff1.int'),),
             (('emailAddress', '[email protected]'),)),
 'subjectAltName': (('DNS', '*.eff1.int'), ('DNS', 'eff1.int')),
 '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, такие, как URI crlDistributionPoints, caIssuers и OCSP.

Изменено в версии 3.8.1: Строки адресов 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.

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--digitology.tech"), а не форму U-метки ("digitölogy.tech").

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=PROTOCOL_TLS)

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

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

client / server 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).

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

SSLContext.cert_store_stats()

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

Пример контекста с одним сертификатом CA и ещё одним сертификатом:

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

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

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

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

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

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

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

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

SSLContext.load_default_certs(purpose=Purpose.SERVER_AUTH)

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

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

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

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

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

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

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

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

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

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

SSLContext.get_ca_certs(binary_form=False)

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

Примечание

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

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

SSLContext.get_ciphers()

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

Пример:

>>> ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
>>> ctx.set_ciphers('ECDHE+AESGCM:!ECDSA')
>>> ctx.get_ciphers()  # OpenSSL 1.0.x
[{'alg_bits': 256,
  'description': 'ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH     Au=RSA  '
                 'Enc=AESGCM(256) Mac=AEAD',
  'id': 50380848,
  'name': 'ECDHE-RSA-AES256-GCM-SHA384',
  'protocol': 'TLSv1/SSLv3',
  'strength_bits': 256},
 {'alg_bits': 128,
  'description': 'ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH     Au=RSA  '
                 'Enc=AESGCM(128) Mac=AEAD',
  'id': 50380847,
  'name': 'ECDHE-RSA-AES128-GCM-SHA256',
  'protocol': 'TLSv1/SSLv3',
  'strength_bits': 128}]

В OpenSSL 1.1 и новее шифр-словарь содержит дополнительные поля:

>>> ctx.get_ciphers()  # OpenSSL 1.1+
[{'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'}]

Доступность: OpenSSL 1.0.2+.

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

SSLContext.set_default_verify_paths()

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

SSLContext.set_ciphers(ciphers)

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

Примечание

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

В OpenSSL 1.1.1 множества шифров TLS 1.3 включены по умолчанию. Пакеты нельзя отключить с помощью set_ciphers().

SSLContext.set_alpn_protocols(protocols)

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

Данный метод вызовет NotImplementedError, если HAS_ALPN равен False.

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

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

SSLContext.set_npn_protocols(protocols)

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

Данный метод вызовет NotImplementedError, если HAS_NPN равен False.

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

SSLContext.sni_callback

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

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

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

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

Из-за ранней фазы согласования TLS подключении можно использовать только ограниченные методы и атрибуты, такие как SSLSocket.selected_alpn_protocol() и SSLSocket.context. SSLSocket.getpeercert(), SSLSocket.getpыeercert(), SSLSocket.getpeercert(), SSLSocket.cipher() и SSLSocket.compress() требуют, чтобы 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-метку ("digitölogy.tech").

Если в имени сервера есть ошибка декодирования, TLS-соединение завершится с отправкой клиенту фатального TLS-предупреждения ALERT_DESCRIPTION_INTERNAL_ERROR.

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

SSLContext.load_dh_params(dhfile)

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

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

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

SSLContext.set_ecdh_curve(curve_name)

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

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

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

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

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 истинно.

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

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

session, см. session.

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

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

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

SSLContext.sslsocket_class

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

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

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

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

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

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

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

SSLContext.sslobject_class

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

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

SSLContext.session_stats()

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

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

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

Пример:

import socket, ssl

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

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = context.wrap_socket(s, server_hostname='digitology.tech')
ssl_sock.connect(('digitology.tech', 443))

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

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

Примечание

Для этой функции требуется OpenSSL 0.9.8f или новее.

SSLContext.keylog_filename

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

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

Примечание

Для этой функции требуется OpenSSL 1.1.1 или новее.

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.

Примечание

Данный атрибут недоступен, если модуль ssl не скомпилирован с OpenSSL 1.1.0g или новее.

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

SSLContext.minimum_version

То же, что и SSLContext.maximum_version, за исключением того, что это самая низкая поддерживаемая версия или TLSVersion.MINIMUM_SUPPORTED.

Примечание

Данный атрибут недоступен, если модуль ssl не скомпилирован с OpenSSL 1.1.0g или новее.

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

SSLContext.num_tickets

Контролируйте количество билетов сеанса TLS 1.3 контекста TLS_PROTOCOL_SERVER. Данный параметр не влияет на соединения TLS 1.0–1.2.

Примечание

Данный атрибут недоступен, если модуль ssl не скомпилирован с OpenSSL 1.1.1 или новее.

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

SSLContext.options

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

Примечание

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

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

>>> ssl.create_default_context().options  # doctest: +SKIP
<Options.OP_ALL|OP_NO_SSLv3|OP_NO_SSLv2|OP_NO_COMPRESSION: 2197947391>
SSLContext.post_handshake_auth

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

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

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

Примечание

Доступно только при включенных OpenSSL 1.1.1 и TLS 1.3. Без поддержки TLS 1.3 значение свойства равно None и не может быть изменено.

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

SSLContext.protocol

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

SSLContext.hostname_checks_common_name

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

Примечание

Доступно только для записи с OpenSSL 1.1.0 или выше.

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

SSLContext.verify_flags

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

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

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

>>> ssl.create_default_context().verify_flags  # doctest: +SKIP
<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-----
... (сертификат в кодировке base64 PEM) ...
-----END CERTIFICATE-----

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

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

-----BEGIN CERTIFICATE-----
... (сертификат для вашего сервера)...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (сертификат для центра сертификации)...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (корневой сертификат для эмитента центра сертификации)...
-----END CERTIFICATE-----

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

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

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

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

-----BEGIN RSA PRIVATE KEY-----
... (закрытый ключ в кодировке base64) ...
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
... (сертификат в кодировке base64 PEM) ...
-----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) [RU]:RU
State or Province Name (full name) [Some-State]:Russia
Locality Name (eg, city) []:Ekb
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Organization, Inc.
Organizational Unit Name (eg, section) []:My Group
Common Name (eg, YOUR name) []:digitology.tech
Email Address []:ops@digitology.tech
%

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

Примеры

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

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

try:
    import ssl
except ImportError:
    pass
else:
    ...  # Сделать что-то, для чего требуется поддержка SSL

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

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

>>> context = ssl.create_default_context()

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

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

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

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

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

>>> conn = context.wrap_socket(socket.socket(socket.AF_INET),
...                            server_hostname="digitology.tech")
>>> conn.connect(("digitology.tech", 443))

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

>>> cert = conn.getpeercert()

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

>>> pprint.pprint(cert)
{'OCSP': ('http://r3.o.lencr.int',),
 'caIssuers': ('http://r3.i.lencr.int/',),
 'issuer': ((('countryName', 'RU'),),
            (('organizationName', "Let's Encrypt"),),
            (('commonName', 'R3'),)),
 'notAfter': 'Jan 31 18:00:09 2023 GMT',
 'notBefore': 'Nov  2 18:00:10 2022 GMT',
 'serialNumber': '049368307874D799BD686ED68BF01A647CE6',
 'subject': ((('commonName', 'digitology.tech'),),),
 'subjectAltName': (('DNS', 'digitology.tech'),),
 'version': 3}

Теперь, когда SSL туннель установлен и сертификат проверен, можно приступить к разговору с сервером:

>>> conn.sendall(b"HEAD / HTTP/1.0\r\nHost: digitology.tech\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(('digitology.tech', 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)
    # пустые данные означают, что клиент закончил с нами
    while data:
        if not do_something(connstream, data):
            # мы предполагаем, что do_something возвращает False
            # когда мы закончим с клиентом
            break
        data = connstream.recv(1024)
    # закончил с клиентом

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

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

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

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

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

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

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

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

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

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

См.также

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

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

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

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

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

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

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

class ssl.SSLObject

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

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

У данного класса нет открытого (public) конструктора. Экземпляр 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 — это неблокирующие. Это означает, что, например, read() вызовет SSLWantReadError, если ему потребуется больше данных, чем доступно во входящем BIO.
  • Нет вызова wrap_bio() на уровне модуля, как для wrap_socket(). SSLObject всегда создаётся через SSLContext.

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

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

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

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

>>> import ssl, smtplib
>>> smtp = smtplib.SMTP("mail.digitology.tech", 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.options |= ssl.OP_NO_TLSv1
>>> client_context.options |= ssl.OP_NO_TLSv1_1

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

Выбор шифра

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

Мультиобработка

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

TLS 1.3

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

Python имеет предварительную и экспериментальную поддержку TLS 1.3 с OpenSSL 1.1.1. Новый протокол ведёт себя немного иначе, чем предыдущая версия 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, конфигурация алгоритма сигнатуре и изменение ключа, пока не поддерживаются.

Поддержка LibreSSL

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

См.также

Класс socket.socket
Документация базового класса socket
Надежное шифрование SSL/TLS: Введение
Введение из документации HTTP-сервера Apache
RFC 1422: Повышение конфиденциальности электронной почты в Интернете: Часть II: Управление ключами на основе сертификатов
Стив Кент
RFC 4086: Требования к случайности для обеспечения безопасности
Дональд Э., Джеффри И. Шиллер
RFC 5280: Сертификат инфраструктуры открытых ключей Интернета X.509 и профиль Списка отзыва сертификатов (CRL)
Д. Купер
RFC 5246: Протокол безопасности транспортного уровня (TLS) версии 1.2
Т. Диркс и др. в.
RFC 6066: Расширения безопасности транспортного уровня (TLS)
Д. Истлейк
IANA TLS: Параметры безопасности транспортного уровня (TLS)
ИАНА
RFC 7525: Рекомендации по безопасному использованию безопасности транспортного уровня (TLS) и безопасности транспортного уровня дейтаграмм (DTLS)
IETF
Рекомендации Mozilla по TLS на стороне сервера
Мозилла