Что мне нужно распространять (ключи, сертификаты) для соединения Python с SSL-сокетом? - PullRequest
0 голосов
/ 06 января 2011

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

Я застрял с 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, либо cert на любом из ящиков, и я получил следующую ошибку, независимо от того, что я удаляю:

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

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

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

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

Спасибо Кафе за помощь в выяснении проблемы. На основании его рекомендации я создал две новые пары сертификатов: spaceman и dmgr. Затем я помещаю обе части «spaceman» (key, cert) в клиентскую программу и то же самое для ключей «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')

1 Ответ

4 голосов
/ 06 января 2011

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

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

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

  • что сертификат действителен (то есть подписан ЦС, которому вы доверяете для этого приложения, не истек, не отозван); и
  • Соответствует одноранговому узлу, к которому вы думаете , с которым вы подключены (т. Е. Сертификат соответствует идентификатору, который запрашивает одноранговый узел). Эта идентификационная информация хранится в поле SubjectName сертификата, и это зависит от приложения, как вы сопоставляете ее с одноранговой идентификацией (это может быть имя пользователя для входа в систему, DNS-имя или что-то еще).
...