How do I verify an SSL certificate in python? – Stack Overflow

How do I verify an SSL certificate in python? - Stack Overflow Сертификаты

Certificates

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

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

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

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

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

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

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

... (certificate in base64 PEM encoding) ...

Constants

Все константы теперь enum.IntFlag коллекциями 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 рекомендуется использовать CERT_REQUIRED для клиентских сокетов.

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

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

ssl.CERT_REQUIRED

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

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

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

class ssl.VerifyMode

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

Новинка в версии 3.6.

ssl.VERIFY_DEFAULT

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

Новинка в версии 3.4.

ssl.VERIFY_CRL_CHECK_LEAF

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

Новинка в версии 3.4.

ssl.VERIFY_CRL_CHECK_CHAIN

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

Новинка в версии 3.4.

ssl.VERIFY_X509_STRICT

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

Новинка в версии 3.4.

ssl.VERIFY_ALLOW_PROXY_CERTS

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

Новинка в версии 3.10.

ssl.VERIFY_X509_TRUSTED_FIRST

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

Новинка в версии 3.4.4.

ssl.VERIFY_X509_PARTIAL_CHAIN

Возможное значение для SSLContext.verify_flags . Он предписывает OpenSSL принимать промежуточные ЦС в хранилище доверенных сертификатов, которые будут рассматриваться как якоря доверия, так же, как самозаверяющие сертификаты корневого ЦС. Это позволяет доверять сертификатам, выпущенным промежуточным ЦС, без необходимости доверять его корневому ЦС-предку.

Новинка в версии 3.10.

class ssl.VerifyFlags

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

Новинка в версии 3.6.

ssl.PROTOCOL_TLS

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

Новинка в версии 3.6.

Не рекомендуется с версии 3.10: клиенты и серверы TLS требуют различных настроек по умолчанию для безопасного обмена данными. Общая константа протокола TLS устарела в пользу PROTOCOL_TLS_CLIENT и PROTOCOL_TLS_SERVER .

ssl.PROTOCOL_TLS_CLIENT

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

Новинка в версии 3.6.

ssl.PROTOCOL_TLS_SERVER

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

Новинка в версии 3.6.

ssl.PROTOCOL_SSLv23

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

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

ssl.PROTOCOL_SSLv2

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

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

Исключено с версии 3.6:В OpenSSL устранена поддержка SSLv2.

ssl.PROTOCOL_SSLv3

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

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

Не рекомендуется, начиная с версии 3.6: OpenSSL устарел для всех протоколов, относящихся к конкретной версии. Вместо этого используйте протокол по умолчанию PROTOCOL_TLS_SERVER или PROTOCOL_TLS_CLIENT с SSLContext.minimum_version и SSLContext.maximum_version .

ssl.PROTOCOL_TLSv1

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

Утратил актуальность с версии 3.6:OpenSSL отказался от всех протоколов,специфичных для данной версии.

ssl.PROTOCOL_TLSv1_1

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

Новинка в версии 3.4.

Утратил актуальность с версии 3.6:OpenSSL отказался от всех протоколов,специфичных для данной версии.

ssl.PROTOCOL_TLSv1_2

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

Новинка в версии 3.4.

Утратил актуальность с версии 3.6:OpenSSL отказался от всех протоколов,специфичных для данной версии.

ssl.OP_ALL

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

Не рекомендуется, начиная с версии 3.7: эта опция устарела, начиная с OpenSSL 1.1.0, используйте вместо SSLContext.maximum_version новые SSLContext.minimum_version и SSLContext.maximum_version .

ssl.OP_NO_TLSv1_1

Предотвращает соединение TLSv1.1. Эта опция применима только вместе с PROTOCOL_TLS . Это предотвращает выбор одноранговыми узлами TLSv1.1 в качестве версии протокола. Доступно только с openssl версии 1.0.1 .

Новинка в версии 3.4.

Исключено с версии 3.7:Опция исключена с версии OpenSSL 1.1.0.

ssl.OP_NO_TLSv1_2

Предотвращает соединение TLSv1.2. Эта опция применима только вместе с PROTOCOL_TLS . Это предотвращает выбор одноранговыми узлами TLSv1.2 в качестве версии протокола. Доступно только с openssl версии 1.0.1 .

Новинка в версии 3.4.

Исключено с версии 3.7:Опция исключена с версии OpenSSL 1.1.0.

ssl.OP_NO_TLSv1_3

Предотвращает соединение TLSv1.3. Эта опция применима только вместе с PROTOCOL_TLS . Это предотвращает выбор одноранговыми узлами TLSv1.3 в качестве версии протокола. TLS 1.3 доступен с OpenSSL 1.1.1 или новее. Когда Python скомпилирован для более старой версии OpenSSL, флаг по умолчанию равен 0 .

Новинка в версии 3.7.

Исключено с версии 3.7:Опция исключена с версии OpenSSL 1.1.0.Она была добавлена в версии 2.7.15,3.6.3 и 3.7.0 для обратной совместимости с OpenSSL 1.0.2.

ssl.OP_NO_RENEGOTIATION

Отключите все перезаключения в TLSv1.2 и ранее.Не посылать сообщения HelloRequest и игнорировать запросы на перезаключение через ClientHello.

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

Новинка в версии 3.7.

ssl.OP_CIPHER_SERVER_PREFERENCE

Используйте предпочтение порядка шифрования сервера, а не клиента. Этот параметр не влияет на клиентские сокеты и серверные сокеты SSLv2.

Новинка в версии 3.3.

ssl.OP_SINGLE_DH_USE

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

Новинка в версии 3.3.

ssl.OP_SINGLE_ECDH_USE

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

Новинка в версии 3.3.

ssl.OP_ENABLE_MIDDLEBOX_COMPAT

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

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

Новинка в версии 3.8.

ssl.OP_NO_COMPRESSION

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

Новинка в версии 3.3.

class ssl.Options

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

ssl.OP_NO_TICKET

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

Новинка в версии 3.6.

ssl.OP_IGNORE_UNEXPECTED_EOF

Игнорировать неожиданное завершение TLS-соединений.

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

Новинка в версии 3.10.

ssl.HAS_ALPN

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

Новинка в версии 3.5.

ssl.HAS_NEVER_CHECK_COMMON_NAME

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

Новинка в версии 3.7.

ssl.HAS_ECDH

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

Новинка в версии 3.3.

ssl.HAS_SNI

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

Новинка в версии 3.2.

ssl.HAS_NPN

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

Новинка в версии 3.3.

ssl.HAS_SSLv2

Имеет ли библиотека OpenSSL встроенную поддержку протокола SSL 2.0.

Новинка в версии 3.7.

ssl.HAS_SSLv3

Имеет ли библиотека OpenSSL встроенную поддержку протокола SSL 3.0.

Новинка в версии 3.7.

ssl.HAS_TLSv1

Имеет ли библиотека OpenSSL встроенную поддержку протокола TLS 1.0.

Новинка в версии 3.7.

ssl.HAS_TLSv1_1

Имеет ли библиотека OpenSSL встроенную поддержку протокола TLS 1.1.

Новинка в версии 3.7.

ssl.HAS_TLSv1_2

Имеет ли библиотека OpenSSL встроенную поддержку протокола TLS 1.2.

Новинка в версии 3.7.

ssl.HAS_TLSv1_3

Имеет ли библиотека OpenSSL встроенную поддержку протокола TLS 1.3.

Новинка в версии 3.7.

ssl.CHANNEL_BINDING_TYPES

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

Новинка в версии 3.3.

ssl.OPENSSL_VERSION

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

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

Новинка в версии 3.2.

ssl.OPENSSL_VERSION_INFO

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

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

Новинка в версии 3.2.

ssl.OPENSSL_VERSION_NUMBER

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

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

Новинка в версии 3.2.

ssl.ALERT_DESCRIPTION_HANDSHAKE_FAILURE
ssl.ALERT_DESCRIPTION_INTERNAL_ERROR
ALERT_DESCRIPTION_*

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

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

Новинка в версии 3.4.

class ssl.AlertDescription

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

Новинка в версии 3.6.

Purpose.SERVER_AUTH

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

Новинка в версии 3.4.

Purpose.CLIENT_AUTH

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

Новинка в версии 3.4.

class ssl.SSLErrorNumber

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

Новинка в версии 3.6.

class ssl.TLSVersion

enum.IntEnum коллекция версий SSL и TLS дляSSLContext.maximum_version иSSLContext.minimum_version .

Новинка в версии 3.7.

TLSVersion.MINIMUM_SUPPORTED
TLSVersion.MAXIMUM_SUPPORTED

Минимальная или максимальная поддерживаемая версия SSL или TLS. Это магические константы. Их значения не отражают самую низкую и самую высокую доступные версии TLS / SSL.

TLSVersion.SSLv3
TLSVersion.TLSv1
TLSVersion.TLSv1_1
TLSVersion.TLSv1_2
TLSVersion.TLSv1_3

SSL 3.0 до TLS 1.3.

Устаревший начиная с версии 3.10: Все TLSVersion члены кроме TLSVersion.TLSv1_2 и TLSVersion.TLSv1_3 устарели.

Про сертификаты:  Разъяснение о допуске без сертификата специалиста или свидетельства об аккредитации специалиста - DENTALMAGAZINE.RU

Exceptions

exception ssl.SSLError

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

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

library

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

Новинка в версии 3.3.

reason

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

Новинка в версии 3.3.

exception ssl.SSLZeroReturnError

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

Новинка в версии 3.3.

exception ssl.SSLWantReadError

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

Новинка в версии 3.3.

exception ssl.SSLWantWriteError

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

Новинка в версии 3.3.

exception ssl.SSLSyscallError

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

Новинка в версии 3.3.

exception ssl.SSLEOFError

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

Новинка в версии 3.3.

exception ssl.SSLCertVerificationError

Подкласс SSLError , возникающий при сбое проверки сертификата.

Новинка в версии 3.7.

verify_code

Числовой номер ошибки,обозначающий ошибку верификации.

verify_message

Человеческая строка ошибки верификации.

exception ssl.CertificateError

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

Изменено в версии 3.7: теперь исключение представляет собой псевдоним для SSLCertVerificationError .

Footnotes

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.

Изменено в версии 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 ) устанавливаются по умолчанию.

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

Изменено в версии 3.10: комплекты шифров по умолчанию теперь включают только безопасные шифры AES и ChaCha20 с прямой секретностью и уровнем безопасности 2.

Ключи RSA и DH с менее чем 2048 битами и ключи ECC с менее чем 224 битами запрещены. PROTOCOL_TLS , PROTOCOL_TLS_CLIENT и PROTOCOL_TLS_SERVER используют TLS 1.2 как минимальную версию TLS.

How do i verify an ssl certificate in python?

I need to verify that a certificate was signed by my custom CA. Using OpenSSL command-line utilities this is easy to do:

# Custom CA file: ca-cert.pem
# Cert signed by above CA: bob.cert
$ openssl verify -CAfile test-ca-cert.pem bob.cert
bob.cert: OK

But I need to do the same thing in Python, and I really don’t want to call out to command-line utilities. As far as I’m aware, M2Crypto is the “most complete” python wrapper for OpenSSL, but I can’t figure out how to accomplish what the command-line utility does!

Referencing this question for how to accomplish this same task in C code, I’ve been able to get about half-way. The variable names I chose are the same ones used in the source code for the openssl verify command-line utility, see openssl-xxx/apps/verify.c.

import M2Crypto as m2
# Load the certificates
cacert = m2.X509.load_cert('test-ca-cert.pem')   # Create cert object from CA cert file
bobcert = m2.X509.load_cert('bob.cert')     # Create cert object from Bob's cert file
cert_ctx = m2.X509.X509_Store()             # Step 1 from referenced C code steps
csc = m2.X509.X509_Store_Context(cert_ctx)  # Step 2 & 5
cert_ctx.add_cert(cacert)                   # Step 3
cert_ctx.add_cert(bobcert)                  # ditto
# Skip step 4 (no CRLs to add)
# Step 5 is combined with step 2...I think. (X509_STORE_CTX_init: Python creates and 
#   initialises an object in the same step)
# Skip step 6? (can't find anything corresponding to 
#   X509_STORE_CTX_set_purpose, not sure if we need to anyway???)
# 
# It all falls apart at this point, as steps 7 and 8 don't have any corresponding
# functions in M2Crypto -- I even grepped the entire source code of M2Crypto, and
# neither of the following functions are present in it:
# Step 7: X509_STORE_CTX_set_cert - Tell the context which certificate to validate.
# Step 8: X509_verify_cert - Finally, validate it

So I’m halfway there, but I can’t seem to actually get the validation done! Am I missing something? Is there some other function I should be using from M2Crypto? Should I be looking for a completely different python wrapper of OpenSSL? How can I accomplish this task in python!?!?

Note that I’m using certificates to encrypt/decrypt FILES, so I’m not interested in using the SSL-connection-based peer certificate verification (which has already been answered), because I don’t have any SSL connections going.

Ssl-сокеты

class ssl.SSLSocket(socket.socket)

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

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

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

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

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

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

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

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

Про сертификаты:  Судебный пристав его полномочия и обязанности

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

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

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

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

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

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

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

SSLSocket.write(buf)

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

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

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

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

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

SSLSocket.do_handshake()

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

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

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

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

SSLSocket.getpeercert(binary_form=False)

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

Если параметр binary_form имеет значение False и сертификат был получен от однорангового узла , этот метод возвращает экземпляр dict . Если сертификат не прошел валидацию, dict пуст. Если сертификат был проверен, он возвращает dict с несколькими ключами, среди которых subject (принципал, для которого был выпущен сертификат) и issuer (принципал, выдавший сертификат). Если сертификат содержит экземпляр расширения альтернативного имени субъекта (см. RFC 3280 ), в словаре также будет ключ subjectAltName .

В subject и issuer поля являются кортежи , содержащие последовательность относительных различающихся имен (RDNS) , приведенных в структуре данных сертификата для соответствующих полей, и каждый РДН представляет собой последовательность пар имя-значение. Вот реальный пример:

{'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 2021 GMT',
 'notBefore': 'Nov 21 03:09:52 2021 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}

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

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

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

Изменения в версии 3.9:Строки адресов IPv6 больше не имеют новой строки в конце.

SSLSocket.cipher()

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

SSLSocket.shared_ciphers()

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

Новинка в версии 3.5.

Контексты ssl

Новинка в версии 3.2.

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

class ssl.SSLContext(protocol=None)

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

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

Footnotes

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.

Изменено в версии 3.6: контекст создается с безопасными значениями по умолчанию. Варианты OP_NO_COMPRESSION , OP_CIPHER_SERVER_PREFERENCE , OP_SINGLE_DH_USE , OP_SINGLE_ECDH_USE , OP_NO_SSLv2 (за исключением PROTOCOL_SSLv2 ) и OP_NO_SSLv3 (за исключением PROTOCOL_SSLv3 ) устанавливаются по умолчанию. Первоначальный список шифров содержит только HIGH – шифры, ни NULL – шифров, ни шифров MD5 (кроме PROTOCOL_SSLv2 ).

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

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

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

SSLContext.cert_store_stats()

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

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

>>> 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 сертификатов , необходимых для установления подлинности сертификата. Файл_ключа строка, если она присутствует, должна указывать на файл , содержащий закрытый ключ. В противном случае секретный ключ будет взят из CERTFILE , а также. См. Обсуждение сертификатов для получения дополнительной информации о том, как сертификат хранится в файле сертификата .

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

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

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

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

SSLContext.load_default_certs(purpose=Purpose.SERVER_AUTH)

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

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

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

Capath строка, если он присутствует, путь к каталогу , содержащему несколько сертификатов CA в формате PEM, следующих в макете OpenSSL конкретного .

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

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

SSLContext.get_ca_certs(binary_form=False)

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

Новинка в версии 3.4.

SSLContext.get_ciphers()

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

Example:

>>> ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
>>> ctx.set_ciphers('ECDHE AESGCM:!ECDSA')
>>> ctx.get_ciphers()
[{'aead': True,
  'alg_bits': 256,
  'auth': 'auth-rsa',
  'description': 'ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH     Au=RSA  ''Enc=AESGCM(256) Mac=AEAD',
  'digest': None,
  'id': 50380848,
  'kea': 'kx-ecdhe',
  'name': 'ECDHE-RSA-AES256-GCM-SHA384',
  'protocol': 'TLSv1.2',
  'strength_bits': 256,
  'symmetric': 'aes-256-gcm'},
 {'aead': True,
  'alg_bits': 128,
  'auth': 'auth-rsa',
  'description': 'ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH     Au=RSA  ''Enc=AESGCM(128) Mac=AEAD',
  'digest': None,
  'id': 50380847,
  'kea': 'kx-ecdhe',
  'name': 'ECDHE-RSA-AES128-GCM-SHA256',
  'protocol': 'TLSv1.2',
  'strength_bits': 128,
  'symmetric': 'aes-128-gcm'}]

Новинка в версии 3.6.

SSLContext.set_default_verify_paths()

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

SSLContext.set_ciphers(ciphers)

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

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

Новинка в версии 3.5.

Про сертификаты:  Сертификация услуг отелей и гостиниц

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

Сетевой API ввода-вывода идентичен API-интерфейсу socket.socket , от которого также наследуется SSLSocket .

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

Это в основном актуально для таких платформ, как Windows, где эта модель неэффективна. Для этой цели предоставляется вариант SSLSocket с сокращенной областью действия, называемый SSLObject .

class ssl.SSLObject

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

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

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

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

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

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

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

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

class ssl.MemoryBIO

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

pending

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

eof

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

read(n=- 1)

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

write(buf)

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

Возвращаемое значение – это количество записанных байтов, которое всегда равно длине buf .

write_eof()

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

Случайное генерирование

ssl.RAND_bytes(num)

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

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

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

Новинка в версии 3.3.

ssl.RAND_pseudo_bytes(num)

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

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

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

Новинка в версии 3.3.

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

ssl.RAND_status()

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

ssl.RAND_add(bytes, entropy)

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

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

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

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

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

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

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

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

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

Note

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

Изменено в версии 3.10: контекст теперь использует протокол PROTOCOL_TLS_CLIENT или PROTOCOL_TLS_SERVER вместо общего PROTOCOL_TLS .

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

Так как Python 3.2 и 2.7.9, рекомендуется использовать SSLContext.wrap_socket() из в SSLContext , например , чтобы обернуть сокетов , как SSLSocket объекты.

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

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

import socket
import ssl

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

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

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

hostname = 'www.python.org'
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.load_verify_locations('path/to/cabundle.pem')

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

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

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

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

Соображения безопасности

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

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

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

try:
    import ssl
except ImportError:
    passelse:
    ...  

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

>>>context = ssl.create_default_context()

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

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

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

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

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

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

Тогда ты можешь получить сертификат:

>>>cert = conn.getpeercert()

Оцените статью
Мой сертификат
Добавить комментарий