Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用TLS和Python进行身份验证_Python_Authentication_Ssl_Twisted - Fatal编程技术网

使用TLS和Python进行身份验证

使用TLS和Python进行身份验证,python,authentication,ssl,twisted,Python,Authentication,Ssl,Twisted,我想为一个运行在Raspberry Pi上的软件编写一个小的更新脚本,它的工作方式类似于本地服务器。它应该连接到web中的主服务器,以获取软件更新,并验证软件的许可证。 为此,我设置了两个python脚本。我想让它们通过TLS插座连接。然后客户端检查服务器证书,服务器检查它是否是授权客户端之一。我使用twisted on找到了解决方案 现在还剩下一个问题。我想知道哪个客户端(取决于证书)正在建立连接。在Python3中使用twisted有没有办法做到这一点 我对每个答案都很满意。一句话:是的,这

我想为一个运行在Raspberry Pi上的软件编写一个小的更新脚本,它的工作方式类似于本地服务器。它应该连接到web中的主服务器,以获取软件更新,并验证软件的许可证。 为此,我设置了两个python脚本。我想让它们通过TLS插座连接。然后客户端检查服务器证书,服务器检查它是否是授权客户端之一。我使用twisted on找到了解决方案

现在还剩下一个问题。我想知道哪个客户端(取决于证书)正在建立连接。在Python3中使用twisted有没有办法做到这一点


我对每个答案都很满意。

一句话:是的,这是完全可能的,所有必要的东西都是 移植到Python3上-我在Mac上的Python3.4下测试了以下所有内容,它似乎 干得好

简单的回答是 "" 但考虑到要达到这一点需要大量的准备工作 可能的话,我已经构建了一个完整的工作示例,您应该能够 试一试,并以此为基础

对于后代,您首先需要生成一些客户端证书 由同一CA签署。您可能已经这样做了,但其他人也可以这样做 理解答案并自己尝试(这样我就可以测试我的答案) 回答我自己;-)),他们需要这样的代码:

# newcert.py
from twisted.python.filepath import FilePath
from twisted.internet.ssl import PrivateCertificate, KeyPair, DN

def 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 caCert

def 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.encode("utf-8")).dumpPEM()
    FilePath(name.encode("utf-8") + b".client.private.pem").setContent(pem)
使用此程序,您可以创建一些证书,如下所示:

$ python newcert.py a
$ python newcert.py b
现在,您应该有一些可以使用的文件:

$ ls -1 *.pem
a.client.private.pem
b.client.private.pem
ca-private-cert.pem
然后您需要一个使用这些证书之一的客户端,并发送一些 数据:

最后,一个能够区分它们的服务器:

# whichclient.py
from twisted.python.filepath import FilePath
from twisted.internet.endpoints import SSL4ServerEndpoint
from twisted.internet.ssl import PrivateCertificate, Certificate
from twisted.internet.defer import Deferred
from twisted.internet.task import react
from twisted.internet.protocol import Protocol, Factory

class ReportWhichClient(Protocol):
    def dataReceived(self, data):
        peerCertificate = Certificate.peerFromTransport(self.transport)
        print(peerCertificate.getSubject().commonName.decode('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
,然后运行
pythontlsclient.py;
python tlsclient.py b
在另一个窗口中,并查看打印出来的
whichclient.py
a
b
分别通过
commonName
证书主题中的字段

这里需要注意的一点是,您最初可能希望将该调用提交给
Certificate.peerFromTransport
到一个
connectionMade
方法中;那不会的 工作 ; 希望它最终会实现,但在它实现之前,你必须等到你成功 从对等方接收到一些经过身份验证的数据,以确保握手成功 完整的。对于几乎所有的应用程序,这都很好,因为 已收到执行任何操作的指示(在您的情况下,下载更新)
同行必须已经发送了证书。

感谢您提供了这一伟大而完整的解决方案以及您的快速帮助。这是向我的脚本的最终解决方案迈出的一大步。@Glyph是否可以让客户端在Windows上使用类似pyinstaller的东西?还是twisted不再支持windows?你的站点的windows部分已经过时了:(@nsij22 Twisted在windows上仍然完全受支持,事实上,我最近一直在投入大量精力。最新的版本更容易“
pip安装”
”例如,在Windows上。是的,类似pyinstaller的东西应该可以工作。如果不行,请报告问题并在扭曲列表上讨论(或者在这里问另一个问题,一个问题的评论太小,无法适当讨论)。@Glyph删除了我的旧评论并发表了一篇新文章
# whichclient.py
from twisted.python.filepath import FilePath
from twisted.internet.endpoints import SSL4ServerEndpoint
from twisted.internet.ssl import PrivateCertificate, Certificate
from twisted.internet.defer import Deferred
from twisted.internet.task import react
from twisted.internet.protocol import Protocol, Factory

class ReportWhichClient(Protocol):
    def dataReceived(self, data):
        peerCertificate = Certificate.peerFromTransport(self.transport)
        print(peerCertificate.getSubject().commonName.decode('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, [])