Session & Key Exchange Pabba Sumanth
1. Implement Diffie-Hellman Algorithm and DH Key exchange AP18110010172 CSE-C
def power(a,b,P):
if (b == 1):
return a;
else:
return ((pow(a, b)) % P);
P = int(input("Enter the prime number :"))
print("The value of P :", P)
G = int(input("Enter the primitve root for pervious prime number :"))
print("The value of G :", G)
a = int(input("Enter the chosen private key A :"))
print("The private key a :", a)
x = power(G, a, P)
b = int(input("Enter the chosen private key B :"))
print("The private key b :", b)
y = power(G, b, P)
ka = power(y, a, P)
kb = power(x, b, P)
print("Secret key for a is :", ka)
print("Secret Key for b is :", kb)
2. Encrypted communication over socket using AES
Server Code:
import base64
import hashlib
import socket
from Crypto import Random
from Crypto.Cipher import AES
class AESCipher(object):
def __init__(self, key):
self.bs = AES.block_size
self.key = hashlib.sha256(key.encode()).digest()
def encrypt(self, raw):
raw = self._pad(raw)
iv = Random.new().read(AES.block_size)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return base64.b64encode(iv + cipher.encrypt(raw.encode()))
def decrypt(self, enc):
enc = base64.b64decode(enc)
iv = enc[:AES.block_size]
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return
self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')
def _pad(self, s):
return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) %
self.bs)
@staticmethod
def _unpad(s):
return s[:-ord(s[len(s)-1:])]
string="Pabba Sumanth"
password="djknBDS89dHFS(*HFSD())"
enc_string=str(AESCipher(password).encrypt(string))
enc_string_2=AESCipher(password).encrypt(string)
dec_string=str(AESCipher(password).decrypt(enc_string_2))
print("This is the password " + password)
print("Decrypted string: " + string)
print("Encrypted string: " + enc_string)
print("Decrypted string (v2): " + str(dec_string))
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('10.0.2.15', 4444))
sock.listen(5)
print("Listening for connections...")
conn, addr = sock.accept()
conn.send(enc_string_2)
conn.close()
Client Code:
import socket
import base64
from Crypto import Random
from Crypto.Cipher import AES
import hashlib
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('10.0.2.15', 4444))
class AESCipher(object):
def __init__(self, key):
self.bs = AES.block_size
self.key = hashlib.sha256(key.encode()).digest()
def encrypt(self, raw):
raw = self._pad(raw)
iv = Random.new().read(AES.block_size)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return base64.b64encode(iv + cipher.encrypt(raw.encode()))
def decrypt(self, enc):
enc = base64.b64decode(enc)
iv = enc[:AES.block_size]
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-
8')
def _pad(self, s):
return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) %
self.bs)
@staticmethod
def _unpad(s):
return s[:-ord(s[len(s)-1:])]
password="djknBDS89dHFS(*HFSD())"
data=sock.recv(4096)
decoded=AESCipher(password).decrypt(data.decode('utf-8'))
print(str(decoded))
sock.close()
Output:
Session Key establishment using RSA
Server code:
import socket
import math
from random import choice, randint
import itertools as it
if __name__ == '__main__':
key=222
svr = socket.socket()
host = socket.gethostname()
print("Server will start on host:", host)
port = 5544
svr.bind((host, port))
print("Server is bound successfully")
svr.listen(1)
svr, addr = svr.accept()
print(addr, "has connected")
while 1:
r_msg = svr.recv(1024).decode()
print("\n*************** Message received *************")
print('received message :', r_msg)
k = r_msg.split('~')
#print(k)
session_key=int(k[1])
print('request received from client and response is being sent to
client from for the session key ',session_key)
rec_res=k[0]
encrypted_text='response from server for
'+rec_res+'~'+str(session_key)
print('sent message :', encrypted_text)
svr.send(encrypted_text.encode())
#Client side code :
import random
import math
import socket
from collections import namedtuple
class RSA:
def __init__(self):
self.key = namedtuple("Key",["modulus","exponent"])
def generateKeys(self):
# two distinct prime numbers p and q
p = self.__findPrime()
q = self.__findPrime()
# the modulus value
n = p * q
phi = (p - 1) * (q - 1)
e = self.__findExponent(phi)
d = self.__multiplicativeInverse(e,phi)
publicKey = self.key(n,e)
privateKey = self.key(n,d)
return publicKey, privateKey
def encrypt(self,message,key):
return self.__squareMultiply(message,key.exponent) % key.modulus
def decrypt(self,message,key):
return self.__squareMultiply(message,key.exponent) % key.modulus
def __isPrime(self,n):
# 2 and 3 are prime, 0 and 1 not
if n <= 3:
return n >= 2
# easy check for 2 and 3
if n % 2 == 0 or n % 3 == 0:
return False
# other numbers
for i in range(5, int(math.sqrt(n)) + 1, 6):
if n % i == 0 or n % (i + 2) == 0:
return False
return True
def __findPrime(self):
# look for the first 10-bit prime
n = random.randrange(1024)
while(self.__isPrime(n) == False):
n = random.randrange(1024)
return n
def __gcd(self,a,b):
temp = a
# switch a for b so that
# a is always greater b
if b > a:
a = b
b = temp
while(temp):
temp = a % b
a = b
b = temp
return a
def __findExponent(self,phi):
e = random.randrange(2,phi)
while(self.__gcd(phi,e) != 1):
e = random.randrange(2,phi)
return e
def __multiplicativeInverse(self,value,modulus):
coef = 1
coefDelay = 0
valueDelay = modulus
while(value):
quotient = valueDelay//value
valueDelay, value = value, valueDelay - quotient * value
coefDelay, coef = coef, coefDelay - quotient * coef
if coefDelay < 0:
coefDelay += modulus
return coefDelay
def __squareMultiply(self,base,power):
if power < 0:
raise ValueError("Negative powers not allowed")
if power == 0:
return 1
if power == 1:
return base
# if power is odd, x_new = x * (x^2)^((n-1)/2)
if power % 2:
return base * self.__squareMultiply(base*base,(power-1)/2)
# if power is even, x_new = (x^2)^(n/2)
return self.__squareMultiply(base*base,power/2)
if __name__ == '__main__':
s = socket.socket()
host = 'DESKTOP-DVGT262'
port = 5544
try:
s.connect((host, port))
print("connected to server")
except:
print("connection to server is failed : (")
rsa = RSA()
public_key, private_key = rsa.generateKeys()
session_key= random.randint(0, 200)
while 1:
raw_session_key = random.randint(0, 200)
print("\n*****************************\n")
msg = input("YOU:>> ")
session_key=rsa.encrypt(raw_session_key,public_key)
encrypted_text = msg + '~' + str(session_key)
print('\ngenerated random session key : ',session_key)
print("\nEncrypted message :", encrypted_text)
s.send(encrypted_text.encode())
r_msg = s.recv(1024).decode()
print("\n*************** Message recieved *************")
print('recieved message :',r_msg)
k=r_msg.split('~')
rec_sk=int(k[1])
dec=rsa.decrypt(rec_sk, private_key)
print('decoded session key using private key : ', dec )
print('original session key :',raw_session_key)
if(dec==raw_session_key):
print('session key verified')
Output: