import ssl, socket, traceback, sys ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) ctx.verify_mode = ssl.CERT_REQUIRED ctx.check_hostname = True ctx.load_default_certs() incoming, outgoing = ssl.MemoryBIO(), ssl.MemoryBIO() host = 'bugs.python.org' get=b'GET / HTTP/1.1\r\nHost: bugs.python.org\r\nConnection: close\r\n\r\n' # create the SSLObject for the client side of SSL. sslobj = ctx.wrap_bio(incoming, outgoing, server_hostname=host) # connect the socket and make the initial TCP connection sock = socket.create_connection((host, 443)) # start the handshake by attempting to encrypt the get request while True: try: sslobj.write(get) break # exit the loop if the write succeeds. except ssl.SSLWantReadError: # we expect this as handshake data must be exchanged # show the buffers' state print('SSLWantRead exception') print((incoming.pending, outgoing.pending)) sock.sendall(outgoing.read()) # send any outgoing data data = sock.recv(2048) incoming.write(data) print((incoming.pending, outgoing.pending)) print((incoming.pending, outgoing.pending)) sock.sendall(outgoing.read()) # Now the handshake is finished. The peer's certificate should # be available. try: print('Attempting to retrieve server cert') cert = sslobj.getpeercert(False) except: # unfortunately, this raises a ValueError exception traceback.print_exc(file=sys.stdout) # show the buffers' state before and after do_handshake call print('Before do_handshake()') print((incoming.pending, outgoing.pending)) sslobj.do_handshake() print('After do_handshake()') print((incoming.pending, outgoing.pending)) # no outward changes have occured because of the do_handshake() call. # In particular, a handshake has not begun. # However, now the getpeercert() call succeeds. cert = sslobj.getpeercert(False) print(cert) # close the connection, we don't really care about the response try: sslobj.unwrap() except: pass print('After ssl shutdown') print((incoming.pending, outgoing.pending)) sock.sendall(outgoing.read()) sock.close()