{"id":344,"date":"2023-08-05T12:01:19","date_gmt":"2023-08-05T12:01:19","guid":{"rendered":"https:\/\/python.garden\/?p=344"},"modified":"2023-08-07T16:17:39","modified_gmt":"2023-08-07T16:17:39","slug":"sending-encrypted-messages-with-a-simple-chat-program-in-python","status":"publish","type":"post","link":"https:\/\/python.garden\/index.php\/2023\/08\/05\/sending-encrypted-messages-with-a-simple-chat-program-in-python\/","title":{"rendered":"Sending Encrypted Messages with a Simple Chat Program in Python"},"content":{"rendered":"\n<p>In the era of cyber threats, privacy and data security have become paramount. One of the most effective ways to protect data during transmission is through encryption. In this article, we will guide you to create a simple chat program in Python that sends encrypted messages.<\/p>\n\n\n\n<p>Before we start, you need to have Python installed on your computer. You also need to install a couple of Python libraries &#8211; <code>socket<\/code> for creating a network connection, and <code>cryptography<\/code> for encryption. If not already installed, you can add these with pip:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">pip install cryptography<\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Creating the Chat Server<\/h3>\n\n\n\n<p>Here&#8217;s a simple chat server that can accept connections from multiple clients:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">import socket\nimport threading\n\nclass Server:\n    def __init__(self, host = '127.0.0.1', port = 55555):\n        self.host = host\n        self.port = port\n        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        self.server.bind((self.host, self.port))\n        self.server.listen()\n        self.clients = []\n        self.nicknames = []\n        \n\n    def broadcast(self, message):\n        for client in self.clients:\n            client.send(message)\n\n    def handle(self, client):\n        while True:\n            try:\n                message = client.recv(1024)\n                self.broadcast(message)\n            except:\n                index = self.clients.index(client)\n                self.clients.remove(client)\n                client.close()\n                nickname = self.nicknames[index]\n                self.nicknames.remove(nickname)\n                self.broadcast(f'{nickname} left the chat!'.encode('ascii'))\n                break\n\n    def receive(self):\n        while True:\n            client, address = self.server.accept()\n            print(f'Connected with {str(address)}')\n\n            client.send('NICK'.encode('ascii'))\n            nickname = client.recv(1024).decode('ascii')\n            self.nicknames.append(nickname)\n            self.clients.append(client)\n\n            print(f'Nickname of the client is {nickname}!')\n            self.broadcast(f'{nickname} joined the chat!'.encode('ascii'))\n            client.send('Connected to the server!'.encode('ascii'))\n\n            thread = threading.Thread(target=self.handle, args=(client,))\n            thread.start()\n\nif __name__ == &quot;__main__&quot;:\n    server = Server()\n    server.receive()<\/pre><\/div>\n\n\n\n<p>This server will accept connections, handle incoming messages, and broadcast messages to all connected clients.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Creating the Chat Client<\/h3>\n\n\n\n<p>Next, we create a chat client that can connect to the server and send\/receive messages:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">import socket\nimport threading\n\nclass Client:\n    def __init__(self, host = '127.0.0.1', port = 55555):\n        self.nickname = input(&quot;Enter your nickname: &quot;)\n        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        self.client.connect((host, port))\n\n    def receive(self):\n        while True:\n            try:\n                message = self.client.recv(1024).decode('ascii')\n                if message == 'NICK':\n                    self.client.send(self.nickname.encode('ascii'))\n                else:\n                    print(message)\n            except:\n                print(&quot;Error!&quot;)\n                self.client.close()\n                break\n\n    def write(self):\n        while True:\n            message = f'{self.nickname}: {input(&quot;&quot;)}'\n            self.client.send(message.encode('ascii'))\n\n    def run(self):\n        receive_thread = threading.Thread(target=self.receive)\n        receive_thread.start()\n\n        write_thread = threading.Thread(target=self.write)\n        write_thread.start()\n\nif __name__ == &quot;__main__&quot;:\n    client = Client()\n    client.run()<\/pre><\/div>\n\n\n\n<p>This client will connect to the server, send its nickname, and then send\/receive messages.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Adding Encryption<\/h3>\n\n\n\n<p>So far, we have created a simple chat program, but the messages are sent in plain text. To enhance security, we need to encrypt the messages using the <code>cryptography<\/code> library. We&#8217;ll use Fernet symmetric encryption for simplicity.<\/p>\n\n\n\n<p>First, we generate a key and save it to a file:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">from cryptography.fernet import Fernet\n\nkey = Fernet.generate_key()\nwith open(&quot;secret.key&quot;, &quot;wb&quot;) as key_file:\n    key_file.write(key)<\/pre><\/div>\n\n\n\n<p>Both the server and client should have access to this key file. We can load the key with:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">def load_key():\n    return open(&quot;secret.key&quot;, &quot;rb&quot;).read()<\/pre><\/div>\n\n\n\n<p>We can create a couple of helper functions for encryption and decryption:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">from cryptography.fernet import Fernet\n\ndef encrypt_message(message, key):\n    encoded_message = message.encode()\n    f = Fernet(key)\n    encrypted_message = f.encrypt(encoded_message)\n    return encrypted_message\n\ndef decrypt_message(encrypted_message, key):\n    f = Fernet(key)\n    decrypted_message = f.decrypt(encrypted_message)\n    return decrypted_message.decode()<\/pre><\/div>\n\n\n\n<p>Now, we can modify our server and client code to use these encryption and decryption functions. For the server, before broadcasting a message, we encrypt it, and before displaying a received message, we decrypt it. Similarly, for the client, before sending a message, we encrypt it, and before printing a received message, we decrypt it.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Before we dive deeper.<\/h3>\n\n\n\n<p>The code presented here is a basic implementation and can be further enhanced by handling more edge cases, enhancing user experience, and improving security. Encryption is a vital aspect of secure communication, and using Python to achieve it is straightforward due to its powerful libraries.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How the Server Works<\/h2>\n\n\n\n<p>In the previous section, we&#8217;ve introduced a Server class that is designed to accept connections from multiple clients, receive messages, and broadcast them to all connected clients. Here, we&#8217;ll go through this Server class in detail, breaking down its various components and how they work.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">class Server:\n    def __init__(self, host = '127.0.0.1', port = 55555):\n        self.host = host\n        self.port = port\n        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        self.server.bind((self.host, self.port))\n        self.server.listen()\n        self.clients = []\n        self.nicknames = []<\/pre><\/div>\n\n\n\n<p>In the <code>__init__<\/code> method, we initialize our Server class. We create a socket object and bind it to the provided host and port. We then set the server to listen for incoming connections. We also initialize two empty lists, <code>clients<\/code> and <code>nicknames<\/code>, to keep track of all connected clients and their corresponding nicknames.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">def broadcast(self, message):\n    for client in self.clients:\n        client.send(message)<\/pre><\/div>\n\n\n\n<p>The <code>broadcast<\/code> method is used to send a message to all connected clients. It iterates through the list of clients and sends the message to each one.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">def handle(self, client):\n    while True:\n        try:\n            message = client.recv(1024)\n            self.broadcast(message)\n        except:\n            index = self.clients.index(client)\n            self.clients.remove(client)\n            client.close()\n            nickname = self.nicknames[index]\n            self.nicknames.remove(nickname)\n            self.broadcast(f'{nickname} left the chat!'.encode('ascii'))\n            break<\/pre><\/div>\n\n\n\n<p>The <code>handle<\/code> method is used to handle incoming messages from each client. For each client, it starts an infinite loop where it tries to receive messages from the client and broadcast them. If receiving a message fails, which can happen if the client has disconnected, it removes the client from the clients list, closes the socket, removes the client&#8217;s nickname from the nicknames list, and broadcasts a message to the other clients that this client has left the chat.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">def receive(self):\n    while True:\n        client, address = self.server.accept()\n        print(f'Connected with {str(address)}')\n\n        client.send('NICK'.encode('ascii'))\n        nickname = client.recv(1024).decode('ascii')\n        self.nicknames.append(nickname)\n        self.clients.append(client)\n\n        print(f'Nickname of the client is {nickname}!')\n        self.broadcast(f'{nickname} joined the chat!'.encode('ascii'))\n        client.send('Connected to the server!'.encode('ascii'))\n\n        thread = threading.Thread(target=self.handle, args=(client,))\n        thread.start()<\/pre><\/div>\n\n\n\n<p>The <code>receive<\/code> method is used to accept new connections. For each new connection, it sends the string &#8216;NICK&#8217; to prompt the client to send its nickname. It then adds the new client and its nickname to the respective lists, broadcasts a message to the other clients that a new client has joined, and starts a new thread to handle this client&#8217;s messages.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">if __name__ == &quot;__main__&quot;:\n    server = Server()\n    server.receive()<\/pre><\/div>\n\n\n\n<p>Finally, if this script is being run directly (and not being imported as a module), it creates a Server object and starts the <code>receive<\/code> method to start accepting connections.<\/p>\n\n\n\n<p>This sums up the server&#8217;s functionality. The main thread of the server is used to accept new connections, while a separate thread is created for each client to handle its messages. All messages are broadcast to all connected clients.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How the Client Works.<\/h2>\n\n\n\n<p>Absolutely! In the previous section, we&#8217;ve introduced a Client class that is designed to connect to a server and send\/receive messages. Now, let&#8217;s break down the Client class and how it functions.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">class Client:\n    def __init__(self, host = '127.0.0.1', port = 55555):\n        self.nickname = input(&quot;Enter your nickname: &quot;)\n        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        self.client.connect((host, port))<\/pre><\/div>\n\n\n\n<p>In the <code>__init__<\/code> method, the client is asked to input a nickname which is stored in <code>self.nickname<\/code>. A socket object is created and it attempts to connect to the server at the given host and port.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">def receive(self):\n    while True:\n        try:\n            message = self.client.recv(1024).decode('ascii')\n            if message == 'NICK':\n                self.client.send(self.nickname.encode('ascii'))\n            else:\n                print(message)\n        except:\n            print(&quot;Error!&quot;)\n            self.client.close()\n            break<\/pre><\/div>\n\n\n\n<p>The <code>receive<\/code> method is designed to continuously listen for incoming messages from the server. It runs an infinite loop that waits for messages and decodes them. If the received message is &#8216;NICK&#8217;, the client sends back its nickname to the server. Any other message is printed to the console. If there&#8217;s an exception (like the server disconnecting), it prints an error message, closes the client connection, and breaks the loop.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">def write(self):\n    while True:\n        message = f'{self.nickname}: {input(&quot;&quot;)}'\n        self.client.send(message.encode('ascii'))<\/pre><\/div>\n\n\n\n<p>The <code>write<\/code> method allows the client to write messages to the server. It runs an infinite loop that takes input from the user, prefixes it with the client&#8217;s nickname, encodes it, and sends it to the server.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">def run(self):\n    receive_thread = threading.Thread(target=self.receive)\n    receive_thread.start()\n\n    write_thread = threading.Thread(target=self.write)\n    write_thread.start()<\/pre><\/div>\n\n\n\n<p>The <code>run<\/code> method is responsible for running the client&#8217;s processes. It creates and starts two threads: one for receiving messages from the server and one for writing messages to the server. The use of separate threads allows the client to write and receive messages simultaneously.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">if __name__ == &quot;__main__&quot;:\n    client = Client()\n    client.run()<\/pre><\/div>\n\n\n\n<p>Finally, if this script is being run directly (and not being imported as a module), it creates a Client object and calls the <code>run<\/code> method to start the client&#8217;s operations.<\/p>\n\n\n\n<p>The client&#8217;s main functionality includes sending messages to the server and receiving messages from the server. It uses separate threads to perform these tasks concurrently, enabling real-time chat.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Using the key, in theory.<\/h2>\n\n\n\n<p>In our chat program, we&#8217;ve used symmetric encryption with the <code>cryptography<\/code> library, specifically the Fernet encryption method. Symmetric encryption uses the same key for both the encryption and decryption of the message.<\/p>\n\n\n\n<p>Before the client and server can start exchanging encrypted messages, they must agree on a secret key. This secret key must be generated once and shared between the server and the client. It&#8217;s crucial to keep this key secure, as anyone with access to the key can decrypt the messages.<\/p>\n\n\n\n<p>Here is how the key is generated:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">from cryptography.fernet import Fernet\n\nkey = Fernet.generate_key()\nwith open(&quot;secret.key&quot;, &quot;wb&quot;) as key_file:\n    key_file.write(key)<\/pre><\/div>\n\n\n\n<p>This code generates a new key using Fernet&#8217;s <code>generate_key<\/code> function and writes it to a file named <code>secret.key<\/code>.<\/p>\n\n\n\n<p>To use this key in encryption and decryption, it needs to be loaded from the file. Here is a simple function to load the key:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">def load_key():\n    return open(&quot;secret.key&quot;, &quot;rb&quot;).read()<\/pre><\/div>\n\n\n\n<p>This function simply opens the <code>secret.key<\/code> file in binary mode, reads the contents, and returns them.<\/p>\n\n\n\n<p>After the key is loaded, it can be used in the <code>encrypt_message<\/code> and <code>decrypt_message<\/code> functions:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">def encrypt_message(message, key):\n    encoded_message = message.encode()\n    f = Fernet(key)\n    encrypted_message = f.encrypt(encoded_message)\n    return encrypted_message\n\ndef decrypt_message(encrypted_message, key):\n    f = Fernet(key)\n    decrypted_message = f.decrypt(encrypted_message)\n    return decrypted_message.decode()<\/pre><\/div>\n\n\n\n<p>In <code>encrypt_message<\/code>, the plain-text message is first encoded into bytes, then a Fernet object is created with the provided key. This object is used to encrypt the encoded message. The resulting encrypted message is in bytes format and is returned by the function.<\/p>\n\n\n\n<p>In <code>decrypt_message<\/code>, a Fernet object is again created with the provided key. This object is used to decrypt the encrypted message. The result is a byte string of the original message, which is then decoded back into a regular string and returned by the function.<\/p>\n\n\n\n<p>To send an encrypted message from the client to the server, the client would first call <code>encrypt_message<\/code> with its message and the shared key, then send the resulting encrypted message. On the server side, when receiving a message, the server would call <code>decrypt_message<\/code> with the received message and the shared key to obtain the original message.<\/p>\n\n\n\n<p>Likewise, to send an encrypted message from the server to the client, the server would first call <code>encrypt_message<\/code> with its message and the shared key, then send the resulting encrypted message. On the client side, when receiving a message, the client would call <code>decrypt_message<\/code> with the received message and the shared key to obtain the original message.<\/p>\n\n\n\n<p>Remember that it is crucial to keep the shared key secure. If an attacker gains access to this key, they can easily decrypt all messages. In a real-world application, you would want to use more advanced key management solutions to securely exchange and store the key.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Using the Key in Practice on the Server.<\/h2>\n\n\n\n<p>Sure! Here&#8217;s a simple chat server that uses the Fernet symmetric encryption scheme to encrypt and decrypt messages. I will create a &#8220;secret.key&#8221; file in the same directory as the script, you should replace it with your actual key.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">from cryptography.fernet import Fernet\nimport socket\nimport threading\n\nclass Server:\n    def __init__(self, host = '127.0.0.1', port = 55555):\n        self.host = host\n        self.port = port\n        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        self.server.bind((self.host, self.port))\n        self.server.listen()\n        self.clients = []\n        self.nicknames = []\n        self.key = self.load_key()\n        self.fernet = Fernet(self.key)\n\n    def load_key(self):\n        return open(&quot;secret.key&quot;, &quot;rb&quot;).read()\n\n    def broadcast(self, message):\n        encrypted_message = self.fernet.encrypt(message.encode('ascii'))\n        for client in self.clients:\n            client.send(encrypted_message)\n\n    def handle(self, client):\n        while True:\n            try:\n                encrypted_message = client.recv(1024)\n                decrypted_message = self.fernet.decrypt(encrypted_message).decode('ascii')\n                self.broadcast(decrypted_message)\n            except:\n                index = self.clients.index(client)\n                self.clients.remove(client)\n                client.close()\n                nickname = self.nicknames[index]\n                self.nicknames.remove(nickname)\n                self.broadcast(f'{nickname} left the chat!'.encode('ascii'))\n                break\n\n    def receive(self):\n        while True:\n            client, address = self.server.accept()\n            print(f&quot;Connected with {str(address)}&quot;)\n\n            client.send('NICK'.encode('ascii'))\n            nickname = client.recv(1024).decode('ascii')\n            self.nicknames.append(nickname)\n            self.clients.append(client)\n\n            print(f'Nickname of the client is {nickname}!')\n            self.broadcast(f'{nickname} joined the chat!'.encode('ascii'))\n            client.send('Connected to the server!'.encode('ascii'))\n\n            thread = threading.Thread(target=self.handle, args=(client,))\n            thread.start()\n\nif __name__ == &quot;__main__&quot;:\n    server = Server()\n    server.receive()<\/pre><\/div>\n\n\n\n<p>This server program encrypts messages before broadcasting them to clients and decrypts messages as they come in from clients. It uses the Fernet symmetric encryption scheme, where the same key is used for both encryption and decryption.<\/p>\n\n\n\n<p>Please note that the server and client must use the same encryption key for this to work. In this example, the key is loaded from a file named &#8220;secret.key&#8221;. You would want to implement a secure way of distributing the encryption key to both the server and the client in a real-world scenario.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Practical Client Implementation<\/h2>\n\n\n\n<p>Similar to the server, the client uses the key to create a <code>Fernet<\/code> object, which is then used to encrypt messages before they&#8217;re sent and to decrypt messages as they&#8217;re received. Let&#8217;s look at an example client script that uses symmetric encryption:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">import socket\nimport threading\nfrom cryptography.fernet import Fernet\n\nclass Client:\n    def __init__(self, host = '127.0.0.1', port = 55555):\n        self.nickname = input(&quot;Enter your nickname: &quot;)\n        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        self.client.connect((host, port))\n        self.key = self.load_key()\n        self.fernet = Fernet(self.key)\n\n    def load_key(self):\n        return open(&quot;secret.key&quot;, &quot;rb&quot;).read()\n\n    def receive(self):\n        while True:\n            try:\n                message = self.client.recv(1024)\n                decrypted_message = self.fernet.decrypt(message).decode('ascii')\n                if message == 'NICK':\n                    self.client.send(self.nickname.encode('ascii'))\n                else:\n                    print(decrypted_message)\n            except:\n                print(&quot;An error occured!&quot;)\n                self.client.close()\n                break\n\n    def write(self):\n        while True:\n            message = f'{self.nickname}: {input(&quot;&quot;)}'\n            encrypted_message = self.fernet.encrypt(message.encode('ascii'))\n            self.client.send(encrypted_message)\n\n    def run(self):\n        receive_thread = threading.Thread(target=self.receive)\n        receive_thread.start()\n\n        write_thread = threading.Thread(target=self.write)\n        write_thread.start()\n\nif __name__ == &quot;__main__&quot;:\n    client = Client()\n    client.run()<\/pre><\/div>\n\n\n\n<p>In this script, the <code>Client<\/code> class first loads the key from the <code>secret.key<\/code> file in its constructor. The key is used to create a <code>Fernet<\/code> object, which is stored in <code>self.fernet<\/code>.<\/p>\n\n\n\n<p>In the <code>receive<\/code> method, incoming messages (which are expected to be encrypted) are decrypted using the <code>self.fernet<\/code> object. Note that the decrypted message is decoded into a string before it&#8217;s printed to the console or compared to &#8216;NICK&#8217;.<\/p>\n\n\n\n<p>In the <code>write<\/code> method, messages are encrypted before they&#8217;re sent to the server. Each message is first encoded into bytes, then encrypted using the <code>self.fernet<\/code> object.<\/p>\n\n\n\n<p>A more secure method could be to use a key exchange algorithm like Diffie-Hellman, or to have a trusted third party distribute the keys.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Running the Server or the Client<\/h2>\n\n\n\n<p>We can create a Python script that asks the user whether they would like to launch a server or a client, and then launches the chosen one.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">from server import Server\nfrom client import Client\n\ndef launch():\n    choice = input(&quot;Would you like to launch a (s)erver or a (c)lient? &quot;)\n\n    if choice.lower() == &quot;s&quot;:\n        server = Server()\n        server.receive()\n    elif choice.lower() == &quot;c&quot;:\n        client = Client()\n        client.run()\n    else:\n        print(&quot;Invalid choice. Please enter 's' for server or 'c' for client.&quot;)\n\nif __name__ == &quot;__main__&quot;:\n    launch()<\/pre><\/div>\n\n\n\n<p>To run this script, the user would enter &#8216;s&#8217; to launch a server or &#8216;c&#8217; to launch a client. Note that the server and client code should be in separate Python files named &#8216;server.py&#8217; and &#8216;client.py&#8217; in the same directory as this script.<\/p>\n\n\n\n<p>This script assumes the existence of a <code>Server<\/code> class with a <code>receive<\/code> method in &#8216;server.py&#8217; and a <code>Client<\/code> class with a <code>run<\/code> method in &#8216;client.py&#8217;. These classes should be the server and client classes from the previous examples.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Launching the Server or the Client<\/h2>\n\n\n\n<p>Sure, you can use Python&#8217;s command-line interface to run the server and client scripts.<\/p>\n\n\n\n<p>Before running these commands, make sure you&#8217;re in the correct directory (the one that contains the server and client scripts). You can navigate to the correct directory with the <code>cd<\/code> command. For example:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">cd path\/to\/your\/directory<\/pre><\/div>\n\n\n\n<p>Replace <code>path\/to\/your\/directory<\/code> with the path to the directory that contains your scripts.<\/p>\n\n\n\n<p>Once you&#8217;re in the correct directory, you can run the server and client scripts with the <code>python<\/code> or <code>python3<\/code> command, followed by the script name.<\/p>\n\n\n\n<p>To launch the server, you would use:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">python server.py<\/pre><\/div>\n\n\n\n<p>or<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">python3 server.py<\/pre><\/div>\n\n\n\n<p>Depending on your system setup, you might need to use <code>python3<\/code> instead of <code>python<\/code> to specify that you want to use Python 3.<\/p>\n\n\n\n<p>The server script should start running and listening for incoming connections.<\/p>\n\n\n\n<p>To launch a client, you would open a new terminal or command prompt window, navigate to the correct directory as before, and then use:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">python client.py<\/pre><\/div>\n\n\n\n<p>or<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">python3 client.py<\/pre><\/div>\n\n\n\n<p>The client script should start running and attempt to connect to the server. You should be able to start sending and receiving messages.<\/p>\n\n\n\n<p>Remember, you need to replace <code>server.py<\/code> and <code>client.py<\/code> with the actual names of your server and client scripts if they are different. The <code>.py<\/code> extension indicates that these are Python scripts.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the era of cyber threats, privacy and data security have become paramount. One of the most effective ways to protect data during transmission is through encryption. In this article,&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[214,213],"tags":[],"class_list":["post-344","post","type-post","status-publish","format-standard","hentry","category-beginners-guide","category-python"],"featured_image_src":null,"author_info":{"display_name":"shababdoo","author_link":"https:\/\/python.garden\/index.php\/author\/shababdoo\/"},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/python.garden\/index.php\/wp-json\/wp\/v2\/posts\/344","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/python.garden\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/python.garden\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/python.garden\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/python.garden\/index.php\/wp-json\/wp\/v2\/comments?post=344"}],"version-history":[{"count":0,"href":"https:\/\/python.garden\/index.php\/wp-json\/wp\/v2\/posts\/344\/revisions"}],"wp:attachment":[{"href":"https:\/\/python.garden\/index.php\/wp-json\/wp\/v2\/media?parent=344"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/python.garden\/index.php\/wp-json\/wp\/v2\/categories?post=344"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/python.garden\/index.php\/wp-json\/wp\/v2\/tags?post=344"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}