Denizhalil

Python: Creating an Encrypted Server and Client

Introduction

In this article, we’ll demonstrate how to establish secure communication using Python. We’ll create a basic encryption application using the cryptography library to ensure that data sent between a server and a client remains confidential. The server and client applications will communicate over a network, encrypting and decrypting data as it is transmitted.

Before starting the article, I recommend you to read our server/client connection article in its unencrypted version 😉

Server Application: server.py
import socket
from cryptography.fernet import Fernet

# Generate key
key = Fernet.generate_key()
cipher_suite = Fernet(key)


# Create server socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Server address and port
host = "127.0.0.1"  # localhost
port = 12345

# Connect the server socket to the specified address and port
server_socket.bind((host, port))

# Set the maximum number of connections we will accept
server_socket.listen(5)
print(f"\tServer {host}:{port} Works.")
print(f"\nthe key: {key}")
while True:
    # Accept the connection
    client_socket, addr = server_socket.accept()
    print(f"Connection accepted from: {addr} ")

    # Receive encrypted data from client
    encrypted_data = client_socket.recv(1024)
    
    # decode data
    decrypted_data = cipher_suite.decrypt(encrypted_data).decode("utf-8")
    print(f"Message from Client: {decrypted_data}")

    # Send response to client (encrypted)
    response = "Response from the server: I received your message!"
    encrypted_response = cipher_suite.encrypt(response.encode("utf-8"))
    client_socket.send(encrypted_response)

    # close connection
    client_socket.close()

The server application creates a server socket that listens on a specific port and accepts incoming connections. It receives encrypted data and decrypts it before sending a response.

Client Application: client.py
import socket
from cryptography.fernet import Fernet

# Set key (server-side generated key)
key = input('enter the key: ')

# Create client socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Server address and port
server_host = "127.0.0.1"  # localhost
server_port = 12345

# Connect to server
client_socket.connect((server_host, server_port))

# Prepare the message to be encrypted
message = "Hello, it's server"
encrypted_message = Fernet(key).encrypt(message.encode("utf-8"))

# Send encrypted message to server
client_socket.send(encrypted_message)

# Get encrypted response from server
encrypted_response = client_socket.recv(1024)

# solve the answer
decrypted_response = Fernet(key).decrypt(encrypted_response).decode("utf-8")
print(f"Response from server: {decrypted_response}")

# close connection
client_socket.close()

The client application creates a client socket to connect to the server and sends an encrypted message. It decrypts the encrypted response received from the server and presents it to the user.

program outputs

To listen to the output of the program, I first checked it with Wireshark, then I checked it by writing a simple script in Python.

wireshark output:

python output:

Code Explanations

In this section, we’ll explain important code segments in both applications:

  • Key Generation: The server application generates the encryption key to be used between both applications.
  • Server Socket Creation: The server creates a socket to listen on a specific IP address and port.
  • Client Connection: The client establishes a connection to the server using a specified IP address and port.
  • Message Encryption and Sending: The client encrypts a message for transmission to the server.
  • Receiving and Decrypting Messages: The server receives the encrypted message from the client, decrypts it, and sends a response.

Conclusion

In this article, we’ve learned the fundamentals of establishing secure communication using Python. We’ve created server and client applications using the cryptography library, which can be particularly useful when sensitive data needs to be transmitted securely. These applications can serve as a starting point and can be extended for more complex projects.

Encryption is a critical concept for network security and privacy, and using a flexible language like Python makes developing such applications accessible. For increased security and privacy requirements, further research and additional security measures should be explored and implemented.

Leave a Comment

Join our Mailing list!

Get all latest news, exclusive deals and academy updates.