ssl.md
1> **Источник:** https://python-all.ru/3.4/library/ssl.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 18.2. [`ssl`](https://python-all.ru/3.4/library/ssl.html#module-ssl) – обёртка TLS/SSL для объектов сокетов89**Исходный код:** [Lib/ssl.py](https://python-all.ru/src/3.4/Lib/ssl.py)1011---1213Этот модуль предоставляет доступ к шифрованию и аутентификации одноранговых узлов с помощью протокола Transport Layer Security (часто называемого «Secure Sockets Layer») для сетевых сокетов, как на стороне клиента, так и на стороне сервера. В этом модуле используется библиотека OpenSSL. Он доступен на всех современных Unix-системах, Windows, Mac OS X и, вероятно, на других платформах, если на них установлен OpenSSL.1415> **Примечание**16>17> Некоторые особенности поведения могут зависеть от платформы, так как вызовы производятся к API сокетов операционной системы. Установленная версия OpenSSL также может приводить к различиям в поведении. Например, TLSv1.1 и TLSv1.2 поставляются с openssl версии 1.0.1.1819> **Предупреждение**20>21> Не следует использовать этот модуль без ознакомления с [*рекомендациями по безопасности*](https://python-all.ru/3.4/library/ssl.html#ssl-security). В противном случае может возникнуть ложное ощущение безопасности, поскольку настройки по умолчанию модуля ssl не обязательно подходят для конкретного приложения.2223В этом разделе описываются объекты и функции модуля `ssl`; за более общей информацией о TLS, SSL и сертификатах обращайтесь к документам в разделе «См. также» внизу.2425Этот модуль предоставляет класс [`ssl.SSLSocket`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket), производный от типа [`socket.socket`](https://python-all.ru/3.4/library/socket.html#socket.socket), и предоставляющий обёртку, похожую на сокет, которая также шифрует и расшифровывает данные, передаваемые через сокет с помощью SSL. Он поддерживает дополнительные методы, такие как `getpeercert()`, который возвращает сертификат другой стороны соединения, и `cipher()`, который возвращает шифр, используемый для безопасного соединения.2627Для более сложных приложений класс [`ssl.SSLContext`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext) помогает управлять настройками и сертификатами, которые затем могут наследоваться SSL-сокетами, созданными через метод [`SSLContext.wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.wrap_socket).2829## 18.2.1. Функции, константы и исключения3031#### `exception ssl.SSLError`3233Возникает для сигнализации об ошибке из нижележащей реализации SSL (в настоящее время предоставляемой библиотекой OpenSSL). Это указывает на некоторую проблему в высокоуровневом уровне шифрования и аутентификации, который накладывается на нижележащее сетевое соединение. Эта ошибка является подтипом [`OSError`](https://python-all.ru/3.4/library/exceptions.html#OSError). Код ошибки и сообщение экземпляров [`SSLError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLError) предоставляются библиотекой OpenSSL.3435Изменено в версии 3.3: [`SSLError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLError) раньше был подтипом [`socket.error`](https://python-all.ru/3.4/library/socket.html#socket.error).3637#### `library`3839Строковый мнемонический код, обозначающий подмодуль OpenSSL, в котором произошла ошибка, например `SSL`, `PEM` или `X509`. Диапазон возможных значений зависит от версии OpenSSL.4041Новое в версии 3.3.4243#### `reason`4445Строковый мнемонический код, обозначающий причину этой ошибки, например `CERTIFICATE_VERIFY_FAILED`. Диапазон возможных значений зависит от версии OpenSSL.4647Новое в версии 3.3.4849#### `exception ssl.SSLZeroReturnError`5051Подкласс [`SSLError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLError), возникающий при попытке чтения или записи, когда SSL-соединение было корректно закрыто. Обратите внимание, что это не означает, что нижележащий транспорт (читай TCP) был закрыт.5253Новое в версии 3.3.5455#### `exception ssl.SSLWantReadError`5657Подкласс [`SSLError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLError), возбуждаемый [*неблокирующим SSL-сокетом*](https://python-all.ru/3.4/library/ssl.html#ssl-nonblocking) при попытке чтения или записи данных, когда требуется получить больше данных по нижележащему TCP-транспорту, прежде чем запрос может быть выполнен.5859Новое в версии 3.3.6061#### `exception ssl.SSLWantWriteError`6263Подкласс [`SSLError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLError), возбуждаемый [*неблокирующим SSL-сокетом*](https://python-all.ru/3.4/library/ssl.html#ssl-nonblocking) при попытке чтения или записи данных, когда требуется отправить больше данных по нижележащему TCP-транспорту, прежде чем запрос может быть выполнен.6465Новое в версии 3.3.6667#### `exception ssl.SSLSyscallError`6869Подкласс [`SSLError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLError), возбуждаемый при возникновении системной ошибки при попытке выполнения операции над SSL-сокетом. К сожалению, нет простого способа проверить исходный номер errno.7071Новое в версии 3.3.7273#### `exception ssl.SSLEOFError`7475Подкласс [`SSLError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLError), возбуждаемый при внезапном завершении SSL-соединения. Как правило, при возникновении этой ошибки не следует пытаться повторно использовать нижележащий транспорт.7677Новое в версии 3.3.7879#### `exception ssl.CertificateError`8081Возникает для сигнализации об ошибке с сертификатом (например, несовпадение имени хоста). Однако ошибки сертификата, обнаруженные OpenSSL, возбуждают [`SSLError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLError).8283### 18.2.1.1. Создание сокета8485Следующая функция позволяет создать сокет независимо. Начиная с Python 3.2, может быть более гибким использование [`SSLContext.wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.wrap_socket) вместо этого.8687#### `ssl.wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version={see docs}, ca_certs=None, do_handshake_on_connect=True, suppress_ragged_eofs=True, ciphers=None)`8889Принимает экземпляр `sock` типа [`socket.socket`](https://python-all.ru/3.4/library/socket.html#socket.socket) и возвращает экземпляр [`ssl.SSLSocket`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket), подтипа [`socket.socket`](https://python-all.ru/3.4/library/socket.html#socket.socket), который оборачивает нижележащий сокет в контекст SSL. `sock` должен быть сокетом [`SOCK_STREAM`](https://python-all.ru/3.4/library/socket.html#socket.SOCK_STREAM); другие типы сокетов не поддерживаются.9091Для клиентских сокетов построение контекста ленивое; если нижележащий сокет ещё не подключен, построение контекста будет выполнено после вызова `connect()` на сокете. Для серверных сокетов, если сокет не имеет удалённого узла, предполагается, что это слушающий сокет, и серверная SSL-обёртка автоматически выполняется для клиентских соединений, принятых через метод `accept()`. [`wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.wrap_socket) может возбуждать [`SSLError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLError).9293Параметры `keyfile` и `certfile` задают необязательные файлы, содержащие сертификат, используемый для идентификации локальной стороны соединения. См. обсуждение [*Certificates*](https://python-all.ru/3.4/library/ssl.html#ssl-certificates) для получения дополнительной информации о том, как сертификат хранится в `certfile`.9495Параметр `server_side` – это логическое значение, которое определяет, требуется ли от этого сокета поведение серверной или клиентской стороны.9697Параметр `cert_reqs` задаёт, требуется ли сертификат от другой стороны соединения и будет ли он проверен, если предоставлен. Он должен быть одним из трёх значений: [`CERT_NONE`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_NONE) (сертификаты игнорируются), [`CERT_OPTIONAL`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_OPTIONAL) (не требуется, но проверяется, если предоставлен) или [`CERT_REQUIRED`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_REQUIRED) (требуется и проверяется). Если значение этого параметра не [`CERT_NONE`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_NONE), то параметр `ca_certs` должен указывать на файл с сертификатами ЦС.9899Файл `ca_certs` содержит набор объединённых сертификатов «центров сертификации», которые используются для проверки сертификатов, переданных с другого конца соединения. См. обсуждение [*Certificates*](https://python-all.ru/3.4/library/ssl.html#ssl-certificates) для получения дополнительной информации о том, как организовать сертификаты в этом файле.100101Параметр `ssl_version` определяет, какую версию протокола SSL использовать. Обычно сервер выбирает конкретную версию протокола, а клиент должен подстраиваться под выбор сервера. Большинство версий несовместимы друг с другом. Если параметр не задан, по умолчанию используется [`PROTOCOL_SSLv23`](https://python-all.ru/3.4/library/ssl.html#ssl.PROTOCOL_SSLv23); он обеспечивает наилучшую совместимость с другими версиями.102103Ниже приведена таблица, показывающая, какие версии на стороне клиента (по вертикали) могут подключаться к каким версиям на стороне сервера (по горизонтали):104105> | *клиент* / **сервер** | **SSLv2** | **SSLv3** | **SSLv23** | **TLSv1** | **TLSv1.1** | **TLSv1.2** |106> | --- | --- | --- | --- | --- | --- | --- |107> | *SSLv2* | да | нет | да | нет | нет | нет |108> | *SSLv3* | нет | да | да | нет | нет | нет |109> | *SSLv23* | нет | да | да | да | да | да |110> | *TLSv1* | нет | нет | да | да | нет | нет |111> | *TLSv1.1* | нет | нет | да | нет | да | нет |112> | *TLSv1.2* | нет | нет | да | нет | нет | да |113114> **Примечание**115>116> Какие соединения будут успешными, зависит от версии OpenSSL. Например, до OpenSSL 1.0.0 клиент SSLv23 всегда пытался устанавливать соединения SSLv2.117118Параметр *ciphers* задаёт доступные шифры для этого объекта SSL. Он должен быть строкой в [формате списка шифров OpenSSL](https://python-all.ru/3.4/library/ssl.html).119120Параметр `do_handshake_on_connect` определяет, выполнять ли квитирование SSL автоматически после вызова `socket.connect()`, или же программа должна вызывать его явно с помощью метода [`SSLSocket.do_handshake()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.do_handshake). Явный вызов [`SSLSocket.do_handshake()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.do_handshake) даёт программе контроль над блокирующим поведением операций ввода-вывода сокета, участвующих в квитировании.121122Параметр `suppress_ragged_eofs` определяет, как метод `SSLSocket.recv()` должен сигнализировать о неожиданном конце файла (EOF) с другого конца соединения. Если указано значение [`True`](https://python-all.ru/3.4/library/constants.html#True) (по умолчанию), он возвращает обычный EOF (пустой объект bytes) в ответ на ошибки неожиданного EOF, возникающие в базовом сокете; если [`False`](https://python-all.ru/3.4/library/constants.html#False), он будет пробрасывать исключения обратно вызывающему коду.123124Изменено в версии 3.2: Новый необязательный аргумент *ciphers*.125126### 18.2.1.2. Создание контекста127128Вспомогательная функция помогает создавать объекты [`SSLContext`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext) для типовых задач.129130#### `ssl.create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None, capath=None, cadata=None)`131132Возвращает новый объект [`SSLContext`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext) с настройками по умолчанию для заданного *purpose*. Настройки выбираются модулем [`ssl`](https://python-all.ru/3.4/library/ssl.html#module-ssl), и обычно обеспечивают более высокий уровень безопасности, чем при прямом вызове конструктора [`SSLContext`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext).133134*cafile*, *capath* и *cadata* представляют необязательные сертификаты ЦС для проверки сертификатов, как в [`SSLContext.load_verify_locations()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.load_verify_locations). Если все три равны [`None`](https://python-all.ru/3.4/library/constants.html#None), эта функция может вместо этого использовать системные сертификаты ЦС по умолчанию.135136Используются следующие настройки: [`PROTOCOL_SSLv23`](https://python-all.ru/3.4/library/ssl.html#ssl.PROTOCOL_SSLv23), [`OP_NO_SSLv2`](https://python-all.ru/3.4/library/ssl.html#ssl.OP_NO_SSLv2) и [`OP_NO_SSLv3`](https://python-all.ru/3.4/library/ssl.html#ssl.OP_NO_SSLv3) с набором шифров высокой надёжности без RC4 и без неаутентифицированных шифров. Передача [`SERVER_AUTH`](https://python-all.ru/3.4/library/ssl.html#ssl.Purpose.SERVER_AUTH) в качестве *purpose* устанавливает [`verify_mode`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.verify_mode) в [`CERT_REQUIRED`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_REQUIRED) и либо загружает сертификаты ЦС (когда задан хотя бы один из *cafile*, *capath* или *cadata*), либо использует [`SSLContext.load_default_certs()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.load_default_certs) для загрузки сертификатов ЦС по умолчанию.137138> **Примечание**139>140> Протокол, параметры, шифр и другие настройки могут в любой момент измениться на более строгие значения без предварительного уведомления об устаревании. Эти значения представляют собой разумный баланс между совместимостью и безопасностью.141>142> Если приложению требуются особые настройки, следует создать [`SSLContext`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext) и применить настройки самостоятельно.143144> **Примечание**145>146> Если при использовании [`SSLContext`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext), созданного этой функцией, некоторые старые клиенты или серверы при попытке подключения выдают ошибку «Несовпадение протокола или набора шифров», возможно, они поддерживают только SSL 3.0, который в этой функции отключён с помощью [`OP_NO_SSLv3`](https://python-all.ru/3.4/library/ssl.html#ssl.OP_NO_SSLv3). SSL 3.0 широко считается [полностью скомпрометированным](https://python-all.ru/3.4/library/ssl.html). Если всё же требуется продолжать использовать эту функцию, но при этом разрешить подключения по SSL 3.0, его можно снова включить следующим образом:147>148> ```python149> ctx = ssl.create_default_context(Purpose.CLIENT_AUTH)150> ctx.options &= ~ssl.OP_NO_SSLv3151> ```152153Новое в версии 3.4.154155Изменено в версии 3.4.4: RC4 был удалён из строки шифров по умолчанию.156157Изменено в версии 3.4.7: ChaCha20/Poly1305 была добавлена в строку шифров по умолчанию.1581593DES был удалён из строки шифров по умолчанию.160161### 18.2.1.3. Генерация случайных чисел162163#### `ssl.RAND_bytes(num)`164165Возвращает *num* криптостойких псевдослучайных байтов. Вызывает исключение [`SSLError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLError), если ГПСЧ не был инициализирован достаточным количеством данных или если операция не поддерживается текущим методом RAND. [`RAND_status()`](https://python-all.ru/3.4/library/ssl.html#ssl.RAND_status) можно использовать для проверки состояния ГПСЧ, а [`RAND_add()`](https://python-all.ru/3.4/library/ssl.html#ssl.RAND_add) – для его инициализации.166167Для большинства приложений предпочтительнее использовать [`os.urandom()`](https://python-all.ru/3.4/library/os.html#os.urandom).168169Прочитайте статью в Википедии, [Криптографически стойкий генератор псевдослучайных чисел (CSPRNG)](https://python-all.ru/3.4/library/ssl.html), чтобы узнать требования к криптографическому генератору.170171Новое в версии 3.3.172173#### `ssl.RAND_pseudo_bytes(num)`174175Возвращает (bytes, is\_cryptographic): bytes – это *num* псевдослучайных байтов, is\_cryptographic равно `True`, если сгенерированные байты являются криптостойкими. Вызывает исключение [`SSLError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLError), если операция не поддерживается текущим методом RAND.176177Сгенерированные последовательности псевдослучайных байтов будут уникальными, если они имеют достаточную длину, но не обязательно непредсказуемы. Их можно использовать для некриптографических целей и для некоторых целей в криптографических протоколах, но обычно не для генерации ключей и т.д.178179Для большинства приложений предпочтительнее использовать [`os.urandom()`](https://python-all.ru/3.4/library/os.html#os.urandom).180181Новое в версии 3.3.182183#### `ssl.RAND_status()`184185Возвращает `True`, если ГПСЧ SSL был инициализирован «достаточной» энтропией, и `False` в противном случае. Для увеличения энтропии генератора псевдослучайных чисел можно использовать [`ssl.RAND_egd()`](https://python-all.ru/3.4/library/ssl.html#ssl.RAND_egd) и [`ssl.RAND_add()`](https://python-all.ru/3.4/library/ssl.html#ssl.RAND_add).186187#### `ssl.RAND_egd(path)`188189Если где-то запущен демон сбора энтропии (EGD) и *path* – это имя пути к сокетному соединению, открытому для него, то из сокета будет прочитано 256 байт случайных данных и добавлено в генератор псевдослучайных чисел SSL для повышения безопасности генерируемых секретных ключей. Обычно это необходимо только в системах, где нет более качественных источников случайности.190191См. [http://egd.sourceforge.net/](https://python-all.ru/3.4/library/ssl.html) или [http://prngd.sourceforge.net/](https://python-all.ru/3.4/library/ssl.html) для получения исходных текстов демонов сбора энтропии.192193#### `ssl.RAND_add(bytes, entropy)`194195Смешивает заданные *bytes* (байты) с генератором псевдослучайных чисел SSL. Параметр *entropy* (число с плавающей точкой) задаёт нижнюю границу энтропии, содержащейся в строке (поэтому всегда можно использовать `0.0`). См. [**RFC 1750**](https://python-all.ru/3.4/library/ssl.html) для получения дополнительной информации об источниках энтропии.196197### 18.2.1.4. Обработка сертификатов198199#### `ssl.match_hostname(cert, hostname)`200201Проверяет, что *cert* (в декодированном формате, возвращённом функцией [`SSLSocket.getpeercert()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.getpeercert)) соответствует заданному *hostname*. Применяются правила проверки идентичности HTTPS-серверов, описанные в [**RFC 2818**](https://python-all.ru/3.4/library/ssl.html) и [**RFC 6125**](https://python-all.ru/3.4/library/ssl.html), за исключением того, что IP-адреса в настоящее время не поддерживаются. Помимо HTTPS, эта функция подходит для проверки идентичности серверов в различных протоколах на основе SSL, таких как FTPS, IMAPS, POPS и другие.202203[`CertificateError`](https://python-all.ru/3.4/library/ssl.html#ssl.CertificateError) возбуждается при неудаче. В случае успеха функция ничего не возвращает:204205```python206>>> cert = {'subject': ((('commonName', 'example.com'),),)}207>>> ssl.match_hostname(cert, "example.com")208>>> ssl.match_hostname(cert, "example.org")209Traceback (most recent call last):210 File "<stdin>", line 1, in <module>211 File "/home/py3k/Lib/ssl.py", line 130, in match_hostname212ssl.CertificateError: hostname 'example.org' doesn't match 'example.com'213```214215Новое в версии 3.2.216217Изменено в версии 3.3.3: Теперь функция следует [**RFC 6125**](https://python-all.ru/3.4/library/ssl.html), разделу 6.4.3, и не сопоставляет ни множественные подстановочные символы (например, `*.*.com` или `*a*.example.org`), ни подстановочный символ внутри фрагмента интернационализированного доменного имени (IDN). Метки IDN A-типа, такие как `www*.xn--pthon-kva.org`, по-прежнему поддерживаются, но `x*.python.org` больше не соответствует `xn--tda.python.org`.218219#### `ssl.cert_time_to_seconds(timestring)`220221Возвращает значение с плавающей запятой, содержащее обычное время в секундах от начала эпохи, для строки времени, представляющей дату “notBefore” или “notAfter” из сертификата.222223Вот пример:224225```python226>>> import ssl227>>> ssl.cert_time_to_seconds("May 9 00:00:00 2007 GMT")2281178694000.0229>>> import time230>>> time.ctime(ssl.cert_time_to_seconds("May 9 00:00:00 2007 GMT"))231'Wed May 9 00:00:00 2007'232```233234#### `ssl.get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None)`235236По заданному адресу `addr` SSL-защищённого сервера, в виде пары (*hostname*, *port-number*), получает сертификат сервера и возвращает его в виде строки в кодировке PEM. Если указан `ssl_version`, используется эта версия протокола SSL для попытки подключения к серверу. Если указан `ca_certs`, это должен быть файл, содержащий список корневых сертификатов, в том же формате, который используется для одноимённого параметра в [`wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.wrap_socket). Вызов попытается проверить сертификат сервера по этому набору корневых сертификатов, и завершится неудачей, если проверка не пройдёт.237238Изменено в версии 3.3: Эта функция теперь совместима с IPv6.239240#### `ssl.DER_cert_to_PEM_cert(DER_cert_bytes)`241242Принимая сертификат в виде набора байтов в кодировке DER, возвращает версию того же сертификата в виде строки в кодировке PEM.243244#### `ssl.PEM_cert_to_DER_cert(PEM_cert_string)`245246Принимая сертификат в виде строки ASCII в формате PEM, возвращает последовательность байтов в кодировке DER для того же сертификата.247248#### `ssl.get_default_verify_paths()`249250Возвращает именованный кортеж с путями к cafile и capath OpenSSL по умолчанию. Пути такие же, как используются в [`SSLContext.set_default_verify_paths()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.set_default_verify_paths). Возвращаемое значение – [*именованный кортеж*](https://python-all.ru/3.4/glossary.html#term-named-tuple) `DefaultVerifyPaths`:251252- `cafile` – разрешённый путь к cafile или None, если файл не существует,253- `capath` – разрешённый путь к capath или None, если каталог не существует,254- `openssl_cafile_env` – ключ окружения OpenSSL, указывающий на cafile,255- `openssl_cafile` – жёстко заданный путь к cafile,256- `openssl_capath_env` – ключ окружения OpenSSL, указывающий на capath,257- `openssl_capath` – жёстко заданный путь к каталогу capath258259Новое в версии 3.4.260261#### `ssl.enum_certificates(store_name)`262263Извлекает сертификаты из системного хранилища сертификатов Windows. *store\_name* может быть одним из `CA`, `ROOT` или `MY`. Windows также может предоставлять дополнительные хранилища сертификатов.264265Функция возвращает список кортежей (cert\_bytes, encoding\_type, trust). Параметр encoding\_type задаёт кодировку cert\_bytes. Это либо `x509_asn` для данных X.509 ASN.1, либо `pkcs_7_asn` для данных PKCS#7 ASN.1. Параметр trust задаёт назначение сертификата как набор OID или именно `True`, если сертификат заслуживает доверия для всех целей.266267Пример:268269```python270>>> ssl.enum_certificates("CA")271[(b'data...', 'x509_asn', {'1.3.6.1.5.5.7.3.1', '1.3.6.1.5.5.7.3.2'}),272 (b'data...', 'x509_asn', True)]273```274275Доступность: Windows.276277Новое в версии 3.4.278279#### `ssl.enum_crls(store_name)`280281Извлекает списки отзыва (CRL) из системного хранилища сертификатов Windows. *store\_name* может быть одним из `CA`, `ROOT` или `MY`. Windows также может предоставлять дополнительные хранилища сертификатов.282283Функция возвращает список кортежей (cert\_bytes, encoding\_type, trust). Параметр encoding\_type задаёт кодировку cert\_bytes. Это либо `x509_asn` для данных X.509 ASN.1, либо `pkcs_7_asn` для данных PKCS#7 ASN.1.284285Доступность: Windows.286287Новое в версии 3.4.288289### 18.2.1.5. Константы290291#### `ssl.CERT_NONE`292293Возможное значение для [`SSLContext.verify_mode`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.verify_mode) или параметра `cert_reqs` для [`wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.wrap_socket). В этом режиме (по умолчанию) от другой стороны сокетного соединения не требуется сертификатов. Если сертификат получен от другой стороны, никаких попыток его проверки не предпринимается.294295См. обсуждение [*соображений безопасности*](https://python-all.ru/3.4/library/ssl.html#ssl-security) ниже.296297#### `ssl.CERT_OPTIONAL`298299Возможное значение для [`SSLContext.verify_mode`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.verify_mode) или параметра `cert_reqs` для [`wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.wrap_socket). В этом режиме от другой стороны сокетного соединения не требуется сертификатов; но если они предоставлены, будет предпринята попытка проверки, и при неудаче будет возбуждено [`SSLError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLError).300301Использование этого параметра требует, чтобы был передан действительный набор сертификатов ЦС – либо в [`SSLContext.load_verify_locations()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.load_verify_locations), либо в качестве значения параметра `ca_certs` для [`wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.wrap_socket).302303#### `ssl.CERT_REQUIRED`304305Возможное значение для [`SSLContext.verify_mode`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.verify_mode) или параметра `cert_reqs` для [`wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.wrap_socket). В этом режиме от другой стороны сокетного соединения требуются сертификаты; [`SSLError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLError) будет возбуждено, если сертификат не предоставлен или его проверка не пройдена.306307Использование этого параметра требует передачи корректного набора сертификатов ЦС – либо в [`SSLContext.load_verify_locations()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.load_verify_locations), либо в качестве значения параметра `ca_certs` в [`wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.wrap_socket).308309#### `ssl.VERIFY_DEFAULT`310311Возможное значение для [`SSLContext.verify_flags`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.verify_flags). В этом режиме списки отзыва сертификатов (CRL) не проверяются. По умолчанию OpenSSL ни требует, ни проверяет CRL.312313Новое в версии 3.4.314315#### `ssl.VERIFY_CRL_CHECK_LEAF`316317Возможное значение для [`SSLContext.verify_flags`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.verify_flags). В этом режиме проверяется только сертификат однорангового узла, но не промежуточные сертификаты ЦС. Режим требует действительного CRL, подписанного эмитентом сертификата однорангового узла (его прямым вышестоящим ЦС). Если подходящий объект не был загружен с помощью [`SSLContext.load_verify_locations`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.load_verify_locations), проверка завершится неудачей.318319Новое в версии 3.4.320321#### `ssl.VERIFY_CRL_CHECK_CHAIN`322323Возможное значение для [`SSLContext.verify_flags`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.verify_flags). В этом режиме проверяются CRL всех сертификатов в цепочке сертификатов однорангового узла.324325Новое в версии 3.4.326327#### `ssl.VERIFY_X509_STRICT`328329Возможное значение для [`SSLContext.verify_flags`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.verify_flags), отключающее обходные решения для повреждённых сертификатов X.509.330331Новое в версии 3.4.332333#### `ssl.VERIFY_X509_TRUSTED_FIRST`334335Возможное значение для [`SSLContext.verify_flags`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.verify_flags). Указывает OpenSSL предпочитать доверенные сертификаты при построении цепочки доверия для проверки сертификата. Этот флаг включён по умолчанию.336337Новое в версии 3.4.4.338339#### `ssl.PROTOCOL_SSLv23`340341Выбирает самую высокую версию протокола, поддерживаемую как клиентом, так и сервером. Несмотря на название, этот параметр может выбирать протоколы «TLS», а также «SSL».342343#### `ssl.PROTOCOL_SSLv2`344345Выбирает SSL версии 2 в качестве протокола шифрования канала.346347Этот протокол недоступен, если OpenSSL скомпилирован с флагом `OPENSSL_NO_SSL2`.348349> **Предупреждение**350>351> SSL версии 2 небезопасен. Его использование крайне не рекомендуется.352353#### `ssl.PROTOCOL_SSLv3`354355Выбирает SSL версии 3 в качестве протокола шифрования канала.356357Этот протокол недоступен, если OpenSSL скомпилирован с флагом `OPENSSL_NO_SSLv3`.358359> **Предупреждение**360>361> SSL версии 3 небезопасен. Его использование крайне не рекомендуется.362363#### `ssl.PROTOCOL_TLSv1`364365Выбирает TLS версии 1.0 в качестве протокола шифрования канала.366367#### `ssl.PROTOCOL_TLSv1_1`368369Выбирает TLS версии 1.1 в качестве протокола шифрования канала. Доступно только в openssl версии 1.0.1+.370371Новое в версии 3.4.372373#### `ssl.PROTOCOL_TLSv1_2`374375Выбирает TLS версии 1.2 в качестве протокола шифрования канала. Это самая современная версия и, вероятно, лучший выбор для максимальной защиты, если обе стороны могут её поддерживать. Доступна только с openssl версии 1.0.1 и выше.376377Новое в версии 3.4.378379#### `ssl.OP_ALL`380381Включает обходные решения для различных ошибок, присутствующих в других реализациях SSL. Этот параметр установлен по умолчанию. Он не обязательно устанавливает те же флаги, что и константа `SSL_OP_ALL` в OpenSSL.382383Новое в версии 3.2.384385#### `ssl.OP_NO_SSLv2`386387Запрещает соединение SSLv2. Этот параметр применим только в сочетании с [`PROTOCOL_SSLv23`](https://python-all.ru/3.4/library/ssl.html#ssl.PROTOCOL_SSLv23). Он не позволяет одноранговым узлам выбирать SSLv2 в качестве версии протокола.388389Новое в версии 3.2.390391#### `ssl.OP_NO_SSLv3`392393Запрещает соединение SSLv3. Этот параметр применим только в сочетании с [`PROTOCOL_SSLv23`](https://python-all.ru/3.4/library/ssl.html#ssl.PROTOCOL_SSLv23). Он не позволяет одноранговым узлам выбирать SSLv3 в качестве версии протокола.394395Новое в версии 3.2.396397#### `ssl.OP_NO_TLSv1`398399Запрещает соединение TLSv1. Этот параметр применим только в сочетании с [`PROTOCOL_SSLv23`](https://python-all.ru/3.4/library/ssl.html#ssl.PROTOCOL_SSLv23). Он не позволяет одноранговым узлам выбирать TLSv1 в качестве версии протокола.400401Новое в версии 3.2.402403#### `ssl.OP_NO_TLSv1_1`404405Запрещает соединение TLSv1.1. Этот параметр применим только в сочетании с [`PROTOCOL_SSLv23`](https://python-all.ru/3.4/library/ssl.html#ssl.PROTOCOL_SSLv23). Он не позволяет одноранговым узлам выбирать TLSv1.1 в качестве версии протокола. Доступно только в OpenSSL версии 1.0.1 и выше.406407Новое в версии 3.4.408409#### `ssl.OP_NO_TLSv1_2`410411Запрещает соединение TLSv1.2. Этот параметр применим только в сочетании с [`PROTOCOL_SSLv23`](https://python-all.ru/3.4/library/ssl.html#ssl.PROTOCOL_SSLv23). Он не позволяет одноранговым узлам выбирать TLSv1.2 в качестве версии протокола. Доступно только в OpenSSL версии 1.0.1 и выше.412413Новое в версии 3.4.414415#### `ssl.OP_CIPHER_SERVER_PREFERENCE`416417Использовать порядок шифров, заданный на сервере, а не на клиенте. Этот параметр не влияет на клиентские сокеты и сокеты сервера SSLv2.418419Новое в версии 3.3.420421#### `ssl.OP_SINGLE_DH_USE`422423Предотвращает повторное использование одного и того же DH-ключа для разных SSL-сессий. Это улучшает прямую секретность, но требует больше вычислительных ресурсов. Данная опция применяется только к серверным сокетам.424425Новое в версии 3.3.426427#### `ssl.OP_SINGLE_ECDH_USE`428429Предотвращает повторное использование одного и того же ECDH-ключа для разных SSL-сессий. Это улучшает прямую секретность, но требует больше вычислительных ресурсов. Данная опция применяется только к серверным сокетам.430431Новое в версии 3.3.432433#### `ssl.OP_NO_COMPRESSION`434435Отключает сжатие в SSL-канале. Это полезно, если прикладной протокол поддерживает собственный механизм сжатия.436437Эта опция доступна только в OpenSSL 1.0.0 и более поздних версиях.438439Новое в версии 3.3.440441#### `ssl.HAS_ECDH`442443Определяет, имеет ли библиотека OpenSSL встроенную поддержку обмена ключами Диффи-Хеллмана на основе эллиптических кривых. Должно быть истинно, если только эта возможность не была явно отключена распространителем.444445Новое в версии 3.3.446447#### `ssl.HAS_SNI`448449Указывает, имеет ли библиотека OpenSSL встроенную поддержку расширения *Server Name Indication* (как определено в [**RFC 4366**](https://python-all.ru/3.4/library/ssl.html)).450451Новое в версии 3.2.452453#### `ssl.HAS_NPN`454455Поддерживает ли библиотека OpenSSL встроенную поддержку *Next Protocol Negotiation*, как описано в [черновике спецификации NPN](https://python-all.ru/3.4/library/ssl.html). Если значение истинно, можно использовать метод [`SSLContext.set_npn_protocols()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.set_npn_protocols) для указания поддерживаемых протоколов.456457Новое в версии 3.3.458459#### `ssl.CHANNEL_BINDING_TYPES`460461Список поддерживаемых типов привязки каналов TLS. Строки из этого списка можно использовать в качестве аргументов для [`SSLSocket.get_channel_binding()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.get_channel_binding).462463Новое в версии 3.3.464465#### `ssl.OPENSSL_VERSION`466467Строка с версией библиотеки OpenSSL, загруженной интерпретатором:468469```python470>>> ssl.OPENSSL_VERSION471'OpenSSL 0.9.8k 25 Mar 2009'472```473474Новое в версии 3.2.475476#### `ssl.OPENSSL_VERSION_INFO`477478Кортеж из пяти целых чисел, содержащий информацию о версии библиотеки OpenSSL:479480```python481>>> ssl.OPENSSL_VERSION_INFO482(0, 9, 8, 11, 15)483```484485Новое в версии 3.2.486487#### `ssl.OPENSSL_VERSION_NUMBER`488489Сырой номер версии библиотеки OpenSSL в виде целого числа:490491```python492>>> ssl.OPENSSL_VERSION_NUMBER4939470143494>>> hex(ssl.OPENSSL_VERSION_NUMBER)495'0x9080bf'496```497498Новое в версии 3.2.499500#### `ssl.ALERT_DESCRIPTION_HANDSHAKE_FAILURE`501502#### `ssl.ALERT_DESCRIPTION_INTERNAL_ERROR`503504#### `ALERT_DESCRIPTION_*`505506Описания предупреждений из [**RFC 5246**](https://python-all.ru/3.4/library/ssl.html) и других источников. [Реестр предупреждений TLS IANA](https://python-all.ru/3.4/library/ssl.html) содержит этот список и ссылки на RFC, где определено их значение.507508Используется как возвращаемое значение функции обратного вызова в [`SSLContext.set_servername_callback()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.set_servername_callback).509510Новое в версии 3.4.511512#### `Purpose.SERVER_AUTH`513514Параметр для [`create_default_context()`](https://python-all.ru/3.4/library/ssl.html#ssl.create_default_context) и [`SSLContext.load_default_certs()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.load_default_certs). Это значение указывает, что контекст может использоваться для аутентификации веб-серверов (поэтому он будет использоваться для создания клиентских сокетов).515516Новое в версии 3.4.517518#### `Purpose.CLIENT_AUTH`519520Параметр для [`create_default_context()`](https://python-all.ru/3.4/library/ssl.html#ssl.create_default_context) и [`SSLContext.load_default_certs()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.load_default_certs). Это значение указывает, что контекст может использоваться для аутентификации веб-клиентов (поэтому он будет использоваться для создания серверных сокетов).521522Новое в версии 3.4.523524## 18.2.2. SSL-сокеты525526#### `class ssl.SSLSocket(socket.socket)`527528SSL-сокеты предоставляют следующие методы [*объектов сокетов*](https://python-all.ru/3.4/library/socket.html#socket-objects):529530- [`accept()`](https://python-all.ru/3.4/library/socket.html#socket.socket.accept)531- [`bind()`](https://python-all.ru/3.4/library/socket.html#socket.socket.bind)532- [`close()`](https://python-all.ru/3.4/library/socket.html#socket.socket.close)533- [`connect()`](https://python-all.ru/3.4/library/socket.html#socket.socket.connect)534- [`detach()`](https://python-all.ru/3.4/library/socket.html#socket.socket.detach)535- [`fileno()`](https://python-all.ru/3.4/library/socket.html#socket.socket.fileno)536- [`getpeername()`](https://python-all.ru/3.4/library/socket.html#socket.socket.getpeername), [`getsockname()`](https://python-all.ru/3.4/library/socket.html#socket.socket.getsockname)537- [`getsockopt()`](https://python-all.ru/3.4/library/socket.html#socket.socket.getsockopt), [`setsockopt()`](https://python-all.ru/3.4/library/socket.html#socket.socket.setsockopt)538- [`gettimeout()`](https://python-all.ru/3.4/library/socket.html#socket.socket.gettimeout), [`settimeout()`](https://python-all.ru/3.4/library/socket.html#socket.socket.settimeout), [`setblocking()`](https://python-all.ru/3.4/library/socket.html#socket.socket.setblocking)539- [`listen()`](https://python-all.ru/3.4/library/socket.html#socket.socket.listen)540- [`makefile()`](https://python-all.ru/3.4/library/socket.html#socket.socket.makefile)541- [`recv()`](https://python-all.ru/3.4/library/socket.html#socket.socket.recv), [`recv_into()`](https://python-all.ru/3.4/library/socket.html#socket.socket.recv_into) (но передача ненулевого аргумента `flags` не допускается)542- [`send()`](https://python-all.ru/3.4/library/socket.html#socket.socket.send), [`sendall()`](https://python-all.ru/3.4/library/socket.html#socket.socket.sendall) (с тем же ограничением)543- [`shutdown()`](https://python-all.ru/3.4/library/socket.html#socket.socket.shutdown)544545Однако, поскольку протокол SSL (и TLS) имеет собственную структуру поверх TCP, абстракция SSL-сокетов может в некоторых аспектах отличаться от спецификации обычных сокетов на уровне ОС. Особенно см. [*примечания о неблокирующих сокетах*](https://python-all.ru/3.4/library/ssl.html#ssl-nonblocking).546547Обычно объекты [`SSLSocket`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket) не создаются напрямую, а с помощью функции [`wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.wrap_socket) или метода [`SSLContext.wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.wrap_socket).548549SSL-сокеты также имеют следующие дополнительные методы и атрибуты:550551#### `SSLSocket.read(len=0, buffer=None)`552553Читает до *len* байт данных из SSL-сокета и возвращает результат в виде экземпляра `bytes`. Если указан *buffer*, то читает в буфер вместо этого и возвращает количество прочитанных байт.554555Возбуждает [`SSLWantReadError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLWantReadError) или [`SSLWantWriteError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLWantWriteError), если сокет [*неблокирующий*](https://python-all.ru/3.4/library/ssl.html#ssl-nonblocking) и чтение заблокируется.556557Поскольку в любой момент возможно пересогласование, вызов [`read()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.read) может также инициировать операции записи.558559#### `SSLSocket.write(buf)`560561Записывает *buf* в SSL-сокет и возвращает количество записанных байт. Аргумент *buf* должен быть объектом, поддерживающим буферный интерфейс.562563Возбуждает [`SSLWantReadError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLWantReadError) или [`SSLWantWriteError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLWantWriteError), если сокет [*неблокирующий*](https://python-all.ru/3.4/library/ssl.html#ssl-nonblocking) и запись заблокируется.564565Поскольку в любой момент возможно пересогласование, вызов [`write()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.write) может также инициировать операции чтения.566567> **Примечание**568>569> Методы [`read()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.read) и [`write()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.write) являются низкоуровневыми методами, которые читают и записывают незашифрованные данные прикладного уровня, расшифровывая/зашифровывая их в зашифрованные сетевые данные. Эти методы требуют активного SSL-соединения, то есть рукопожатие должно быть завершено и [`SSLSocket.unwrap()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.unwrap) не вызывался.570>571> Обычно следует использовать методы сокетного API, такие как [`recv()`](https://python-all.ru/3.4/library/socket.html#socket.socket.recv) и [`send()`](https://python-all.ru/3.4/library/socket.html#socket.socket.send), вместо этих методов.572573#### `SSLSocket.do_handshake()`574575Выполняет рукопожатие для настройки SSL.576577Изменено в версии 3.4: Метод рукопожатия также выполняет [`match_hostname()`](https://python-all.ru/3.4/library/ssl.html#ssl.match_hostname), когда атрибут [`check_hostname`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.check_hostname) сокетного [`контекста`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.context) истинен.578579#### `SSLSocket.getpeercert(binary_form=False)`580581Если сертификат для узла на другом конце соединения отсутствует, возвращает `None`. Если рукопожатие SSL ещё не выполнено, возбуждает [`ValueError`](https://python-all.ru/3.4/library/exceptions.html#ValueError).582583If the `binary_form` parameter is [`False`](https://python-all.ru/3.4/library/constants.html#False), and a certificate was received from the peer, this method returns a [`dict`](https://python-all.ru/3.4/library/stdtypes.html#dict) instance. If the certificate was not validated, the dict is empty. If the certificate was validated, it returns a dict with several keys, amongst them `subject` (the principal for which the certificate was issued) and `issuer` (the principal issuing the certificate). If a certificate contains an instance of the *Subject Alternative Name* extension (see [**RFC 3280**](https://python-all.ru/3.4/library/ssl.html)), there will also be a `subjectAltName` key in the dictionary.584585Поля `subject` и `issuer` являются кортежами, содержащими последовательность относительных уникальных имен (RDN), указанных в структуре данных сертификата для соответствующих полей. Каждый RDN представляет собой последовательность пар «имя-значение». Вот пример из реального мира:586587```python588{'issuer': ((('countryName', 'IL'),),589 (('organizationName', 'StartCom Ltd.'),),590 (('organizationalUnitName',591 'Secure Digital Certificate Signing'),),592 (('commonName',593 'StartCom Class 2 Primary Intermediate Server CA'),)),594 'notAfter': 'Nov 22 08:15:19 2013 GMT',595 'notBefore': 'Nov 21 03:09:52 2011 GMT',596 'serialNumber': '95F0',597 'subject': ((('description', '571208-SLe257oHY9fVQ07Z'),),598 (('countryName', 'US'),),599 (('stateOrProvinceName', 'California'),),600 (('localityName', 'San Francisco'),),601 (('organizationName', 'Electronic Frontier Foundation, Inc.'),),602 (('commonName', '*.eff.org'),),603 (('emailAddress', 'hostmaster@eff.org'),)),604 'subjectAltName': (('DNS', '*.eff.org'), ('DNS', 'eff.org')),605 'version': 3}606```607608> **Примечание**609>610> Для проверки сертификата для конкретной службы можно использовать функцию [`match_hostname()`](https://python-all.ru/3.4/library/ssl.html#ssl.match_hostname).611612Если параметр `binary_form` равен [`True`](https://python-all.ru/3.4/library/constants.html#True) и сертификат был предоставлен, этот метод возвращает DER-кодированную форму всего сертификата в виде последовательности байт или [`None`](https://python-all.ru/3.4/library/constants.html#None), если узел не предоставил сертификат. Предоставляет ли узел сертификат, зависит от роли SSL-сокета:613614- для клиентского SSL-сокета сервер всегда предоставляет сертификат, независимо от того, требовалась ли проверка;615- для серверного SSL-сокета клиент предоставляет сертификат только по запросу сервера; поэтому [`getpeercert()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.getpeercert) вернет [`None`](https://python-all.ru/3.4/library/constants.html#None), если было использовано [`CERT_NONE`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_NONE) (а не [`CERT_OPTIONAL`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_OPTIONAL) или [`CERT_REQUIRED`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_REQUIRED)).616617Изменено в версии 3.2: Возвращаемый словарь включает дополнительные элементы, такие как `issuer` и `notBefore`.618619Изменено в версии 3.4: [`ValueError`](https://python-all.ru/3.4/library/exceptions.html#ValueError) возбуждается, если рукопожатие не выполнено. Возвращаемый словарь включает дополнительные элементы расширений X509v3, такие как `crlDistributionPoints`, `caIssuers` и URI `OCSP`.620621#### `SSLSocket.cipher()`622623Возвращает кортеж из трех значений, содержащий название используемого шифра, версию протокола SSL, которая определяет его использование, и количество используемых секретных битов. Если соединение не установлено, возвращает `None`.624625#### `SSLSocket.compression()`626627Возвращает используемый алгоритм сжатия в виде строки или `None`, если соединение не сжато.628629Если протокол более высокого уровня поддерживает собственный механизм сжатия, можно использовать [`OP_NO_COMPRESSION`](https://python-all.ru/3.4/library/ssl.html#ssl.OP_NO_COMPRESSION) для отключения сжатия на уровне SSL.630631Новое в версии 3.3.632633#### `SSLSocket.get_channel_binding(cb_type="tls-unique")`634635Получает данные привязки канала для текущего соединения в виде объекта bytes. Возвращает `None`, если соединение не установлено или рукопожатие не завершено.636637Параметр *cb\_type* позволяет выбрать желаемый тип привязки канала. Допустимые типы привязки канала перечислены в списке [`CHANNEL_BINDING_TYPES`](https://python-all.ru/3.4/library/ssl.html#ssl.CHANNEL_BINDING_TYPES). В настоящее время поддерживается только привязка канала «tls-unique», определенная в [**RFC 5929**](https://python-all.ru/3.4/library/ssl.html). Если запрошен неподдерживаемый тип привязки канала, будет возбуждено [`ValueError`](https://python-all.ru/3.4/library/exceptions.html#ValueError).638639Новое в версии 3.3.640641#### `SSLSocket.selected_npn_protocol()`642643Возвращает протокол, выбранный во время рукопожатия TLS/SSL. Если [`SSLContext.set_npn_protocols()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.set_npn_protocols) не была вызвана, или другая сторона не поддерживает NPN, или рукопожатие ещё не произошло, возвращается `None`.644645Новое в версии 3.3.646647#### `SSLSocket.unwrap()`648649Выполняет рукопожатие завершения SSL, которое удаляет слой TLS из базового сокета и возвращает объект базового сокета. Это можно использовать для перехода от зашифрованной работы по соединению к незашифрованной. Возвращённый сокет всегда следует использовать для дальнейшего обмена данными с другой стороной соединения, а не исходный сокет.650651#### `SSLSocket.pending()`652653Возвращает количество уже расшифрованных байтов, доступных для чтения, ожидающих на соединении.654655#### `SSLSocket.context`656657Объект [`SSLContext`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext), к которому привязан данный SSL-сокет. Если SSL-сокет был создан с помощью функции верхнего уровня [`wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.wrap_socket) (а не [`SSLContext.wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.wrap_socket)), то это пользовательский объект контекста, созданный для данного SSL-сокета.658659Новое в версии 3.2.660661#### `SSLSocket.server_side`662663Логическое значение: `True` для серверных сокетов и `False` для клиентских.664665Новое в версии 3.2.666667#### `SSLSocket.server_hostname`668669Имя хоста сервера: тип [`str`](https://python-all.ru/3.4/library/stdtypes.html#str) или `None` для серверного сокета, или если имя хоста не было указано в конструкторе.670671Новое в версии 3.2.672673## 18.2.3. SSL-контексты674675Новое в версии 3.2.676677Контекст SSL хранит различные данные, которые живут дольше, чем отдельные SSL-соединения, такие как параметры конфигурации SSL, сертификат(ы) и закрытый(е) ключ(и). Он также управляет кешем SSL-сессий для серверных сокетов, чтобы ускорить повторные подключения от одних и тех же клиентов.678679#### `class ssl.SSLContext(protocol)`680681Создаёт новый SSL-контекст. Необходимо передать *протокол*, который должен быть одной из констант `PROTOCOL_*`, определённых в этом модуле. [`PROTOCOL_SSLv23`](https://python-all.ru/3.4/library/ssl.html#ssl.PROTOCOL_SSLv23) в настоящее время рекомендуется для максимальной совместимости.682683> **См. также**684>685> [`create_default_context()`](https://python-all.ru/3.4/library/ssl.html#ssl.create_default_context) позволяет модулю [`ssl`](https://python-all.ru/3.4/library/ssl.html#module-ssl) выбирать настройки безопасности для заданной цели.686687Объекты [`SSLContext`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext) имеют следующие методы и атрибуты:688689#### `SSLContext.cert_store_stats()`690691Возвращает словарь со статистикой о количестве загруженных X.509 сертификатов, количестве сертификатов X.509, помеченных как сертификаты CA, и списках отзыва сертификатов.692693Пример для контекста с одним сертификатом CA и одним другим сертификатом:694695```python696>>> context.cert_store_stats()697{'crl': 0, 'x509_ca': 1, 'x509': 2}698```699700Новое в версии 3.4.701702#### `SSLContext.load_cert_chain(certfile, keyfile=None, password=None)`703704Загружает закрытый ключ и соответствующий сертификат. Строка *certfile* должна быть путём к одному файлу в формате PEM, содержащему сертификат, а также любое количество сертификатов УЦ, необходимых для подтверждения подлинности сертификата. Строка *keyfile*, если указана, должна указывать на файл, содержащий закрытый ключ. В противном случае закрытый ключ также будет взят из *certfile*. Смотрите обсуждение [*Certificates*](https://python-all.ru/3.4/library/ssl.html#ssl-certificates) для получения дополнительной информации о том, как сертификат хранится в *certfile*.705706Аргумент *password* может быть функцией, вызываемой для получения пароля для расшифровки закрытого ключа. Она будет вызвана только в том случае, если закрытый ключ зашифрован и требуется пароль. Она будет вызвана без аргументов, и должна возвращать строку, bytes или bytearray. Если возвращаемое значение – строка, она будет закодирована в UTF-8 перед использованием для расшифровки ключа. В качестве альтернативы, строка, bytes или bytearray могут быть переданы напрямую в качестве аргумента *password*. Этот аргумент будет проигнорирован, если закрытый ключ не зашифрован и пароль не требуется.707708Если аргумент *password* не указан и требуется пароль, будет использован встроенный механизм запроса пароля OpenSSL для интерактивного запроса пароля у пользователя.709710Исключение [`SSLError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLError) возбуждается, если закрытый ключ не соответствует сертификату.711712Изменено в версии 3.3: Новый необязательный аргумент *password*.713714#### `SSLContext.load_default_certs(purpose=Purpose.SERVER_AUTH)`715716Загружает набор стандартных сертификатов «удостоверяющего центра» (CA) из стандартных расположений. В Windows загружает сертификаты CA из системных хранилищ `CA` и `ROOT`. В других системах вызывает [`SSLContext.set_default_verify_paths()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.set_default_verify_paths). В будущем метод может также загружать сертификаты CA из других расположений.717718Флаг *purpose* определяет, какие сертификаты CA загружаются. Настройка по умолчанию [`Purpose.SERVER_AUTH`](https://python-all.ru/3.4/library/ssl.html#ssl.Purpose.SERVER_AUTH) загружает сертификаты, помеченные и доверенные для аутентификации TLS-веб-сервера (клиентские сокеты). [`Purpose.CLIENT_AUTH`](https://python-all.ru/3.4/library/ssl.html#ssl.Purpose.CLIENT_AUTH) загружает сертификаты CA для проверки клиентского сертификата на стороне сервера.719720Новое в версии 3.4.721722#### `SSLContext.load_verify_locations(cafile=None, capath=None, cadata=None)`723724Загружает набор сертификатов «удостоверяющего центра» (CA), используемых для проверки сертификатов других участников, когда [`verify_mode`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.verify_mode) отличен от [`CERT_NONE`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_NONE). Должен быть указан хотя бы один из параметров *cafile* или *capath*.725726Этот метод также может загружать списки отзыва сертификатов (CRL) в формате PEM или DER. Чтобы использовать CRL, [`SSLContext.verify_flags`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.verify_flags) должен быть настроен соответствующим образом.727728Строка *cafile*, если присутствует, содержит путь к файлу, содержащему объединённые сертификаты CA в формате PEM. См. обсуждение [*Сертификаты*](https://python-all.ru/3.4/library/ssl.html#ssl-certificates) для получения дополнительной информации о том, как организовать сертификаты в этом файле.729730Строка *capath*, если присутствует, задаёт путь к каталогу, содержащему несколько сертификатов CA в формате PEM, согласно [специфической структуре OpenSSL](https://python-all.ru/3.4/library/ssl.html).731732Объект *cadata*, если присутствует, представляет собой либо ASCII-строку с одним или несколькими сертификатами в кодировке PEM, либо [*байтоподобный объект*](https://python-all.ru/3.4/glossary.html#term-bytes-like-object) с сертификатами в кодировке DER. Как и в случае с *capath*, дополнительные строки вокруг сертификатов в кодировке PEM игнорируются, но должен присутствовать хотя бы один сертификат.733734Изменено в версии 3.4: Новый необязательный аргумент *cadata*735736#### `SSLContext.get_ca_certs(binary_form=False)`737738Get a list of loaded “certification authority” (CA) certificates. If the `binary_form` parameter is [`False`](https://python-all.ru/3.4/library/constants.html#False) each list entry is a dict like the output of [`SSLSocket.getpeercert()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.getpeercert). Otherwise the method returns a list of DER-encoded certificates. The returned list does not contain certificates from *capath* unless a certificate was requested and loaded by a SSL connection.739740> **Примечание**741>742> Сертификаты в каталоге capath не загружаются, пока не будут использованы хотя бы один раз.743744Новое в версии 3.4.745746#### `SSLContext.set_default_verify_paths()`747748Загружает набор сертификатов по умолчанию “certification authority” (CA) из пути файловой системы, заданного при сборке библиотеки OpenSSL. К сожалению, нет простого способа узнать, успешно ли выполняется этот метод: ошибка не возвращается, если сертификаты не найдены. Однако, если библиотека OpenSSL поставляется как часть операционной системы, она, скорее всего, настроена правильно.749750#### `SSLContext.set_ciphers(ciphers)`751752Устанавливает доступные шифры для сокетов, созданных с этим контекстом. Это должна быть строка в [формате списка шифров OpenSSL](https://python-all.ru/3.4/library/ssl.html). Если ни один шифр не может быть выбран (из-за опций компиляции или других настроек, запрещающих использование всех указанных шифров), будет возбуждено исключение [`SSLError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLError).753754> **Примечание**755>756> при подключении метод [`SSLSocket.cipher()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.cipher) SSL-сокетов вернёт текущий выбранный шифр.757758#### `SSLContext.set_npn_protocols(protocols)`759760Определяет, какие протоколы сокет будет объявлять во время рукопожатия SSL/TLS. Это должен быть список строк, например `['http/1.1', 'spdy/2']`, упорядоченный по предпочтению. Выбор протокола произойдёт во время рукопожатия и будет выполняться в соответствии с [черновиком спецификации NPN](https://python-all.ru/3.4/library/ssl.html). После успешного рукопожатия метод [`SSLSocket.selected_npn_protocol()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.selected_npn_protocol) вернёт согласованный протокол.761762Этот метод возбудит [`NotImplementedError`](https://python-all.ru/3.4/library/exceptions.html#NotImplementedError), если [`HAS_NPN`](https://python-all.ru/3.4/library/ssl.html#ssl.HAS_NPN) равен False.763764Новое в версии 3.3.765766#### `SSLContext.set_servername_callback(server_name_callback)`767768Регистрирует функцию обратного вызова, которая будет вызвана после получения сервером SSL/TLS сообщения TLS Client Hello, когда клиент TLS указывает индикацию имени сервера. Механизм индикации имени сервера описан в [**RFC 6066**](https://python-all.ru/3.4/library/ssl.html) раздел 3 – Server Name Indication.769770На каждый `SSLContext` можно установить только один колбэк. Если *server\_name\_callback* равно `None`, то колбэк отключён. Повторный вызов этой функции отключит ранее зарегистрированный колбэк.771772Функция колбэка *server\_name\_callback* вызывается с тремя аргументами: первый – [`ssl.SSLSocket`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket), второй – строка, представляющая имя сервера, с которым клиент намерен установить связь (или [`None`](https://python-all.ru/3.4/library/constants.html#None), если TLS Client Hello не содержит имени сервера), а третий аргумент – исходный [`SSLContext`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext). Аргумент с именем сервера – это имя сервера, декодированное в IDNA.773774Типичное использование этого колбэка – изменение атрибута [`SSLSocket.context`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.context) объекта [`ssl.SSLSocket`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket) на новый объект типа [`SSLContext`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext), представляющий цепочку сертификатов, соответствующую имени сервера.775776Из-за ранней фазы согласования TLS-соединения доступны только ограниченные методы и атрибуты, например [`SSLSocket.selected_npn_protocol()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.selected_npn_protocol) и [`SSLSocket.context`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.context). Методы [`SSLSocket.getpeercert()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.getpeercert), [`SSLSocket.getpeercert()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.getpeercert), [`SSLSocket.cipher()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.cipher) и `SSLSocket.compress()` требуют, чтобы TLS-соединение продвинулось дальше TLS Client Hello, и поэтому не вернут осмысленных значений, и их нельзя безопасно вызывать.777778Функция *server\_name\_callback* должна возвращать `None`, чтобы позволить продолжить согласование TLS. Если требуется ошибка TLS, можно вернуть константу [`ALERT_DESCRIPTION_*`](https://python-all.ru/3.4/library/ssl.html#ssl.ALERT_DESCRIPTION_INTERNAL_ERROR). Другие возвращаемые значения приведут к фатальной ошибке TLS с [`ALERT_DESCRIPTION_INTERNAL_ERROR`](https://python-all.ru/3.4/library/ssl.html#ssl.ALERT_DESCRIPTION_INTERNAL_ERROR).779780Если при декодировании IDNA имени сервера происходит ошибка, TLS-соединение завершится фатальным предупреждением TLS [`ALERT_DESCRIPTION_INTERNAL_ERROR`](https://python-all.ru/3.4/library/ssl.html#ssl.ALERT_DESCRIPTION_INTERNAL_ERROR), отправленным клиенту.781782Если из функции *server\_name\_callback* выбрасывается исключение, TLS-соединение завершится фатальным предупреждением TLS [`ALERT_DESCRIPTION_HANDSHAKE_FAILURE`](https://python-all.ru/3.4/library/ssl.html#ssl.ALERT_DESCRIPTION_HANDSHAKE_FAILURE).783784Этот метод вызовет [`NotImplementedError`](https://python-all.ru/3.4/library/exceptions.html#NotImplementedError), если библиотека OpenSSL была собрана с определённым OPENSSL\_NO\_TLSEXT.785786Новое в версии 3.4.787788#### `SSLContext.load_dh_params(dhfile)`789790Загружает параметры генерации ключей для обмена ключами Диффи-Хеллмана (DH). Использование обмена ключами DH улучшает прямую секретность за счет вычислительных ресурсов (как на сервере, так и на клиенте). Параметр *dhfile* должен быть путем к файлу, содержащему параметры DH в формате PEM.791792Этот параметр не применяется к клиентским сокетам. Для дальнейшего повышения безопасности можно также использовать опцию [`OP_SINGLE_DH_USE`](https://python-all.ru/3.4/library/ssl.html#ssl.OP_SINGLE_DH_USE).793794Новое в версии 3.3.795796#### `SSLContext.set_ecdh_curve(curve_name)`797798Устанавливает имя кривой для обмена ключами на основе эллиптических кривых Diffie-Hellman (ECDH). ECDH значительно быстрее обычного DH и при этом, по-видимому, столь же безопасен. Параметр *curve\_name* должен быть строкой, описывающей известную эллиптическую кривую, например `prime256v1` для широко поддерживаемой кривой.799800Этот параметр не применяется к клиентским сокетам. Для дальнейшего повышения безопасности можно также использовать опцию [`OP_SINGLE_ECDH_USE`](https://python-all.ru/3.4/library/ssl.html#ssl.OP_SINGLE_ECDH_USE).801802Этот метод недоступен, если [`HAS_ECDH`](https://python-all.ru/3.4/library/ssl.html#ssl.HAS_ECDH) равен False.803804Новое в версии 3.3.805806> **См. также**807>808> **[SSL/TLS и совершенная прямая секретность](https://python-all.ru/3.4/library/ssl.html)**809>810> Vincent Bernat.811812#### `SSLContext.wrap_socket(sock, server_side=False, do_handshake_on_connect=True, suppress_ragged_eofs=True, server_hostname=None)`813814Оборачивает существующий Python-сокет *sock* и возвращает объект [`SSLSocket`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket). *sock* должен быть сокетом [`SOCK_STREAM`](https://python-all.ru/3.4/library/socket.html#socket.SOCK_STREAM); другие типы сокетов не поддерживаются.815816Возвращаемый SSL-сокет привязан к контексту, его настройкам и сертификатам. Параметры *server\_side*, *do\_handshake\_on\_connect* и *suppress\_ragged\_eofs* имеют тот же смысл, что и в функции верхнего уровня [`wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.wrap_socket).817818При клиентских подключениях необязательный параметр *server\_hostname* задаёт имя хоста службы, к которой выполняется подключение. Это позволяет одному серверу обслуживать несколько SSL-сервисов с разными сертификатами, по аналогии с HTTP-виртуальными хостами. Указание *server\_hostname* приведёт к возбуждению [`ValueError`](https://python-all.ru/3.4/library/exceptions.html#ValueError), если *server\_side* истинно.819820Изменено в версии 3.4.3: Всегда разрешается передавать server\_hostname, даже если OpenSSL не поддерживает SNI.821822#### `SSLContext.session_stats()`823824Получает статистику о сеансах SSL, созданных или управляемых этим контекстом. Возвращается словарь, который сопоставляет названия каждого [фрагмента информации](https://python-all.ru/3.4/library/ssl.html) с их числовыми значениями. Например, вот общее количество попаданий и промахов в кэше сеансов с момента создания контекста:825826```python827>>> stats = context.session_stats()828>>> stats['hits'], stats['misses']829(0, 0)830```831832#### `SSLContext.check_hostname`833834Определяет, следует ли сопоставлять имя хоста сертификата однорангового узла с помощью [`match_hostname()`](https://python-all.ru/3.4/library/ssl.html#ssl.match_hostname) в [`SSLSocket.do_handshake()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.do_handshake). Для этого [`verify_mode`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.verify_mode) контекста должен быть установлен в [`CERT_OPTIONAL`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_OPTIONAL) или [`CERT_REQUIRED`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_REQUIRED), и необходимо передать *server\_hostname* в [`wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.wrap_socket) для сопоставления имени хоста.835836Пример:837838```python839import socket, ssl840841context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)842context.verify_mode = ssl.CERT_REQUIRED843context.check_hostname = True844context.load_default_certs()845846s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)847ssl_sock = context.wrap_socket(s, server_hostname='www.verisign.com')848ssl_sock.connect(('www.verisign.com', 443))849```850851Новое в версии 3.4.852853> **Примечание**854>855> Эта возможность требует OpenSSL 0.9.8f или новее.856857#### `SSLContext.options`858859Целое число, представляющее набор SSL-опций, включённых в этом контексте. Значение по умолчанию – [`OP_ALL`](https://python-all.ru/3.4/library/ssl.html#ssl.OP_ALL), но можно задать другие опции, например [`OP_NO_SSLv2`](https://python-all.ru/3.4/library/ssl.html#ssl.OP_NO_SSLv2), объединяя их логическим ИЛИ.860861> **Примечание**862>863> В версиях OpenSSL старше 0.9.8m можно только устанавливать опции, но не сбрасывать их. Попытка сбросить опцию (путём сброса соответствующих битов) вызовет `ValueError`.864865#### `SSLContext.protocol`866867Версия протокола, выбранная при создании контекста. Этот атрибут доступен только для чтения.868869#### `SSLContext.verify_flags`870871Флаги операций проверки сертификатов. Можно устанавливать такие флаги, как [`VERIFY_CRL_CHECK_LEAF`](https://python-all.ru/3.4/library/ssl.html#ssl.VERIFY_CRL_CHECK_LEAF), объединяя их логическим ИЛИ. По умолчанию OpenSSL не требует и не проверяет списки отзыва сертификатов (CRL). Доступно только в openssl версии 0.9.8 и выше.872873Новое в версии 3.4.874875#### `SSLContext.verify_mode`876877Определяет, следует ли пытаться проверять сертификаты других одноранговых узлов и как себя вести при неудачной проверке. Этот атрибут должен быть одним из [`CERT_NONE`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_NONE), [`CERT_OPTIONAL`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_OPTIONAL) или [`CERT_REQUIRED`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_REQUIRED).878879## 18.2.4. Сертификаты880881Сертификаты в целом являются частью системы открытых и закрытых ключей. В этой системе каждому *субъекту* (которым может быть машина, человек или организация) присваивается уникальный двухчастный ключ шифрования. Одна часть ключа является открытой и называется *открытым ключом*; другая часть хранится в секрете и называется *закрытым ключом*. Две части связаны так, что если зашифровать сообщение одной частью, его можно расшифровать только другой частью, и **только** другой частью.882883Сертификат содержит информацию о двух субъектах. Он содержит имя *субъекта* и его открытый ключ. Также он содержит утверждение второго субъекта, *издателя*, о том, что субъект является тем, за кого себя выдаёт, и что это действительно открытый ключ субъекта. Утверждение издателя подписано закрытым ключом издателя, который известен только издателю. Однако любой может проверить утверждение издателя, найдя его открытый ключ, расшифровав им утверждение и сравнив его с другой информацией в сертификате. Сертификат также содержит информацию о периоде времени, в течение которого он действителен. Это выражается двумя полями, называемыми «notBefore» и «notAfter».884885При использовании сертификатов в Python клиент или сервер может использовать сертификат для подтверждения своей личности. Другая сторона сетевого соединения также может быть обязана предоставить сертификат, и этот сертификат может быть проверен к удовлетворению клиента или сервера, требующего такой проверки. Можно настроить попытку соединения так, чтобы она вызывала исключение, если проверка не удалась. Проверка выполняется автоматически базовым фреймворком OpenSSL; приложению не нужно вникать в её механику. Но приложению обычно необходимо предоставить наборы сертификатов, чтобы этот процесс мог происходить.886887Python uses files to contain certificates. They should be formatted as “PEM” (see [**RFC 1422**](https://python-all.ru/3.4/library/ssl.html)), which is a base-64 encoded form wrapped with a header line and a footer line:888889```python890-----BEGIN CERTIFICATE-----891... (certificate in base64 PEM encoding) ...892-----END CERTIFICATE-----893```894895### 18.2.4.1. Цепочки сертификатов896897The Python files which contain certificates can contain a sequence of certificates, sometimes called a *certificate chain*. This chain should start with the specific certificate for the principal who “is” the client or server, and then the certificate for the issuer of that certificate, and then the certificate for the issuer of *that* certificate, and so on up the chain till you get to a certificate which is *self-signed*, that is, a certificate which has the same subject and issuer, sometimes called a *root certificate*. The certificates should just be concatenated together in the certificate file. For example, suppose we had a three certificate chain, from our server certificate to the certificate of the certification authority that signed our server certificate, to the root certificate of the agency which issued the certification authority’s certificate:898899```python900-----BEGIN CERTIFICATE-----901... (certificate for your server)...902-----END CERTIFICATE-----903-----BEGIN CERTIFICATE-----904... (the certificate for the CA)...905-----END CERTIFICATE-----906-----BEGIN CERTIFICATE-----907... (the root certificate for the CA's issuer)...908-----END CERTIFICATE-----909```910911### 18.2.4.2. Сертификаты УЦ912913Если требуется проверка сертификата другой стороны соединения, необходимо предоставить файл «CA сертификаты», содержащий цепочки сертификатов для каждого центра сертификации, которому вы доверяете. Этот файл просто содержит эти цепочки, объединённые вместе. Для проверки Python будет использовать первую подходящую цепочку, найденную в файле. Файл сертификатов платформы можно использовать, вызвав [`SSLContext.load_default_certs()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.load_default_certs); это делается автоматически с помощью [`create_default_context()`](https://python-all.ru/3.4/library/ssl.html#ssl.create_default_context).914915### 18.2.4.3. Совмещённый ключ и сертификат916917Часто закрытый ключ хранится в том же файле, что и сертификат; в этом случае нужно передать только параметр `certfile` в [`SSLContext.load_cert_chain()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.load_cert_chain) и [`wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.wrap_socket). Если закрытый ключ хранится вместе с сертификатом, он должен располагаться перед первым сертификатом в цепочке сертификатов:918919```python920-----BEGIN RSA PRIVATE KEY-----921... (private key in base64 encoding) ...922-----END RSA PRIVATE KEY-----923-----BEGIN CERTIFICATE-----924... (certificate in base64 PEM encoding) ...925-----END CERTIFICATE-----926```927928### 18.2.4.4. Самоподписанные сертификаты929930Если планируется создать сервер, предоставляющий услуги SSL-защищённого соединения, потребуется приобрести сертификат для этой службы. Существует много способов получения подходящих сертификатов, например покупка в удостоверяющем центре. Ещё одна распространённая практика – сгенерировать самоподписанный сертификат. Самый простой способ сделать это – использовать пакет OpenSSL, примерно следующим образом:931932```python933% openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem934Generating a 1024 bit RSA private key935.......++++++936.............................++++++937writing new private key to 'cert.pem'938-----939You are about to be asked to enter information that will be incorporated940into your certificate request.941What you are about to enter is what is called a Distinguished Name or a DN.942There are quite a few fields but you can leave some blank943For some fields there will be a default value,944If you enter '.', the field will be left blank.945-----946Country Name (2 letter code) [AU]:US947State or Province Name (full name) [Some-State]:MyState948Locality Name (eg, city) []:Some City949Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Organization, Inc.950Organizational Unit Name (eg, section) []:My Group951Common Name (eg, YOUR name) []:myserver.mygroup.myorganization.com952Email Address []:ops@myserver.mygroup.myorganization.com953%954```955956Недостаток самоподписанного сертификата в том, что он является собственным корневым сертификатом, и никто другой не будет иметь его в своём кэше известных (и доверенных) корневых сертификатов.957958## 18.2.5. Примеры959960### 18.2.5.1. Проверка поддержки SSL961962Чтобы проверить наличие поддержки SSL в установке Python, в пользовательском коде следует использовать следующую идиому:963964```python965try:966 import ssl967except ImportError:968 pass969else:970 ... # сделать что-то, что требует поддержки SSL971```972973### 18.2.5.2. Работа на стороне клиента974975Этот пример создаёт контекст SSL с рекомендуемыми настройками безопасности для клиентских сокетов, включая автоматическую проверку сертификатов:976977```python978>>> context = ssl.create_default_context()979```980981Если вы предпочитаете настраивать параметры безопасности самостоятельно, можно создать контекст с нуля (но имейте в виду, что настройки могут оказаться неверными):982983```python984>>> context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)985>>> context.verify_mode = ssl.CERT_REQUIRED986>>> context.check_hostname = True987>>> context.load_verify_locations("/etc/ssl/certs/ca-bundle.crt")988```989990(предполагается, что ваша операционная система размещает набор всех сертификатов ЦС в `/etc/ssl/certs/ca-bundle.crt`; если это не так, вы получите ошибку и должны будете указать правильное расположение)991992При использовании контекста для подключения к серверу [`CERT_REQUIRED`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_REQUIRED) проверяет сертификат сервера: он гарантирует, что сертификат сервера был подписан одним из сертификатов ЦС, и проверяет корректность подписи:993994```python995>>> conn = context.wrap_socket(socket.socket(socket.AF_INET),996... server_hostname="www.python.org")997>>> conn.connect(("www.python.org", 443))998```9991000Затем можно получить сертификат:10011002```python1003>>> cert = conn.getpeercert()1004```10051006Визуальная проверка показывает, что сертификат действительно идентифицирует нужный сервис (то есть HTTPS-хост `www.python.org`):10071008```python1009>>> pprint.pprint(cert)1010{'OCSP': ('http://ocsp.digicert.com',),1011 'caIssuers': ('http://cacerts.digicert.com/DigiCertSHA2ExtendedValidationServerCA.crt',),1012 'crlDistributionPoints': ('http://crl3.digicert.com/sha2-ev-server-g1.crl',1013 'http://crl4.digicert.com/sha2-ev-server-g1.crl'),1014 'issuer': ((('countryName', 'US'),),1015 (('organizationName', 'DigiCert Inc'),),1016 (('organizationalUnitName', 'www.digicert.com'),),1017 (('commonName', 'DigiCert SHA2 Extended Validation Server CA'),)),1018 'notAfter': 'Sep 9 12:00:00 2016 GMT',1019 'notBefore': 'Sep 5 00:00:00 2014 GMT',1020 'serialNumber': '01BB6F00122B177F36CAB49CEA8B6B26',1021 'subject': ((('businessCategory', 'Private Organization'),),1022 (('1.3.6.1.4.1.311.60.2.1.3', 'US'),),1023 (('1.3.6.1.4.1.311.60.2.1.2', 'Delaware'),),1024 (('serialNumber', '3359300'),),1025 (('streetAddress', '16 Allen Rd'),),1026 (('postalCode', '03894-4801'),),1027 (('countryName', 'US'),),1028 (('stateOrProvinceName', 'NH'),),1029 (('localityName', 'Wolfeboro,'),),1030 (('organizationName', 'Python Software Foundation'),),1031 (('commonName', 'www.python.org'),)),1032 'subjectAltName': (('DNS', 'www.python.org'),1033 ('DNS', 'python.org'),1034 ('DNS', 'pypi.python.org'),1035 ('DNS', 'docs.python.org'),1036 ('DNS', 'testpypi.python.org'),1037 ('DNS', 'bugs.python.org'),1038 ('DNS', 'wiki.python.org'),1039 ('DNS', 'hg.python.org'),1040 ('DNS', 'mail.python.org'),1041 ('DNS', 'packaging.python.org'),1042 ('DNS', 'pythonhosted.org'),1043 ('DNS', 'www.pythonhosted.org'),1044 ('DNS', 'test.pythonhosted.org'),1045 ('DNS', 'us.pycon.org'),1046 ('DNS', 'id.python.org')),1047 'version': 3}1048```10491050Теперь, когда SSL-канал установлен и сертификат проверен, можно продолжить обмен данными с сервером:10511052```python1053>>> conn.sendall(b"HEAD / HTTP/1.0\r\nHost: linuxfr.org\r\n\r\n")1054>>> pprint.pprint(conn.recv(1024).split(b"\r\n"))1055[b'HTTP/1.1 200 OK',1056 b'Date: Sat, 18 Oct 2014 18:27:20 GMT',1057 b'Server: nginx',1058 b'Content-Type: text/html; charset=utf-8',1059 b'X-Frame-Options: SAMEORIGIN',1060 b'Content-Length: 45679',1061 b'Accept-Ranges: bytes',1062 b'Via: 1.1 varnish',1063 b'Age: 2188',1064 b'X-Served-By: cache-lcy1134-LCY',1065 b'X-Cache: HIT',1066 b'X-Cache-Hits: 11',1067 b'Vary: Cookie',1068 b'Strict-Transport-Security: max-age=63072000; includeSubDomains',1069 b'Connection: close',1070 b'',1071 b'']1072```10731074См. обсуждение [*соображений безопасности*](https://python-all.ru/3.4/library/ssl.html#ssl-security) ниже.10751076### 18.2.5.3. Работа на стороне сервера10771078Для работы сервера обычно нужен сертификат сервера и закрытый ключ, каждый в отдельном файле. Сначала создаётся контекст, содержащий ключ и сертификат, чтобы клиенты могли проверить вашу подлинность. Затем открывается сокет, привязывается к порту, вызывается `listen()`, и начинается ожидание подключения клиентов:10791080```python1081import socket, ssl10821083context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)1084context.load_cert_chain(certfile="mycertfile", keyfile="mykeyfile")10851086bindsocket = socket.socket()1087bindsocket.bind(('myaddr.mydomain.com', 10023))1088bindsocket.listen(5)1089```10901091Когда клиент подключается, вызывается `accept()` на сокете, чтобы получить новый сокет от другой стороны, и используется метод контекста [`SSLContext.wrap_socket()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.wrap_socket) для создания серверного SSL-сокета для соединения:10921093```python1094while True:1095 newsocket, fromaddr = bindsocket.accept()1096 connstream = context.wrap_socket(newsocket, server_side=True)1097 try:1098 deal_with_client(connstream)1099 finally:1100 connstream.shutdown(socket.SHUT_RDWR)1101 connstream.close()1102```11031104Затем считываются данные из `connstream` и выполняется с ними какая-то работа, пока не завершится взаимодействие с клиентом (или клиент с вами):11051106```python1107def deal_with_client(connstream):1108 data = connstream.recv(1024)1109 # пустые данные означают, что клиент закончил работу с нами1110 while data:1111 if not do_something(connstream, data):1112 # будем считать, что do_something возвращает False1113 # когда мы закончили с клиентом1114 break1115 data = connstream.recv(1024)1116 # закончили с клиентом1117```11181119И возврат к ожиданию новых клиентских подключений (конечно, настоящий сервер, вероятно, обрабатывал бы каждое клиентское соединение в отдельном потоке или переводил сокеты в неблокирующий режим и использовал цикл событий).11201121## 18.2.6. Замечания о неблокирующих сокетах11221123SSL-сокеты ведут себя несколько иначе, чем обычные сокеты в неблокирующем режиме. При работе с неблокирующими сокетами необходимо учитывать несколько моментов:11241125- Большинство методов [`SSLSocket`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket) вызовут [`SSLWantWriteError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLWantWriteError) или [`SSLWantReadError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLWantReadError) вместо [`BlockingIOError`](https://python-all.ru/3.4/library/exceptions.html#BlockingIOError), если операция ввода-вывода заблокируется. [`SSLWantReadError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLWantReadError) будет возникать, если необходимо выполнить чтение из нижележащего сокета, а [`SSLWantWriteError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLWantWriteError) – для записи в нижележащий сокет. Обратите внимание, что попытки *записи* в SSL-сокет могут потребовать сначала *чтения* из нижележащего сокета, а попытки *чтения* из SSL-сокета могут потребовать предварительной *записи* в нижележащий сокет.1126- Вызов [`select()`](https://python-all.ru/3.4/library/select.html#select.select) сообщает, что сокет на уровне ОС можно читать (или писать), но это не означает, что на верхнем уровне SSL имеется достаточно данных. Например, может прийти только часть SSL-фрейма. Поэтому необходимо быть готовым обработать ошибки `SSLSocket.recv()` и `SSLSocket.send()` и повторить попытку после очередного вызова [`select()`](https://python-all.ru/3.4/library/select.html#select.select).1127- И наоборот, поскольку у SSL есть собственное обрамление, SSL-сокет может всё ещё иметь данные для чтения, даже если [`select()`](https://python-all.ru/3.4/library/select.html#select.select) об этом не знает. Поэтому сначала следует вызвать `SSLSocket.recv()`, чтобы забрать все потенциально доступные данные, и только затем, если всё ещё необходимо, блокироваться на вызове [`select()`](https://python-all.ru/3.4/library/select.html#select.select).11281129 (конечно, аналогичные положения применяются при использовании других примитивов, таких как [`poll()`](https://python-all.ru/3.4/library/select.html#select.poll), или тех, что в модуле [`selectors`](https://python-all.ru/3.4/library/selectors.html#module-selectors))1130- Само рукопожатие SSL будет неблокирующим: метод [`SSLSocket.do_handshake()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.do_handshake) нужно повторять до успешного завершения. Вот краткий пример с использованием [`select()`](https://python-all.ru/3.4/library/select.html#select.select) для ожидания готовности сокета:11311132 ```python1133 while True:1134 try:1135 sock.do_handshake()1136 break1137 except ssl.SSLWantReadError:1138 select.select([sock], [], [])1139 except ssl.SSLWantWriteError:1140 select.select([], [sock], [])1141 ```11421143> **См. также**1144>1145> Модуль [`asyncio`](https://python-all.ru/3.4/library/asyncio.html#module-asyncio) поддерживает неблокирующие SSL-сокеты и предоставляет API более высокого уровня. Он опрашивает события с помощью модуля [`selectors`](https://python-all.ru/3.4/library/selectors.html#module-selectors) и обрабатывает исключения [`SSLWantWriteError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLWantWriteError), [`SSLWantReadError`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLWantReadError) и [`BlockingIOError`](https://python-all.ru/3.4/library/exceptions.html#BlockingIOError). Он также асинхронно выполняет SSL-рукопожатие.11461147## 18.2.7. Рекомендации по безопасности11481149### 18.2.7.1. Наилучшие настройки по умолчанию11501151Для использования **клиентом**, если нет особых требований к политике безопасности, настоятельно рекомендуется использовать функцию [`create_default_context()`](https://python-all.ru/3.4/library/ssl.html#ssl.create_default_context) для создания SSL-контекста. Она загрузит доверенные сертификаты ЦС системы, включит проверку сертификата и имени хоста, а также постарается выбрать достаточно безопасные протоколы и шифры.11521153Например, вот как можно использовать класс [`smtplib.SMTP`](https://python-all.ru/3.4/library/smtplib.html#smtplib.SMTP) для создания доверенного безопасного соединения с SMTP-сервером:11541155```python1156>>> import ssl, smtplib1157>>> smtp = smtplib.SMTP("mail.python.org", port=587)1158>>> context = ssl.create_default_context()1159>>> smtp.starttls(context=context)1160(220, b'2.0.0 Ready to start TLS')1161```11621163Если для соединения требуется клиентский сертификат, его можно добавить с помощью [`SSLContext.load_cert_chain()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.load_cert_chain).11641165Напротив, если создавать SSL-контекст вызовом конструктора [`SSLContext`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext) самостоятельно, в нём по умолчанию не будет включена ни проверка сертификата, ни проверка имени хоста. Если вы так делаете, пожалуйста, прочтите следующие абзацы, чтобы достичь хорошего уровня безопасности.11661167### 18.2.7.2. Ручная настройка11681169#### 18.2.7.2.1. Проверка сертификатов11701171При прямом вызове конструктора [`SSLContext`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext) значением по умолчанию является [`CERT_NONE`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_NONE). Поскольку он не аутентифицирует другую сторону, это может быть небезопасно, особенно в клиентском режиме, где чаще всего нужно убедиться в подлинности сервера, с которым идёт общение. Поэтому в клиентском режиме настоятельно рекомендуется использовать [`CERT_REQUIRED`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_REQUIRED). Однако одного этого недостаточно; необходимо также проверить, что сертификат сервера, который можно получить вызовом [`SSLSocket.getpeercert()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLSocket.getpeercert), соответствует нужному сервису. Для многих протоколов и приложений сервис можно идентифицировать по имени хоста; в этом случае можно использовать функцию [`match_hostname()`](https://python-all.ru/3.4/library/ssl.html#ssl.match_hostname). Эта обычная проверка выполняется автоматически, когда включено [`SSLContext.check_hostname`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.check_hostname).11721173В серверном режиме, если требуется аутентифицировать клиентов с помощью SSL-слоя (а не через механизм аутентификации более высокого уровня), также нужно указать [`CERT_REQUIRED`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_REQUIRED) и аналогично проверять клиентский сертификат.11741175> > **Примечание**1176> >1177> > В клиентском режиме [`CERT_OPTIONAL`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_OPTIONAL) и [`CERT_REQUIRED`](https://python-all.ru/3.4/library/ssl.html#ssl.CERT_REQUIRED) эквивалентны, если не включены анонимные шифры (по умолчанию они отключены).11781179#### 18.2.7.2.2. Версии протоколов11801181Версии SSL 2 и 3 считаются небезопасными, поэтому их использование опасно. Если нужна максимальная совместимость между клиентами и серверами, рекомендуется использовать [`PROTOCOL_SSLv23`](https://python-all.ru/3.4/library/ssl.html#ssl.PROTOCOL_SSLv23) в качестве версии протокола, а затем явно отключить SSLv2 и SSLv3 с помощью атрибута [`SSLContext.options`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.options):11821183```python1184context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)1185context.options |= ssl.OP_NO_SSLv21186context.options |= ssl.OP_NO_SSLv31187```11881189Созданный выше SSL-контекст будет разрешать только соединения TLSv1 и выше (если поддерживается вашей системой).11901191#### 18.2.7.2.3. Выбор шифров11921193Если есть повышенные требования к безопасности, можно точно настроить шифры, разрешённые при согласовании SSL-сеанса, через метод [`SSLContext.set_ciphers()`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext.set_ciphers). Начиная с Python 3.2.3, модуль ssl отключает некоторые слабые шифры по умолчанию, но может потребоваться дополнительно ограничить выбор шифров. Обязательно прочтите документацию OpenSSL о [формате списка шифров](https://python-all.ru/3.4/library/ssl.html). Чтобы узнать, какие шифры разрешены заданным списком, используйте команду `openssl ciphers` в вашей системе.11941195### 18.2.7.3. Многопроцессность11961197Если этот модуль используется в составе многопроцессного приложения (например, с модулями [`multiprocessing`](https://python-all.ru/3.4/library/multiprocessing.html#module-multiprocessing) или [`concurrent.futures`](https://python-all.ru/3.4/library/concurrent.futures.html#module-concurrent.futures)), следует учитывать, что внутренний генератор случайных чисел OpenSSL некорректно обрабатывает порождённые процессы. Приложения должны изменять состояние PRNG родительского процесса, если они используют любые функции SSL с [`os.fork()`](https://python-all.ru/3.4/library/os.html#os.fork). Любой успешный вызов [`RAND_add()`](https://python-all.ru/3.4/library/ssl.html#ssl.RAND_add), [`RAND_bytes()`](https://python-all.ru/3.4/library/ssl.html#ssl.RAND_bytes) или [`RAND_pseudo_bytes()`](https://python-all.ru/3.4/library/ssl.html#ssl.RAND_pseudo_bytes) считается достаточным.11981199> **См. также**1200>1201> **Класс [`socket.socket`](https://python-all.ru/3.4/library/socket.html#socket.socket)**1202>1203> Документация базового класса1204>1205> [`socket`](https://python-all.ru/3.4/library/socket.html#module-socket)1206>1207> **[SSL/TLS: надёжное шифрование. Введение](https://python-all.ru/3.4/library/ssl.html)**1208>1209> Введение из документации веб-сервера Apache1210>1211> **[RFC 1422: Privacy Enhancement for Internet Electronic Mail: Part II: Certificate-Based Key Management](https://python-all.ru/3.4/library/ssl.html)**1212>1213> Steve Kent1214>1215> **[RFC 1750: Randomness Recommendations for Security](https://python-all.ru/3.4/library/ssl.html)**1216>1217> D. Eastlake et. al.1218>1219> **[RFC 3280: Internet X.509 Public Key Infrastructure Certificate and CRL Profile](https://python-all.ru/3.4/library/ssl.html)**1220>1221> Housley et. al.1222>1223> **[RFC 4366: Расширения безопасности транспортного уровня (TLS)](https://python-all.ru/3.4/library/ssl.html)**1224>1225> Blake-Wilson et. al.1226>1227> **[RFC 5246: Протокол безопасности транспортного уровня (TLS) версии 1.2](https://python-all.ru/3.4/library/ssl.html)**1228>1229> T. Dierks et. al.1230>1231> **[RFC 6066: Расширения безопасности транспортного уровня (TLS)](https://python-all.ru/3.4/library/ssl.html)**1232>1233> D. Eastlake1234>1235> **[IANA TLS: Параметры безопасности транспортного уровня (TLS)](https://python-all.ru/3.4/library/ssl.html)**1236>1237> IANA1238