我正在尝试编写一个通用的服务器客户端应用程序,它将能够在服务器之间交换数据。
我已经阅读了相当多的 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 的行为。我真的需要将私钥和公共证书分发给所有客户吗?
我试图避免任何巨大的安全问题,而泄露私钥往往会是一个大问题......
感谢您的帮助!
=================================================== ================
感谢caf帮我解决了这个问题。根据他的推荐,我创建了两个新的证书对:spaceman 和 dmgr。然后,我将两个“spaceman”部分(密钥、证书)放入客户端程序中,“dmgr”密钥也同样如此。
基本上,尽管在 openssl 方面做了很多工作,但 Client 中仅更改了以下两行。
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')
I'm trying to write a generic server-client application that will be able to exchange data amongst servers.
I've read over quite a few OpenSSL documents, and I have successfully setup my own CA and created a cert (and private key) for testing purposes.
I'm stuck with Python 2.3, so I can't use the standard "ssl" library. Instead, I'm stuck with PyOpenSSL, which doesn't seem bad, but there aren't many documents out there about it.
My question isn't really about getting it working. I'm more confused about the certificates and where they need to go.
Here are my two programs that do work:
Server:
#!/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)
Client:
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()
I found this information from ftp://ftp.pbone.net/mirror/ftp.pld-linux.org/dists/2.0/PLD/i586/PLD/RPMS/python-pyOpenSSL-examples-0.6-2.i586.rpm which contains some example scripts.
As you might gather, I don't fully understand the sections between the " # ????????." I don't get why the certificate and private key are needed on both the client and server. I'm not sure where each should go, but shouldn't I only need to distribute one part of the key (probably the public part)? It undermines the purpose of having asymmetric keys if you still need both on each server, right?
I tried alternating removing either the pkey or cert on either box, and I get the following error no matter which I remove:
OpenSSL.SSL.Error: [('SSL routines', 'SSL3_READ_BYTES', 'sslv3 alert handshake failure'), ('SSL routines', 'SSL3_WRITE_BYTES', 'ssl handshake failure')]
Could someone explain if this is the expected behavior for SSL. Do I really need to distribute the private key and public cert to all my clients?
I'm trying to avoid any huge security problems, and leaking private keys would tend to be a big one...
Thanks for the help!
==================================================================
Thanks to caf for helping me figure out the problem. Based on his recommendation, I created two new certificate pairs: spaceman and dmgr. I then put both of the "spaceman" parts (key, cert) in the client program, and the same for the "dmgr" keys.
Basically, only the following two lines in Client changed, although there was plently of work with openssl on the side.
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')
Corrected version:
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)
在 SSL 事务中,每一方都可以出示证书来向另一方验证其身份。为此,它需要拥有与该证书对应的私钥。这些证书旨在成为两个不同的证书,因此每一方都将拥有两个不同的私钥。
此证书/私钥对是您使用
use_privatekey_file()
和use_certificate_file()
设置的一对。这应该是服务器和客户端上不同的证书/密钥对。验证对等证书时,您需要检查:
SubjectName
字段中,如何将其映射到对等身份(可能是用户登录名、DNS 名称或其他名称)是特定于应用程序的。In an SSL transaction, each side can present a certificate to verify its identity to the other side. To do this, it needs to have the private key corresponding to that certificate. These are intended to be two different certificates, so each side will have two different private keys.
This certificate/private key pair is the one that you are setting using
use_privatekey_file()
anduse_certificate_file()
. This should be a different certificate/key pair on the server and the client.When verifying the peers certificate, you then need to check:
SubjectName
field of the certificate, and it is application-specific how you map this to a peer identity (it might be a user login name, a DNS name, or something else).