Документация Python неофициальный перевод

ssl.md

505 строк · 37.2 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.1/library/ssl.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 17.3. `ssl` – TLS/SSL-обёртка для сокетов89Этот модуль предоставляет доступ к шифрованию и аутентификации одноранговых узлов с помощью протокола Transport Layer Security (часто называемого «Secure Sockets Layer») для сетевых сокетов, как на стороне клиента, так и на стороне сервера. В этом модуле используется библиотека OpenSSL. Он доступен на всех современных Unix-системах, Windows, Mac OS X и, вероятно, на других платформах, если на них установлен OpenSSL.1011> **Примечание**12>13> Некоторое поведение может зависеть от платформы, поскольку вызовы выполняются к API сокетов операционной системы. Установленная версия OpenSSL также может вызывать различия в поведении.1415В этом разделе описываются объекты и функции модуля `ssl`; за более общей информацией о TLS, SSL и сертификатах обращайтесь к документам в разделе «См. также» внизу.1617Данный модуль предоставляет класс `ssl.SSLSocket`, производный от типа [`socket.socket`](https://python-all.ru/3.1/library/socket.html#socket.socket), и реализует обёртку, похожую на сокет, которая также шифрует и расшифровывает данные, передаваемые через сокет по протоколу SSL. Он поддерживает дополнительные методы `read()` и `write()`, а также метод `getpeercert()` для получения сертификата другой стороны соединения и метод `cipher()` для получения шифра, используемого для защищённого соединения.1819## 17.3.1. Функции, константы и исключения2021#### `exception ssl.SSLError`2223Возбуждается для сигнализации об ошибке в базовой реализации SSL. Это указывает на некоторую проблему в вышележащем уровне шифрования и аутентификации, который накладывается на нижележащее сетевое соединение. Эта ошибка является подтипом2425[`socket.error`](https://python-all.ru/3.1/library/socket.html#socket.error)2627, который, в свою очередь, является подтипом2829[`IOError`](https://python-all.ru/3.1/library/exceptions.html#IOError)3031.3233#### `ssl.wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version={see docs}, ca_certs=None, do_handshake_on_connect=True, suppress_ragged_eofs=True)`3435Принимает экземпляр `sock` класса [`socket.socket`](https://python-all.ru/3.1/library/socket.html#socket.socket) и возвращает экземпляр `ssl.SSLSocket`, подтип [`socket.socket`](https://python-all.ru/3.1/library/socket.html#socket.socket), который оборачивает базовый сокет в контекст SSL. Для клиентских сокетов построение контекста является отложенным; если базовый сокет ещё не подключён, построение контекста будет выполнено после вызова `connect()` на сокете. Для серверных сокетов, если у сокета нет удалённого узла, он считается слушающим сокетом, и серверная SSL-обёртка автоматически выполняется для клиентских подключений, принятых через метод `accept()`. [`wrap_socket()`](https://python-all.ru/3.1/library/ssl.html#ssl.wrap_socket) может возбудить [`SSLError`](https://python-all.ru/3.1/library/ssl.html#ssl.SSLError).3637Параметры `keyfile` и `certfile` задают необязательные файлы, содержащие сертификат, используемый для идентификации локальной стороны соединения. См. обсуждение [*Certificates*](https://python-all.ru/3.1/library/ssl.html#ssl-certificates) для получения дополнительной информации о том, как сертификат хранится в `certfile`.3839Часто закрытый ключ хранится в том же файле, что и сертификат; в этом случае достаточно передать только параметр `certfile`. Если закрытый ключ хранится в отдельном файле, необходимо использовать оба параметра. Если закрытый ключ хранится в `certfile`, он должен предшествовать первому сертификату в цепочке сертификатов:4041```python42-----BEGIN RSA PRIVATE KEY-----43... (private key in base64 encoding) ...44-----END RSA PRIVATE KEY-----45-----BEGIN CERTIFICATE-----46... (certificate in base64 PEM encoding) ...47-----END CERTIFICATE-----48```4950Параметр `server_side` – это логическое значение, которое определяет, требуется ли от этого сокета поведение серверной или клиентской стороны.5152Параметр `cert_reqs` задаёт, требуется ли сертификат от другой стороны соединения и будет ли он проверен, если предоставлен. Он должен быть одним из трёх значений: [`CERT_NONE`](https://python-all.ru/3.1/library/ssl.html#ssl.CERT_NONE) (сертификаты игнорируются), [`CERT_OPTIONAL`](https://python-all.ru/3.1/library/ssl.html#ssl.CERT_OPTIONAL) (не требуется, но проверяется, если предоставлен) или [`CERT_REQUIRED`](https://python-all.ru/3.1/library/ssl.html#ssl.CERT_REQUIRED) (требуется и проверяется). Если значение этого параметра не [`CERT_NONE`](https://python-all.ru/3.1/library/ssl.html#ssl.CERT_NONE), то параметр `ca_certs` должен указывать на файл с сертификатами ЦС.5354Файл `ca_certs` содержит набор объединённых сертификатов «центров сертификации», которые используются для проверки сертификатов, переданных с другого конца соединения. См. обсуждение [*Certificates*](https://python-all.ru/3.1/library/ssl.html#ssl-certificates) для получения дополнительной информации о том, как организовать сертификаты в этом файле.5556Параметр `ssl_version` определяет, какая версия протокола SSL будет использоваться. Обычно сервер выбирает конкретную версию протокола, а клиент должен подстраиваться под выбор сервера. Большинство версий несовместимы друг с другом. Если параметр не указан, для работы на стороне клиента по умолчанию используется SSLv3; для работы на стороне сервера – SSLv23. Такой выбор версий обеспечивает наибольшую совместимость с другими версиями.5758Ниже приведена таблица, показывающая, какие версии на стороне клиента (по вертикали) могут подключаться к каким версиям на стороне сервера (по горизонтали):5960> | *клиент* / **сервер** | **SSLv2** | **SSLv3** | **SSLv23** | **TLSv1** |61> | --- | --- | --- | --- | --- |62> | *SSLv2* | да | нет | yes\* | нет |63> | *SSLv3* | да | да | да | нет |64> | *SSLv23* | да | нет | да | нет |65> | *TLSv1* | нет | нет | да | да |6667В некоторых старых версиях OpenSSL (например, 0.9.7l на OS X 10.4) клиент SSLv2 не мог подключиться к серверу SSLv23.6869Параметр `do_handshake_on_connect` определяет, выполнять ли квитирование SSL автоматически после вызова `socket.connect()`, или же программа должна вызывать его явно с помощью метода [`SSLSocket.do_handshake()`](https://python-all.ru/3.1/library/ssl.html#ssl.SSLSocket.do_handshake). Явный вызов [`SSLSocket.do_handshake()`](https://python-all.ru/3.1/library/ssl.html#ssl.SSLSocket.do_handshake) даёт программе контроль над блокирующим поведением операций ввода-вывода сокета, участвующих в квитировании.7071Параметр `suppress_ragged_eofs` определяет, как метод [`SSLSocket.read()`](https://python-all.ru/3.1/library/ssl.html#ssl.SSLSocket.read) должен обрабатывать неожиданный EOF с другой стороны соединения. Если указано [`True`](https://python-all.ru/3.1/library/constants.html#True) (значение по умолчанию), метод возвращает обычный EOF в ответ на ошибки неожиданного EOF, возникающие в нижележащем сокете; если [`False`](https://python-all.ru/3.1/library/constants.html#False), исключения будут передаваться обратно вызывающему коду.7273#### `ssl.RAND_status()`7475Возвращает True, если SSL-генератор псевдослучайных чисел был инициализирован «достаточным» количеством случайности, и False в противном случае. Для увеличения случайности генератора псевдослучайных чисел можно использовать7677[`ssl.RAND_egd()`](https://python-all.ru/3.1/library/ssl.html#ssl.RAND_egd)7879и8081[`ssl.RAND_add()`](https://python-all.ru/3.1/library/ssl.html#ssl.RAND_add)8283.8485#### `ssl.RAND_egd(path)`8687Если где-то запущен демон сбора энтропии (EGD) и `path` является именем пути сокетного соединения, открытого к нему, то эта функция прочитает 256 байт случайности из сокета и добавит их в SSL-генератор псевдослучайных чисел для повышения безопасности генерируемых секретных ключей. Обычно это необходимо только в системах без лучших источников случайности.8889См. [http://egd.sourceforge.net/](https://python-all.ru/3.1/library/ssl.html) или [http://prngd.sourceforge.net/](https://python-all.ru/3.1/library/ssl.html) для получения исходных текстов демонов сбора энтропии.9091#### `ssl.RAND_add(bytes, entropy)`9293Смешивает заданные9495`bytes`9697с SSL-генератором псевдослучайных чисел. Параметр9899`entropy`100101(число с плавающей запятой) является нижней границей энтропии, содержащейся в строке (поэтому всегда можно использовать102103`0.0`104105). См.106107[**RFC 1750**](https://python-all.ru/3.1/library/ssl.html)108109для получения дополнительной информации об источниках энтропии.110111#### `ssl.cert_time_to_seconds(timestring)`112113Возвращает значение с плавающей запятой, содержащее обычное время в секундах от начала эпохи, для строки времени, представляющей дату “notBefore” или “notAfter” из сертификата.114115Вот пример:116117```python118>>> import ssl119>>> ssl.cert_time_to_seconds("May  9 00:00:00 2007 GMT")1201178694000.0121>>> import time122>>> time.ctime(ssl.cert_time_to_seconds("May  9 00:00:00 2007 GMT"))123'Wed May  9 00:00:00 2007'124>>>125```126127#### `ssl.get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None)`128129По заданному адресу130131`addr`132133SSL-защищённого сервера, в виде пары (134135*hostname*136137,138139*port-number*140141), получает сертификат сервера и возвращает его в виде строки в кодировке PEM. Если указан142143`ssl_version`144145, используется эта версия протокола SSL для попытки подключения к серверу. Если указан146147`ca_certs`148149, это должен быть файл, содержащий список корневых сертификатов, в том же формате, который используется для одноимённого параметра в150151[`wrap_socket()`](https://python-all.ru/3.1/library/ssl.html#ssl.wrap_socket)152153. Вызов попытается проверить сертификат сервера по этому набору корневых сертификатов, и завершится неудачей, если проверка не пройдёт.154155#### `ssl.DER_cert_to_PEM_cert(DER_cert_bytes)`156157Принимая сертификат в виде набора байтов в кодировке DER, возвращает версию того же сертификата в виде строки в кодировке PEM.158159#### `ssl.PEM_cert_to_DER_cert(PEM_cert_string)`160161Принимая сертификат в виде строки ASCII в формате PEM, возвращает последовательность байтов в кодировке DER для того же сертификата.162163#### `ssl.CERT_NONE`164165Значение, передаваемое параметру166167`cert_reqs`168169функции170171`sslobject()`172173, когда не требуется запрашивать или проверять сертификаты с другой стороны сокетного соединения.174175#### `ssl.CERT_OPTIONAL`176177Значение, передаваемое параметру178179`cert_reqs`180181функции182183`sslobject()`184185, когда сертификаты не требуются с другой стороны сокетного соединения, но если они предоставлены, то проверяются. Обратите внимание, что использование этой настройки требует также передачи валидного файла для проверки сертификатов в качестве значения параметра186187`ca_certs`188189.190191#### `ssl.CERT_REQUIRED`192193Значение, передаваемое параметру194195`cert_reqs`196197функции198199`sslobject()`200201, когда сертификаты требуются с другой стороны сокетного соединения. Обратите внимание, что использование этой настройки требует также передачи валидного файла для проверки сертификатов в качестве значения параметра202203`ca_certs`204205.206207#### `ssl.PROTOCOL_SSLv2`208209Выбирает SSL версии 2 в качестве протокола шифрования канала.210211Этот протокол недоступен, если OpenSSL скомпилирован с флагом OPENSSL\_NO\_SSL2 .212213> **Предупреждение**214>215> SSL версии 2 небезопасен. Его использование крайне не рекомендуется.216217#### `ssl.PROTOCOL_SSLv23`218219Выбирает SSL версии 2 или 3 в качестве протокола шифрования канала. Это настройка для использования с серверами для максимальной совместимости с другой стороной SSL-соединения, но может привести к выбору довольно низкокачественных шифров для шифрования.220221#### `ssl.PROTOCOL_SSLv3`222223Выбирает SSL версии 3 в качестве протокола шифрования канала. Для клиентов это максимально совместимый вариант SSL.224225#### `ssl.PROTOCOL_TLSv1`226227Выбирает TLS версии 1 в качестве протокола шифрования канала. Это самая современная версия и, вероятно, лучший выбор для максимальной защиты, если обе стороны её поддерживают.228229## 17.3.2. Объекты SSLSocket230231#### `SSLSocket.read(nbytes=1024, buffer=None)`232233Reads up to234235`nbytes`236237bytes from the SSL-encrypted channel and returns them. If the238239`buffer`240241is specified, it will attempt to read into the buffer the minimum of the size of the buffer and242243`nbytes`244245, if that is specified. If no buffer is specified, an immutable buffer is allocated and returned with the data read from the socket.246247#### `SSLSocket.write(data)`248249Writes the250251`data`252253to the other side of the connection, using the SSL channel to encrypt. Returns the number of bytes written.254255#### `SSLSocket.do_handshake()`256257Performs the SSL setup handshake. If the socket is non-blocking, this method may raise [`SSLError`](https://python-all.ru/3.1/library/ssl.html#ssl.SSLError) with the value of the exception instance’s `args[0]` being either `SSL_ERROR_WANT_READ` or `SSL_ERROR_WANT_WRITE`, and should be called again until it stops raising those exceptions. Here’s an example of how to do that:258259```python260while True:261    try:262        sock.do_handshake()263        break264    except ssl.SSLError as err:265        if err.args[0] == ssl.SSL_ERROR_WANT_READ:266            select.select([sock], [], [])267        elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:268            select.select([], [sock], [])269        else:270            raise271```272273#### `SSLSocket.getpeercert(binary_form=False)`274275Если на другом конце соединения нет сертификата у удаленной стороны, возвращается `None`.276277If the parameter `binary_form` is [`False`](https://python-all.ru/3.1/library/constants.html#False), and a certificate was received from the peer, this method returns a [`dict`](https://python-all.ru/3.1/library/stdtypes.html#dict) instance. If the certificate was not validated, the dict is empty. If the certificate was validated, it returns a dict with the keys `subject` (the principal for which the certificate was issued), and `notAfter` (the time after which the certificate should not be trusted). The certificate was already validated, so the `notBefore` and `issuer` fields are not returned. If a certificate contains an instance of the *Subject Alternative Name* extension (see [**RFC 3280**](https://python-all.ru/3.1/library/ssl.html)), there will also be a `subjectAltName` key in the dictionary.278279Поле «subject» представляет собой кортеж, содержащий последовательность относительных отличительных имён (RDN), заданных в структуре данных сертификата для субъекта, и каждый RDN – это последовательность пар «имя-значение»:280281```python282{'notAfter': 'Feb 16 16:54:50 2013 GMT',283 'subject': ((('countryName', 'US'),),284             (('stateOrProvinceName', 'Delaware'),),285             (('localityName', 'Wilmington'),),286             (('organizationName', 'Python Software Foundation'),),287             (('organizationalUnitName', 'SSL'),),288             (('commonName', 'somemachine.python.org'),))}289```290291Если параметр `binary_form` равен [`True`](https://python-all.ru/3.1/library/constants.html#True) и сертификат был предоставлен, этот метод возвращает полный сертификат в DER-кодировке в виде последовательности байтов или [`None`](https://python-all.ru/3.1/library/constants.html#None), если одноранговый узел не предоставил сертификат. Возвращаемое значение не зависит от проверки; если проверка требовалась ([`CERT_OPTIONAL`](https://python-all.ru/3.1/library/ssl.html#ssl.CERT_OPTIONAL) или [`CERT_REQUIRED`](https://python-all.ru/3.1/library/ssl.html#ssl.CERT_REQUIRED)), сертификат будет проверен, но если для установки соединения использовалось [`CERT_NONE`](https://python-all.ru/3.1/library/ssl.html#ssl.CERT_NONE), то сертификат (если он есть) проверен не будет.292293#### `SSLSocket.cipher()`294295Возвращает кортеж из трех значений, содержащий название используемого шифра, версию протокола SSL, которая определяет его использование, и количество используемых секретных битов. Если соединение не установлено, возвращает296297`None`298299.300301#### `SSLSocket.unwrap()`302303Выполняет рукопожатие завершения SSL, которое удаляет слой TLS из базового сокета и возвращает объект базового сокета. Это можно использовать для перехода от зашифрованной работы по соединению к незашифрованной. Возвращённый сокет всегда следует использовать для дальнейшего обмена данными с другой стороной соединения, а не исходный сокет.304305## 17.3.3. Сертификаты306307Сертификаты в целом являются частью системы открытых и закрытых ключей. В этой системе каждому *субъекту* (которым может быть машина, человек или организация) присваивается уникальный двухчастный ключ шифрования. Одна часть ключа является открытой и называется *открытым ключом*; другая часть хранится в секрете и называется *закрытым ключом*. Две части связаны так, что если зашифровать сообщение одной частью, его можно расшифровать только другой частью, и **только** другой частью.308309Сертификат содержит информацию о двух субъектах. Он содержит имя *субъекта* и его открытый ключ. Также он содержит утверждение второго субъекта, *издателя*, о том, что субъект является тем, за кого себя выдаёт, и что это действительно открытый ключ субъекта. Утверждение издателя подписано закрытым ключом издателя, который известен только издателю. Однако любой может проверить утверждение издателя, найдя его открытый ключ, расшифровав им утверждение и сравнив его с другой информацией в сертификате. Сертификат также содержит информацию о периоде времени, в течение которого он действителен. Это выражается двумя полями, называемыми «notBefore» и «notAfter».310311При использовании сертификатов в Python клиент или сервер может использовать сертификат для подтверждения своей личности. Другая сторона сетевого соединения также может быть обязана предоставить сертификат, и этот сертификат может быть проверен к удовлетворению клиента или сервера, требующего такой проверки. Можно настроить попытку соединения так, чтобы она вызывала исключение, если проверка не удалась. Проверка выполняется автоматически базовым фреймворком OpenSSL; приложению не нужно вникать в её механику. Но приложению обычно необходимо предоставить наборы сертификатов, чтобы этот процесс мог происходить.312313Python uses files to contain certificates. They should be formatted as “PEM” (see [**RFC 1422**](https://python-all.ru/3.1/library/ssl.html)), which is a base-64 encoded form wrapped with a header line and a footer line:314315```python316-----BEGIN CERTIFICATE-----317... (certificate in base64 PEM encoding) ...318-----END CERTIFICATE-----319```320321The Python files which contain certificates can contain a sequence of certificates, sometimes called a *certificate chain*. This chain should start with the specific certificate for the principal who “is” the client or server, and then the certificate for the issuer of that certificate, and then the certificate for the issuer of *that* certificate, and so on up the chain till you get to a certificate which is *self-signed*, that is, a certificate which has the same subject and issuer, sometimes called a *root certificate*. The certificates should just be concatenated together in the certificate file. For example, suppose we had a three certificate chain, from our server certificate to the certificate of the certification authority that signed our server certificate, to the root certificate of the agency which issued the certification authority’s certificate:322323```python324-----BEGIN CERTIFICATE-----325... (certificate for your server)...326-----END CERTIFICATE-----327-----BEGIN CERTIFICATE-----328... (the certificate for the CA)...329-----END CERTIFICATE-----330-----BEGIN CERTIFICATE-----331... (the root certificate for the CA's issuer)...332-----END CERTIFICATE-----333```334335Если требуется проверка сертификата другой стороны соединения, необходимо предоставить файл «CA certs», содержащий цепочки сертификатов для каждого издателя, которому вы готовы доверять. Этот файл просто содержит эти цепочки, объединённые вместе. Для проверки Python будет использовать первую подходящую цепочку в файле. Некоторые «стандартные» корневые сертификаты доступны от различных центров сертификации: [CACert.org](https://python-all.ru/3.1/library/ssl.html), [Thawte](https://python-all.ru/3.1/library/ssl.html), [Verisign](https://python-all.ru/3.1/library/ssl.html), [Positive SSL](https://python-all.ru/3.1/library/ssl.html) (используется python.org), [Equifax и GeoTrust](https://python-all.ru/3.1/library/ssl.html).336337В общем случае, если вы используете SSL3 или TLS1, не нужно помещать полную цепочку в файл «CA certs»; достаточно корневых сертификатов, а удалённый узел должен предоставить остальные сертификаты, необходимые для построения цепочки от своего сертификата до корневого. См. [**RFC 4158**](https://python-all.ru/3.1/library/ssl.html) для более подробного обсуждения способов построения цепочек сертификатов.338339Если планируется создать сервер, предоставляющий услуги SSL-защищённого соединения, потребуется приобрести сертификат для этой службы. Существует много способов получения подходящих сертификатов, например покупка в удостоверяющем центре. Ещё одна распространённая практика – сгенерировать самоподписанный сертификат. Самый простой способ сделать это – использовать пакет OpenSSL, примерно следующим образом:340341```python342% openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem343Generating a 1024 bit RSA private key344.......++++++345.............................++++++346writing new private key to 'cert.pem'347-----348You are about to be asked to enter information that will be incorporated349into your certificate request.350What you are about to enter is what is called a Distinguished Name or a DN.351There are quite a few fields but you can leave some blank352For some fields there will be a default value,353If you enter '.', the field will be left blank.354-----355Country Name (2 letter code) [AU]:US356State or Province Name (full name) [Some-State]:MyState357Locality Name (eg, city) []:Some City358Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Organization, Inc.359Organizational Unit Name (eg, section) []:My Group360Common Name (eg, YOUR name) []:myserver.mygroup.myorganization.com361Email Address []:ops@myserver.mygroup.myorganization.com362%363```364365Недостаток самоподписанного сертификата в том, что он является собственным корневым сертификатом, и никто другой не будет иметь его в своём кэше известных (и доверенных) корневых сертификатов.366367## 17.3.4. Примеры368369### 17.3.4.1. Проверка поддержки SSL370371Чтобы проверить наличие поддержки SSL в установке Python, в пользовательском коде следует использовать следующую идиому:372373```python374try:375    import ssl376except ImportError:377    pass378else:379    ... # сделать что-то, что требует поддержки SSL380```381382### 17.3.4.2. Работа на стороне клиента383384Этот пример подключается к SSL-серверу, выводит адрес и сертификат сервера, отправляет несколько байт и читает часть ответа:385386```python387import socket, ssl, pprint388389s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)390391# требовать сертификат от сервера392ssl_sock = ssl.wrap_socket(s,393                           ca_certs="/etc/ca_certs_file",394                           cert_reqs=ssl.CERT_REQUIRED)395396ssl_sock.connect(('www.verisign.com', 443))397398print(repr(ssl_sock.getpeername()))399pprint.pprint(ssl_sock.getpeercert())400print(pprint.pformat(ssl_sock.getpeercert()))401402# Установить простой HTTP-запрос – в реальном коде используйте http.client.403ssl_sock.write("""GET / HTTP/1.0\r404Host: www.verisign.com\r\n\r\n""")405406# Прочитать порцию данных. Не обязательно407# прочитать все данные, возвращённые сервером.408data = ssl_sock.read()409410# закрытие SSLSocket также закроет нижележащий сокет411ssl_sock.close()412```413414По состоянию на 6 сентября 2007 года сертификат, выводимый этой программой, выглядел так:415416```python417{'notAfter': 'May  8 23:59:59 2009 GMT',418 'subject': ((('serialNumber', '2497886'),),419             (('1.3.6.1.4.1.311.60.2.1.3', 'US'),),420             (('1.3.6.1.4.1.311.60.2.1.2', 'Delaware'),),421             (('countryName', 'US'),),422             (('postalCode', '94043'),),423             (('stateOrProvinceName', 'California'),),424             (('localityName', 'Mountain View'),),425             (('streetAddress', '487 East Middlefield Road'),),426             (('organizationName', 'VeriSign, Inc.'),),427             (('organizationalUnitName',428               'Production Security Services'),),429             (('organizationalUnitName',430               'Terms of use at www.verisign.com/rpa (c)06'),),431             (('commonName', 'www.verisign.com'),))}432```433434which is a fairly poorly-formed `subject` field.435436### 17.3.4.3. Работа на стороне сервера437438For server operation, typically you’d need to have a server certificate, and private key, each in a file. You’d open a socket, bind it to a port, call `listen()` on it, then start waiting for clients to connect:439440```python441import socket, ssl442443bindsocket = socket.socket()444bindsocket.bind(('myaddr.mydomain.com', 10023))445bindsocket.listen(5)446```447448When one did, you’d call `accept()` on the socket to get the new socket from the other end, and use [`wrap_socket()`](https://python-all.ru/3.1/library/ssl.html#ssl.wrap_socket) to create a server-side SSL context for it:449450```python451while True:452    newsocket, fromaddr = bindsocket.accept()453    connstream = ssl.wrap_socket(newsocket,454                                 server_side=True,455                                 certfile="mycertfile",456                                 keyfile="mykeyfile",457                                 ssl_version=ssl.PROTOCOL_TLSv1)458    try:459        deal_with_client(connstream)460    finally:461        connstream.shutdown(socket.SHUT_RDWR)462        connstream.close()463```464465Then you’d read data from the `connstream` and do something with it till you are finished with the client (or the client is finished with you):466467```python468def deal_with_client(connstream):469    data = connstream.read()470    # null-данные означают, что клиент завершил работу с нами471    while data:472        if not do_something(connstream, data):473            # будем считать, что do_something возвращает False474            # когда мы закончили с клиентом475            break476        data = connstream.read()477    # закончили с клиентом478```479480И вернуться к ожиданию новых подключений клиентов.481482> **См. также**483>484> **Класс [`socket.socket`](https://python-all.ru/3.1/library/socket.html#socket.socket)**485>486> Документация базового класса487>488> [`socket`](https://python-all.ru/3.1/library/socket.html#module-socket)489>490> **[Introducing SSL and Certificates using OpenSSL](https://python-all.ru/3.1/library/ssl.html)**491>492> Frederick J. Hirsch493>494> **[RFC 1422: Улучшение конфиденциальности для интернет-электронной почты: Часть II: Управление ключами на основе сертификатов](https://python-all.ru/3.1/library/ssl.html)**495>496> Steve Kent497>498> **[RFC 1750: Рекомендации по случайности для безопасности](https://python-all.ru/3.1/library/ssl.html)**499>500> D. Eastlake et. al.501>502> **[RFC 3280: Инфраструктура открытых ключей Internet X.509 – профиль сертификатов и списков отзыва](https://python-all.ru/3.1/library/ssl.html)**503>504> Housley et. al.505