-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path59.c
190 lines (168 loc) · 8.79 KB
/
59.c
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
/**
* XOR decryption
*
* Problem 59
*
* Each character on a computer is assigned a unique code and the preferred
* standard is ASCII (American Standard Code for Information Interchange). For
* example, uppercase A = 65, asterisk (*) = 42, and lowercase k = 107.
*
* A modern encryption method is to take a text file, convert the bytes to
* ASCII, then XOR each byte with a given value, taken from a secret key. The
* advantage with the XOR function is that using the same encryption key on the
* cipher text, restores the plain text; for example, 65 XOR 42 = 107, then 107
* XOR 42 = 65.
*
* For unbreakable encryption, the key is the same length as the plain text
* message, and the key is made up of random bytes. The user would keep the
* encrypted message and the encryption key in different locations, and without
* both "halves", it is impossible to decrypt the message.
*
* Unfortunately, this method is impractical for most users, so the modified
* method is to use a password as a key. If the password is shorter than the
* message, which is likely, the key is repeated cyclically throughout the
* message. The balance for this method is using a sufficiently long password
* key for security, but short enough to be memorable.
*
* Your task has been made easy, as the encryption key consists of three lower
* case characters. Using p059_cipher.txt (right click and 'Save Link/Target
* As...'), a file containing the encrypted ASCII codes, and the knowledge that
* the plain text must contain common English words, decrypt the message and
* find the sum of the ASCII values in the original text.
*/
#include <stdio.h>
#include <string.h>
#define CIPHER_SIZE 1455
const char encrypted[CIPHER_SIZE] = {
36, 22, 80, 0, 0, 4, 23, 25, 19, 17, 88, 4, 4, 19, 21, 11, 88, 22, 23, 23, 29,
69, 12, 24, 0, 88, 25, 11, 12, 2, 10, 28, 5, 6, 12, 25, 10, 22, 80, 10, 30,
80, 10, 22, 21, 69, 23, 22, 69, 61, 5, 9, 29, 2, 66, 11, 80, 8, 23, 3, 17, 88,
19, 0, 20, 21, 7, 10, 17, 17, 29, 20, 69, 8, 17, 21, 29, 2, 22, 84, 80, 71,
60, 21, 69, 11, 5, 8, 21, 25, 22, 88, 3, 0, 10, 25, 0, 10, 5, 8, 88, 2, 0, 27,
25, 21, 10, 31, 6, 25, 2, 16, 21, 82, 69, 35, 63, 11, 88, 4, 13, 29, 80, 22,
13, 29, 22, 88, 31, 3, 88, 3, 0, 10, 25, 0, 11, 80, 10, 30, 80, 23, 29, 19,
12, 8, 2, 10, 27, 17, 9, 11, 45, 95, 88, 57, 69, 16, 17, 19, 29, 80, 23, 29,
19, 0, 22, 4, 9, 1, 80, 3, 23, 5, 11, 28, 92, 69, 9, 5, 12, 12, 21, 69, 13,
30, 0, 0, 0, 0, 27, 4, 0, 28, 28, 28, 84, 80, 4, 22, 80, 0, 20, 21, 2, 25, 30,
17, 88, 21, 29, 8, 2, 0, 11, 3, 12, 23, 30, 69, 30, 31, 23, 88, 4, 13, 29, 80,
0, 22, 4, 12, 10, 21, 69, 11, 5, 8, 88, 31, 3, 88, 4, 13, 17, 3, 69, 11, 21,
23, 17, 21, 22, 88, 65, 69, 83, 80, 84, 87, 68, 69, 83, 80, 84, 87, 73, 69,
83, 80, 84, 87, 65, 83, 88, 91, 69, 29, 4, 6, 86, 92, 69, 15, 24, 12, 27, 24,
69, 28, 21, 21, 29, 30, 1, 11, 80, 10, 22, 80, 17, 16, 21, 69, 9, 5, 4, 28, 2,
4, 12, 5, 23, 29, 80, 10, 30, 80, 17, 16, 21, 69, 27, 25, 23, 27, 28, 0, 84,
80, 22, 23, 80, 17, 16, 17, 17, 88, 25, 3, 88, 4, 13, 29, 80, 17, 10, 5, 0,
88, 3, 16, 21, 80, 10, 30, 80, 17, 16, 25, 22, 88, 3, 0, 10, 25, 0, 11, 80,
12, 11, 80, 10, 26, 4, 4, 17, 30, 0, 28, 92, 69, 30, 2, 10, 21, 80, 12, 12,
80, 4, 12, 80, 10, 22, 19, 0, 88, 4, 13, 29, 80, 20, 13, 17, 1, 10, 17, 17,
13, 2, 0, 88, 31, 3, 88, 4, 13, 29, 80, 6, 17, 2, 6, 20, 21, 69, 30, 31, 9,
20, 31, 18, 11, 94, 69, 54, 17, 8, 29, 28, 28, 84, 80, 44, 88, 24, 4, 14, 21,
69, 30, 31, 16, 22, 20, 69, 12, 24, 4, 12, 80, 17, 16, 21, 69, 11, 5, 8, 88,
31, 3, 88, 4, 13, 17, 3, 69, 11, 21, 23, 17, 21, 22, 88, 25, 22, 88, 17, 69,
11, 25, 29, 12, 24, 69, 8, 17, 23, 12, 80, 10, 30, 80, 17, 16, 21, 69, 11, 1,
16, 25, 2, 0, 88, 31, 3, 88, 4, 13, 29, 80, 21, 29, 2, 12, 21, 21, 17, 29, 2,
69, 23, 22, 69, 12, 24, 0, 88, 19, 12, 10, 19, 9, 29, 80, 18, 16, 31, 22, 29,
80, 1, 17, 17, 8, 29, 4, 0, 10, 80, 12, 11, 80, 84, 67, 80, 10, 10, 80, 7, 1,
80, 21, 13, 4, 17, 17, 30, 2, 88, 4, 13, 29, 80, 22, 13, 29, 69, 23, 22, 69,
12, 24, 12, 11, 80, 22, 29, 2, 12, 29, 3, 69, 29, 1, 16, 25, 28, 69, 12, 31,
69, 11, 92, 69, 17, 4, 69, 16, 17, 22, 88, 4, 13, 29, 80, 23, 25, 4, 12, 23,
80, 22, 9, 2, 17, 80, 70, 76, 88, 29, 16, 20, 4, 12, 8, 28, 12, 29, 20, 69,
26, 9, 69, 11, 80, 17, 23, 80, 84, 88, 31, 3, 88, 4, 13, 29, 80, 21, 29, 2,
12, 21, 21, 17, 29, 2, 69, 12, 31, 69, 12, 24, 0, 88, 20, 12, 25, 29, 0, 12,
21, 23, 86, 80, 44, 88, 7, 12, 20, 28, 69, 11, 31, 10, 22, 80, 22, 16, 31, 18,
88, 4, 13, 25, 4, 69, 12, 24, 0, 88, 3, 16, 21, 80, 10, 30, 80, 17, 16, 25,
22, 88, 3, 0, 10, 25, 0, 11, 80, 17, 23, 80, 7, 29, 80, 4, 8, 0, 23, 23, 8,
12, 21, 17, 17, 29, 28, 28, 88, 65, 75, 78, 68, 81, 65, 67, 81, 72, 70, 83,
64, 68, 87, 74, 70, 81, 75, 70, 81, 67, 80, 4, 22, 20, 69, 30, 2, 10, 21, 80,
8, 13, 28, 17, 17, 0, 9, 1, 25, 11, 31, 80, 17, 16, 25, 22, 88, 30, 16, 21,
18, 0, 10, 80, 7, 1, 80, 22, 17, 8, 73, 88, 17, 11, 28, 80, 17, 16, 21, 11,
88, 4, 4, 19, 25, 11, 31, 80, 17, 16, 21, 69, 11, 1, 16, 25, 2, 0, 88, 2, 10,
23, 4, 73, 88, 4, 13, 29, 80, 11, 13, 29, 7, 29, 2, 69, 75, 94, 84, 76, 65,
80, 65, 66, 83, 77, 67, 80, 64, 73, 82, 65, 67, 87, 75, 72, 69, 17, 3, 69, 17,
30, 1, 29, 21, 1, 88, 0, 23, 23, 20, 16, 27, 21, 1, 84, 80, 18, 16, 25, 6, 16,
80, 0, 0, 0, 23, 29, 3, 22, 29, 3, 69, 12, 24, 0, 88, 0, 0, 10, 25, 8, 29, 4,
0, 10, 80, 10, 30, 80, 4, 88, 19, 12, 10, 19, 9, 29, 80, 18, 16, 31, 22, 29,
80, 1, 17, 17, 8, 29, 4, 0, 10, 80, 12, 11, 80, 84, 86, 80, 35, 23, 28, 9, 23,
7, 12, 22, 23, 69, 25, 23, 4, 17, 30, 69, 12, 24, 0, 88, 3, 4, 21, 21, 69, 11,
4, 0, 8, 3, 69, 26, 9, 69, 15, 24, 12, 27, 24, 69, 49, 80, 13, 25, 20, 69, 25,
2, 23, 17, 6, 0, 28, 80, 4, 12, 80, 17, 16, 25, 22, 88, 3, 16, 21, 92, 69, 49,
80, 13, 25, 6, 0, 88, 20, 12, 11, 19, 10, 14, 21, 23, 29, 20, 69, 12, 24, 4,
12, 80, 17, 16, 21, 69, 11, 5, 8, 88, 31, 3, 88, 4, 13, 29, 80, 22, 29, 2, 12,
29, 3, 69, 73, 80, 78, 88, 65, 74, 73, 70, 69, 83, 80, 84, 87, 72, 84, 88, 91,
69, 73, 95, 87, 77, 70, 69, 83, 80, 84, 87, 70, 87, 77, 80, 78, 88, 21, 17,
27, 94, 69, 25, 28, 22, 23, 80, 1, 29, 0, 0, 22, 20, 22, 88, 31, 11, 88, 4,
13, 29, 80, 20, 13, 17, 1, 10, 17, 17, 13, 2, 0, 88, 31, 3, 88, 4, 13, 29, 80,
6, 17, 2, 6, 20, 21, 75, 88, 62, 4, 21, 21, 9, 1, 92, 69, 12, 24, 0, 88, 3,
16, 21, 80, 10, 30, 80, 17, 16, 25, 22, 88, 29, 16, 20, 4, 12, 8, 28, 12, 29,
20, 69, 26, 9, 69, 65, 64, 69, 31, 25, 19, 29, 3, 69, 12, 24, 0, 88, 18, 12,
9, 5, 4, 28, 2, 4, 12, 21, 69, 80, 22, 10, 13, 2, 17, 16, 80, 21, 23, 7, 0,
10, 89, 69, 23, 22, 69, 12, 24, 0, 88, 19, 12, 10, 19, 16, 21, 22, 0, 10, 21,
11, 27, 21, 69, 23, 22, 69, 12, 24, 0, 88, 0, 0, 10, 25, 8, 29, 4, 0, 10, 80,
10, 30, 80, 4, 88, 19, 12, 10, 19, 9, 29, 80, 18, 16, 31, 22, 29, 80, 1, 17,
17, 8, 29, 4, 0, 10, 80, 12, 11, 80, 84, 86, 80, 36, 22, 20, 69, 26, 9, 69,
11, 25, 8, 17, 28, 4, 10, 80, 23, 29, 17, 22, 23, 30, 12, 22, 23, 69, 49, 80,
13, 25, 6, 0, 88, 28, 12, 19, 21, 18, 17, 3, 0, 88, 18, 0, 29, 30, 69, 25, 18,
9, 29, 80, 17, 23, 80, 1, 29, 4, 0, 10, 29, 12, 22, 21, 69, 12, 24, 0, 88, 3,
16, 21, 3, 69, 23, 22, 69, 12, 24, 0, 88, 3, 16, 26, 3, 0, 9, 5, 0, 22, 4, 69,
11, 21, 23, 17, 21, 22, 88, 25, 11, 88, 7, 13, 17, 19, 13, 88, 4, 13, 29, 80,
0, 0, 0, 10, 22, 21, 11, 12, 3, 69, 25, 2, 0, 88, 21, 19, 29, 30, 69, 22, 5,
8, 26, 21, 23, 11, 94
};
char decrypted[CIPHER_SIZE];
void print_decrypted() {
printf("Decrypted text:\n");
for (int i = 0; i < CIPHER_SIZE; i++) {
printf("%c", decrypted[i]);
}
printf("\n\n");
}
int common_words_match() {
char *common_words[10] = {
"the", "be", "to", "of", "and",
"a", "in", "that", "have", "I"
};
int match_count = 0;
for (int j = 0; j < 10; j++) {
char *word = common_words[j];
size_t word_len = strlen(word);
for (int i = 0; i < CIPHER_SIZE - word_len; i++) {
if (strncmp(word, &decrypted[i], word_len) == 0) {
match_count++;
break;
}
}
}
return match_count == 10;
}
int main(int argc, char *argv[]) {
int i, j, k, l;
for (i = 'a'; i <= 'z'; i++) {
for (j = 'a'; j <= 'z'; j++) {
for (k = 'a'; k <= 'z'; k++) {
// 1455 is perfectly divisable by 3, luckily
for (l = 0; l < CIPHER_SIZE; l += 3) {
decrypted[l] = encrypted[l] ^ i;
decrypted[l + 1] = encrypted[l + 1] ^ j;
decrypted[l + 2] = encrypted[l + 2] ^ k;
}
int all_in_range = 1;
// Continue if any characters are non-ASCII
for (l = 0; l < CIPHER_SIZE; l++) {
if (decrypted[l] < ' ' || decrypted[l] > '~') {
all_in_range = 0;
break;
}
}
if (all_in_range && common_words_match()) {
goto done;
}
}
}
}
done: print_decrypted();
int sum = 0;
for (int i = 0; i < CIPHER_SIZE; i++) {
sum += decrypted[i];
}
printf("Sum of ASCII values: %d\n", sum);
return 0;
}