-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathenigma.py
150 lines (129 loc) · 5.28 KB
/
enigma.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# file to do encryption and reordering
# @oscars47
# How to run this file:
# 1. enter your text you desire to encrypt in the file labeled "enigma_input.txt"
# 2. use the existing methods to perform (a) character shifts and (b) position shifts
# 3. follow the example structure to decode the messages by performing in reverse order all the methods you used to encrypt
# 4. your encrypted message will read "encoded:" and your input will read "original" so you can confirm you did the decoding correct
import numpy as np
ALPHABET = ['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', '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', '.', ',', ';', ':', '—', '!', '#',
'$', '%', '&', '(', ')', '*', '/', '?', '@', '[',
']', '^', '-', '_', '{', '|', '}', "'"]
# encrypt-------------------------
def encrypt(input, key):
output='' # initialize output
for i, char in enumerate(input):
if char != '\n' and char != '\t' and char != ' ':
shift = key[i] # get key
output+= ALPHABET[(ALPHABET.index(char)+shift)%len(ALPHABET)]
# print(output)
else:
output+=char
return output
def decrypt(input, key):
output='' # initialize output
for i, char in enumerate(input):
if char != '\n' and char != '\t' and char != ' ':
shift = key[i] # get key
output+= ALPHABET[(ALPHABET.index(char)-shift)%len(ALPHABET)]
# print(output)
else:
output+=char
return output
# for reordering----------------------------
# Simultaneous must be used only when each element in key is unique
def buildDicts(input, key):
encr_dict = dict(zip(list(range(len(input))), key))
decr_dict = dict(zip(key, list(range(len(input)))))
# print(encr_dict)
# print(decr_dict)
return encr_dict, decr_dict
# function to hold pairs of switches
def buildPairs(input, key):
encr_ls = list(zip(list(range(len(input))), key))
decr_ls = list(zip(key, list(range(len(input)))))
# reverse decr list
decr_ls_new = [decr_ls[i] for i in range(len(decr_ls)-1, -1, -1)]
#print('dec', decr_ls_new)
return encr_ls, decr_ls_new
def reorderSimultaneous(input, key):
output = [' ' for i in range(len(input))] # initialize output vector
encr_dict, _ = buildDicts(input, key) # get the dictionary
for i, c in enumerate(input):
output[encr_dict[i]] = c # move characters where they need to go according to key
output_str = ''
for c in output:
output_str+=c
return output_str
def rereorderSimultaneous(input, key):
output = [' ' for i in range(len(input))] # initialize output vector
_, decr_dict = buildDicts(input, key) # get the dictionary
for i, c in enumerate(input):
output[decr_dict[i]] = c # move characters where they need to go according to key
output_str = ''
for c in output:
output_str+=c
return output_str
def reorderSequential(input, key):
input_ls = [c for c in input]
encr_ls, _ = buildPairs(input, key) # get the dictionary
for i, c in enumerate(input_ls):
index = encr_ls[i][1]
#print(i, index, c)
input_ls.insert(index, input_ls.pop(i))
#print(input_ls)
output=''
for c in input_ls:
output+=c
return output
def rereorderSequential(input, key):
input_ls = [c for c in input]
_, decr_ls = buildPairs(input, key) # get the dictionary
for i in range(len(input_ls)):
current_index = decr_ls[i][0]
next_index = decr_ls[i][1]
c = input_ls[current_index]
#print(current_index, next_index, c)
input_ls.insert(next_index, input_ls.pop(current_index))
#print(input_ls)
output=''
for c in input_ls:
output+=c
return output
# function to clean inputs
def clean(input):
output = ''
for c in input:
if not(c in ALPHABET): # if forbidden character
if c == '“' or c== '”':
output+='"'
elif c=='’':
output+="'"
elif c == ' ': # don't forget spaces
output+=' '
elif c == '\n':
output+='\n'
else:
output+=c
return output
# read in file which you can type your message
# define your input in the textfile! you can define an English input and encode it by reordering and/or encrypting using the functions above
# or you can enter an encoded input and call from the functions above to decode the message. you can follow the example below!
with open('enigma_input.txt') as f:
input = f.read()
input = clean(input)
# key = [(i+np.random.randint(0, len(input)))%len(input) for i in range(len(input))]
# key2 = [np.random.randint(0, len(input)) for i in range(len(input))]
key = [(i+i)%len(input) for i in range(len(input))] #key holds reordering key
key2 = [i for i in range(len(input))] # key2 is for encrypting
input2 = encrypt(input, key2)
input3 = reorderSequential(input2, key)
print('encoded:', input3)
# input3 represents the complete encrypted and reordered message. now we can undo this encoding.
input4 = rereorderSequential(input3, key)
input5 = decrypt(input4, key2)
print('original:', input5)