我试图找出如何在python中验证服务器的自签名证书。我在谷歌找不到太多数据。我还想确保服务器URL
提前感谢任何见解。
答案 0 :(得分:10)
从评论到我的第一个回复,我发现存在一个普遍的误解,即“验证证书意味着什么”。我将尝试在这里写一个简短的解释来消除一些幻想。
证书验证是针对某些加密签名检查证书元数据上的签名(即主题,有效期,扩展名等)。
如果验证的所有内容都是自签名证书,则除非您事先知道密钥证书的密钥,否则无法将其与具有完全相同元数据但具有完全相同元数据的另一个自签名证书区分开来。并且不要忘记您建立所有这些验证程序以取消具有此预共享知识的要求。通过定期证书验证,您无法完全删除具有某些预共享知识的要求,这是一组第三方证书,也称为“CA证书”。由于这些知识是预先共享的,因此这些证书可能是自签名的,但请记住,您已收到有关这些证书的有效性的信息,而不是来自验证过程,而是来自某些外部知识。
如果在对等体之间分配了一组受信任的“CA证书”,则可以使用这些证书签署其他证书,并根据可信CA的预共享知识检查签名。
但是,如果您对自签名证书没有其他知识,除了证书本身,您不能对此特定证书的信任做出任何假设,因为它可以由一些邪恶的黑客以及您值得信赖的服务器发布。 / p>
在实施任何类型的证书验证流程之前,请先获取有关Man in the middle attack,Public key infrastructure和Public key cryptography的一些知识。
请理解,对自签名证书的盲目验证不会保护您,甚至不会保护您自己网络中的聪明黑客,甚至不会考虑网络安全。
编辑:问题作者澄清说他实际上正在寻找如何使用M2Crypto绑定验证证书上的verisign(或其他CA)签名。以下是两个例子:
from M2Crypto import X509, SSL
# manual validation of a signature on a certificate using a given CA cert:
ca = X509.load_cert('/path/to/ca_cert.pem')
cert = X509.load_cert('certificate_to_validate.pem')
print "Verification results:", cert.verify(ca.get_pubkey())
# adding a given CA cert to the SSL Context for verification
ctx = SSL.Context()
# load a certificate from file
ctx.load_verify_locations(cafile='/path/to/ca_cert.pem')
# or use all certificate in a CA directory
ctx.load_verify_locations(capath='/path/to/ca/dir')
# or you can specify both options at the same time.
如果要使用包含许多CA证书的目录(通常更方便),则必须将每个证书重命名为<hash>.0
,其中<hash>
是证书主题的哈希值(通过{获得) {1}})。
答案 1 :(得分:2)
我假设您使用了一些OpenSSL绑定。我看到了两种解决问题的方法。
openssl version -d
以查看您的系统)。这将影响您机器上使用openssl的所有程序。
x509 = OpenSSL.crypto.load_certificate(...)
ctx = OpenSSL.SSL.Context(...)
store = ctx.get_cert_store()
store.add_cert(x509)
ctx.set_verify(VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, ...)
答案 2 :(得分:0)
由于其本质,无法验证自签名证书:它是自签名的。
您必须通过其他受信任的第三方证书签署证书才能验证任何内容,然后您可以将该第三方证书添加到您的可信CA列表中,然后您就可以验证签名证书通过该证书/ CA。
如果您需要有关如何在Python中执行此操作的建议,则应提供您正在使用的SSL库的名称,因为可以选择Python的SSL库。
答案 3 :(得分:0)
您询问了“使用 python 验证 SSL 中的对等点”。
我倾向于使用本地“信任存储” - 一个完整的目录或 .crt
、.pem
或 .der
文件,以基于该本地目录来验证服务器是否值得信赖证书:
#!/usr/bin/env python3
from socket import socket
import ssl
hostname = 'google.com'
port = 443
with socket() as sock:
sock.setblocking(True)
sock.connect((hostname, port))
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.verify_flags = 0x80000 # will verify if either the Root CA or Int CA is present for the server
context.load_verify_locations(cafile=None,
cadata=None,
capath="ca_files/")
with context.wrap_socket(sock=sock,
server_hostname=hostname,
do_handshake_on_connect=False) as ssl_sock:
ssl_sock.do_handshake()
print(hostname, ssl_sock.getpeername(), ssl_sock.version())
print(ssl_sock)
正如@abbott 所说 - 在运行该脚本之前 - 您需要 capath
的符号链接才能工作。如果您安装了 OpenSSL
,这将非常简单:
$ export CERTS=/path/to/ca_files
$ openssl/bin/c_rehash ${CERTS}
如果您不运行 c_rehash
,它将不起作用。如需更多信息man c_rehash
。