-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathpolyalphabetic.h
More file actions
302 lines (252 loc) · 10 KB
/
polyalphabetic.h
File metadata and controls
302 lines (252 loc) · 10 KB
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
#ifndef POLYALPHABETIC_H
#define POLYALPHABETIC_H
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <strings.h>
#include <unistd.h>
#include <stdint.h>
#define KRYPTOS 0
#define CRIB_CHECK 0
#define VIGENERE 0
#define QUAGMIRE_1 1
#define QUAGMIRE_2 2
#define QUAGMIRE_3 3
#define QUAGMIRE_4 4
#define BEAUFORT 5
#define PORTA 6
#define AUTOKEY_0 7
#define AUTOKEY_1 8
#define AUTOKEY_2 9
#define AUTOKEY_3 10
#define AUTOKEY_4 11
#define AUTOKEY_BEAU 12
#define AUTOKEY_PORTA 13
#define ALPHABET_SIZE 26
#define MAX_CIPHER_LENGTH 10000
#define MAX_FILENAME_LEN 100
#define MAX_KEYWORD_LEN 26
#define MAX_CYCLEWORD_LEN 300
#define MAX_NGRAM_SIZE 8
#define MAX_DICT_WORD_LEN 30
#define FREQUENCY_WEIGHTED_SELECTION 1
#define DICTIONARY 1
#define INACTIVE -9999
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))
// --- Configuration Structs ---
typedef struct {
int cipher_type;
int ngram_size;
int n_hill_climbs;
int n_restarts;
// Keyword/Cycleword constraints
int plaintext_keyword_len;
int ciphertext_keyword_len;
int min_keyword_len;
int plaintext_max_keyword_len;
int ciphertext_max_keyword_len;
int max_cycleword_len;
int cycleword_len;
// Input Flags for lengths
bool plaintext_keyword_len_present;
bool ciphertext_keyword_len_present;
bool cycleword_len_present;
// Explicit User Keywords (Strings)
char user_plaintext_keyword[ALPHABET_SIZE + 1];
char user_ciphertext_keyword[ALPHABET_SIZE + 1];
bool user_plaintext_keyword_present;
bool user_ciphertext_keyword_present;
// Probabilities & Thresholds
double n_sigma_threshold;
double ioc_threshold;
double backtracking_probability;
double keyword_permutation_probability;
double slip_probability;
// Weights
float weight_ngram;
float weight_crib;
float weight_ioc;
float weight_entropy;
// Files
char ciphertext_file[MAX_FILENAME_LEN];
char batch_file[MAX_FILENAME_LEN];
char crib_file[MAX_FILENAME_LEN];
char dictionary_file[MAX_FILENAME_LEN];
char ngram_file[MAX_FILENAME_LEN];
// Flags
bool verbose;
bool cipher_present;
bool batch_present;
bool crib_present;
bool dictionary_present;
bool variant;
bool beaufort;
bool optimal_cycleword;
bool same_key_cycle;
// Transpositions.
bool transperoffset_present;
int trans_offset;
int trans_period;
bool transmatrix_present;
int trans_w1;
int trans_w2;
int trans_clockwise; // 1 for clockwise, 0 for anti-clockwise
} PolyalphabeticConfig;
typedef struct {
float *ngram_data;
char **dict;
int n_dict_words;
int max_dict_word_len;
} SharedData;
// --- Statistics Data ---
static int n_english_word_length_frequency_letters = 25;
static double english_word_length_frequencies[] = {
0.0316, 0.16975, 0.21192, 0.15678, 0.10852, 0.08524, 0.07724,
0.05623, 0.04032, 0.02766, 0.01582, 0.00917, 0.00483, 0.00262,
0.00099, 0.0005, 0.00027, 0.00022, 0.00011, 0.00006, 0.00005,
0.00002, 0.00001, 0.00001, 0.00001};
static double english_monograms[] = {
0.085517, 0.016048, 0.031644, 0.038712, 0.120965, 0.021815,
0.020863, 0.049557, 0.073251, 0.002198, 0.008087, 0.042065,
0.025263, 0.071722, 0.074673, 0.020662, 0.001040, 0.063327,
0.067282, 0.089381, 0.026816, 0.010593, 0.018254, 0.001914,
0.017214, 0.001138
};
// Core Logic
void solve_cipher(char *ciphertext_str, char *cribtext_str, PolyalphabeticConfig *cfg, SharedData *shared);
// Porta cipher
void porta_decrypt(int output[], int input[], int len, int cycleword_indices[], int cycleword_len);
void porta_encrypt(int output[], int input[], int len, int cycleword_indices[], int cycleword_len);
// Vigenere cipher
void vigenere_decrypt(int decrypted[], int cipher_indices[], int cipher_len,
int cycleword_indices[], int cycleword_len, bool variant);
void vigenere_encrypt(int encrypted[], int plaintext_indices[], int cipher_len,
int cycleword_indices[], int cycleword_len, bool variant);
// Beaufort cipher
void beaufort_decrypt(int decrypted[], int cipher_indices[], int cipher_len,
int cycleword_indices[], int cycleword_len);
void beaufort_encrypt(int encrypted[], int plaintext_indices[], int cipher_len,
int cycleword_indices[], int cycleword_len);
// Quagmire I - IV ciphers
void quagmire_decrypt(int decrypted[], int cipher_indices[], int cipher_len,
int plaintext_keyword_indices[], int ciphertext_keyword_indices[],
int cycleword_indices[], int cycleword_len, bool variant);
void quagmire_encrypt(int encrypted[], int plaintext_indices[], int cipher_len,
int plaintext_keyword_indices[], int ciphertext_keyword_indices[],
int cycleword_indices[], int cycleword_len, bool variant);
// Autokey
void autokey_decrypt(PolyalphabeticConfig *cfg, int decrypted[], int cipher_indices[],
int cipher_len, int plaintext_keyword[], int ciphertext_keyword[],
int key_indices[], int key_len);
// Transposition
void transperoffset(int plaintext[], int len, int d, int n);
void matrix_rotate(int text[], int len, int width, int clockwise);
void transmatrix(int text[], int len, int w1, int w2, int clockwise);
// Hill Climber
double shotgun_hill_climber(
PolyalphabeticConfig *cfg,
int cipher_indices[], int cipher_len,
int crib_indices[], int crib_positions[], int n_cribs,
int cycleword_len, int plaintext_keyword_len, int ciphertext_keyword_len,
float *ngram_data,
int decrypted[MAX_CIPHER_LENGTH], int plaintext_keyword[ALPHABET_SIZE],
int ciphertext_keyword[ALPHABET_SIZE], int cycleword[MAX_CYCLEWORD_LEN]);
void derive_optimal_cycleword(
PolyalphabeticConfig *cfg,
int cipher_indices[], int cipher_len,
int plaintext_keyword_indices[], int ciphertext_keyword_indices[],
int cycleword_state[], int cycleword_len);
// Helpers
int map_crib_to_cipher_pos(PolyalphabeticConfig *cfg, int crib_pos, int cipher_len);
int get_matrix_rotate_old_idx(int target_idx, int len, int width, int clockwise);
bool cribs_satisfied_p(PolyalphabeticConfig *cfg, int cipher_indices[], int cipher_len, int crib_indices[],
int crib_positions[], int n_cribs, int cycleword_len, bool verbose);
bool constrain_cycleword(PolyalphabeticConfig *cfg, int cipher_indices[], int cipher_len,
int crib_indices[], int crib_positions[], int n_cribs,
int plaintext_keyword_indices[], int ciphertext_keyword_indices[],
int cycleword_indices[], int cycleword_len,
bool variant, bool verbose);
void decrypt_state(PolyalphabeticConfig *cfg, int cipher_indices[], int cipher_len,
int plaintext_keyword_state[], int ciphertext_keyword_state[],
int cycleword_state[], int cycleword_len,
int decrypted[]);
double state_score(int decrypted[], int cipher_len,
int crib_indices[], int crib_positions[], int n_cribs,
float *ngram_data, int ngram_size,
float weight_ngram, float weight_crib,
float weight_ioc, float weight_entropy);
void straight_alphabet(int keyword[], int len);
void make_keyed_alphabet(char *keyword_str, int *output_indices); // NEW
double ngram_score(int decrypted[], int cipher_len, float *ngram_data, int ngram_size);
double crib_score(int text[], int len, int crib_indices[], int crib_positions[], int n_cribs);
double entropy(int text[], int len);
double chi_squared(int plaintext[], int len);
// I/O & Data
void load_dictionary(char *filename, char ***dict, int *n_dict_words, int *max_dict_word_len, bool verbose);
void free_dictionary(char **dict, int n_dict_words);
int find_dictionary_words(char *plaintext, char **dict, int n_dict_words, int max_dict_word_len);
float* load_ngrams(char *ngram_file, int ngram_size, bool verbose);
int ngram_index_int(int *ngram, int ngram_size);
int ngram_index_str(char *ngram, int ngram_size);
// Randomization
void perturbate_keyword(int state[], int len, int keyword_len);
void random_keyword(int keyword[], int len, int keyword_len);
void random_cycleword(int cycleword[], int max, int keyword_len);
void perturbate_cycleword(int state[], int max, int len);
int rand_int_frequency_weighted(int state[], int min_index, int max_index);
void shuffle(int *array, size_t n);
// Stats
double mean_ioc(int text[], int len, int len_cycleword, int *caesar_column);
void estimate_cycleword_lengths(int text[], int len, int max_cycleword_len,
double n_sigma_threshold, double ioc_threshold,
int *n_cycleword_lengths, int cycleword_lengths[], bool verbose);
double vec_mean(double vec[], int len);
double vec_stddev(double vec[], int len);
// Utils
static inline uint32_t fast_rand(void);
static inline void seed_fast_rand(uint32_t seed);
static inline uint32_t fast_rand_bounded(uint32_t range);
int gcd(int a, int b);
int parse_cipher_type(const char *arg);
int unique_len(char *str);
void vec_print(int vec[], int len);
void print_text(int indices[], int len);
void ord(char *text, int indices[]);
float index_of_coincidence(int plaintext[], int len);
void tally(int plaintext[], int len, int frequencies[], int n_frequencies);
bool file_exists(const char * filename);
void vec_copy(int src[], int dest[], int len);
int int_pow(int base, int exp);
extern uint32_t rng_state;
// Fast inline Xorshift32 generator
static inline uint32_t fast_rand(void) {
uint32_t x = rng_state;
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
return rng_state = x;
}
// Function to seed the PRNG
static inline void seed_rand(uint32_t seed) {
if (seed == 0) seed = 1; // State cannot be 0
rng_state = seed;
}
// Lemire's method to map the 32-bit random integer to a specific range [0, range)
static inline uint32_t rand_bounded(uint32_t range) {
return (uint32_t)(((uint64_t)fast_rand() * range) >> 32);
}
static inline int rand_int(int min, int max) {
if (min >= max) return min;
uint32_t range = (uint32_t)(max - min);
return min + (int)rand_bounded(range);
}
static inline double frand(void) {
// Divided by 2^32 to ensure the result is strictly < 1.0
return (double)fast_rand() / 4294967296.0;
}
#endif