[英]How can I do certificate pinning for TLS sockets in python 2.7?
I have a python TLS server using a self signed certificate. 我有一个使用自签名证书的python TLS服务器。 That works. 这样可行。 The code looks like this for now: 现在的代码如下所示:
#!/usr/bin/python
import socket, ssl
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile="server.crt", keyfile="server.key")
bindsocket = socket.socket()
bindsocket.bind(('127.0.0.1', 8888))
bindsocket.listen(5)
while True:
newsocket, fromaddr = bindsocket.accept()
connstream = context.wrap_socket(newsocket, server_side=True)
try:
print("Got connection!")
finally:
connstream.shutdown(socket.SHUT_RDWR)
connstream.close()
I am now trying to make a client in python that connects to this server. 我现在正在尝试在python中建立连接到该服务器的客户端。 On the first connection attempt, I'd like to retrieve either the public key, or a hash of the public key, and then verify this on all future connections. 第一次尝试连接时,我想检索公共密钥或公共密钥的哈希,然后在以后的所有连接中进行验证。 How can I do with with python and the ssl package? 如何使用python和ssl包?
This is the code I'm playing with: 这是我正在使用的代码:
#!/usr/bin/python
import ssl, socket, pprint
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = False
cnx = context.wrap_socket(socket.socket(socket.AF_INET), certfile="server.crt")
cnx.connect(('127.0.0.1', 8888))
pprint.pprint(cnx.getpeercert())
As it stands right now, it fails because there is no certificate chain to verify the cert. 就目前而言,它失败了,因为没有证书链可以验证证书。 I don't care about that, though. 不过,我不在乎。 All I care about is that the server I'm talking to has the private key that matches the public key. 我只关心与之交谈的服务器具有与公钥匹配的私钥。 What do I do? 我该怎么办?
So I've made this work, though it's not exactly what I hoped for. 所以我做了这项工作,尽管这并不是我所希望的。 My biggest complaint is that it requires storing the entire server certificate in a file on disk, whereas really all I care about is the public key. 我最大的抱怨是,它需要将整个服务器证书存储在磁盘上的文件中,而我真正关心的只是公共密钥。 However, here's what I have working: 但是,这是我的工作:
#!/usr/bin/python
import ssl, socket, pprint, os, sys
# If we haven't retrieved the certificate previously...
if not os.path.isfile('server_cert.pem'):
# Grab the cert
cert = ssl.get_server_certificate(('127.0.0.1', 8888))
# If it worked...
if cert:
# Write it to a file
with open('server_cert.pem', 'w') as f:
f.write(cert)
else:
sys.exit()
# Prepare context, including reference to the server's certificate
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = False
context.load_verify_locations(cafile='server_cert.pem')
cnx = context.wrap_socket(socket.socket(socket.AF_INET))
# Connect and evaluate
cnx.connect(('127.0.0.1', 8888))
I'll wait a bit to mark this answer accepted to see if someone can find a cleaner way of doing this. 我将稍等一下以将此答案标记为已接受,以查看是否有人可以找到一种更干净的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.