18.2. ssl – обёртка TLS/SSL для сокетов
Исходный код: Lib/ssl.py
Этот модуль предоставляет доступ к шифрованию и проверке подлинности партнёров (peer authentication) для сетевых сокетов с использованием протокола Transport Layer Security (часто называемого «Secure Sockets Layer»), как на стороне клиента, так и на стороне сервера. Модуль использует библиотеку 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.
18.2.1. Функции, константы и исключения
-
exception
ssl.SSLError¶ Возникает при ошибке в нижележащей реализации SSL (в настоящее время предоставляемой библиотекой OpenSSL). Это указывает на проблему в высокоуровневом уровне шифрования и аутентификации, который наложен на нижележащее сетевое соединение. Эта ошибка является подтипом
OSError. Код ошибки и сообщение экземпляровSSLErrorпредоставляются библиотекой OpenSSL.Изменено в версии 3.3:
SSLErrorраньше был подтипомsocket.error.-
library¶ Строковое мнемоническое обозначение подмодуля OpenSSL, в котором произошла ошибка, например
SSL,PEMилиX509. Набор возможных значений зависит от версии OpenSSL.Новое в версии 3.3.
-
reason¶ Строковое мнемоническое обозначение причины этой ошибки, например
CERTIFICATE_VERIFY_FAILED. Набор возможных значений зависит от версии OpenSSL.Новое в версии 3.3.
-
-
exception
ssl.SSLZeroReturnError¶ Подкласс
SSLError, возникающий при попытке чтения или записи, когда SSL-соединение было корректно закрыто. Обратите внимание, что это не означает, что нижележащий транспорт (например, TCP) был закрыт.Новое в версии 3.3.
-
exception
ssl.SSLWantReadError¶ Подкласс
SSLError, возбуждаемый неблокирующим SSL-сокетом при попытке чтения или записи данных, но до выполнения запроса необходимо получить больше данных по нижележащему TCP-транспорту.Новое в версии 3.3.
-
exception
ssl.SSLWantWriteError¶ Подкласс
SSLError, возбуждаемый неблокирующим SSL-сокетом при попытке чтения или записи данных, но до выполнения запроса необходимо отправить больше данных по нижележащему TCP-транспорту.Новое в версии 3.3.
-
exception
ssl.SSLSyscallError¶ Подкласс
SSLError, возникающий при обнаружении системной ошибки при попытке выполнить операцию с SSL-сокетом. К сожалению, нет простого способа узнать исходный номер errno.Новое в версии 3.3.
-
exception
ssl.SSLEOFError¶ Подкласс
SSLError, возникающий при внезапном разрыве SSL-соединения. Как правило, при возникновении этой ошибки не следует пытаться повторно использовать нижележащий транспорт.Новое в версии 3.3.
-
exception
ssl.CertificateError¶ Возбуждается при ошибке с сертификатом (например, несовпадение имени хоста). Однако ошибки сертификата, обнаруженные OpenSSL, вызывают
SSLError.
18.2.1.1. Создание сокета
Следующая функция позволяет создавать автономные сокеты. Начиная с Python 3.2, может быть более гибким использовать SSLContext.wrap_socket().
-
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)¶ Принимает экземпляр
sockклассаsocket.socketи возвращает экземплярssl.SSLSocket, подтипsocket.socket, который оборачивает базовый сокет в контекст SSL.sockдолжен быть сокетомSOCK_STREAM; другие типы сокетов не поддерживаются.Для клиентских сокетов построение контекста является ленивым; если базовый сокет ещё не подключён, построение контекста будет выполнено после вызова
connect()на сокете. Для серверных сокетов, если сокет не имеет удалённого узла, предполагается, что это прослушивающий сокет, и серверная SSL-обёртка автоматически выполняется для клиентских подключений, принятых через методaccept().wrap_socket()может вызватьSSLError.Параметры
keyfileиcertfileзадают необязательные файлы, содержащие сертификат, используемый для идентификации локальной стороны соединения. См. обсуждение в разделе Сертификаты для получения дополнительной информации о том, как сертификат хранится вcertfile.Параметр
server_side– логическое значение, определяющее, требуется ли от этого сокета поведение сервера или клиента.Параметр
cert_reqsопределяет, требуется ли сертификат от другой стороны соединения и будет ли он проверен, если предоставлен. Он должен быть одним из трёх значений:CERT_NONE(сертификаты игнорируются),CERT_OPTIONAL(не требуется, но проверяется, если предоставлен) илиCERT_REQUIRED(требуется и проверяется). Если значение этого параметра не равноCERT_NONE, то параметрca_certsдолжен указывать на файл сертификатов ЦС.Файл
ca_certsсодержит набор объединённых сертификатов «центров сертификации», которые используются для проверки сертификатов, поступивших с другого конца соединения. См. обсуждение в разделе Сертификаты для получения дополнительной информации о размещении сертификатов в этом файле.Параметр
ssl_versionуказывает, какую версию протокола SSL использовать. Обычно сервер выбирает определённую версию протокола, а клиент должен адаптироваться к выбору сервера. Большинство версий несовместимы друг с другом. Если не указано, по умолчанию используетсяPROTOCOL_TLS, который обеспечивает наибольшую совместимость с другими версиями.Ниже приведена таблица, показывающая, какие версии на стороне клиента (по левой стороне) могут подключаться к каким версиям на стороне сервера (по верхней стороне):
Сноски
- 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.
Примечание
Какие соединения будут успешными, зависит от версии OpenSSL. Например, до OpenSSL 1.0.0 клиент SSLv23 всегда пытался установить SSLv2-соединения.
Параметр ciphers задаёт доступные шифры для данного SSL-объекта. Это должна быть строка в формате списка шифров OpenSSL.
Параметр
do_handshake_on_connectуказывает, следует ли выполнять SSL-рукопожатие автоматически послеsocket.connect(), или же приложение будет вызывать его явно с помощью методаSSLSocket.do_handshake(). Явный вызовSSLSocket.do_handshake()даёт программе контроль над блокирующим поведением ввода-вывода сокета, участвующего в рукопожатии.Параметр
suppress_ragged_eofsопределяет, как методSSLSocket.recv()должен сигнализировать о неожиданном EOF с другого конца соединения. Если указаноTrue(по умолчанию), он возвращает обычный EOF (пустой объект bytes) в ответ на ошибки неожиданного EOF, возникающие от базового сокета; еслиFalse, он передаёт исключения обратно вызывающему.Изменено в версии 3.2: Новый необязательный аргумент ciphers.
18.2.1.2. Создание контекста
Удобная функция помогает создавать объекты SSLContext для общих целей.
-
ssl.create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None, capath=None, cadata=None)¶ Возвращает новый объект
SSLContextс настройками по умолчанию для заданного назначения. Настройки выбираются модулемsslи обычно представляют более высокий уровень безопасности, чем при прямом вызове конструктораSSLContext.cafile, capath, cadata представляют необязательные сертификаты ЦС для доверия при проверке сертификатов, как в
SSLContext.load_verify_locations(). Если все три равныNone, эта функция может вместо этого доверять системным сертификатам ЦС по умолчанию.Настройки:
PROTOCOL_TLS,OP_NO_SSLv2иOP_NO_SSLv3с высокозащищёнными наборами шифров без RC4 и без неаутентифицированных наборов шифров. ПередачаSERVER_AUTHв качестве purpose устанавливаетverify_modeвCERT_REQUIREDи либо загружает сертификаты ЦС (когда задан хотя бы один из cafile, capath или cadata), либо используетSSLContext.load_default_certs()для загрузки сертификатов ЦС по умолчанию.Примечание
Протокол, параметры, шифры и другие настройки могут в любое время измениться на более строгие значения без предварительного уведомления об устаревании. Эти значения представляют собой разумный баланс между совместимостью и безопасностью.
Если вашему приложению требуются определённые настройки, вам следует создать
SSLContextи применить настройки самостоятельно.Примечание
Если вы обнаружите, что при попытке определённых старых клиентов или серверов подключиться с
SSLContext, созданным этой функцией, возникает ошибка «Несовпадение протокола или набора шифров», возможно, они поддерживают только SSL 3.0, который эта функция исключает с помощьюOP_NO_SSLv3. SSL 3.0 широко считается полностью взломанным. Если вы всё же хотите продолжать использовать эту функцию, но разрешить подключения SSL 3.0, вы можете снова включить их, используя:pythonctx = ssl.create_default_context(Purpose.CLIENT_AUTH) ctx.options &= ~ssl.OP_NO_SSLv3Новое в версии 3.4.
Изменено в версии 3.4.4: RC4 был удалён из строки шифров по умолчанию.
Изменено в версии 3.6: ChaCha20/Poly1305 был добавлен в строку шифров по умолчанию.
3DES был удалён из строки шифров по умолчанию.
18.2.1.3. Генерация случайных чисел
-
ssl.RAND_bytes(num)¶ Возвращает num криптостойких псевдослучайных байт. Возбуждает исключение
SSLError, если ГПСЧ не был инициализирован достаточным количеством энтропии или если операция не поддерживается текущим методом RAND.RAND_status()можно использовать для проверки состояния ГПСЧ, аRAND_add()– для его инициализации.Для большинства приложений предпочтительнее
os.urandom().Прочитайте статью в Википедии «Криптографически стойкий генератор псевдослучайных чисел (CSPRNG)», чтобы узнать требования к криптографическому генератору.
Новое в версии 3.3.
-
ssl.RAND_pseudo_bytes(num)¶ Возвращает (bytes, is_cryptographic): bytes – это num псевдослучайных байтов, is_cryptographic равно
True, если сгенерированные байты криптографически стойкие. ВозбуждаетSSLError, если операция не поддерживается текущим методом RAND.Сгенерированные последовательности псевдослучайных байтов будут уникальными, если они имеют достаточную длину, но не обязательно непредсказуемыми. Их можно использовать для некриптографических целей и для некоторых целей в криптографических протоколах, но обычно не для генерации ключей и т.д.
Для большинства приложений предпочтительнее
os.urandom().Новое в версии 3.3.
Устарело с версии 3.6: OpenSSL объявил устаревшим
ssl.RAND_pseudo_bytes(), используйтеssl.RAND_bytes()вместо этого.
-
ssl.RAND_status()¶ Возвращает
True, если генератор псевдослучайных чисел SSL был инициализирован достаточной случайностью, иFalseв противном случае. Можно использоватьssl.RAND_egd()иssl.RAND_add()для увеличения случайности генератора псевдослучайных чисел.
-
ssl.RAND_egd(путь)¶ Если вы запустили где-то демон сбора энтропии (EGD) и path – это путь к сокетному соединению с ним, то будет прочитано 256 байт случайности из сокета и добавлено в генератор псевдослучайных чисел SSL для повышения безопасности создаваемых секретных ключей. Обычно это требуется только в системах, не имеющих лучших источников случайности.
Смотрите http://egd.sourceforge.net/ или http://prngd.sourceforge.net/ для получения исходных кодов демонов сбора энтропии.
Доступность: недоступно в LibreSSL и OpenSSL > 1.1.0
-
ssl.RAND_add(bytes, entropy)¶ Mix the given bytes into the SSL pseudo-random number generator. The parameter entropy (a float) is a lower bound on the entropy contained in string (so you can always use
0.0). See RFC 1750 for more information on sources of entropy.Изменено в версии 3.5: Теперь принимается записываемый байтоподобный объект.
18.2.1.4. Обработка сертификатов
-
ssl.match_hostname(cert, hostname)¶ Проверяет, что cert (в декодированном формате, возвращаемом
SSLSocket.getpeercert()) соответствует заданному hostname. Применяются правила проверки подлинности HTTPS-серверов, описанные в RFC 2818, RFC 5280 и RFC 6125. В дополнение к HTTPS эта функция подходит для проверки подлинности серверов в различных протоколах на основе SSL, таких как FTPS, IMAPS, POPS и других.CertificateErrorвозбуждается при ошибке. При успехе функция ничего не возвращает:python>>> cert = {'subject': ((('commonName', 'example.com'),),)} >>> ssl.match_hostname(cert, "example.com") >>> ssl.match_hostname(cert, "example.org") Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/py3k/Lib/ssl.py", line 130, in match_hostname ssl.CertificateError: hostname 'example.org' doesn't match 'example.com'Новое в версии 3.2.
Изменено в версии 3.3.3: Теперь функция следует RFC 6125, раздел 6.4.3, и не соответствует множественным шаблонам (например,
*.*.comили*a*.example.org), а также шаблону внутри фрагмента интернационализированного доменного имени (IDN). IDN A-метки, такие какwww*.xn--pthon-kva.org, по-прежнему поддерживаются, ноx*.python.orgбольше не соответствуетxn--tda.python.org.Изменено в версии 3.5: Теперь поддерживается сопоставление IP-адресов, если они присутствуют в поле subjectAltName сертификата.
-
ssl.cert_time_to_seconds(cert_time)¶ Возвращает время в секундах с начала эпохи (Epoch) для строки
cert_time, представляющей дату «notBefore» или «notAfter» из сертификата в формате strptime"%b %d %H:%M:%S %Y %Z"(локаль C).Пример:
pycon3>>> 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” or “notAfter” dates must use GMT (RFC 5280).
Изменено в версии 3.5: Входное время теперь интерпретируется как время в UTC, как указано часовым поясом «GMT» во входной строке. Ранее использовался местный часовой пояс. Возвращает целое число (без долей секунды во входном формате).
-
ssl.get_server_certificate(addr, ssl_version=PROTOCOL_TLS, ca_certs=None)¶ По заданному адресу
addrSSL-защищённого сервера в виде пары (имя_хоста, порт) получает сертификат сервера и возвращает его в виде строки в формате PEM. Если указанssl_version, используется указанная версия протокола SSL для попытки подключения к серверу. Если указанca_certs, это должен быть файл, содержащий список корневых сертификатов, в том же формате, что используется для того же параметра в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()¶ Returns a named tuple with paths to OpenSSL’s default cafile and capath. The paths are the same as used by
SSLContext.set_default_verify_paths(). The return value is a named tupleDefaultVerifyPaths:cafile– полный путь к cafile илиNone, если файл не существует,capath– полный путь к capath илиNone, если каталог не существует,openssl_cafile_env– переменная окружения OpenSSL, указывающая на cafile,openssl_cafile– жёстко заданный путь к 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. Параметр trust задаёт назначение сертификата в виде набора OID или ровноTrue, если сертификат является доверенным для всех целей.Пример:
python>>> 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.
18.2.1.5. Константы
Все константы теперь являются коллекциями
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. В этом режиме проверяется только сертификат однорангового узла, но ни один из промежуточных сертификатов ЦС. Режим требует действительный 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¶ Псевдоним для data: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. Эта опция установлена по умолчанию. Она не обязательно устанавливает те же флаги, что и константа
SSL_OP_ALLв OpenSSL.Новое в версии 3.2.
-
ssl.OP_NO_SSLv2¶ Предотвращает соединение SSLv2. Этот параметр применим только в сочетании с
PROTOCOL_TLS. Он не позволяет сторонам выбирать SSLv2 в качестве версии протокола.Новое в версии 3.2.
Устарело с версии 3.6: SSLv2 устарел
-
ssl.OP_NO_SSLv3¶ Предотвращает соединение по SSLv3. Этот параметр применим только вместе с
PROTOCOL_TLS. Он не позволяет пирам выбирать SSLv3 в качестве версии протокола.Новое в версии 3.2.
Устарело с версии 3.6: SSLv3 устарел
-
ssl.OP_NO_TLSv1¶ Предотвращает соединение по TLSv1. Этот параметр применим только вместе с
PROTOCOL_TLS. Он не позволяет пирам выбирать TLSv1 в качестве версии протокола.Новое в версии 3.2.
-
ssl.OP_NO_TLSv1_1¶ Предотвращает соединение по TLSv1.1. Этот параметр применим только вместе с
PROTOCOL_TLS. Он не позволяет пирам выбирать TLSv1.1 в качестве версии протокола. Доступно только в openssl версии 1.0.1+.Новое в версии 3.4.
-
ssl.OP_NO_TLSv1_2¶ Предотвращает соединение по TLSv1.2. Этот параметр применим только вместе с
PROTOCOL_TLS. Он не позволяет пирам выбирать TLSv1.2 в качестве версии протокола. Доступно только в openssl версии 1.0.1+.Новое в версии 3.4.
-
ssl.OP_NO_TLSv1_3¶ Предотвращает соединение по TLSv1.3. Этот параметр применим только вместе с
PROTOCOL_TLS. Он не позволяет пирам выбирать TLSv1.3 в качестве версии протокола. TLS 1.3 доступен в OpenSSL 1.1.1 и новее. Если Python скомпилирован с более старой версией OpenSSL, флаг по умолчанию равен 0.Новое в версии 3.6.3.
-
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.6.7.
-
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_ECDH¶ Определяет, имеет ли библиотека OpenSSL встроенную поддержку обмена ключами Диффи-Хеллмана на основе эллиптических кривых. Должно быть истинно, если только эта возможность не была явно отключена дистрибьютором.
Новое в версии 3.3.
-
ssl.HAS_SNI¶ Указывает, имеет ли библиотека OpenSSL встроенную поддержку расширения Server Name Indication (определённого в RFC 6066).
Новое в версии 3.2.
-
ssl.HAS_NPN¶ Определяет, имеет ли библиотека OpenSSL встроенную поддержку согласования следующего протокола, как описано в черновике спецификации NPN. Если истинно, вы можете использовать метод
SSLContext.set_npn_protocols()для объявления протоколов, которые вы хотите поддерживать.Новое в версии 3.3.
-
ssl.HAS_TLSv1_3¶ Указывает, имеет ли библиотека OpenSSL встроенную поддержку протокола TLS 1.3.
Новое в версии 3.6.3.
-
ssl.CHANNEL_BINDING_TYPES¶ Список поддерживаемых типов привязки каналов TLS. Строки из этого списка могут использоваться как аргументы для
SSLSocket.get_channel_binding().Новое в версии 3.3.
-
ssl.OPENSSL_VERSION¶ Строка версии библиотеки OpenSSL, загруженной интерпретатором:
python>>> ssl.OPENSSL_VERSION 'OpenSSL 1.0.2k 26 Jan 2017'Новое в версии 3.2.
-
ssl.OPENSSL_VERSION_INFO¶ Кортеж из пяти целых чисел, представляющий информацию о версии библиотеки OpenSSL:
python>>> ssl.OPENSSL_VERSION_INFO (1, 0, 2, 11, 15)Новое в версии 3.2.
-
ssl.OPENSSL_VERSION_NUMBER¶ Сырой номер версии библиотеки OpenSSL в виде одного целого числа:
python>>> ssl.OPENSSL_VERSION_NUMBER 268443839 >>> hex(ssl.OPENSSL_VERSION_NUMBER) '0x100020bf'Новое в версии 3.2.
-
ssl.ALERT_DESCRIPTION_HANDSHAKE_FAILURE¶ -
ssl.ALERT_DESCRIPTION_INTERNAL_ERROR¶ -
ALERT_DESCRIPTION_* Описания оповещений из RFC 5246 и других источников. Реестр оповещений TLS IANA TLS Alert Registry содержит этот список и ссылки на RFC, где определено их значение.
Используется как возвращаемое значение колбэка в
SSLContext.set_servername_callback().Новое в версии 3.4.
-
class
ssl.AlertDescription¶ enum.IntEnum– коллекция констант ALERT_DESCRIPTION_*.Новое в версии 3.6.
-
Purpose.SERVER_AUTH¶ Опция для
create_default_context()иSSLContext.load_default_certs(). Это значение указывает, что контекст может использоваться для аутентификации веб-серверов (следовательно, он будет использоваться для создания клиентских сокетов).Новое в версии 3.4.
-
Purpose.CLIENT_AUTH¶ Опция для
create_default_context()иSSLContext.load_default_certs(). Это значение указывает, что контекст может использоваться для аутентификации веб-клиентов (поэтому он будет использоваться для создания серверных сокетов).Новое в версии 3.4.
-
class
ssl.SSLErrorNumber¶ enum.IntEnum– коллекция констант SSL_ERROR_*.Новое в версии 3.6.
18.2.2. SSL-сокеты
-
class
ssl.SSLSocket(socket.socket)¶ SSL сокеты предоставляют следующие методы объектов сокетов:
recv(),recv_into()(но передача ненулевого аргументаflagsне допускается)sendfile()(ноos.sendfileбудет использоваться только для сокетов открытого текста, иначе будет использоватьсяsend())
Однако, поскольку протокол SSL (и TLS) имеет свою собственную структуру кадров поверх TCP, абстракция SSL-сокетов в некоторых аспектах может отличаться от спецификации обычных сокетов уровня ОС. См. особенно примечания о неблокирующих сокетах.
Обычно
SSLSocketне создаются напрямую, а с помощью методаSSLContext.wrap_socket().Изменено в версии 3.5: Метод
sendfile()был добавлен.Изменено в версии 3.5:
shutdown()больше не сбрасывает тайм-аут сокета каждый раз, когда байты получаются или отправляются. Тайм-аут сокета теперь указывает на максимальную общую продолжительность завершения соединения.Устарело с версии 3.6: Создавать экземпляр
SSLSocketнапрямую устарело; используйтеSSLContext.wrap_socket()для обёртывания сокета.
SSL-сокеты также имеют следующие дополнительные методы и атрибуты:
-
SSLSocket.read(len=1024, buffer=None)¶ Читает до len байт данных из SSL-сокета и возвращает результат в виде экземпляра
bytes. Если указан buffer, то читает в буфер и возвращает количество прочитанных байтов.Вызывает исключение
SSLWantReadErrorилиSSLWantWriteError, если сокет неблокирующий и чтение привело бы к блокировке.Так как в любой момент возможна повторная аутентификация (re-negotiation), вызов
read()может также инициировать операции записи.Изменено в версии 3.5: Тайм-аут сокета больше не сбрасывается каждый раз при получении или отправке байтов. Тайм-аут сокета теперь указывает на максимальную общую продолжительность чтения до len байт.
Устарело с версии 3.6: Используйте
recv()вместоread().
-
SSLSocket.write(buf)¶ Записывает buf в SSL-сокет и возвращает количество записанных байт. Аргумент buf должен быть объектом, поддерживающим буферный интерфейс.
Вызывает
SSLWantReadErrorилиSSLWantWriteError, если сокет неблокирующий и запись будет заблокирована.Поскольку повторное согласование возможно в любой момент, вызов
write()может также вызывать операции чтения.Изменено в версии 3.5: Тайм-аут сокета больше не сбрасывается каждый раз при получении или отправке байтов. Тайм-аут сокета теперь указывает на максимальную общую продолжительность записи buf.
Устарело с версии 3.6: Используйте
send()вместоwrite().
Примечание
Методы read() и write() являются низкоуровневыми методами, которые читают и записывают незашифрованные данные прикладного уровня и расшифровывают/шифруют их в зашифрованные данные уровня передачи. Эти методы требуют активного SSL-соединения, т.е. рукопожатие выполнено и SSLSocket.unwrap() не вызывался.
Обычно вместо этих методов следует использовать методы сокетного API, такие как recv() и send().
-
SSLSocket.do_handshake()¶ Выполняет рукопожатие настройки SSL.
Изменено в версии 3.4: Метод рукопожатия также выполняет
match_hostname(), когда атрибутcheck_hostnameобъектаcontextсокета равен true.Изменено в версии 3.5: Тайм-аут сокета больше не сбрасывается каждый раз при получении или отправке байтов. Тайм-аут сокета теперь указывает на максимальную общую продолжительность рукопожатия.
-
SSLSocket.getpeercert(binary_form=False)¶ Если для удаленной стороны на другом конце соединения нет сертификата, возвращает
None. Если рукопожатие SSL еще не выполнено, вызываетValueError.Если параметр
binary_formравенFalseи от удаленной стороны был получен сертификат, этот метод возвращает экземплярdict. Если сертификат не был проверен, словарь пуст. Если сертификат был проверен, возвращается словарь с несколькими ключами, среди которыхsubject(субъект, на который выдан сертификат) иissuer(субъект, выпустивший сертификат). Если сертификат содержит экземпляр расширения Subject Alternative Name (см. RFC 3280), в словаре также будет ключsubjectAltName.Поля
subjectиissuerпредставляют собой кортежи, содержащие последовательность относительных отличительных имен (RDN) в структуре данных сертификата для соответствующих полей, и каждый RDN представляет собой последовательность пар имя-значение. Вот пример из реального мира:python{'issuer': ((('countryName', 'IL'),), (('organizationName', 'StartCom Ltd.'),), (('organizationalUnitName', 'Secure Digital Certificate Signing'),), (('commonName', 'StartCom Class 2 Primary Intermediate Server CA'),)), 'notAfter': 'Nov 22 08:15:19 2013 GMT', 'notBefore': 'Nov 21 03:09:52 2011 GMT', 'serialNumber': '95F0', 'subject': ((('description', '571208-SLe257oHY9fVQ07Z'),), (('countryName', 'US'),), (('stateOrProvinceName', 'California'),), (('localityName', 'San Francisco'),), (('organizationName', 'Electronic Frontier Foundation, Inc.'),), (('commonName', '*.eff.org'),), (('emailAddress', 'hostmaster@eff.org'),)), 'subjectAltName': (('DNS', '*.eff.org'), ('DNS', 'eff.org')), 'version': 3}Примечание
Чтобы проверить сертификат для конкретного сервиса, можно использовать функцию
match_hostname().Если параметр
binary_formравенTrueи сертификат был предоставлен, этот метод возвращает DER-кодированную форму всего сертификата в виде последовательности байтов илиNone, если удаленная сторона не предоставила сертификата. Предоставляет ли удаленная сторона сертификат, зависит от роли SSL-сокета:для клиентского SSL-сокета сервер всегда предоставляет сертификат, независимо от того, требовалась ли проверка;
для серверного SSL-сокета клиент предоставляет сертификат только по запросу сервера; следовательно,
getpeercert()вернетNone, если вы использовалиCERT_NONE(а неCERT_OPTIONALилиCERT_REQUIRED).
Изменено в версии 3.2: Возвращаемый словарь включает дополнительные элементы, такие как
issuerиnotBefore.Изменено в версии 3.4:
ValueErrorвызывается, когда рукопожатие не выполнено. Возвращаемый словарь включает дополнительные элементы расширений X509v3, такие какcrlDistributionPoints,caIssuersиOCSPURI.
-
SSLSocket.cipher()¶ Возвращает кортеж из трех значений, содержащий имя используемого шифра, версию протокола SSL, которая определяет его использование, и количество используемых секретных битов. Если соединение не было установлено, возвращает
None.
Возвращает список шифров, переданных клиентом во время рукопожатия. Каждый элемент возвращённого списка – это кортеж из трёх значений, содержащий имя шифра, версию протокола SSL, определяющую его использование, и количество битов секретного ключа, используемых шифром.
shared_ciphers()возвращаетNone, если соединение не установлено или сокет является клиентским сокетом.Новое в версии 3.5.
-
SSLSocket.compression()¶ Возвращает используемый алгоритм сжатия в виде строки или
None, если соединение не сжато.Если протокол более высокого уровня поддерживает собственный механизм сжатия, можно использовать
OP_NO_COMPRESSIONдля отключения сжатия на уровне SSL.Новое в версии 3.3.
-
SSLSocket.get_channel_binding(cb_type="tls-unique")¶ Возвращает данные привязки канала для текущего соединения в виде объекта bytes. Возвращает
None, если соединение не установлено или рукопожатие не завершено.The cb_type parameter allow selection of the desired channel binding type. Valid channel binding types are listed in the
CHANNEL_BINDING_TYPESlist. Currently only the ‘tls-unique’ channel binding, defined by RFC 5929, is supported.ValueErrorwill be raised if an unsupported channel binding type is requested.Новое в версии 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.Новое в версии 3.6.7.
Примечание
Доступно только при наличии OpenSSL 1.1.1 и включённом TLS 1.3. Без поддержки TLS 1.3 метод возбуждает
NotImplementedError.
-
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.
-
SSLSocket.session¶ SSLSessionдля этого SSL-соединения. Сессия доступна для сокетов на стороне клиента и сервера после выполнения рукопожатия TLS. Для клиентских сокетов сессию можно установить до вызоваdo_handshake(), чтобы повторно использовать сессию.Новое в версии 3.6.
-
SSLSocket.session_reused¶ Новое в версии 3.6.
18.2.3. Контексты SSL
Новое в версии 3.2.
SSL-контекст хранит различные данные, время жизни которых больше, чем у отдельных SSL-соединений, такие как параметры SSL-конфигурации, сертификаты и закрытые ключи. Он также управляет кэшем SSL-сессий для сокетов на стороне сервера, чтобы ускорить повторные соединения от одних и тех же клиентов.
-
class
ssl.SSLContext(protocol=PROTOCOL_TLS)¶ Создаёт новый контекст SSL. Вы можете передать протокол, который должен быть одной из констант
PROTOCOL_*, определённых в этом модуле. В настоящее время для максимальной совместимости рекомендуетсяPROTOCOL_TLS, и оно является значением по умолчанию.Смотрите также
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-сертификатом и одним обычным сертификатом:
python>>> context.cert_store_stats() {'crl': 0, 'x509_ca': 1, 'x509': 2}Новое в версии 3.4.
-
SSLContext.load_cert_chain(certfile, keyfile=None, password=None)¶ Загружает закрытый ключ и соответствующий сертификат. Строка certfile должна быть путём к единственному файлу в формате PEM, содержащему сертификат, а также любое количество сертификатов ЦС, необходимых для подтверждения подлинности сертификата. Строка keyfile, если указана, должна указывать на файл, содержащий закрытый ключ. В противном случае закрытый ключ также будет взят из certfile. См. обсуждение Certificates для получения дополнительной информации о том, как сертификат хранится в certfile.
Аргумент password может быть функцией, вызываемой для получения пароля для расшифровки закрытого ключа. Она будет вызвана только в том случае, если закрытый ключ зашифрован и требуется пароль. Функция вызывается без аргументов и должна возвращать строку, bytes или bytearray. Если возвращаемое значение – строка, она будет закодирована в UTF-8 перед использованием для расшифровки ключа. В качестве аргумента password можно также передать непосредственно строку, bytes или bytearray. Этот аргумент будет проигнорирован, если закрытый ключ не зашифрован и пароль не требуется.
Если аргумент password не указан, а пароль требуется, будет использован встроенный механизм запроса пароля OpenSSL для интерактивного запроса пароля у пользователя.
Возникает
SSLError, если закрытый ключ не соответствует сертификату.Изменено в версии 3.3: Новый опциональный аргумент password.
-
SSLContext.load_default_certs(purpose=Purpose.SERVER_AUTH)¶ Загружает набор стандартных сертификатов «удостоверяющего центра» (ЦС) из расположений по умолчанию. В Windows загружает сертификаты ЦС из системных хранилищ
CAиROOT. В других системах вызываетSSLContext.set_default_verify_paths(). В будущем метод может также загружать сертификаты ЦС из других расположений.Флаг 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. Дополнительную информацию о том, как организовать сертификаты в этом файле, см. в обсуждении Certificates.
Строка capath, если указана, – это путь к каталогу, содержащему несколько CA-сертификатов в формате PEM, с организацией согласно специфической структуре OpenSSL.
Объект cadata, если указан, представляет собой либо ASCII-строку с одним или несколькими PEM-кодированными сертификатами, либо bytes-подобный объект с DER-кодированными сертификатами. Как и в случае с capath, лишние строки вокруг PEM-сертификатов игнорируются, но должен присутствовать хотя бы один сертификат.
Изменено в версии 3.4: Новый опциональный аргумент cadata.
-
SSLContext.get_ca_certs(binary_form=False)¶ Возвращает список загруженных сертификатов «удостоверяющего центра» (CA). Если параметр
binary_formравенFalse, каждый элемент списка представляет собой словарь, как в выводеSSLSocket.getpeercert(). В противном случае метод возвращает список DER-кодированных сертификатов. Возвращаемый список не содержит сертификаты из capath, если только сертификат не был запрошен и загружен через SSL-соединение.Примечание
Сертификаты в каталоге capath не загружаются, пока не будут использованы хотя бы один раз.
Новое в версии 3.4.
-
SSLContext.get_ciphers()¶ Возвращает список включённых шифров. Список отсортирован по приоритету шифров. См.
SSLContext.set_ciphers().Пример:
python>>> 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 и новее словарь шифров содержит дополнительные поля::
- text
>>> 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.Примечание
при подключении метод
SSLSocket.cipher()SSL-сокетов возвращает текущий выбранный шифр.В 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'], упорядоченных по предпочтению. Выбор протокола происходит во время рукопожатия и осуществляется в соответствии с черновиком спецификации NPN. После успешного рукопожатия методSSLSocket.selected_npn_protocol()вернёт согласованный протокол.Этот метод вызывает
NotImplementedError, еслиHAS_NPNравно False.Новое в версии 3.3.
-
SSLContext.set_servername_callback(server_name_callback)¶ Регистрирует функцию обратного вызова, которая будет вызвана после того, как сервер SSL/TLS получит сообщение рукопожатия TLS Client Hello, когда клиент TLS указывает указание имени сервера. Механизм указания имени сервера описан в RFC 6066, раздел 3 – Server Name Indication.
На один
SSLContextможно установить только один колбэк. Если server_name_callback равноNone, то колбэк отключается. Повторный вызов этой функции отключит ранее зарегистрированный колбэк.Функция обратного вызова server_name_callback будет вызвана с тремя аргументами: первый – это
ssl.SSLSocket, второй – строка, представляющая имя сервера, с которым клиент намерен установить связь (илиNone, если TLS Client Hello не содержит имени сервера), и третий аргумент – исходныйSSLContext. Аргумент имени сервера – это имя сервера, декодированное по IDNA.Типичное применение этого колбэка – изменить атрибут
SSLSocket.contextобъектаssl.SSLSocketна новый объект типаSSLContext, представляющий цепочку сертификатов, соответствующую имени сервера.Из-за ранней фазы согласования TLS-соединения доступны лишь ограниченные методы и атрибуты, такие как
SSLSocket.selected_alpn_protocol()иSSLSocket.context. МетодыSSLSocket.getpeercert(),SSLSocket.getpeercert(),SSLSocket.cipher()иSSLSocket.compress()требуют, чтобы TLS-соединение продвинулось дальше TLS Client Hello, и поэтому не будут возвращать осмысленных значений и не могут быть безопасно вызваны.Функция server_name_callback должна возвращать
None, чтобы продолжить согласование TLS. Если требуется ошибка TLS, можно вернуть константуALERT_DESCRIPTION_*. Другие возвращаемые значения приведут к фатальной ошибке TLS сALERT_DESCRIPTION_INTERNAL_ERROR.Если при декодировании IDNA имени сервера возникает ошибка, TLS-соединение завершится отправкой клиенту фатального предупреждающего сообщения TLS с кодом
ALERT_DESCRIPTION_INTERNAL_ERROR.Если из функции server_name_callback будет возбуждено исключение, TLS-соединение завершится фатальным предупреждающим сообщением TLS
ALERT_DESCRIPTION_HANDSHAKE_FAILURE.Этот метод вызовет
NotImplementedError, если библиотека OpenSSL была собрана с определённым OPENSSL_NO_TLSEXT.Новое в версии 3.4.
-
SSLContext.load_dh_params(dhfile)¶ Загружает параметры генерации ключей для обмена ключами Диффи-Хеллмана (DH). Использование обмена ключами DH повышает прямую секретность ценой вычислительных ресурсов (как на сервере, так и на клиенте). Параметр dhfile должен быть путём к файлу, содержащему параметры DH в формате PEM.
Этот параметр не применяется к клиентским сокетам. Для дальнейшего повышения безопасности можно также использовать опцию
OP_SINGLE_DH_USE.Новое в версии 3.3.
-
SSLContext.set_ecdh_curve(curve_name)¶ Устанавливает имя кривой для обмена ключами на основе эллиптических кривых (ECDH). ECDH значительно быстрее обычного DH, при этом, возможно, столь же безопасен. Параметр curve_name должен быть строкой, описывающей известную эллиптическую кривую, например
prime256v1для широко поддерживаемой кривой.Этот параметр не применяется к клиентским сокетам. Для дальнейшего повышения безопасности можно также использовать опцию
OP_SINGLE_ECDH_USE.Этот метод недоступен, если
HAS_ECDHравноFalse.Новое в версии 3.3.
Смотрите также
- SSL/TLS и совершенная прямая секретность
Vincent Bernat.
-
SSLContext.wrap_socket(sock, server_side=False, do_handshake_on_connect=True, suppress_ragged_eofs=True, server_hostname=None, session=None)¶ Оборачивает существующий сокет Python sock и возвращает объект
SSLSocket. Сокет sock должен быть сокетомSOCK_STREAM; другие типы сокетов не поддерживаются.Возвращаемый SSL-сокет привязан к контексту, его настройкам и сертификатам. Параметры server_side, do_handshake_on_connect и suppress_ragged_eofs имеют тот же смысл, что и в функции верхнего уровня
wrap_socket().При клиентских подключениях необязательный параметр server_hostname задаёт имя хоста службы, к которой выполняется подключение. Это позволяет одному серверу размещать несколько служб на основе SSL с различными сертификатами, примерно как виртуальные хосты HTTP. Указание server_hostname вызовет
ValueError, если server_side равно true.session, см.
session.Изменено в версии 3.5: Всегда разрешается передавать server_hostname, даже если OpenSSL не поддерживает SNI.
Изменено в версии 3.6: Добавлен аргумент session.
-
SSLContext.wrap_bio(incoming, outgoing, server_side=False, server_hostname=None, session=None)¶ Создаёт новый экземпляр
SSLObject, оборачивая BIO-объекты incoming и outgoing. Процедуры SSL будут читать входные данные из входящего BIO и записывать данные в исходящий BIO.Параметры server_side, server_hostname и session имеют тот же смысл, что и в
SSLContext.wrap_socket().Изменено в версии 3.6: Добавлен аргумент session.
-
SSLContext.session_stats()¶ Возвращает статистику по SSL-сессиям, созданным или управляемым этим контекстом. Возвращается словарь, который сопоставляет названия каждого элемента информации с их числовыми значениями. Например, вот общее количество попаданий и промахов в кеше сессий с момента создания контекста:
python>>> 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(), чтобы сопоставить имя хоста.Пример:
pythonimport socket, ssl context = ssl.SSLContext() context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = True context.load_default_certs() s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ssl_sock = context.wrap_socket(s, server_hostname='www.verisign.com') ssl_sock.connect(('www.verisign.com', 443))Новое в версии 3.4.
Примечание
Для этой функции требуется OpenSSL 0.9.8f или новее.
-
SSLContext.options¶ Целое число, представляющее набор опций SSL, включённых в этом контексте. Значение по умолчанию –
OP_ALL, но можно указать другие опции, такие какOP_NO_SSLv2, объединяя их через OR.Примечание
В версиях OpenSSL старше 0.9.8m можно только установить параметры, но не сбросить их. Попытка сбросить параметр (сбросив соответствующие биты) вызовет
ValueError.Изменено в версии 3.6:
SSLContext.optionsвозвращаетOptionsфлаги:text>>> ssl.create_default_context().options <Options.OP_ALL|OP_NO_SSLv3|OP_NO_SSLv2|OP_NO_COMPRESSION: 2197947391>
-
SSLContext.post_handshake_auth¶ Включает аутентификацию клиента после рукопожатия TLS 1.3. Аутентификация после рукопожатия по умолчанию отключена, и сервер может запрашивать сертификат клиента только во время начального рукопожатия. При включении сервер может запросить сертификат клиента в любое время после рукопожатия.
При включении на стороне клиента сокет клиента сообщает серверу, что он поддерживает аутентификацию после рукопожатия.
При включении на стороне сервера
SSLContext.verify_modeтакже должен быть установлен вCERT_OPTIONALилиCERT_REQUIRED. Фактический обмен сертификатом клиента откладывается до вызоваSSLSocket.verify_client_post_handshake()и выполнения некоторого ввода-вывода.Новое в версии 3.6.7.
Примечание
Доступно только с OpenSSL 1.1.1 и включённым TLS 1.3. Без поддержки TLS 1.3 значение свойства равно None и не может быть изменено.
-
SSLContext.protocol¶ Версия протокола, выбранная при создании контекста. Этот атрибут доступен только для чтения.
-
SSLContext.verify_flags¶ Флаги операций проверки сертификатов. Вы можете установить флаги, например
VERIFY_CRL_CHECK_LEAF, скомбинировав их через OR. По умолчанию OpenSSL не требует и не проверяет списки отзыва сертификатов (CRL). Доступно только с openssl version 0.9.8+.Новое в версии 3.4.
Изменено в версии 3.6:
SSLContext.verify_flagsвозвращаетVerifyFlagsфлаги:text>>> ssl.create_default_context().verify_flags <VerifyFlags.VERIFY_X509_TRUSTED_FIRST: 32768>
-
SSLContext.verify_mode¶ Определяет, следует ли пытаться проверять сертификаты других участников соединения и как вести себя при неудачной проверке. Этот атрибут должен быть одним из
CERT_NONE,CERT_OPTIONALилиCERT_REQUIRED.Изменено в версии 3.6:
SSLContext.verify_modeвозвращаетVerifyModeперечисление:text>>> ssl.create_default_context().verify_mode <VerifyMode.CERT_REQUIRED: 2>
18.2.4. Сертификаты
Сертификаты в целом являются частью системы с открытым и закрытым ключами. В этой системе каждому субъекту (которым может быть машина, человек или организация) назначается уникальный двухкомпонентный ключ шифрования. Одна часть ключа является открытой и называется открытым ключом; другая часть хранится в секрете и называется закрытым ключом. Эти две части связаны таким образом, что если зашифровать сообщение одной частью, то расшифровать его можно только другой частью, и только другой частью.
Сертификат содержит информацию о двух субъектах. Он содержит имя субъекта и его открытый ключ. Также он содержит заявление второго субъекта – издателя, о том, что субъект действительно тот, за кого себя выдает, и что это действительно его открытый ключ. Заявление издателя подписано закрытым ключом издателя, который известен только издателю. Однако любой может проверить заявление издателя, найдя его открытый ключ, расшифровав заявление с его помощью и сравнив с другой информацией в сертификате. Сертификат также содержит информацию о периоде действия, которая выражается двумя полями: “notBefore” и “notAfter”.
При использовании сертификатов в Python клиент или сервер могут использовать сертификат для подтверждения своей подлинности. Другая сторона сетевого соединения также может быть обязана предоставить сертификат, и этот сертификат может быть проверен с удовлетворением требований клиента или сервера, запрашивающего такую проверку. При попытке соединения можно настроить вызов исключения в случае неудачной проверки. Проверка выполняется автоматически встроенным фреймворком OpenSSL; приложению не нужно вникать в её механику. Однако приложение обычно должно предоставлять наборы сертификатов, чтобы этот процесс мог состояться.
Python использует файлы для хранения сертификатов. Они должны быть отформатированы как “PEM” (см. RFC 1422), что представляет собой форму кодирования base-64, заключенную между строкой заголовка и строкой нижнего колонтитула:
-----BEGIN CERTIFICATE-----
... (certificate in base64 PEM encoding) ...
-----END CERTIFICATE-----
18.2.4.1. Цепочки сертификатов
Файлы Python, содержащие сертификаты, могут содержать последовательность сертификатов, иногда называемую цепочкой сертификатов. Эта цепочка должна начинаться с сертификата субъекта, который является клиентом или сервером, затем сертификат издателя этого сертификата, затем сертификат издателя этого сертификата и так далее по цепочке, пока не будет достигнут сертификат, который является самоподписанным, то есть сертификат, у которого субъект и издатель совпадают, иногда называемый корневым сертификатом. Сертификаты должны быть просто объединены друг за другом в файле сертификатов. Например, предположим, у нас есть цепочка из трех сертификатов: от сертификата нашего сервера до сертификата удостоверяющего центра, подписавшего наш серверный сертификат, и до корневого сертификата агентства, выпустившего сертификат удостоверяющего центра:
-----BEGIN CERTIFICATE-----
... (certificate for your server)...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (the certificate for the CA)...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (the root certificate for the CA's issuer)...
-----END CERTIFICATE-----
18.2.4.2. Сертификаты УЦ
Для проверки сертификата другой стороны соединения необходимо предоставить файл “CA certs”, заполненный цепочками сертификатов для каждого издателя, которому вы готовы доверять. Опять же, этот файл просто содержит эти цепочки, объединенные вместе. Для проверки Python будет использовать первую найденную в файле подходящую цепочку. Файл сертификатов платформы можно использовать, вызвав SSLContext.load_default_certs(); это делается автоматически с помощью create_default_context().
18.2.4.3. Объединённые ключ и сертификат
Часто закрытый ключ хранится в том же файле, что и сертификат; в этом случае достаточно передать только параметр certfile в SSLContext.load_cert_chain() и wrap_socket(). Если закрытый ключ хранится вместе с сертификатом, он должен располагаться перед первым сертификатом в цепочке сертификатов:
-----BEGIN RSA PRIVATE KEY-----
... (private key in base64 encoding) ...
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
... (certificate in base64 PEM encoding) ...
-----END CERTIFICATE-----
18.2.4.4. Самоподписанные сертификаты
Если вы собираетесь создать сервер, предоставляющий услуги SSL-шифрованного соединения, вам потребуется получить сертификат для этой службы. Существует множество способов получения подходящих сертификатов, например, покупка у центра сертификации. Другой распространённой практикой является генерация самоподписанного сертификата. Самый простой способ сделать это – использовать пакет OpenSSL, например, следующим образом:
% openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem
Generating a 1024 bit RSA private key
.......++++++
.............................++++++
writing new private key to 'cert.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:MyState
Locality Name (eg, city) []:Some City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Organization, Inc.
Organizational Unit Name (eg, section) []:My Group
Common Name (eg, YOUR name) []:myserver.mygroup.myorganization.com
Email Address []:ops@myserver.mygroup.myorganization.com
%
Недостаток самоподписанного сертификата заключается в том, что он является собственным корневым сертификатом, и никто другой не будет иметь его в кэше известных (и доверенных) корневых сертификатов.
18.2.5. Примеры
18.2.5.1. Проверка поддержки SSL
Для проверки наличия поддержки SSL в установке Python пользовательский код должен использовать следующий идиоматический приём:
try:
import ssl
except ImportError:
pass
else:
... # выполнить действие, требующее поддержки SSL
18.2.5.2. Работа на стороне клиента
Этот пример создаёт контекст SSL с рекомендуемыми настройками безопасности для клиентских сокетов, включая автоматическую проверку сертификата:
>>> context = ssl.create_default_context()
Если вы предпочитаете настраивать параметры безопасности самостоятельно, вы можете создать контекст с нуля (но учтите, что вы можете не получить правильные настройки):
>>> context = ssl.SSLContext()
>>> context.verify_mode = ssl.CERT_REQUIRED
>>> context.check_hostname = True
>>> context.load_verify_locations("/etc/ssl/certs/ca-bundle.crt")
(этот фрагмент предполагает, что ваша операционная система помещает набор всех сертификатов ЦС в /etc/ssl/certs/ca-bundle.crt; если нет, вы получите ошибку и вам придётся изменить расположение)
При использовании контекста для подключения к серверу CERT_REQUIRED
проверяет сертификат сервера: он гарантирует, что сертификат сервера
был подписан одним из сертификатов УЦ, и проверяет корректность подписи:
>>> conn = context.wrap_socket(socket.socket(socket.AF_INET),
... server_hostname="www.python.org")
>>> conn.connect(("www.python.org", 443))
Затем вы можете получить сертификат:
>>> cert = conn.getpeercert()
Визуальный осмотр показывает, что сертификат действительно идентифицирует нужную службу (то есть HTTPS-хост www.python.org):
>>> pprint.pprint(cert)
{'OCSP': ('http://ocsp.digicert.com',),
'caIssuers': ('http://cacerts.digicert.com/DigiCertSHA2ExtendedValidationServerCA.crt',),
'crlDistributionPoints': ('http://crl3.digicert.com/sha2-ev-server-g1.crl',
'http://crl4.digicert.com/sha2-ev-server-g1.crl'),
'issuer': ((('countryName', 'US'),),
(('organizationName', 'DigiCert Inc'),),
(('organizationalUnitName', 'www.digicert.com'),),
(('commonName', 'DigiCert SHA2 Extended Validation Server CA'),)),
'notAfter': 'Sep 9 12:00:00 2016 GMT',
'notBefore': 'Sep 5 00:00:00 2014 GMT',
'serialNumber': '01BB6F00122B177F36CAB49CEA8B6B26',
'subject': ((('businessCategory', 'Private Organization'),),
(('1.3.6.1.4.1.311.60.2.1.3', 'US'),),
(('1.3.6.1.4.1.311.60.2.1.2', 'Delaware'),),
(('serialNumber', '3359300'),),
(('streetAddress', '16 Allen Rd'),),
(('postalCode', '03894-4801'),),
(('countryName', 'US'),),
(('stateOrProvinceName', 'NH'),),
(('localityName', 'Wolfeboro,'),),
(('organizationName', 'Python Software Foundation'),),
(('commonName', 'www.python.org'),)),
'subjectAltName': (('DNS', 'www.python.org'),
('DNS', 'python.org'),
('DNS', 'pypi.org'),
('DNS', 'docs.python.org'),
('DNS', 'testpypi.org'),
('DNS', 'bugs.python.org'),
('DNS', 'wiki.python.org'),
('DNS', 'hg.python.org'),
('DNS', 'mail.python.org'),
('DNS', 'packaging.python.org'),
('DNS', 'pythonhosted.org'),
('DNS', 'www.pythonhosted.org'),
('DNS', 'test.pythonhosted.org'),
('DNS', 'us.pycon.org'),
('DNS', 'id.python.org')),
'version': 3}
Теперь, когда SSL-канал установлен и сертификат проверен, вы можете продолжить общение с сервером:
>>> conn.sendall(b"HEAD / HTTP/1.0\r\nHost: linuxfr.org\r\n\r\n")
>>> pprint.pprint(conn.recv(1024).split(b"\r\n"))
[b'HTTP/1.1 200 OK',
b'Date: Sat, 18 Oct 2014 18:27:20 GMT',
b'Server: nginx',
b'Content-Type: text/html; charset=utf-8',
b'X-Frame-Options: SAMEORIGIN',
b'Content-Length: 45679',
b'Accept-Ranges: bytes',
b'Via: 1.1 varnish',
b'Age: 2188',
b'X-Served-By: cache-lcy1134-LCY',
b'X-Cache: HIT',
b'X-Cache-Hits: 11',
b'Vary: Cookie',
b'Strict-Transport-Security: max-age=63072000; includeSubDomains',
b'Connection: close',
b'',
b'']
Смотрите обсуждение Вопросов безопасности ниже.
18.2.5.3. Операция на стороне сервера
Для работы сервера обычно требуется иметь сертификат сервера и закрытый ключ, каждый в отдельном файле. Сначала вы создадите контекст, содержащий ключ и сертификат, чтобы клиенты могли проверить вашу подлинность. Затем вы откроете сокет, привяжете его к порту, вызовете на нём listen() и начнёте ожидать подключения клиентов:
import socket, ssl
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile="mycertfile", keyfile="mykeyfile")
bindsocket = socket.socket()
bindsocket.bind(('myaddr.mydomain.com', 10023))
bindsocket.listen(5)
Когда клиент подключается, вы вызовете accept() на сокете, чтобы получить новый сокет с другого конца, и используете метод контекста SSLContext.wrap_socket() для создания серверного SSL-сокета для подключения:
while True:
newsocket, fromaddr = bindsocket.accept()
connstream = context.wrap_socket(newsocket, server_side=True)
try:
deal_with_client(connstream)
finally:
connstream.shutdown(socket.SHUT_RDWR)
connstream.close()
Затем вы будете читать данные из connstream и что-то с ними делать, пока не закончите работу с клиентом (или клиент не закончит с вами):
def deal_with_client(connstream):
data = connstream.recv(1024)
# пустые данные означают, что клиент закончил работу с нами
while data:
if not do_something(connstream, data):
# будем считать, что do_something возвращает False
# когда мы закончили с клиентом
break
data = connstream.recv(1024)
# закончили с клиентом
И вернуться к прослушиванию новых клиентских подключений (конечно, настоящий сервер, вероятно, обрабатывал бы каждое клиентское подключение в отдельном потоке или переводил бы сокеты в неблокирующий режим и использовал цикл событий).
18.2.6. Замечания по неблокирующим сокетам
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()для ожидания готовности сокета:pythonwhile 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-рукопожатие асинхронно.
18.2.7. Поддержка Memory BIO
Новое в версии 3.5.
С момента появления модуля SSL в Python 2.6 класс SSLSocket предоставляет две связанные, но различные области функциональности:
Обработка протокола SSL
Сетевой ввод-вывод
API сетевого ввода-вывода идентичен тому, который предоставляется socket.socket, от которого также наследует SSLSocket. Это позволяет использовать SSL-сокет как прямую замену обычного сокета, что значительно упрощает добавление поддержки SSL в существующее приложение.
Объединение обработки протокола SSL и сетевого ввода-вывода обычно работает хорошо, но есть случаи, когда это не так. Примером являются асинхронные фреймворки ввода-вывода, которые хотят использовать другую модель мультиплексирования IO, отличную от модели «select/poll на файловом дескрипторе» (основанной на готовности), которая предполагается socket.socket и внутренними процедурами сокетного IO OpenSSL. Это в основном актуально для таких платформ, как Windows, где эта модель неэффективна. Для этой цели предоставляется вариант SSLSocket с ограниченной областью применения, называемый SSLObject.
-
class
ssl.SSLObject¶ Вариант
SSLSocketс ограниченной областью применения, представляющий экземпляр протокола SSL, который не содержит методов сетевого ввода-вывода. Этот класс обычно используется разработчиками фреймворков, которые хотят реализовать асинхронный ввод-вывод для SSL через буферы памяти.Этот класс реализует интерфейс поверх низкоуровневого SSL-объекта, реализованного OpenSSL. Этот объект хранит состояние SSL-соединения, но сам не предоставляет никакого сетевого ввода-вывода. Ввод-вывод должен выполняться через отдельные объекты «BIO», которые являются уровнем абстракции ввода-вывода OpenSSL.
Экземпляр
SSLObjectможно создать с помощью методаwrap_bio(). Этот метод создаст экземплярSSLObjectи привяжет его к паре BIO. Входящий BIO используется для передачи данных из Python в экземпляр протокола SSL, а исходящий BIO – для передачи данных в обратном направлении.Доступны следующие методы:
По сравнению с
SSLSocket, у этого объекта отсутствуют следующие возможности:Любая форма сетевого ввода-вывода;
recv()иsend()читают и записывают данные только в базовые буферыMemoryBIO.Отсутствует механизм do_handshake_on_connect. Необходимо всегда вручную вызывать
do_handshake(), чтобы начать рукопожатие.Отсутствует обработка suppress_ragged_eofs. Все ситуации конца файла, нарушающие протокол, сообщаются через исключение
SSLEOFError.Вызов метода
unwrap()ничего не возвращает, в отличие от SSL-сокета, где он возвращает базовый сокет.Колбэк server_name_callback, переданный в
SSLContext.set_servername_callback(), получит экземплярSSLObjectвместо экземпляраSSLSocketв качестве первого параметра.
Некоторые замечания, касающиеся использования
SSLObject:Весь ввод-вывод на
SSLObjectявляется неблокирующим. Это означает, что, например,read()вызовет исключениеSSLWantReadError, если ему потребуется больше данных, чем есть во входящем BIO.Не существует вызова
wrap_bio()на уровне модуля, как дляwrap_socket().SSLObjectвсегда создается черезSSLContext.
SSLObject взаимодействует с внешним миром, используя буферы памяти. Класс MemoryBIO предоставляет буфер памяти, который можно использовать для этой цели. Он оборачивает объект OpenSSL memory BIO (базовый ввод-вывод):
-
class
ssl.MemoryBIO¶ Буфер памяти, который можно использовать для передачи данных между Python и экземпляром протокола SSL.
-
pending¶ Возвращает количество байтов, находящихся в данный момент в буфере памяти.
-
eof¶ Логическое значение, указывающее, находится ли memory BIO в текущий момент в позиции конца файла.
-
read(n=-1)¶ Читает до n байтов из буфера памяти. Если n не указан или отрицателен, возвращаются все байты.
-
write(buf)¶ Записывает байты из buf в memory BIO. Аргумент buf должен быть объектом, поддерживающим буферный протокол.
Возвращаемое значение – количество записанных байтов, которое всегда равно длине buf.
-
18.2.8. Сессия SSL
Новое в версии 3.6.
18.2.9. Вопросы безопасности
18.2.9.1. Рекомендуемые настройки по умолчанию
Для использования на стороне клиента, если у вас нет особых требований к политике безопасности, настоятельно рекомендуется использовать функцию create_default_context() для создания SSL-контекста. Она загрузит доверенные сертификаты ЦС вашей системы, включит проверку сертификатов и имени хоста, а также попытается выбрать достаточно безопасные настройки протокола и шифров.
Например, вот как можно использовать класс smtplib.SMTP для создания доверенного безопасного соединения с SMTP-сервером:
>>> import ssl, smtplib
>>> smtp = smtplib.SMTP("mail.python.org", port=587)
>>> context = ssl.create_default_context()
>>> smtp.starttls(context=context)
(220, b'2.0.0 Ready to start TLS')
Если для соединения требуется клиентский сертификат, его можно добавить с помощью SSLContext.load_cert_chain().
Напротив, если вы создаёте SSL-контекст, вызывая конструктор SSLContext самостоятельно, по умолчанию в нём не будут включены проверка сертификатов и проверка имени хоста. Если вы так делаете, пожалуйста, прочитайте следующие абзацы, чтобы достичь хорошего уровня безопасности.
18.2.9.2. Ручные настройки
18.2.9.2.1. Проверка сертификатов
При прямом вызове конструктора SSLContext по умолчанию используется CERT_NONE. Поскольку он не аутентифицирует другую сторону, это может быть небезопасно, особенно в клиентском режиме, где в большинстве случаев требуется убедиться в подлинности сервера, с которым ведется обмен. Поэтому в клиентском режиме настоятельно рекомендуется использовать CERT_REQUIRED. Однако только этого недостаточно; необходимо также проверить, что сертификат сервера, который можно получить с помощью SSLSocket.getpeercert(), соответствует требуемой службе. Для многих протоколов и приложений службу можно идентифицировать по имени хоста; в этом случае можно использовать функцию match_hostname(). Эта проверка выполняется автоматически, если включено SSLContext.check_hostname.
В серверном режиме, если вы хотите аутентифицировать клиентов с помощью уровня SSL (а не использовать механизм аутентификации более высокого уровня), вам также придётся указать CERT_REQUIRED и аналогично проверить клиентский сертификат.
18.2.9.2.2. Версии протоколов
Версии 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
подразумевает проверку сертификата и проверку имени хоста по умолчанию. Необходимо загрузить сертификаты в контекст.
18.2.9.2.3. Выбор шифров
Если у вас повышенные требования к безопасности, тонкая настройка шифров, доступных при согласовании SSL-сессии, возможна через метод SSLContext.set_ciphers(). Начиная с Python 3.2.3 модуль ssl отключает некоторые слабые шифры по умолчанию, но вы можете дополнительно ограничить выбор шифров. Обязательно прочитайте документацию OpenSSL о формате списка шифров. Если вы хотите проверить, какие шифры включены для данного списка шифров, используйте SSLContext.get_ciphers() или команду openssl ciphers в вашей системе.
18.2.9.3. Многопроцессность
При использовании этого модуля в многопроцессном приложении (например, с модулями multiprocessing или concurrent.futures) следует учитывать, что внутренний генератор случайных чисел OpenSSL некорректно обрабатывает разветвленные процессы. Приложения должны изменить состояние PRNG родительского процесса, если они используют какие-либо функции SSL с os.fork(). Любого успешного вызова RAND_add(), RAND_bytes() или RAND_pseudo_bytes() достаточно.
18.2.10. Поддержка LibreSSL
LibreSSL – это форк OpenSSL 1.0.1. Модуль ssl имеет ограниченную поддержку LibreSSL. Некоторые функции недоступны, когда модуль ssl скомпилирован с LibreSSL.
LibreSSL >= 2.6.1 больше не поддерживает NPN. Методы
SSLContext.set_npn_protocols()иSSLSocket.selected_npn_protocol()недоступны.SSLContext.set_default_verify_paths()игнорирует переменные окруженияSSL_CERT_FILEиSSL_CERT_PATH, хотяget_default_verify_paths()по-прежнему сообщает о них.
Смотрите также
- Класс
socket.socket Документация базового класса
socket- SSL/TLS. Надёжное шифрование: введение
Введение из документации Apache HTTP Server
- RFC 1422: Усиление конфиденциальности для электронной почты в Интернете. Часть II: Управление ключами на основе сертификатов
Steve Kent
- RFC 4086: Требования к случайности для безопасности
Donald E., Jeffrey I. Schiller
- RFC 5280: Инфраструктура открытых ключей X.509. Профиль сертификата и списка отзыва сертификатов (CRL)
D. Cooper
- RFC 5246: Протокол безопасности транспортного уровня (TLS) версии 1.2
T. Dierks et. al.
- RFC 6066: Расширения безопасности транспортного уровня (TLS)
D. Eastlake
- IANA TLS: Параметры безопасности транспортного уровня (TLS)
IANA
- RFC 7525: Рекомендации по безопасному использованию безопасности транспортного уровня (TLS) и безопасности дейтаграмного транспортного уровня (DTLS)
IETF
- Рекомендации Mozilla по TLS на стороне сервера
Mozilla