如何使用Python验证具有证书颁发机构的公钥?

时间:2015-01-20 12:09:15

标签: python ssl openssl public-key-encryption x509

import OpenSSL

key = ...
signature = ...
data = ...

x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1, key)
OpenSSL.crypto.verify(x509, signature, data, 'sha1')

到目前为止,我能够毫无问题地完成所有这些工作。但是,它并不觉得这是足够的安全性,因为密钥本身是通过URL(我应该信任*)给我的,并且构建签名的方法是公开可用的。

因此,据说密钥被“VeriSign Class 3 Code Signing 2010 CA”验证,有人可以告诉我如何检查这是一个有效的声明吗?

我猜我需要在我的机器上本地获得VeriSign证书。假设我这样做,我从那里去哪里?

谢谢!

* URL作为JSON请求中的参数提供给我。当然,URL将是HTTPS,我可以检查域名和所有这些。但似乎我应该对证书本身进行检查

2 个答案:

答案 0 :(得分:2)

也许我只能部分解决你的问题。您最大的担心似乎是获取密钥的渠道的安全性。您没有显示任何获取该密钥的代码,但您说您通过HTTPS检索它,现在您想通过证书验证来验证此连接的真实性。

您可以使用完善的第三方Web客户端框架requests轻松完成此操作。

引自the docs

  

请求可以验证HTTPS请求的SSL证书,就像a   网页浏览器。要检查主机的SSL证书,您可以使用验证   参数:

requests.get(url, verify=True)

此外:

  

您可以将证书路径验证通过证书的CA_BUNDLE文件   受信任的CA.

后者可能看起来像

requests.get(url, verify='/path/to/cert.pem')

如果您确实想要控制(并降低复杂性),请从http://www.symantec.com/page.jsp?id=roots加载正确的文件并采用verify='/path/to/cert.pem'方法。我想你需要http://www.symantec.com/content/en/us/enterprise/verisign/roots/Class-3-Public-Primary-Certification-Authority-G2.pem

答案 1 :(得分:2)

你应该检查证书本身是对的。是的,您需要VeriSign根证书(以及任何其他具有完整信任链的中间证书),该证书签署了要检查的证书。

可以在here中找到zipfile的当前Symantec(VeriSign)根证书。

下载并解压缩zip文件,找到您希望信任的所有证书,并将它们(以pem格式)放在一个证书包文件中。

现在您需要进行实际验证。不幸的是,您需要的OpenSSL调用是X509_verify_certificate。我查看了pyopenssl和M2Crypto的源代码,并且都没有公开该调用,所以没有直接的Python代码可以调用来验证这些软件包中的任何一个。

但是,由于您使用的是pyopenssl,因此您显然可以使用openssl库。因此,您可能已经或可以轻松安装openssl命令行工具集。如果是这样,您可以通过管道调用openssl verify命令,方法如下:

cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1, key)
# the command like likes pem format
cert_pem = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)

# the bundle that you created from the zip extraction
certificate_bundle = 'verisign-root-bundle.pem'

# Pipe the cert to the openssl verify command and check the return code
# a return code of 0 is successful verify
import subprocess
p = subprocess.Popen(['openssl', 'verify', '-CAfile', certificate_bundle],
                     stdin=subprocess.PIPE)
p.communicate(input=cert_pem)
p.wait()
if (p.returncode == 0):
    print('Certificate Verified.')
else:
    print('Problem with certificate')

上面的管道运行命令

openssl verify -CAfile ca.bundle certificate.pem

最后,如果您不熟悉openssl,则显示证书的命令是

openssl x509 -inform PEM -text -in certificate.pem

希望这有帮助!