Spec-Zone.ru › Python 3.5

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

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

Этот модуль предоставляет доступ к средствам шифрования 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().

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.

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; он обеспечивает наибольшую совместимость с другими версиями.

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

клиент / сервер SSLv2 SSLv3 TLS TLSv1 TLSv1.1 TLSv1.2
SSLv2 да нет да нет нет нет
SSLv3 нет да да нет нет нет
TLS (SSLv23) нет да да да да да
TLSv1 нет нет да да нет нет
TLSv1.1 нет нет да нет да нет
TLSv1.2 нет нет да нет нет да

Примечание

Какие соединения будут успешны, зависит от версии 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 (пустой байтовый объект) в ответ на неожиданные ошибки EOF, возникшие в базовом сокете; если False, он перебросит исключения вызывающей стороне.

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

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

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

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

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

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

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

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

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

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

1.3. Генерация случайных чисел

ssl.RAND_bytes(num)

Возвращает num криптографически стойких псевдослучайных байтов. Возбуждает исключение SSLError, если генератор псевдослучайных чисел (ПСПЧ) не был инициализирован достаточным количеством данных или если операция не поддерживается текущим методом RAND. RAND_status() может использоваться для проверки состояния ПСПЧ, а RAND_add() — для его инициализации.

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

Прочитайте статью в Википедии Cryptographically secure pseudorandom number generator (CSPRNG), чтобы узнать требования к криптографическому генератору.

Новая в версии 3.3.

ssl.RAND_pseudo_bytes(num)

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

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

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

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

ssl.RAND_status()

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

ssl.RAND_egd(path)

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

См. http://egd.sourceforge.net/ или http://prngd.sourceforge.net/ для получения источников демонов сбора энтропии.

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

ssl.RAND_add(bytes, entropy)

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

Изменено в версии 3.5: Теперь принимается объект-подобный байтам.

1.4. Обработка сертификатов

ssl.match_hostname(cert, hostname)

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

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

>>> 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, такие как www*.xn--pthon-kva.org , всё ещё поддерживаются, но x*.python.org больше не соответствует xn--tda.python.org.

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

ssl.cert_time_to_seconds(cert_time)

Возвращает время в секундах с начала эпохи, заданное строкой cert_time , представляющей дату «notBefore» или «notAfter» из сертификата в формате "%b %d %H:%M:%S %Y %Z" strptime (локаль C).

Вот пример:

>>> import ssl
>>> timestamp = ssl.cert_time_to_seconds("Jan  5 09:34:43 2018 GMT")
>>> timestamp
1515144883
>>> from datetime import datetime
>>> print(datetime.utcfromtimestamp(timestamp))
2018-01-05 09:34:43

Даты «notBefore» или «notAfter» должны использовать GMT (RFC 5280).

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

ssl.get_server_certificate(addr, ssl_version=PROTOCOL_TLS, ca_certs=None)

Принимая адрес addr защищённого SSL сервера, как пару (hostname, port-number), получает сертификат сервера и возвращает его в виде 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()

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

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

Доступность: 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 , если сертификат надёжен для всех целей.

Пример:

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

1.5. Константы

ssl.CERT_NONE

Возможная величина для SSLContext.verify_mode или параметра cert_reqs для wrap_socket(). В этом режиме (по умолчанию) сертификаты не требуются от другой стороны сокет-соединения. Если сертификат получен от другой стороны, попытка его валидации не предпринимается.

См. обсуждение Рекомендации по безопасности ниже.

ssl.CERT_OPTIONAL

Возможная величина для SSLContext.verify_mode или параметра cert_reqs для wrap_socket(). В этом режиме сертификаты не требуются от другой стороны сокет-соединения, но если они предоставлены, попытка их валидации будет предпринята, и при ошибке будет поднято исключение SSLError.

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

ssl.CERT_REQUIRED

Возможная величина для SSLContext.verify_mode или параметра cert_reqs для wrap_socket(). В этом режиме сертификаты требуются от другой стороны сокет-соединения; исключение SSLError будет поднято, если сертификат не предоставлен или его валидация завершится неудачно.

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

ssl.VERIFY_DEFAULT

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

Новая версия с 3.4.

ssl.VERIFY_CRL_CHECK_LEAF

Возможная величина для SSLContext.verify_flags. В этом режиме проверяется только сертификат участника, но не промежуточные сертификаты УЦ. Режим требует действительного CRL, подписанного эмитентом сертификата участника (его непосредственным предком УЦ). Если соответствующий 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.

ssl.PROTOCOL_TLS

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

Новая версия с 3.5.3.

ssl.PROTOCOL_SSLv23

Псевдоним для данных:PROTOCOL_TLS.

Устарело начиная с версии 3.5.3: Используйте данные:PROTOCOL_TLS вместо этого.

ssl.PROTOCOL_SSLv2

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

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

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

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

Устарело начиная с версии 3.5.3: OpenSSL удалил поддержку SSLv2.

ssl.PROTOCOL_SSLv3

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

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

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

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

Устарело начиная с версии 3.5.3: OpenSSL устарел все специфичные версии протоколов. Используйте протокол по умолчанию данных:PROTOCOL_TLS с флагами, например, данных:OP_NO_SSLv3 вместо этого.

ssl.PROTOCOL_TLSv1

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

Устарело начиная с версии 3.5.3: OpenSSL устарел все специфичные версии протоколов. Используйте протокол по умолчанию данных:PROTOCOL_TLS с флагами, например, данных:OP_NO_SSLv3 вместо этого.

ssl.PROTOCOL_TLSv1_1

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

Новая версия с 3.4.

Устарело начиная с версии 3.5.3: OpenSSL устарел все специфичные версии протоколов. Используйте протокол по умолчанию данных:PROTOCOL_TLS с флагами, например, данных:OP_NO_SSLv3 вместо этого.

ssl.PROTOCOL_TLSv1_2

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

Новая версия с 3.4.

Устарело начиная с версии 3.5.3: 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.5.3: SSLv2 устарел.

ssl.OP_NO_SSLv3

Препятствует подключению SSLv3. Этот параметр применим только совместно с PROTOCOL_TLS. Он не позволяет сторонам выбирать SSLv3 в качестве версии протокола.

Новая версия с 3.2.

Устарело начиная с версии 3.5.3: 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_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_NO_COMPRESSION

Отключает сжатие на канале SSL. Это полезно, если прикладной протокол поддерживает свою собственную схему сжатия.

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

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

ssl.HAS_ALPN

Поддерживает ли библиотека OpenSSL встроенную поддержку расширения TLS Application-Layer Protocol Negotiation, описанного в RFC 7301.

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

ssl.HAS_ECDH

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

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

ssl.HAS_SNI

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

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

ssl.HAS_NPN

Поддерживает ли библиотека OpenSSL встроенную поддержку Next Protocol Negotiation, как описано в спецификации черновика NPN. При true, вы можете использовать метод SSLContext.set_npn_protocols() для объявления поддерживаемых протоколов.

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

ssl.CHANNEL_BINDING_TYPES

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

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

ssl.OPENSSL_VERSION

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

>>> ssl.OPENSSL_VERSION
'OpenSSL 0.9.8k 25 Mar 2009'

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

ssl.OPENSSL_VERSION_INFO

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

>>> ssl.OPENSSL_VERSION_INFO
(0, 9, 8, 11, 15)

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

ssl.OPENSSL_VERSION_NUMBER

Числовая версия библиотеки OpenSSL, как целое число:

>>> ssl.OPENSSL_VERSION_NUMBER
9470143
>>> hex(ssl.OPENSSL_VERSION_NUMBER)
'0x9080bf'

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

ssl.ALERT_DESCRIPTION_HANDSHAKE_FAILURE
ssl.ALERT_DESCRIPTION_INTERNAL_ERROR
ALERT_DESCRIPTION_*

Описание предупреждений из RFC 5246 и других источников. Регистр предупреждений TLS IANA содержит этот список и ссылки на RFC, где определено их значение.

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

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

Purpose.SERVER_AUTH

Параметр для create_default_context() и SSLContext.load_default_certs(). Это значение указывает, что контекст может быть использован для аутентификации веб-серверов (следовательно, он будет использоваться для создания клиентских сокетов).

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

Purpose.CLIENT_AUTH

Параметр для create_default_context() и SSLContext.load_default_certs(). Это значение указывает, что контекст может быть использован для аутентификации веб-клиентов (следовательно, он будет использоваться для создания серверных сокетов).

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

2. SSL Сокеты

class ssl.SSLSocket(socket.socket)

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

  • accept()
  • bind()
  • close()
  • connect()
  • detach()
  • fileno()
  • getpeername(), getsockname()
  • getsockopt(), setsockopt()
  • gettimeout(), settimeout(), setblocking()
  • listen()
  • makefile()
  • recv(), recv_into() (но передача аргумента flags, отличного от нуля, запрещена)
  • send(), sendall() (с тем же ограничением)
  • sendfile() (но os.sendfile будет использоваться только для текстовых сокетов, иначе будет использоваться send())
  • shutdown()

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

Обычно SSLSocket не создаются напрямую, а с помощью функции wrap_socket() или метода SSLContext.wrap_socket().

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

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

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

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

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

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

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

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

SSLSocket.write(buf)

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

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

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

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

Примечание

Методы 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 представляют собой кортежи, содержащие последовательность относительных отличительных имён (RDNs), заданных в структуре данных сертификата для соответствующих полей, а каждое RDN — последовательность пар имя-значение. Вот пример из реальной жизни:

{'issuer': ((('countryName', 'IL'),),
            (('organizationName', 'StartCom Ltd.'),),
            (('organizationalUnitName',
              'Secure Digital Certificate Signing'),),
            (('commonName',
              'StartCom Class 2 Primary Intermediate Server CA'),)),
 'notAfter': 'Nov 22 08:15:19 2013 GMT',
 'notBefore': 'Nov 21 03:09:52 2011 GMT',
 'serialNumber': '95F0',
 'subject': ((('description', '571208-SLe257oHY9fVQ07Z'),),
             (('countryName', 'US'),),
             (('stateOrProvinceName', 'California'),),
             (('localityName', 'San Francisco'),),
             (('organizationName', 'Electronic Frontier Foundation, Inc.'),),
             (('commonName', '*.eff.org'),),
             (('emailAddress', 'hostmaster@eff.org'),)),
 'subjectAltName': (('DNS', '*.eff.org'), ('DNS', 'eff.org')),
 'version': 3}

Примечание

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

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

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

Изменено в версии 3.2: Возвращаемый словарь включает дополнительные элементы, такие как issuer и notBefore.

Изменено в версии 3.4: ValueError возникает, когда рукопожатие не завершено. Возвращаемый словарь включает дополнительные элементы расширений X509v3, такие как crlDistributionPoints, caIssuers и OCSP URI.

SSLSocket.cipher()

Возвращает кортеж из трёх значений: имя используемого шифра, версия протокола SSL, определяющая его использование, и количество секретных битов. Если соединение не установлено, возвращает None.

SSLSocket.shared_ciphers()

Возвращает список шифров, общих для клиента во время рукопожатия. Каждый элемент возвращаемого списка — кортеж из трёх значений: имя шифра, версия протокола SSL, определяющая его использование, и количество секретных битов шифра. shared_ciphers() возвращает None , если соединение не установлено или сокет является клиентским.

Новое в версии 3.5.

SSLSocket.compression()

Возвращает используемый алгоритм сжатия в виде строки или None , если сжатие не используется.

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

Новое в версии 3.3.

SSLSocket.get_channel_binding(cb_type="tls-unique")

Получает данные канала связи для текущего соединения в виде объекта bytes. Возвращает None , если соединение не установлено или рукопожатие не завершено.

Параметр cb_type позволяет выбрать нужный тип связи канала. Действительные типы связей канала перечислены в списке CHANNEL_BINDING_TYPES. В настоящее время поддерживается только тип связи канала «tls-unique», определённый в RFC 5929. Если запрошен неподдерживаемый тип связи канала, будет вызвано исключение ValueError.

Новое в версии 3.3.

SSLSocket.selected_alpn_protocol()

Возвращает протокол, выбранный во время рукопожатия TLS. Если SSLContext.set_alpn_protocols() не вызывался, если другая сторона не поддерживает ALPN, если этот сокет не поддерживает ни один из предложенных клиентом протоколов, или если рукопожатие ещё не произошло, возвращается None.

Новое в версии 3.5.

SSLSocket.selected_npn_protocol()

Возвращает протокол более высокого уровня, выбранный во время рукопожатия TLS/SSL. Если SSLContext.set_npn_protocols() не вызывался, или если другая сторона не поддерживает NPN, или если рукопожатие ещё не произошло, будет возвращено None.

Новое в версии 3.3.

SSLSocket.unwrap()

Выполняет рукопожатие закрытия SSL, удаляя слой TLS из базового сокета и возвращая объект базового сокета. Это можно использовать для перехода от шифрованного к нешифрованному режиму работы по соединению. Возвращённый сокет всегда должен использоваться для дальнейшего общения с другой стороной соединения, а не исходный сокет.

SSLSocket.version()

Возвращает фактическую версию протокола SSL, согласованную соединением, в виде строки, или None , если безопасное соединение не установлено. На момент написания возможные возвращаемые значения включают "SSLv2", "SSLv3", "TLSv1", "TLSv1.1" и "TLSv1.2" . Более поздние версии OpenSSL могут определять больше возвращаемых значений.

Новое в версии 3.5.

SSLSocket.pending()

Возвращает количество уже расшифрованных байтов, доступных для чтения, ожидающих соединения.

SSLSocket.context

Объект SSLContext, к которому привязан этот сокет SSL. Если сокет SSL был создан с помощью функции верхнего уровня wrap_socket() (а не SSLContext.wrap_socket()), это — специальный объект контекста, созданный для данного сокета SSL.

Новое в версии 3.2.

SSLSocket.server_side

Логическое значение, равное True для серверных сокетов и False для клиентских сокетов.

Новое в версии 3.2.

SSLSocket.server_hostname

Имя хоста сервера: тип str или None для серверного сокета или если имя хоста не было указано в конструкторе.

Новое в версии 3.2.

3. SSL Контексты

Новое в версии 3.2.

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

class ssl.SSLContext(protocol=PROTOCOL_TLS)

Создайте новый контекст SSL. Вы можете передать протокол, который должен быть одним из PROTOCOL_* констант, определённых в этом модуле. PROTOCOL_TLS в настоящее время рекомендуется для максимальной совместимости и является значением по умолчанию.

См. также

create_default_context() позволяет модулю ssl выбрать параметры безопасности для заданной цели.

Изменено в версии 3.5.3: PROTOCOL_TLS является значением по умолчанию.

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

SSLContext.cert_store_stats()

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

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

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

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

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

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

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

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

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

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

SSLContext.load_default_certs(purpose=Purpose.SERVER_AUTH)

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

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

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

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

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

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

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

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

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

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

SSLContext.get_ca_certs(binary_form=False)

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

Примечание

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

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

SSLContext.set_default_verify_paths()

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

SSLContext.set_ciphers(ciphers)

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

Примечание

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

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+ прервёт рукопожатие и поднимет исключение SSLError, когда обе стороны поддерживают ALPN, но не могут договориться о протоколе.

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

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

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

Функция обратного вызова server_name_callback будет вызвана с тремя аргументами: первым будет ssl.SSLSocket, вторым — строка, представляющая имя сервера, с которым клиент намеревается связаться (или None, если TLS Client Hello не содержит имя сервера), а третьим — исходный SSLContext. Аргумент имени сервера — декодированное имя сервера по IDNA.

Типичное использование этого обратного вызова — изменение атрибута ssl.SSLSocket’s SSLSocket.context на новый объект типа 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 & Perfect Forward Secrecy
Винсент Бернат.
SSLContext.wrap_socket(sock, server_side=False, do_handshake_on_connect=True, suppress_ragged_eofs=True, server_hostname=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.

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

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

Создаёт новый экземпляр SSLObject путём обёртки объектов BIO incoming и outgoing. SSL-процедуры будут читать входные данные из BIO incoming и записывать данные в BIO outgoing.

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

SSLContext.session_stats()

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

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

Определяет, нужно ли сопоставлять имя хоста серверного сертификата с match_hostname() в SSLSocket.do_handshake(). Атрибут verify_mode контекста должен быть установлен в CERT_OPTIONAL или CERT_REQUIRED, и вы должны передать server_hostname в wrap_socket() для сопоставления имени хоста.

Пример:

import socket, ssl

context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
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.

SSLContext.protocol

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

SSLContext.verify_flags

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

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

END_OF_DOCUMENT_MARKER
SSLContext.verify_mode

Требуется ли проверка сертификатов других участников и как вести себя при ошибке проверки. Это свойство должно быть одним из CERT_NONE, CERT_OPTIONAL или CERT_REQUIRED.

4. Сертификаты

В целом, сертификаты являются частью системы с открытым и закрытым ключами. В этой системе каждому субъекту (который может быть машиной, человеком или организацией) присваивается уникальный двухкомпонентный криптографический ключ. Одна часть ключа является открытой и называется открытым ключом; другая часть держится в секрете и называется закрытым ключом. Эти две части взаимосвязаны, так что если вы зашифруете сообщение одной из частей, вы сможете расшифровать его только другой частью.

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

В Python приложениях клиент или сервер могут использовать сертификат, чтобы доказать свою личность. От другой стороны сетевого соединения также может потребоваться представить сертификат, и этот сертификат может быть проверен клиентом или сервером, требующим такой проверки. В случае ошибки проверки попытка подключения может вызвать исключение. Проверка выполняется автоматически с помощью базового фреймворка OpenSSL; приложение не должно беспокоиться о её механизмах. Однако приложение обычно должно предоставить наборы сертификатов, чтобы этот процесс мог произойти.

Python использует файлы для хранения сертификатов. Они должны быть отформатированы как «PEM» (см. RFC 1422), что представляет собой форму, закодированную в base-64, обернутую заголовком и подвалом:

-----BEGIN CERTIFICATE-----
... (certificate in base64 PEM encoding) ...
-----END CERTIFICATE-----

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

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

Если вы собираетесь проверить сертификат другой стороны соединения, вам необходимо предоставить файл «CA certs», заполненный цепочками сертификатов каждого эмитента, которому вы доверяете. Опять же, этот файл просто содержит эти цепочки, соединённые вместе. Для проверки Python будет использовать первую цепочку в файле, которая соответствует условиям.

Файл сертификатов платформы можно использовать, вызвав SSLContext.load_default_certs(), это выполняется автоматически с помощью create_default_context().

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

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
%

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

5. Примеры

5.1. Проверка поддержки SSL

Для проверки наличия поддержки SSL в установке Python пользовательский код должен использовать следующий приём:

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

5.2. Операции со стороны клиента

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

>>> context = ssl.create_default_context()

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

>>> context = ssl.SSLContext(ssl.PROTOCOL_TLS)
>>> context.verify_mode = ssl.CERT_REQUIRED
>>> context.check_hostname = True
>>> context.load_verify_locations("/etc/ssl/certs/ca-bundle.crt")

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

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

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

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

>>> cert = conn.getpeercert()

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

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

См. обсуждение Рекомендации по безопасности ниже.

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)
    # empty data means the client is finished with us
    while data:
        if not do_something(connstream, data):
            # we'll assume do_something returns False
            # when we're finished with client
            break
        data = connstream.recv(1024)
    # finished with client

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

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-handshake будет неблокирующим: метод SSLSocket.do_handshake() необходимо повторять до тех пор, пока он не вернёт успех. Вот краткий обзор с использованием select() для ожидания готовности сокета:

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

См. также

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

7. Поддержка BIO с памятью

Введено в версии 3.5.

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

  • Обработка протокола SSL
  • Сеть IO

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

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

class ssl.SSLObject

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

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

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

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

  • context
  • server_side
  • server_hostname
  • read()
  • write()
  • getpeercert()
  • selected_npn_protocol()
  • cipher()
  • shared_ciphers()
  • compression()
  • pending()
  • do_handshake()
  • unwrap()
  • get_channel_binding()

По сравнению с SSLSocket, этому объекту не хватает следующих функций:

  • Любой формы сетевого ввода-вывода, включая методы, такие как recv() и send().
  • Нет механизма 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 предоставляет буфер памяти, который можно использовать для этой цели. Он оборачивает объект памяти BIO OpenSSL (Basic IO):

class ssl.MemoryBIO

Буфер памяти, который можно использовать для передачи данных между Python и экземпляром протокола SSL.

pending

Возвращает количество байтов, в настоящее время находящихся в буфере памяти.

eof

Булево значение, указывающее, находится ли память BIO в текущей позиции конца файла.

read(n=-1)

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

write(buf)

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

Значение возврата — количество записанных байтов, которое всегда равно длине buf.

write_eof()

Записывает маркер EOF в память BIO. После вызова этого метода вызов write() запрещен. Атрибут eof станет истинным после того, как все данные, в настоящее время находящиеся в буфере, будут считаны.

8. Рассмотрение безопасности

8.1. Лучшие значения по умолчанию

Для клиентского использования, если у вас нет особых требований к политике безопасности, настоятельно рекомендуется использовать функцию create_default_context() для создания контекста SSL. Она загрузит доверенные сертификаты CA системы, включит проверку сертификата и проверки имени хоста и попытается выбрать разумно безопасные настройки протокола и шифров.

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

8.2. Настройки вручную

8.2.1. Проверка сертификатов

При прямом вызове конструктора SSLContext, CERT_NONE является значением по умолчанию. Поскольку это не аутентифицирует другой узел, это может быть небезопасно, особенно в режиме клиента, где большинство времени вы хотите убедиться в подлинности сервера, с которым вы общаетесь. Поэтому, в режиме клиента, настоятельно рекомендуется использовать CERT_REQUIRED. Однако этого недостаточно; вам также необходимо проверить, что сертификат сервера, который можно получить, вызвав SSLSocket.getpeercert(), соответствует нужному сервису. Для многих протоколов и приложений сервис может быть идентифицирован по имени хоста; в этом случае может быть использована функция match_hostname(). Эта распространенная проверка автоматически выполняется при включении SSLContext.check_hostname.

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

Примечание

В режиме клиента, CERT_OPTIONAL и CERT_REQUIRED эквивалентны, если не включены анонимные шифры (они отключены по умолчанию).

8.2.2. Версии протоколов

Версии SSL 2 и 3 считаются небезопасными и поэтому их использование опасно. Если вам нужна максимальная совместимость между клиентами и серверами, рекомендуется использовать PROTOCOL_TLS в качестве версии протокола, а затем явно отключить SSLv2 и SSLv3, используя атрибут SSLContext.options:

context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.options |= ssl.OP_NO_SSLv2
context.options |= ssl.OP_NO_SSLv3
context.options |= ssl.OP_NO_TLSv1
context.options |= ssl.OP_NO_TLSv1_1

Созданный выше контекст SSL позволит использовать только соединения TLSv1.2 и более поздние версии (если они поддерживаются вашей системой).

8.2.3. Выбор шифров

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

8.3. Многопроцессорность

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

См. также

Class socket.socket
Документация базового класса socket
SSL/TLS Strong Encryption: An Introduction
Вступление из документации веб-сервера Apache
RFC 1422: Privacy Enhancement for Internet Electronic Mail: Part II: Certificate-Based Key Management
Стив Кент
RFC 1750: Randomness Recommendations for Security
D. Eastlake и др.
RFC 3280: Internet X.509 Public Key Infrastructure Certificate and CRL Profile
Housley и др.
RFC 4366: Transport Layer Security (TLS) Extensions
Blake-Wilson и др.
RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2
T. Dierks и др.
RFC 6066: Transport Layer Security (TLS) Extensions
D. Eastlake
IANA TLS: Transport Layer Security (TLS) Parameters
IANA

© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.5/library/ssl.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API