I have a python TLS server using a self signed certificate. 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. 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?
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.