/
server - TryFixDiffHashOutput.py
129 lines (107 loc) · 5.17 KB
/
server - TryFixDiffHashOutput.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# Victoria Van
# CS 565
# September 14, 2018
# Professor T. Mukherjee
# Project 1: Diffie-Hellman *SERVER*
# --------------------------------------
# Description:
# This program is the server binds to a port and listens to a server
# socket. The client and server agree on a shared keys 'p' and 'g'
# with the server. Server randomly generates prime 'p2' which is used
# to get Pk2. The client and server swap public keys and use their own
# private keys to generate the encryption key. The server encrypts the
# input file and sends it the client, which decrypts it with the
# generated key. The result should be the same as the original input file.
# --------------------------------------
# Code template provided by Professor T.
'''
File transfer server code. Not multi-threaded.
'''
import socket # Import socket module
import sympy # Import symbolic math library - prime generator
import math # power function library
from Crypto.Cipher import AES # AES encryption library
import hashlib # hash library (MD5)
import base64 # binary to plain text library
from sympy.ntheory.residue_ntheory import _primitive_root_prime_iter
# library for primitive roots modulo n (g)
import random # library for randomly picking g from list of g
port = 63000 # Reserve a port for your service (*client must connect with this port number)
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
s.bind((host, port)) # Bind to the port
s.listen(5) # Now wait for client connection and listen for requests
def serve():
"""
The server code. Accepts connections from clients and transfers a file.
The file should be in the same directory. Ensure that there is only
one client connecting. This is not multi-threaded at this point.
"""
print ('Server listening....')
while True:
conn, addr = s.accept() # Establish connection with client, returns a tuple
print ('Got connection from', addr)
data = conn.recv(1024) # Receive from server
print('Server received', repr(data))
# Agree on shared prime 'p' and shared key 'g'
p = sympy.randprime(200,9999) # random prime generator for 'p'
# restricted prime from 200 to 9999 for time & computation sake
print('p = ',p) # print out prime
gList = list(_primitive_root_prime_iter(p)) # generate array of possible g values
# that satisfy g^(p-1) = 1 (mod p)
# print(gList) # Debugging!
randomG = random.SystemRandom()
g = randomG.choice(gList) # get random primitive root modulo from array
print('g = ', g)
conn.sendall(p.to_bytes(16,'big')) # send 'p' as bytes, 16 B, big endian
conn.sendall(g.to_bytes(16,'big')) # send 'g' to client
# Generate secret prime 'p2'
p2 = sympy.randprime(2,2000) # random prime 'p2'
while p2 == p: # p2 != p
p2 = sympy.randprime(2,2000) # random 'p2' prime (secret)
print('p2 = ',p2) # debugging p2 (only server knows)
# Generate public key Pk2 = g^(p2) mod p
Pk2 = pow(g, p2, p) #pow(x,y[,z]) computers g^(y)mod(z) more efficiently
print ('Pk2 = ',Pk2)
# Receive Pk1 from Client (1)
Pk1 = conn.recv(1024)
Pk1 = int.from_bytes(Pk1, byteorder='big') # convert Pk1 bytes -> int
print('Pk1 = ',Pk1)
# Send Pk2 to Client (2)
conn.sendall(Pk2.to_bytes(16,'big'))
# Get Client Shared Key (3)
Pk1_p2 = pow(Pk1, p2)
Pk1_p2 = Pk1_p2 % p # Pk1_p2 = Pk1^p2 % p
print('\nShared DH key: ', Pk1_p2) # should match with client's Pk2_p1
# file to transfer
filename='sample.txt'
f = open(filename,'r') #formerly rb from template (read all at once)
l = f.read() # extract contents of file
l = l.rjust(32) # right justified, width of string
l = str.encode(l) # l as a string to bytes
print('read: ',l)
# debugging
#l = b'Hi there'.rjust(32)
# Encrypt file
Pk1_p2 = Pk1_p2.to_bytes(16,'big') # convert shared key to bytes
print(Pk1_p2)
# AES encryption with key
cipher = AES.new(Pk1_p2, AES.MODE_ECB) # create new AES cipher
ciphertext = base64.b64encode(cipher.encrypt(l)) # encrypt 'l' file text
print('\nCiphertext: ',ciphertext)
# Send encrypted file
conn.sendall(ciphertext) #send -> sendall b/c Python3
print('\nSent ',repr(ciphertext)) # print ciphertext sent to client
# Client acknowledges transfer completed
thankyou = conn.recv(1024)
print(thankyou)
# Implement MD5 hash on Ciphertext
md5hash = hashlib.md5(ciphertext).hexdigest()
print('\nMD5 Hash: ',md5hash)
conn.sendall(str.encode(md5hash)) # send md5hash for comparison
f.close() # close input file
print('Done sending')
#conn.send(b'File transfer complete!')
conn.close() # close socket connection
if __name__=='__main__':
serve()