如何使用 Python 通过证书颁发机构验证 public 密钥?

How to authenticate a public key with certificate authority using Python?

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,我可以检查域名等等。但似乎我应该检查证书本身

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

您可以使用完善的第三方 Web 客户端框架轻松地做到这一点 requests

引自the docs

Requests can verify SSL certificates for HTTPS requests, just like a web browser. To check a host’s SSL certificate, you can use the verify argument:

requests.get(url, verify=True)

还有:

You can pass verify the path to a CA_BUNDLE file with certificates of trusted CAs.

后者可能看起来像

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

如果您真的想控制(并降低复杂性),则从 http://www.symantec.com/page.jsp?id=roots and take the verify='/path/to/cert.pem' approach. I guess you need http://www.symantec.com/content/en/us/enterprise/verisign/roots/Class-3-Public-Primary-Certification-Authority-G2.pem

加载正确的文件

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

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

下载并解压缩 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

希望对您有所帮助!