Instant Messaging App With Vigenère Encryption (Python)

Python Instant Messaging With Vigenere Cipher

Over the last few weeks I have been looking at ciphers and encryption, which has included a Python program to brute force the Caesar cipher, Python to encrypt / decrypt with the Vigenère cipher , some Morse code and RSA Public Keys.

With my recent looks into encryption, especially the look into the Vigenere Cipher, I decided today to try and create a messaging application that includes some encryption. Messaging applications with encryption are quite popular and it seemed like a good way to put my knowledge to the test. With that in mind I turned to my favourite language, Python and the sockets library. I’ve not used sockets (as far as I can remember) since my port scanner project last summer.

The application has four functions:

  • message_server
  • message_client
  • vigenere_enc
  • vigenere_dec

vigenere_enc and vigenere_dec are both straight from my Vigenère Python and handle the encryption and decryption of the message.

message_server is run on the device that will act as the messaging server. Once running it waits for a message from the device acting as the messaging client.

message_client runs on the device that will act as the client. With a device running as the server it can connect and start messaging.

The HOST variable is set to the IP address of the device that is being the server. Most port numbers below 1023 are already allocated, so I would recommend choosing a higher number. Remember to make sure the port number is allowed through your firewall if you have a firewall enabled.

The message_server uses the bind options of socket, and then listens for a connection.

The message_client uses connect option of socket to connect to the IP address and port number that the server has bind.

A loop is used to keep the connection open so that messages can be sent back and forth. Once the loop is closed (by sending /q to cause a break), the close option of socket is used to cleanly close the socket connection. If the program errors or this command is not received then the address/port may stay open until the device is rebooted.

UTF-8 encoding is used to send the encrypted message. UTF-8 is widely used across the world wide web and supports both ASCII and Unicode characters. Check out: https://en.wikipedia.org/wiki/UTF-8for more information about UTF-8.

Time stamps of the server starting up and when the messages are received are pulled from the datetime module.

The encryption key in the below is “test” and the as the Vigenère cipher is symmetric encryption the same key is used for decryption. Both client and server need to use the same key.

Further improvements needed: automatic recovery if the pipe is broken (lost connection / lost packets), option to send messages without awaiting a reply, logging (of server errors and messages). Possibly change from Vigenère cipher to something a little more recent.

I’ve used the program between my Raspberry Pi 4 and my MacBook, with the Pi as message_server() and my MacBook as message_client().

Python Instant Messaging With Vigenere Cipher
Python Instant Messaging With Vigenere Cipher
Python Instant Messaging With Vigenere Cipher
Python Instant Messaging With Vigenere Cipher
Python Instant Messaging With Vigenere Cipher
Python Instant Messaging With Vigenere Cipher
Python Instant Messaging With Vigenere Cipher
Python Instant Messaging With Vigenere Cipher
Python Instant Messaging With Vigenere Cipher
Python Instant Messaging With Vigenere Cipher

#!/usr/bin/python3
# GeekTechStuff
# Libraries to import
# socket handles the connection between devices
import socket
from datetime import datetime
# encryption keys (lower case)
enc_key = “test”
dec_key = enc_key
# Alphabet needed for encryption / decryption
alphabet = “abcdefghijklmnopqrstuvwxyz”
def message_server():
# Details of the device running the server
# HOST is an IP address (requires “”)
HOST = “192.168.0.48”
PORT = 44441
MAX_SIZE = 2048
NOW = datetime.now()
# Establising the connections
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((HOST,PORT))
print(“Server Starting: “, NOW)
print(“Awaiting Client…”)
print(“Send /q to client to exit”)
s.listen(1)
client,addr = s.accept()
# While loop to keep connection open
whileTrue:
data = client.recv(MAX_SIZE)
message_received = data.decode(‘utf-8’)
decrypted = vigenere_dec(message_received)
if decrypted == ‘/q’:
break
print(NOW,” Message Received: “)
print(decrypted)
message_to_client = input(“Enter message to send: “)
message_to_client = message_to_client.lower()
encrypted = vigenere_enc(message_to_client)
message_to_client_encoded = encrypted.encode(‘utf-8’)
client.send(message_to_client_encoded)
if message_to_client == ‘/q’:
encrypted = vigenere_enc(message_to_client)
message_to_client_encoded = encrypted.encode(‘utf-8’)
client.send(message_to_client_encoded)
break
# closing connection
client.close()
s.close()
return()
def message_client():
# Details of the device to connect to
# HOST is an IP address (requires “”)
HOST = “192.168.0.48”
PORT = 44441
MAX_SIZE = 2048
NOW = datetime.now()
# Establising the connections
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((HOST,PORT))
# Informing user that connection is being established
print(“Client Starting: “, NOW)
print(” To exit send /q to server!”)
print(“Awaiting Server…”)
# While loop to keep connection open
whileTrue:
message_to_server = input(“Enter message to server: “)
message_to_server = message_to_server.lower()
encrypted = vigenere_enc(message_to_server)
# UTF-8 is the dominant encoding for the world wide web
message_to_server_encoded = encrypted.encode(‘utf-8’)
s.send(message_to_server_encoded)
if message_to_server == ‘/q’:
break
data = s.recv(MAX_SIZE)
if data.decode(‘utf-8’) == ‘/q’:
break
print(NOW,” Message Received: “)
message_received = data.decode(‘utf-8’)
decrypted = vigenere_dec(message_received)
print(decrypted)
# Closing connection
s.close()
return()
def vigenere_enc(message):
input_string = “”
enc_string = “”
# Takes string from user
input_string = message
input_string = input_string.lower()
# Lengths of input_string
string_length = len(input_string)
# Expands the encryption key to make it longer than the inputted string
expanded_key = enc_key
expanded_key_length = len(expanded_key)
while expanded_key_length < string_length:
# Adds another repetition of the encryption key
expanded_key = expanded_key + enc_key
expanded_key_length = len(expanded_key)
key_position = 0
for letter in input_string:
if letter in alphabet:
# cycles through each letter to find it’s numeric position in the alphabet
position = alphabet.find(letter)
# moves along key and finds the characters value
key_character = expanded_key[key_position]
key_character_position = alphabet.find(key_character)
key_position = key_position + 1
# changes the original of the input string character
new_position = position + key_character_position
if new_position >= 26:
new_position = new_position – 26
new_character = alphabet[new_position]
enc_string = enc_string + new_character
else:
enc_string = enc_string + letter
return(enc_string)
def vigenere_dec(message):
input_string = “”
dec_string = “”
# Takes string from user
input_string = message
input_string = input_string.lower()
# Lengths of input_string
string_length = len(input_string)
# Expands the encryption key to make it longer than the inputted string
expanded_key = dec_key
expanded_key_length = len(expanded_key)
while expanded_key_length < string_length:
# Adds another repetition of the encryption key
expanded_key = expanded_key + dec_key
expanded_key_length = len(expanded_key)
key_position = 0
for letter in input_string:
if letter in alphabet:
# cycles through each letter to find it’s numeric position in the alphabet
position = alphabet.find(letter)
# moves along key and finds the characters value
key_character = expanded_key[key_position]
key_character_position = alphabet.find(key_character)
key_position = key_position + 1
# changes the original of the input string character
new_position = position – key_character_position
if new_position >= 26:
new_position = new_position + 26
new_character = alphabet[new_position]
dec_string = dec_string + new_character
else:
dec_string = dec_string + letter
return(dec_string)

I have uploaded the code for the Python instant messaging app to my GitHub and it is available at: https://github.com/geektechdude/Python_Encryption/blob/master/geektechstuff_vigenere_socket_chat.py

I have included a few links to my own blog posts but if you want more to learn more about encryption / ciphers then I recommend the FutureLearn course from the Raspberry Pi Foundation – https://www.futurelearn.com/courses/encryption-and-cryptography , and it is free.