一言以蔽之: 是的 ,这是完全有可能的,并且所有必要的东西都被移植到了python 3-我在Mac上的Python
3.4下测试了以下所有内容,并且看起来工作正常。
简短的答案是“使用
twisted.internet.ssl.Certificate.peerFromTransport”,但是鉴于要进行尽可能多的设置需要尽可能多的设置,我构建了一个可以正常工作的示例,您应该可以尝试并继续。
为了后代,您首先需要生成一些由同一CA签名的客户端证书。您可能已经做到了,但是其他人可以理解答案并自己尝试一下(这样我就可以自己测试答案了;-)),他们需要这样的代码:
# newcert.pyfrom twisted.python.filepath import FilePathfrom twisted.internet.ssl import PrivateCertificate, KeyPair, DNdef getCAPrivateCert(): privatePath = FilePath(b"ca-private-cert.pem") if privatePath.exists(): return PrivateCertificate.loadPEM(privatePath.getContent()) else: caKey = KeyPair.generate(size=4096) caCert = caKey.selfSignedCert(1, CN="the-authority") privatePath.setContent(caCert.dumpPEM()) return caCertdef clientCertFor(name): signingCert = getCAPrivateCert() clientKey = KeyPair.generate(size=4096) csr = clientKey.requestObject(DN(CN=name), "sha1") clientCert = signingCert.signRequestObject( csr, serialNumber=1, digestAlgorithm="sha1") return PrivateCertificate.fromCertificateAndKeyPair(clientCert, clientKey)if __name__ == '__main__': import sys name = sys.argv[1] pem = clientCertFor(name.enpre("utf-8")).dumpPEM() FilePath(name.enpre("utf-8") + b".client.private.pem").setContent(pem)
使用此程序,您可以创建一些证书,如下所示:
$ python newcert.py a$ python newcert.py b
现在您应该可以使用一些文件了:
$ ls -1 *.pema.client.private.pemb.client.private.pemca-private-cert.pem
然后,您需要一个使用以下证书之一的客户端,并发送一些数据:
# tlsclient.pyfrom twisted.python.filepath import FilePathfrom twisted.internet.endpoints import SSL4ClientEndpointfrom twisted.internet.ssl import ( PrivateCertificate, Certificate, optionsForClientTLS)from twisted.internet.defer import Deferred, inlineCallbacksfrom twisted.internet.task import reactfrom twisted.internet.protocol import Protocol, Factoryclass SendAnyData(Protocol): def connectionMade(self): self.deferred = Deferred() self.transport.write(b"HELLOrn") def connectionLost(self, reason): self.deferred.callback(None)@inlineCallbacksdef main(reactor, name): pem = FilePath(name.enpre("utf-8") + b".client.private.pem").getContent() caPem = FilePath(b"ca-private-cert.pem").getContent() clientEndpoint = SSL4ClientEndpoint( reactor, u"localhost", 4321, optionsForClientTLS(u"the-authority", Certificate.loadPEM(caPem), PrivateCertificate.loadPEM(pem)), ) proto = yield clientEndpoint.connect(Factory.forProtocol(SendAnyData)) yield proto.deferredimport sysreact(main, sys.argv[1:])
最后,一个可以区分它们的服务器:
# whichclient.pyfrom twisted.python.filepath import FilePathfrom twisted.internet.endpoints import SSL4ServerEndpointfrom twisted.internet.ssl import PrivateCertificate, Certificatefrom twisted.internet.defer import Deferredfrom twisted.internet.task import reactfrom twisted.internet.protocol import Protocol, Factoryclass ReportWhichClient(Protocol): def dataReceived(self, data): peerCertificate = Certificate.peerFromTransport(self.transport) print(peerCertificate.getSubject().commonName.depre('utf-8')) self.transport.loseConnection()def main(reactor): pemBytes = FilePath(b"ca-private-cert.pem").getContent() certificateAuthority = Certificate.loadPEM(pemBytes) myCertificate = PrivateCertificate.loadPEM(pemBytes) serverEndpoint = SSL4ServerEndpoint( reactor, 4321, myCertificate.options(certificateAuthority) ) serverEndpoint.listen(Factory.forProtocol(ReportWhichClient)) return Deferred()react(main, [])
为了简单起见,我们将仅对服务器重用CA自己的证书,但是在更现实的情况下,您显然希望使用更合适的证书。
现在
whichclient.py,您可以在一个窗口中运行,然后
python tlsclient.py a; python tlsclient.pyb在另一个窗口中运行,然后查看
whichclient.py打印输出
a,然后
b分别通过
commonName
其证书主题中的字段来识别客户端。
需要注意的是,您最初可能希望将该调用
Certificate.peerFromTransport放入
connectionMade方法中。那行不通。
Twisted目前没有“
TLS握手完成”的回调;希望最终会成功,但是直到这样做之前,您必须等到从对等方收到一些经过身份验证的数据后,才能确保握手已完成。对于几乎所有应用程序来说,这都是很好的,因为到您收到执行任何 *** 作的说明时(对于您而言,是下载更新),对等方必须已经发送了证书。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)