Pergunta

Estou tentando escrever um aplicativo genérico de servidor-cliente que poderá trocar dados entre os servidores. Eu li alguns documentos OpenSSL e configurei com sucesso minha própria CA e criei um cert (e chave privada) para fins de teste.

Estou preso ao Python 2.3, então não posso usar a biblioteca "SSL" padrão. Em vez disso, estou preso a Pyopenssl, o que não parece ruim, mas não há muitos documentos por aí.

Minha pergunta não é realmente sobre fazê -lo funcionar. Estou mais confuso sobre os certificados e para onde eles precisam ir.

Aqui estão meus dois programas que Faz trabalhar:

Servidor:

#!/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)

Cliente:

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()

Eu encontrei esta informação de ftp://ftp.pbone.net/mirror/ftp.pld-linux.org/dists/2.0/pld/i586/pld/rpms/python-pyopenssl-examples-0.6-2.i586.rpm que contém alguns scripts de exemplo.

Como você pode se reunir, eu não entendo completamente as seções entre o " # ????????". Não entendo por que o certificado e a chave privada são necessários tanto no cliente quanto no servidor. Não tenho certeza de onde cada um deve ir, mas não preciso distribuir uma parte da chave (provavelmente a parte pública)? Ele mina o objetivo de ter teclas assimétricas se você ainda precisar de ambas em cada servidor, certo?

Tentei alternar a remoção do PKEY ou do CERT em qualquer uma das caixas e recebo o seguinte erro, não importa o que eu removo:

OpenSSL.SSL.Error: [('SSL Routines', 'SSL3_Read_Bytes', 'SSLV3 Alert Handshake Faille'), ('SSL Rotines', 'SSL3_WRITE_BYTES', 'Falha de mão de mão SSL')]

Alguém poderia explicar se esse é o comportamento esperado para o SSL. Eu realmente preciso distribuir a chave privada e o certificado público para todos os meus clientes? Estou tentando evitar grandes problemas de segurança, e o vazamento de chaves privadas tenderia a ser grande ...

Obrigado pela ajuda!

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

Obrigado ao CAF por me ajudar a descobrir o problema. Com base em sua recomendação, criei dois novos pares de certificados: Spaceman e DMGR. Coloquei as duas partes do "Spaceman" (chave, cert) no programa de clientes e o mesmo para as teclas "DMGR".

Basicamente, apenas as duas linhas a seguir em Cliente mudou, embora houvesse um trabalho com o OpenSSL ao lado.

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')

Versão corrigida:

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

Solução

Em uma transação SSL, cada lado pode apresentar um certificado para verificar sua identidade para o outro lado. Para fazer isso, ele precisa ter a chave privada correspondente a esse certificado. Estes devem ser dois diferente Certificados, portanto, cada lado terá duas chaves privadas diferentes.

Este certificado/par de chaves privadas é o que você está definindo usando use_privatekey_file() e use_certificate_file(). Isso deve ser um diferente Certificado/par de chave no servidor e no cliente.

Ao verificar o certificado de pares, você precisa verificar:

  • Que o certificado é válido (isto é, assinado por uma CA em que você confia para este aplicativo, não expirado, não revogado); e
  • Corresponde ao par que você acho Você está conectado (ou seja, o certificado corresponde à identidade que o pares reivindica). Esta identidade é armazenada dentro do SubjectName Campo do certificado e é específico do aplicativo como você mapeia isso para uma identidade de pares (pode ser um nome de login de usuário, um nome de DNS ou outra coisa).
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top