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.VerifyModeenum.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.VerifyFlagsenum.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_ALLOpenSSL .Новинка в версии 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.Optionsenum.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_FAILUREssl.ALERT_DESCRIPTION_INTERNAL_ERRORALERT_DESCRIPTION_*Описания предупреждений из RFC 5246 и других. IANA TLS оповещение реестр содержит этот список и ссылки на РЛК , где определяются их значение.
Используется как возвращаемое значение функции обратного вызова в
SSLContext.set_servername_callback().Новинка в версии 3.4.
class ssl.AlertDescriptionenum.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.SSLErrorNumberenum.IntEnumколлекция констант SSL_ERROR_ *.Новинка в версии 3.6.
class ssl.TLSVersionenum.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_3SSL 3.0 до TLS 1.3.
Устаревший начиная с версии 3.10: Все
TLSVersionчлены кромеTLSVersion.TLSv1_2иTLSVersion.TLSv1_3устарели.
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иOCSPURI.Изменения в версии 3.9:Строки адресов IPv6 больше не имеют новой строки в конце.
SSLSocket.cipher()Возвращает трехзначный кортеж, содержащий имя используемого шифра, версию протокола SSL, определяющую его использование, и количество используемых секретных битов. Если соединение не было установлено, возвращает
None.
Вернуть список шифров, предоставленных клиентом во время рукопожатия. Каждая запись возвращенного списка представляет собой кортеж из трех значений, содержащий имя шифра, версию протокола 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()