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