The server generates/loads an RSA keypair and listens for TCP connections; a client connects, establishes an ephemeral AES session (encrypted with the server RSA key and signed by the client), and both sides then exchange AES-CBC + HMAC-SHA256 protected JSON messages over a persistent TCP connection.
d:\secure_chat\server.py— server implementation, RSA key persistence, handshake, per-connection session state, message receive loop.d:\secure_chat\client.py— client implementation and Streamlit UI (keeps socket in session_state for persistent session).d:\secure_chat\main.py— Streamlit UI glue that runs server in a background thread and exposes controls (start/stop server, connect/disconnect client, send messages).
- Server boots and loads or generates a long-term RSA keypair (persisted to
server_key.pem). - Client connects via TCP.
- Server immediately sends its RSA public key framed as:
(the
SERVER_PUB\n<server-public-pem>\n\n\n\nsequence is used as the message terminator). - Client generates an ephemeral AES session:
- AES key = 32 random bytes (AES-256)
- IV = 16 random bytes
session_blob = AESkey || IV
- Client encrypts
session_blobwith the server RSA public key using RSA-OAEP (SHA-256). - Client signs
session_blobusing its own RSA private key with PSS (SHA-256). - Client sends a JSON handshake (terminated by
\n\n):{ "enc_session": "<base64 RSA-OAEP(session_blob)>", "client_pub": "<base64 client public PEM>", "client_sig": "<base64 signature>" } - Server:
- base64-decodes fields,
- decrypts
enc_sessionwith its RSA private key to recover AES key and IV, - verifies
client_sigusing the providedclient_pub, - on success, stores per-connection state and accepts encrypted messages persistently on the same socket.
- Client and server exchange encrypted messages formatted as JSON messages (each terminated with
\n\n):{ "cipher": "<base64 of AES-CBC ciphertext>", "hmac": "<base64 of HMAC-SHA256 tag>" }
- Server public key header:
SERVER_PUB\n<PEM>\n\n
- Handshake JSON (client → server, terminated
\n\n):- enc_session, client_pub, client_sig (all base64-encoded)
- Encrypted message JSON (terminated
\n\n):- cipher: base64 AES-CBC ciphertext (PKCS#7 padded)
- hmac: base64 HMAC-SHA256 computed over the ciphertext using the session key
- Server long-term RSA key:
server_key.pem(persisted on disk). - Per-connection server state: global
clientsdict inserver.pymappingconn→{aes_key, aes_iv, client_pub, addr}. - Streamlit client state:
st.session_statestores the active socket and message queue so the client remains connected across reruns. - Server thread: started via
start_server()and runs accept loop in a daemon thread; each connection has a handler thread.
- Uses RSA-OAEP to protect the session blob (confidentiality).
- Uses RSA-PSS signatures for client authenticity.
- Uses AES for bulk encryption and HMAC-SHA256 for integrity.
- Use ephemeral ECDHE for forward secrecy.
- Use HKDF to derive distinct encryption and MAC keys from a shared secret.
- Switch to AEAD (AES-GCM or ChaCha20-Poly1305) to avoid separate HMAC and IV-handling.
- Rotate or include per-message nonces/IVs (do not reuse IVs for CBC).
- Add sequence numbers and anti-replay logic.
- Use length-prefixed framing instead of delimiter-based framing.
- Start the UI:
streamlit run d:\secure_chat\main.py - In the Streamlit sidebar:
- Click "Start server" — server listens on configured host/port and writes
server_key.pemif missing. - Click "Connect client" — client will perform the handshake and keep a socket in
st.session_state.
- Click "Start server" — server listens on configured host/port and writes
- In the main panel:
- Type messages and click "Send" — messages are encrypted and sent over the established session.
- Server logs will show decrypted plaintext lines until session end.
- Click "Stop server" or "Disconnect client" to end the session.
A simplified TLS-like demo:
- Server announces RSA public key.
- Client encrypts an ephemeral AES key+IV with RSA-OAEP and signs it.
- Server decrypts, verifies signature, and both sides then exchange AES-CBC-encrypted messages with HMAC-SHA256 over a persistent TCP connection.
- Streamlit UI keeps server thread and client socket alive so you can exercise the handshake and multiple message exchanges interactively.
