我目前正在尝试编写一个 python 服务器脚本,该脚本应该根据其公钥对当前客户端进行身份验证。由于我使用的是 twisted,因此 twisted 文档中的示例让我开始了。
虽然我可以使用示例代码生成密钥、连接和通信,但我还没有找到以可用格式获取客户端公钥的方法。在这个 stackexchange 问题中,有人从对象中提取公钥,OpenSSL.crypto.PKey
但无法将其转换为可读格式。由于我可以在方法中或通过我的协议的任何方法访问PKey
x509 证书的对象,这将是一个不错的方法。(不接受)答案建议尝试. 不幸的是,这并没有真正产生预期的结果:虽然答案中的and可以通过简单的文本替换函数来修复,但 base64 字符串似乎与公钥不匹配。我已经提取了公钥verifyCallback
self.transport.getPeerCertificate()
crypto.dump_privatekey(PKey)
BEGIN PRIVATE KEY
BEGIN PRIVATE KEY
openssl rsa -in client.key -pubout > client.pub
正如这里提到的。dump_privatekey
它与函数的结果不匹配。
虽然在 launchpad 上仍然存在针对 OpenSSL 的开放错误,但尚未修复。这是 19 个月前报道的,最近(2012 年 10 月)有一些活动,我不希望在回购中快速修复。
client.pub
您是否还有其他想法如何以与我上面提到的文件相当的格式获取公钥?也许有一个扭曲的或 OpenSSL 连接特定的对象来保存此信息。请注意,我必须将公钥存储在协议对象中,以便以后可以访问它。
为什么没有答案被接受?
JF Sebastian 的 M2Crypto
抱歉,我没有想到我无法将证书与连接相关联的可能性。我添加了必须将公钥存储在协议实例中的要求。因此,按照 JF Sebastian 的建议peerX509.as_pem()
在函数内部使用postConnectionCheck
是行不通的。此外,至少在 python-m2crypto 的 0.21.1-2ubuntu3 版本中,我必须调用peerX509.get_rsa().as_pem()
以获得正确的公钥。使用peerX509.as_pem(None)
(因为peerX509.as_pem()
仍然需要密码)产生与 PyOpenSSL 完全相同的输出crypto.dump_privatekey(PKey)
。也许有一个错误。
除此之外,答案向我展示了一种使用以下Echo
协议类编写另一种解决方法的可能方法:
class Echo(Protocol):
def dataReceived(self, data):
"""As soon as any data is received, write it back."""
if self.transport.checked and not self.pubkeyStored:
self.pubkeyStored = True
x509 = m2.ssl_get_peer_cert(self.transport.ssl._ptr())
if x509 is not None:
x509 = X509.X509(x509, 1)
pk = x509.get_pubkey()
self.pubkey = pk.get_rsa().as_pem()
print pk.as_pem(None)
print self.pubkey
self.transport.write(data)
如您所见,这使用了一些我想阻止的内部类。我正在犹豫是否提交一个小补丁,它将向M2Crypto.SSL.TwistedProtocolWrappergetCert
中的类添加一个方法。TLSProtocolWrapper
即使它被上游接受,它也会破坏我的脚本与除了最先进的 m2crypto 版本之外的任何版本的兼容性。你会怎么做?
我的外部 OpenSSL 调用
好吧,这是一个基于外部系统命令的丑陋解决方法,在我看来,这比访问非公共属性还要糟糕。