# Practical 5 – RSA Public-Key Authentication: Server
# Install: pip install cryptography
import secrets
import socket
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding

def receive_exact(conn, size):
    data = b""
    while len(data) < size:
        part = conn.recv(size - len(data))
        if not part:
            raise ConnectionError("Client disconnected")
        data += part
    return data

with open("client_public.pem", "rb") as file:
    public_key = serialization.load_pem_public_key(file.read())

with socket.socket() as server:
    server.bind(("127.0.0.1", 7777))
    server.listen(1)
    print("Local RSA server listening on port 7777")
    conn, _ = server.accept()
    with conn:
        challenge = secrets.token_bytes(32)
        conn.sendall(challenge)
        signature = receive_exact(conn, 256)
        try:
            public_key.verify(signature, challenge, padding.PKCS1v15(),
                              hashes.SHA256())
            conn.sendall(b"AUTH_OK")
            print("RSA authentication successful")
        except InvalidSignature:
            conn.sendall(b"AUTH_FAILED")
            print("RSA authentication failed")

# What this code does: sends a random challenge to a local client and checks
# its RSA signature to demonstrate key-based authentication.
