Что мне нужно распространять (ключи, сертификаты) для Python с подключением через SSL-сокет?

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

Я застрял на Python 2.3, поэтому не могу использовать стандартную библиотеку «ssl». Вместо этого я остановился на PyOpenSSL, который кажется неплохим, но по нему не так много документов.

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

Вот две мои программы, которые работают:

Сервер:

#!/bin/env python

from OpenSSL import SSL
import socket
import pickle

def verify_cb(conn, cert, errnum, depth, ok):
    print('Got cert: %s' % cert.get_subject())
    return ok


ctx = SSL.Context(SSL.TLSv1_METHOD)
ctx.set_verify(SSL.VERIFY_PEER|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)

# ??????
ctx.use_privatekey_file('./Dmgr-key.pem')
ctx.use_certificate_file('Dmgr-cert.pem')
# ??????
ctx.load_verify_locations('./CAcert.pem')

server = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))

server.bind(('', 50000))
server.listen(3)

a, b = server.accept()

c = a.recv(1024)
print(c)

Клиент:

from OpenSSL import SSL
import socket
import pickle


def verify_cb(conn, cert, errnum, depth, ok):
    print('Got cert: %s' % cert.get_subject())
    return ok

ctx = SSL.Context(SSL.TLSv1_METHOD)
ctx.set_verify(SSL.VERIFY_PEER, verify_cb)

# ??????????
ctx.use_privatekey_file('/home/justin/code/work/CA/private/Dmgr-key.pem')
ctx.use_certificate_file('/home/justin/code/work/CA/Dmgr-cert.pem')
# ?????????
ctx.load_verify_locations('/home/justin/code/work/CA/CAcert.pem')

sock = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
sock.connect(('10.0.0.3', 50000))

a = Tester(2, 2)
b = pickle.dumps(a)
sock.send("Hello, world")

sock.flush()
sock.send(b)
sock.shutdown()
sock.close()

Я нашел эту информацию на ftp://ftp.pbone.net/mirror/ftp.pld-linux.org/dists/2.0/PLD/i586/PLD/RPMS/python-pyOpenSSL-examples- 0.6-2.i586.rpm, который содержит несколько примеров скриптов.

Как вы могли догадаться, я не до конца понимаю разделы между " # ????????." Я не понимаю, почему сертификат и закрытый ключ нужны как на клиенте, так и на сервере. Я не уверен, куда каждый из них должен идти, но разве мне не нужно распространять только одну часть ключа (вероятно, открытую часть)? Это подрывает цель иметь асимметричные ключи, если вам все еще нужны оба на каждом сервере, верно?

Я попытался попеременно удалить ключ pkey или сертификат в любом поле, и я получаю следующую ошибку независимо от того, что я удаляю:

OpenSSL.SSL.Error: [('Процедуры SSL', 'SSL3_READ_BYTES', 'Ошибка рукопожатия предупреждения sslv3'), ('Подпрограммы SSL', 'SSL3_WRITE_BYTES', 'Ошибка рукопожатия ssl')]

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

Спасибо за помощь!

==================================================================

Спасибо caf за помощь в решении проблемы. По его рекомендации я создал две новые пары сертификатов: spaceman и dmgr. Затем я поместил обе части «космонавта» (ключ, сертификат) в клиентскую программу и то же самое для ключей «dmgr».

По сути, изменились только следующие две строки в Client, хотя на стороне было много работы с openssl.

ctx.use_privatekey_file('/home/justin/code/work/CA/private/Dmgr-key.pem')
ctx.use_certificate_file('/home/justin/code/work/CA/Dmgr-cert.pem')

Исправленная версия:

ctx.use_privatekey_file('/home/justin/code/work/CA/private/spaceman-key.pem')
ctx.use_certificate_file('/home/justin/code/work/CA/spacemancert.pem')

person fandingo    schedule 05.01.2011    source источник
comment
У меня проблемы с тем же (ошибка рукопожатия ssl). Не могли бы вы точно сказать, что представляет собой каждый из ваших файлов pem. Потому что у меня это: 1) client.key содержит только закрытый ключ клиента. (это я использую в файле use_privatekey_file) 2) ca.crt имеет только сертификат ca в блоке, начинающемся с ===BEGIN CERTIFICATE=== и заканчивающемся на ===END CRTIFICATE=== 3) client.crt, который имеет весь сертификат как общее имя клиента, информация о состоянии .... и затем еще один блок случайных символов   -  person Lelouch Lamperouge    schedule 25.04.2011


Ответы (1)


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

Эта пара сертификат/закрытый ключ устанавливается с помощью use_privatekey_file() и use_certificate_file(). Это должна быть разная пара сертификат/ключ на сервере и клиенте.

При проверке сертификата пиров вам необходимо проверить:

  • Что сертификат действителен (то есть подписан ЦС, которому вы доверяете для этого приложения, не просрочен, не отозван); и
  • Соответствует узлу, к которому вы, думаете, подключены (то есть сертификат соответствует удостоверению, заявленному узлом). Это удостоверение хранится в поле SubjectName сертификата, и то, как вы сопоставляете его с удостоверением однорангового узла (это может быть имя пользователя для входа в систему, имя DNS или что-то еще), зависит от приложения.
person caf    schedule 06.01.2011
comment
Большое спасибо каф. Я думал о SSL больше как о ключах SSH. Я забыл, что вся идея SSL заключается в том, чтобы не нуждаться в предварительном распределении ключей, а только в корневом ЦС. Не было необходимости копировать мои открытые или закрытые ключи на другой сервер. Причина, по которой мои программы работали ранее, была связана не с сопоставлением ключей между компьютерами, а с сопоставлением ключей (открытого и закрытого) в двух функциях проверки. См. исправленный код выше. - person fandingo; 06.01.2011