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.)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
#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.)
_______________________________________________________________________
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
Post a Comment