From f199aa2d0f1b0633ac0b44101fc54ab3a534d158 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Thu, 5 May 2022 23:44:32 +0300 Subject: [PATCH] small improvements and features --- README.md | 6 ++-- example.txt | 4 ++- main.c | 101 +++++++++++++++++++++++++++++++--------------------- 3 files changed, 66 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index b85fe24..81aa5ee 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ You can download the executable from the release tab, or you can compile it your To run the application you need to create a text file containing the cipher text. The cipher text should only contain letters from A-Z, diacritics, punctuation marks and other symbols should be unencrypted. The length of the cipher text highly affects the success rate of decrypting, it should be around 200 characters minimum including whitespaces for a high probability of decrypting. -After creating the file, you can simply do +After creating the file, you can simply do (providing a key argument only decrypts the text using it) ``` -./cvigenere.exe path/to/example.txt +./cvigenere.exe path/to/example.txt key ``` ## How it works The cryptanalysis of the Vigenere cipher is split up in 3 steps: @@ -37,7 +37,7 @@ KFAKFAKFA KFAKFAKFA - lots of coincidences ``` This is just an example. -What happens in a real scenario is that even through the key repeats itself, there isn't a spike in the number of coincidences. +What happens in a real scenario is that even though the key repeats itself, there isn't a spike in the number of coincidences. That's why the success rate highly depends on the length of the cipher text. Keep in mind that there can also be false positive results, when there's a high number of coincidences but the key doesn't repeat. The way the length of the key is determined is by looking for coincidence spikes that occur at same distance. diff --git a/example.txt b/example.txt index eeb4eed..3b6a8f5 100644 --- a/example.txt +++ b/example.txt @@ -1 +1,3 @@ -Dais nhxai aprve tvpsiir odtp? Brbfitst ql nj vfa lfaa ewniddrhl. Spu gcltt eowdtp o joysp sr oqlpm? Ki ne eaisce pi, tfpzx cr jzm pfco grtouoea? Hueh qoprks nugifg oara dscgt sz qsipr rg grta jo lfau. \ No newline at end of file +Dais nhxai aprve tvpsiir odtp? Brbfitst ql nj vfa lfaa ewniddrhl. +Spu gcltt eowdtp o joysp sr oqlpm? Ki ne eaisce pi, tfpzx cr jzm pfco grtouoea? +Hueh qoprks nugifg oara dscgt sz qsipr rg grta jo lfau. \ No newline at end of file diff --git a/main.c b/main.c index 5d4fd68..9e35604 100644 --- a/main.c +++ b/main.c @@ -2,6 +2,8 @@ #include #include #include +#include +#define EOOR 255 typedef struct key_value_pair{ int key, value; @@ -17,33 +19,31 @@ void remove_spacing(char *str){ } void decrypt(char *str, char *key){ - int i, j, len = strlen(key); + int i, j; + char l; + unsigned len = strlen(key); for(i = 0, j = 0; i < strlen(str); i++){ if(!strchr("abcdefghijklmnopqrstuvwxyz", str[i])) continue; - str[i] -= key[j % len] - 'a'; + l = key[j % len]; + str[i] -= l - 'a'; if(str[i] < 'a') str[i] = 'z' - ('a' - str[i]) + 1; j++; } } char* get_key(char *str, int key_len){ - char letters[26] = {'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'}; - float values[26] = { 0.098f, 0.01f, 0.05f, 0.035f, 0.12f, 0.01f, 0.008f, 0.005f, 0.1f, 0.002f, 0.001f, 0.043f, 0.038f, 0.07f, 0.041f, 0.038f, 0.0f, 0.072f, 0.043f, 0.058f, 0.059f, 0.01f, 0.0f, 0.001f, 0.001f, 0.008f}; - int i, j, k, n, len, bin_len, flag; + const char letters[26] = {'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'}; + const float values[26] = { 0.098f, 0.01f, 0.05f, 0.035f, 0.12f, 0.01f, 0.008f, 0.005f, 0.1f, 0.002f, 0.001f, 0.043f, 0.038f, 0.07f, 0.041f, 0.038f, 0.0f, 0.072f, 0.043f, 0.058f, 0.059f, 0.01f, 0.0f, 0.001f, 0.001f, 0.008f}; + int i, j, k, n, bin_len, flag; + unsigned int len; float *scores[key_len], max; - char *bins[key_len], *temp; - char *model = (char*) malloc(sizeof(char) * strlen(str)); - char *key = (char*) malloc(sizeof(char) * key_len + 1); - key[key_len] = '\0'; + char *bins[key_len], *temp, *key; + char *model = (char*) malloc(sizeof(char) * strlen(str) + 1); strcpy(model, str); remove_spacing(model); len = strlen(model); bin_len = (int) ceil((float) len / (float) key_len); - temp = (char*) malloc(bin_len * sizeof(char)); - for(i = 0; i < key_len; i++){ - bins[i] = (char*) calloc(bin_len, sizeof(char)); - scores[i] = (float*) calloc(25, sizeof(float)); - } + for(i = 0; i < key_len; i++) bins[i] = (char*) calloc(bin_len, sizeof(char)); for(i = 0; i < len; i++){ for(j = 0; j < bin_len; j++){ if(bins[i % key_len][j] == 0){ @@ -61,7 +61,9 @@ char* get_key(char *str, int key_len){ } } } + temp = (char*) malloc(bin_len * sizeof(char)); for(i = 0; i < key_len; i++){ + scores[i] = (float*) calloc(26, sizeof(float)); for(j = 0; j < 26; j++){ strcpy(temp, bins[i]); for(k = 0; k < strlen(temp); k++){ @@ -71,6 +73,8 @@ char* get_key(char *str, int key_len){ } } } + key = (char*) malloc(sizeof(char) * key_len + 1); + key[key_len] = '\0'; for(i = 0; i < key_len; i++){ free(bins[i]); max = 0.0f; @@ -82,18 +86,18 @@ char* get_key(char *str, int key_len){ } } key[i] = flag + 'a'; + free(scores[i]); } - for(i = 0; i < key_len; i++) free(scores[i]); return key; } -int find_key_length(char *str, float ratio){ - int i, j, k, len, max_val = 0, max_flag, *scores, *temp, sum = 0, avg, ctr; - char *model = (char*) malloc(sizeof(char) * strlen(str)); - char *shifted = (char*) malloc(sizeof(char) * strlen(str)); - int *spikes = (int*) malloc(sizeof(int)); - int *spike_subs = (int*) malloc(sizeof(int)); - Pair *freqs = malloc(sizeof(Pair)); +int get_key_length(char *str, float ratio){ + int i, j, k, max_val = 0, max_flag, *scores, *temp, *spikes, *spike_subs, sum = 0, avg, ctr; + unsigned int len; + char *model, *shifted; + Pair *freqs; + model = (char*) malloc(sizeof(char) * strlen(str) + 1); + shifted = (char*) malloc(sizeof(char) * strlen(str)); strcpy(model, str); remove_spacing(model); len = strlen(model); @@ -107,7 +111,10 @@ int find_key_length(char *str, float ratio){ } } } - free(model), free(shifted); + free(model); + free(shifted); + spikes = (int*) malloc(sizeof(int)); + spike_subs = (int*) malloc(sizeof(int)); for(i = 1; i < len; i++) sum += scores[i]; avg = (int) floor((float) sum / (float) len); for(i = 2, j = 1; i < len - 1; i++){ @@ -138,6 +145,7 @@ int find_key_length(char *str, float ratio){ temp[i] = ctr; } } + freqs = malloc(sizeof(Pair)); for(i = 0, j = 1; i < k - 1; i++){ if(temp[i] != 0){ freqs[j - 1].key = spike_subs[i]; @@ -146,7 +154,8 @@ int find_key_length(char *str, float ratio){ freqs = realloc(freqs, sizeof(Pair) * j); } } - free(temp), free(spike_subs); + free(temp); + free(spike_subs); for(i = 0; i < j - 1; i++){ if(freqs[i].value > max_val){ max_val = freqs[i].value; @@ -167,38 +176,48 @@ int find_key_length(char *str, float ratio){ size_t get_fsize(FILE *file){ fseek(file, 0, SEEK_END); size_t size = ftell(file); - fseek(file, 0, SEEK_SET); + rewind(file); return size; } +char *file_to_buffer(FILE *file){ + size_t f_size = get_fsize(file); + char *buf = (char*) malloc(f_size * sizeof(char) + 1); + buf[f_size] = '\0'; + fread(buf, sizeof(char), f_size, file); + strlwr(buf); + return buf; +} + int main(int argc, char* argv[]) { + FILE *file; + int key_length; + char *text, *key; if(argc < 2){ - printf("Example: %s [input file path]", argv[0]); + printf("Example: %s [input file path] [optional key]", argv[0]); exit(EINVAL); } - FILE *file; - size_t f_size; - char *text = NULL; - int key_length; - char *key; - file = fopen(argv[1], "r"); + file = fopen(argv[1], "rb"); if(!file){ printf("Error: cannot open file."); exit(ENOENT); } - f_size = get_fsize(file) * sizeof(char) + 1; - text = (char*) malloc(f_size); - fscanf(file, "%[^\n]", text); + text = file_to_buffer(file); fclose(file); - text = strlwr(text); - key_length = (find_key_length(text, 3.0f)) ? find_key_length(text, 3.0f) : find_key_length(text, 2.5f); - if(key_length < 0){ + if(argv[2]){ + decrypt(text, argv[2]); + printf("%s", text); + return 0; + } + key_length = (get_key_length(text, 3.0f)) ? get_key_length(text, 3.0f) : get_key_length(text, 2.5f); + if(!key_length){ printf("COULDN\'T FIND KEY LENGTH"); - exit(255); + exit(EOOR); } key = get_key(text, key_length); - printf("KEY: %s", key); + printf("KEY: %s\n", key); decrypt(text, key); - printf("\n%s", text); + free(key); + printf("%s", text); return 0; }