-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathenigma_machine_non-template_ver.cpp
360 lines (315 loc) · 7.02 KB
/
enigma_machine_non-template_ver.cpp
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
#include <iostream>
#include <string>
#include <Algorithm>
class Enigma_Machine
{
private:
int counter1;
int counter2;
std::string alpha;
std::string rotor1;
std::string rotor2;
std::string rotor3;
std::string reflector;
char perm[26];
//Returns appropriate rotor
std::string get_rotor(int r);
std::string get_reflector();
//Checks if every character in rotor is unique
bool is_all_unique(std::string s);
//Signal goes through first 3 rotors
char converse_encryption(char c, int r);
char reflector_encryption(char c);
//Signal goes back reverse through rotors
char inverse_encryption(char c, int r);
//Checks character's position in alphabet
int char_alpha_pos(char c);
//The last stage of signal
//Goes to assigned value-pair
char permutation_encryption(char c);
char permutation_decryption(char c);
bool permutation_is_unique();
void rotate_rotor();
void space_remove(std::string &imp);
public:
Enigma_Machine();
void rotors_set_start_pos(char r1, char r2, char r3);
void start_enigma();
void rotor_change(int r);
};
Enigma_Machine::Enigma_Machine()
{
counter1 = 0;
counter2 = 0;
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
rotor1 = "EKMFLGDQVZNTOWYHXUSPAIBRCJ"; //"EKMFLGDQVZNTOWYHXUSPAIBRCJ"
rotor2 = "AJDKSIRUXBLHWTMCQGZNPYFVOE";
rotor3 = "BDFHJLCPRTXVZNYEIWGAKMUSQO";
reflector = "FVPJIAOYEDRZXWGCTKUQSBNMHL";
for (int i : {0, 1, 2, 3, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24})
{
perm[i] = NULL;
}
perm[4] = 'a';
perm[5] = 't';
perm[6] = 'd';
perm[7] = 'z';
perm[8] = 'p';
perm[25] = 'c';
}
std::string Enigma_Machine::get_reflector()
{
return reflector;
}
std::string Enigma_Machine::get_rotor(int r)
{
if (r == 1) return rotor1;
else if (r == 2) return rotor2;
else return rotor3;
}
void Enigma_Machine::rotor_change(int r)
{
std::string* rotor_ptr = &get_rotor(r);
std::string inp;
do
{
std::cout << "Replace rotor with valid one" << std::endl;
std::cin >> inp;
} while (inp.length() != 26 && !is_all_unique(inp));
*rotor_ptr = inp;
}
void Enigma_Machine::rotate_rotor()
{
rotor1 = rotor1.substr(1, rotor1.length() - 1) + rotor1[0]; counter1++;
std::cout << rotor1 << std::endl;
if (counter1 >= 26)
{
counter1 = 0;
rotor2 = rotor2.substr(1, rotor2.length() - 1) + rotor2[0]; counter2++;
std::cout << rotor2 << std::endl;
if (counter2 >= 26)
{
counter2 = 0;
rotor3 = rotor3.substr(1, rotor3.length() - 1) + rotor3[0];
std::cout << rotor3 << std::endl;
}
}
}
void Enigma_Machine::start_enigma()
{
std::cout << "Welcome to Enigma" << std::endl;
bool ub;
for (int i = 1; i <= 3; i++)
{
try{
ub = is_all_unique(get_rotor(i));
if (ub == false)
{
throw false;
}
std::cout << "Rotor " << i << " is correct" << std::endl;
std::cout << get_rotor(i) << std::endl;
}
catch (bool e)
{
std::cout << "Rotor " << i << " is invalid" << std::endl;
rotor_change(i);
}
}
std::cout << "Set rotors starting positions" << std::endl;
char r1, r2, r3;
std::cin >> r1 >> r2 >> r3;
rotors_set_start_pos(r1, r2, r3);
std::cout << "Enter your message (no spaces are allowed, meaning becomes obvious with spaces :p): " << std::endl;
std::string message;
std::cin >> message;
transform(message.begin(), message.end(), message.begin(), tolower);
//space_remove(message);
std::string encr_message = "";
//0 - first rotor
//1 - second rotor
//2 - third rotor
//3 - reflector
//4 - inverse third rotor
//5 - inverse second rotor
//6 - inverse first rotor
//7 - permutations
for (int i = 0; i < message.length(); i++) //O(n)
{
char curr = message[i];
for (int j = 0; j < 7; j++) //O(1)
{
if (j < 3)
{
curr = converse_encryption(curr, j + 1);
}
else if (j == 3)
{
curr = reflector_encryption(curr);
}
else if (j < 7 && j > 3)
{
switch (j)
{
case 4: curr = inverse_encryption(curr, 3); break;
case 5: curr = inverse_encryption(curr, 2); break;
case 6: curr = inverse_encryption(curr, 1); break;
}
}
else curr = permutation_encryption(curr);
}
encr_message += curr;
rotate_rotor();
}
std::cout << "Your encrypted message: " << encr_message << std::endl;;
}
void Enigma_Machine::rotors_set_start_pos(char r1, char r2, char r3)
{
//Making characters upper
r1 = toupper(r1);
r2 = toupper(r2);
r3 = toupper(r3);
//Check if character is the same as starting position of rotor
if (r1 != rotor1[0])
{
for (int i = 0; i < rotor1.length(); i++)
{
if (r1 == rotor1[i])
{
rotor1 = rotor1.substr(i, rotor1.length() - i) + rotor1.substr(0, i);
}
}
}
if (r2 != rotor2[0])
{
for (int i = 0; i < rotor2.length(); i++)
{
if (r2 == rotor2[i])
{
rotor2 = rotor2.substr(i, rotor2.length() - i) + rotor2.substr(0, i);
}
}
}
if (r3 != rotor3[0])
{
for (int i = 0; i < rotor3.length(); i++)
{
if (r3 == rotor3[i])
{
rotor3 = rotor3.substr(i, rotor3.length() - i) + rotor3.substr(0, i);
}
}
}
//Print new rotor (optional)
std::cout << rotor1 << std::endl;
std::cout << rotor2 << std::endl;
std::cout << rotor3 << std::endl;
}
//Checks whether rotor have unique character in it
bool Enigma_Machine::is_all_unique(std::string s)
{
//O(n^2) version that doesn't use any additional data structures
/*
for (int i = 0; i < s.length(); i++)
{
int countdooku = 0;
for (int j = 0; j < s.length(); j++)
{
if (s[i] == s[j])
{
countdooku++;
}
}
if (countdooku > 1)
{
return false;
}
}
return true;
*/
//O(n) version which uses extra array
int hash_alpha[26] = {};
for (int i = 0; i < s.length(); i++)
hash_alpha[s[i]]++;
for (int i = 0; i < 26; i++)
if (hash_alpha[i]>1)
return false;
return true;
}
//Returns position of character in alphabet
//Starting position is 0
int Enigma_Machine::char_alpha_pos(char c)
{
c = toupper(c);
try
{
if (isalpha(c) == false)
{
throw false;
}
for (int i = 0; i < alpha.length(); i++)
{
if (alpha[i] == c)
{
return i;
}
}
}
catch (bool b)
{
int i;
std::cout << "Invalid character: ";
std::cin >> i;
char_alpha_pos(i); // Better use loop to avoid stackoverflow
}
}
char Enigma_Machine::converse_encryption(char c, int r)
{
int c_pos = char_alpha_pos(c);
std::string rotor = get_rotor(r);
return rotor[c_pos];
}
char Enigma_Machine::reflector_encryption(char c)
{
int c_pos = char_alpha_pos(c);
return reflector[c_pos];
}
char Enigma_Machine::inverse_encryption(char c, int r)
{
std::string rotor = get_rotor(r);
for (int i = 0; i < 26; i++)
{
if (rotor[i] == c)
{
return alpha[i];
}
}
return '!';
}
bool Enigma_Machine::permutation_is_unique()
{
for (int i = 0; i < 26; i++)
{
for (int j = 0; j < 26; j++)
{
if (perm[i] == perm[j] && perm[i] != NULL) return false;
}
}
return true;
}
char Enigma_Machine::permutation_encryption(char c)
{
if (perm[char_alpha_pos(c)] == NULL)
return c;
return perm[char_alpha_pos(c)];
}
void Enigma_Machine::space_remove(std::string &imp)
{
imp.erase(std::remove(imp.begin(), imp.end(), ' '), imp.end());
}
int main()
{
Enigma_Machine* h = new Enigma_Machine();
h->start_enigma();
return 0;
}