CHAT ROOM WITH END-TO-END-ENCRYPTION 

USING SOCKET PROGRAMMING PYTHON



LEARNING:

  • Socket programming
  • Understanding TCP 
  • Diffe hellman key exchange
  • Encryption
  • Tkinter
  • Threading 

What is  one way function?
  There is no inverse  to this type of functions
         Eg -     5 mod 2 =1
11 mod 2 = 1
25 mod 2 = 1
Any odd no. mod 2 = 1
            Therefore, there are infinite possibilities  of odd numbers.
            Hence, even if we  know remainder and divisor we cannot say what is dividend. (here we are not                involving quotient, hence it is not possible to find the dividend .)

Note: this is modulus property

(g**A mod p)**B mod p =. (g**B mod p)**B mod p = (g **(A*B) mod) p mod p

The same thing is done in diffe hellman key exchange to generate same key

(to view image properly open in new tab.)


––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
            #diffi helman key gen 

class DH_Endpoint(object):
    def __init__(self, public_key1, public_key2, private_key):
        self.public_key1 = public_key1
        self.public_key2 = public_key2
        self.private_key = private_key
        self.full_key = None

    def generate_partial_key(self):
        partial_key = self.public_key1 ** self.private_key
        partial_key = partial_key % self.public_key2
        return partial_key

    def generate_full_key(self, partial_key_r):
        full_key = int(partial_key_r) ** self.private_key
        full_key = full_key % self.public_key2
        self.full_key = full_key
        return full_key
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
                               # encryption module 
class ENC(object):
    def __init__(self):
        self.name = "ram"


    def encrypt_message(self, message, key):
        encrypted_message = ""
        for c in message:
            encrypted_message += chr(ord(c) + key)
        return encrypted_message

    def decrypt_message(self, encrypted_message, key):
        decrypted_message = ""
        for c in encrypted_message:
            decrypted_message += chr(ord(c) - key)
        return decrypted_message
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
                                #prime no. program for generating random pub and priv key

class PrimeNo(object):
    def __init__(self, lower = 5000 , upper = 10000, primelist = []):
        self.upper = upper
        self.lower = lower
        self.primelist = primelist

    def prime(self):
        for x in range( self.lower, self.upper):
            for y in range(2, x):
                if True:
                    if x % y == 0:
                        break
                    else:
                        self.primelist.append(x)



        return  list(set(self.primelist))
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
                                      #server program
import socket
import threading
from DFHKE import  DH_Endpoint
from PrimeNo import PrimeNo
import random
from encrypt import ENC
from threading import *
import time

s = socket.socket()

s.bind(('localhost', 1234))

s.listen(100)
# keys
p = PrimeNo()#creating random prime no
a = p.prime()
pubkey = random.choice(a)# removing the no. from the list so that it wont repeat
a.pop(a.index(pubkey))
privkey = random.choice(a)

# list
keys = []
clients = []
encrp = ENC()




# defining functions

def sendall(message):
     for client in clients:# for every client and its perticular key is used to encrypt message and send
         index = clients.index(client)
         key = keys[index]
         client.send(bytes(encrp.encrypt_message(message, key),'utf-8'))




def receive(client):
    while True:# always listens and if receives sends all
        message = client.recv(1024).decode()
        index = clients.index(client)
        key = keys[index]
        dmessage = encrp.decrypt_message(message, key)
        sendall(dmessage)




def handle():
    while True:
      #diffi hellman exchange is started
        client, address = s.accept()
        client.send(bytes(str(pubkey), 'utf-8'))
        pub2 = int(float(client.recv(1024).decode()))
        serverkey = DH_Endpoint(pub2, pubkey, privkey)
        partialkey = serverkey.generate_partial_key()
        client.send(bytes(str(partialkey), 'utf-8'))
        partial2 = int(float(client.recv(1024).decode()))
        key = serverkey.generate_full_key(partial2)
        print("Connected with {}".format(str(address)))
        keys.append(key)
        clients.append(client)
        # key is generated and appended to the key list 
        # thread is started for a particular client to receive message
        thread = threading.Thread(target=receive, args=(client,))
        thread.start()
        



handle()
–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––--–
Server python program explanation


  • Ready to connect with a client.
  • Once connected key is generated
  • Once key is generated appends client and key in client list and key list
  • Note the index of client and key are same.
  • Starts a thread to receive message from clients
  • Decrypts message with the client key in the list of keys
  • Sends to broadcast.




(to view image properly open in new tab.)



(to view image properly open in new tab.)




––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
                                                                        #client program
import socket
import threading
from DFHME import DH_Endpoint
from PrimeNo import PrimeNo
import random
from encrypt import ENC
from tkinter import *


self = Tk()
self.title("CHAT ROOM {END-TO-END-ENCRYPTED}")
self.configure(bg='#000')
encrp = ENC()
client = socket.socket()
clientkeyone = []# list for key to store

#defining main function which is called when start button is clicked
def main():
    global  client
    self.update()
    global messagelist
    hostVar = hostEntry.get()# getting the value from entry
    port = int(portVar.get())#getting value from entry
    # Connecting To Server
    client.connect((hostVar, port))#connecting server

    # keys
    p = PrimeNo()#generating keys
    a = p.prime()
    pubkey = random.choice(a)
    a.pop(a.index(pubkey))# removing public key from the list to avoid repetation
    privkey = random.choice(a)


    # DFHMKE
    client.send(bytes(str(pubkey), 'utf-8'))
    pub2 = int(float(client.recv(1024).decode('utf-8')))
    clientkey = DH_Endpoint(pubkey, pub2, privkey)
    partialkey = clientkey.generate_partial_key()
    client.send(bytes(str(partialkey), 'utf-8'))
    partial2 = int(float(client.recv(1024).decode('utf-8')))
    key = clientkey.generate_full_key(int(partial2))
    clientkeyone.append(key)
    print(key)


    # defining functions

    def receive():#always ready to receive and decrypt
        while True:
            global  clientkeyone
            key = clientkeyone[0]
            message = client.recv(1024).decode('utf-8')
            dmessage = encrp.decrypt_message(message, key)
            messagelist.insert(END, dmessage)# this is our list which will be in our scroll bar

# starting thread for receiving
    receive_thread = threading.Thread(target=receive)
    receive_thread.start()




def sendall():# sending message to server
    global client
    key = clientkeyone[0]
    name = setsEntry.get()
    sendt = sendVar.get()
    #inputuser =input(" ")
    message = name + ":"+ sendt
    client.send(bytes(encrp.encrypt_message(message, key), 'utf-8'))
    sendVar.set("")

def quit():# when clicked detaches from server safely and removes the previous key
    global clientkeyone
    client.detach()
    clientkeyone = []
def reset():# resets the entries and starts a new socket
    global client
    hostEntry.delete(0, END)
    portVar.set('12345')
    client = socket.socket()
    self.update()


#name label and entry
setsLabel = Label(self, text = "YOUR NAME" , bg='#000', fg='#fff',font=("Arial", 30))
setsLabel.pack()
setsEntry = Entry(self,  bg='#000', fg='#fff', justify='center',font=("Arial", 30), width= 50)
setsEntry.pack()



#host ip
hostLabel = Label(self, text = "HOST NAME :", bg='#000', fg='#fff',font=("Arial", 30))
hostLabel.pack()
hostEntry = Entry(self, bg='#000', fg='#fff', justify='center',font=("Arial", 30), width= 50)
hostEntry.pack()
#hostVar.set()
#host = hostVar.get()




#port num
portLabel = Label(self, text="PORT NUMBER:",bg='#000', fg='#fff', font=("Arial", 30))
portLabel.pack()
portVar = DoubleVar()
portEntry = Entry(self, textvariable=portVar, bg='#000', fg='#fff', justify='center',font=("Arial", 30), width= 50)
portEntry.pack()
portVar.set("1234")


##
#start chat
b = Button(self, text = "START CHAT", command =main, bg='#000', fg='#000', pady=20, padx=5 )
b.pack()

#this is our scroll bar where all the messages are reflected
receivearea = Scrollbar(self)
receivearea.pack(side = RIGHT , fill = Y, ipady = 40 ,ipadx = 10)
messagelist = Listbox(self, yscrollcommand = receivearea.set, bg='#699',font=("Arial", 30), width= 50)
messagelist.pack(side = BOTTOM , fill = BOTH, ipady = 40)
receivearea.config( command = messagelist.yview )

#send label
sendLabel = Label(self, text = "Let's Send Somthing! : " , bg='#000', fg='#fff',font=("Arial", 30))
sendLabel.pack()
sendVar = StringVar()
sendEntry = Entry(self,textvariable= sendVar,  bg ='#000' , fg='#fff',font=("Arial", 40), width= 100)
sendEntry.pack()

#button for reset
br = Button(self, text="RESET", command=reset, bg='#000', fg='#000', pady=20, padx=5, font=("Arial", 10))
br.pack(side=LEFT)
#button to quit
bq = Button(self, text="QUIT", command=quit, bg='#000', fg='#000', pady=20, padx=5, font=("Arial", 10))
bq.pack(side=RIGHT)
#button to send message
bs = Button(self, text = "SEND >>>", command =sendall, bg='#000', fg='#000', pady=20, padx=5,font=("Arial", 30)  )
bs.pack()

# GUI in loop so only exits when window is closed
self.mainloop()
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

Client.py explanation


  • Connects with the server
  • Once connected key is generated
  • Key is stored in a variable
  • Starts a thread to receive and send message.
  • While sending encrypt with key and when received decrypts with key.
OUTPUT:

(to view image properly open in new tab.)

unencrypted:
(to view image properly open in new tab.)

when encrypted


 
(to view image properly open in new tab.)
_______________________________________________________________________

While working no this project i took reference from:
  • https://medium.com/@sadatnazrul/diffie-hellman-key-exchange-explained-python-8d67c378701c
  • NeuralNine  

To download all files refer my github repository- https://github.com/secureram/secureram


Comments

Popular posts from this blog