223 lines
7.9 KiB
Python
223 lines
7.9 KiB
Python
from tkinter import *
|
|
import random
|
|
import time
|
|
|
|
letter = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q",
|
|
"r","s","t","u","v","w","x","y","z",",",".","!","?",' ']
|
|
number = ["01","02","03","04","05","06","07","08","09","10","11","12","13",
|
|
"14","15","16","17","18","19","20","21","22","23","24","25","26","27",
|
|
"28","29","30",'31']
|
|
|
|
n = 2537
|
|
e = 13
|
|
d = 937
|
|
def decrypt(F,d):
|
|
# performs the decryption function on an block of ciphertext
|
|
if d == 0:
|
|
return 1
|
|
if d == 1:
|
|
return F
|
|
w,r = divmod(d,2)
|
|
if r == 1:
|
|
return decrypt(F*F%n,w)*F%n
|
|
else:
|
|
return decrypt(F*F%n,w)
|
|
|
|
def correct():
|
|
# Checks to see if the numerical ciphertext block should have started with a 0 (by seeing if the 0 is missing), if it is, it then adds the 0.
|
|
# example - 0102 is output as 102, which would lead the computer to think the first letter is 10, not 01. This ensures this does not happen.
|
|
for i in range(len(D)):
|
|
if len(str(P[i]))%2 !=0:
|
|
y = str(0)+str(P[i])
|
|
P.remove(str(P[i]))
|
|
P.insert(i,y)
|
|
|
|
def cipher(b,e):
|
|
# Performs the Encryption function on a block of ciphertext
|
|
if e == 0:
|
|
return 1
|
|
if e == 1:
|
|
return b
|
|
w,r = divmod(e,2)
|
|
if r == 1:
|
|
return cipher(b*b%n,w)*b%n
|
|
else:
|
|
return cipher(b*b%n,w)
|
|
|
|
def group(j,h,z):
|
|
# Places the plaintext numbers into blocks for encryption
|
|
for i in range(int(j)):
|
|
y = 0
|
|
for n in range(h):
|
|
y += int(numP[(h*i)+n])*(10**(z-2*n))
|
|
X.append(int(y))
|
|
|
|
|
|
|
|
class App:
|
|
# Creates a Tkineter window, for ease of operation
|
|
def __init__(self, master):
|
|
|
|
frame = Frame(master)
|
|
frame.grid()
|
|
|
|
#create a button with the quit command, and tell it where to go
|
|
quitbutton = Button(frame, text = "quit", fg ="red",
|
|
command = root.quit, width = 10)
|
|
quitbutton.grid(row = 0, column =3)
|
|
|
|
#create an entry box, tell it where it goes, and how large it is
|
|
entry = Entry(frame, width = 100)
|
|
entry.grid(row = 0, column = 0)
|
|
|
|
#set initial content of the entry box
|
|
self.contents = StringVar()
|
|
self.contents.set("Type message here")
|
|
entry["textvariable"] = self.contents
|
|
|
|
# Create a button which initializes the decryption of ciphertext
|
|
decrypt = Button(frame,text = "Decrypt", fg = "blue",
|
|
command = self.Decrypt)
|
|
decrypt.grid(row = 2, column = 1)
|
|
|
|
#create a label to display the number of ciphertext blocks in an encoded message
|
|
label = Label(frame, text = "# of blocks")
|
|
label.grid(row = 1, column = 1)
|
|
|
|
#creates a button which initializes the encryption of plaintext
|
|
encrypt = Button(frame, text="Encrypt", fg = "blue",
|
|
command = self.Encrypt)
|
|
encrypt.grid(row =0, column =1)
|
|
|
|
#create an entry box for the value of "n"
|
|
nbox = Entry(frame, width = 100)
|
|
nbox.grid(row = 3, column = 0)
|
|
|
|
self.n = StringVar()
|
|
self.n.set(n)
|
|
nbox["textvar"] = self.n
|
|
nbox.bind('<Key-Return>', self.set_n) #key binding, when you press "return", the value of "n" is changed to the value now in the box
|
|
|
|
nlabel = Label(frame, text = "the value of 'n'")
|
|
nlabel.grid(row = 3, column = 1)
|
|
|
|
#create an entry box for the value of "e"
|
|
ebox = Entry(frame, width = 100)
|
|
ebox.grid(row = 4, column = 0)
|
|
|
|
self.e = StringVar()
|
|
self.e.set(e)
|
|
ebox["textvar"] = self.e
|
|
ebox.bind('<Key-Return>', self.set_e)
|
|
|
|
elabel = Label(frame, text = "the value of 'e'")
|
|
elabel.grid(row = 4, column = 1)
|
|
|
|
#create an entry box for the value of "d"
|
|
dbox = Entry(frame, width = 100)
|
|
dbox.grid(row =5, column = 0)
|
|
|
|
self.d = StringVar()
|
|
self.d.set(d)
|
|
dbox["textvar"] = self.d
|
|
dbox.bind('<Key-Return>', self.set_d)
|
|
|
|
dlabel = Label(frame, text = "the value of 'd'")
|
|
dlabel.grid(row = 5, column =1)
|
|
|
|
blocks = Label(frame, width = 100)
|
|
blocks.grid(row = 1, column =0)
|
|
|
|
self.block = StringVar()
|
|
self.block.set("number of blocks")
|
|
blocks["textvar"] = self.block
|
|
|
|
output = Entry(frame, width = 100)
|
|
output.grid(row = 2, column = 0)
|
|
|
|
self.answer = StringVar()
|
|
self.answer.set("Ciphertext")
|
|
output["textvar"] = self.answer
|
|
|
|
# The commands of all the buttons are defined below
|
|
def set_n(self,event):
|
|
global n
|
|
n = int(self.n.get())
|
|
print("n set to", n)
|
|
|
|
def set_e(self, event):
|
|
global e
|
|
e = int(self.e.get())
|
|
print("e set to",e)
|
|
|
|
def set_d(self,event):
|
|
global d
|
|
d = int(self.d.get())
|
|
print("d set to", d)
|
|
|
|
def Decrypt(self):
|
|
#decrypts an encoded message
|
|
global m,P,D,x,h,p,Text,y,w,PText
|
|
P = []
|
|
D = str(self.answer.get()) #Pulls the ciphertext out of the ciphertext box
|
|
D = D.lstrip('[') #removes the bracket "[" from the left side of the string
|
|
D = D.rstrip(']')
|
|
D = D.split(',') #splits the string into a list of strings, separating at each comma.
|
|
for i in range(len(D)): #decrypts each block in the list of strings "D"
|
|
x = decrypt(int(D[i]),d)
|
|
P.append(str(x))
|
|
correct() #ensures each block is not missing a 0 at the start
|
|
h = len(P[0])
|
|
p = []
|
|
for i in range(len(D)): #further separates the list P into individual characters, i.e. "0104" becomes "01,04"
|
|
for n in range(int(h/2)):
|
|
p.append(str(P[i][(2*n):((2*n)+2)])) # grabs every 2 character group from the larger block. It gets characters between 2*n, and (2*n)+2, i.e. characters 0,1 then 2,3 etc...
|
|
|
|
Text = []
|
|
for i in range(len(p)): # converts each block back to text characters
|
|
for j in range(len(letter)):
|
|
if str(p[i]) == number[j]:
|
|
Text.append(letter[j])
|
|
PText = str()
|
|
for i in range(len(Text)): #places all text characters in one string
|
|
PText = PText + str(Text[i])
|
|
self.contents.set(str(PText)) #places the decrypted plaintext in the plaintext box
|
|
|
|
|
|
def Encrypt(self):
|
|
#encrypts a plaintext message using the current key
|
|
global plaintext,numP,q,j,z,X,C
|
|
plaintext = self.contents.get() #pulls the plaintext out of the entry box for use
|
|
plaintext = plaintext.lower() #places all plaintext in lower case
|
|
numP = []
|
|
for i in range(len(plaintext)): # converts letters and symbols to their numerical values
|
|
for j in range(len(letter)):
|
|
if plaintext[i] == letter[j]:
|
|
numP.append(number[j])
|
|
h = (len(str(n))//2)-1 # This sets the block length for the code in question, based on the value of "n"
|
|
q = len(numP)%h
|
|
for i in range(h-q):
|
|
numP.append(number[random.randint(0,25)]) # Ensures the final block of plaintext is filled with letters, and is not a single orphaned letter.
|
|
j = len(numP) / h
|
|
X = []
|
|
z = 0
|
|
for m in range(h-1):
|
|
z+=2
|
|
group(j,h,z) # This sets the numerical plaintext into blocks of appropriate size, and places them in the list "X"
|
|
k = len(X)
|
|
C = []
|
|
for i in range(k): # performs the cipher function for each block in the list of plaintext blocks
|
|
b = X[i]
|
|
r = cipher(b,e)
|
|
C.append(r)
|
|
self.answer.set(C)
|
|
self.block.set(len(C)) #places the ciphertext into the ciphertext box
|
|
|
|
|
|
root = Tk()
|
|
|
|
app = App(root)
|
|
|
|
root.mainloop()
|
|
root.destroy()
|