For the context of this specific problem, refer this [link] (Manually performing TLS handshake with Gmail server for secure sign-in). It would explain why the manual implementation is needed.
I'm interested in manually performing a TLS handshake with Gmail's server (Or any other application server) to establish a secure channel for signing in. As I understand, when we open the Gmail page in a browser, the browser first performs a TLS handshake with the Gmail server before sending the username/password over that secure channel.
I'd like to achieve the same thing programmatically in Python but with manual control over key generation, encryption, and decryption. Specifically, I want to generate the private/public keys manually and handle the encryption/decryption process myself.
Is it possible to accomplish this? If so, could someone provide guidance or examples on how to proceed?
This is what I have so far. But there could be a better way too.
import socketfrom cryptography.hazmat.backends import default_backendfrom cryptography.hazmat.primitives.asymmetric import rsafrom cryptography.hazmat.primitives import serializationdef send_message(sock, message): sock.sendall(message)def receive_message(sock): buffer_size = 4096 data = b"" while True: chunk = sock.recv(buffer_size) if not chunk: break data += chunk if len(chunk) < buffer_size: break return data# Define the server's hostname and portserver_hostname = 'www.gmail.com'server_port = 443 # HTTPS default port# Create a TCP socketsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)print("start")# Connect to the serversock.connect((server_hostname, server_port))print("connect")# Start TLS handshake manuallysend_message(sock, "CLIENT_HELLO".encode())server_hello = receive_message(sock)print("received")print("Server Hello:", server_hello)# Parse server_hello message and extract server's public key and other parameters# Generate RSA key pair for the clientprivate_key_client = rsa.generate_private_key( public_exponent=65537, key_size=2048)print("Client Private Key:", private_key_client)public_key_client = private_key_client.public_key()print("Client Public Key:", public_key_client)# Serialize client's public keypublic_key_client_pem = public_key_client.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo)print("Serialized CLient Public Key", public_key_client_pem)send_message(sock, public_key_client_pem)encrypted_server_public_key_and_cert = receive_message(sock)print("Server Response: ", encrypted_server_public_key_and_cert)# I receive nothing
The terminal output is given below.
startconnectreceivedServer Hello: b'\x15\x03\x01\x00\x02\x02F'Client Private Key: <cryptography.hazmat.bindings._rust.openssl.rsa.RSAPrivateKey object at 0x7f50c7de9bb0>Client Public Key: <cryptography.hazmat.bindings._rust.openssl.rsa.RSAPublicKey object at 0x7f50c7002d70>Serialized CLient Public Key b'-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwQSEVSmYyBWsJvp2h/wN\nsP7LtbrBRInDKO4S0kTGzM2vp1ZSHSyL4odwsVaRvZmiSEtUwekTBqHfHMYvfL4s\npLwFtMydROaOYgX0kIc3+qWlVt1R299GvuyHp1WpUqMol9jwjwhBoZuRMaNtAPhB\nCjnYHG32ns+Xe0O1vSLdeTFkUWmWm6HzgDE/V7fFVMXjkoKLfkz9N2pxetb1NriQ\nFuiyhw68nVG1IrZhj75npPkX8nPPiMwLAYu86qR3Q1MACWZSBqsosvNzPekvBUAF\nMNZmPY/IMNOfQPUbMim3zLSTcTh77JQUxqh85558kAM1aDsdfTVtE6FSDqrAwdhV\nywIDAQAB\n-----END PUBLIC KEY-----\n'Server Response: b''
I either receive an empty response or get a BrokenPipeError error.