From 0bce806ec6cffc43e105f3772cb27d826bae0401 Mon Sep 17 00:00:00 2001 From: Dimitri Lozeve Date: Tue, 9 Jun 2020 17:11:07 +0200 Subject: [PATCH] Break the ciphertext in blocks and attempt to decipher it --- src/ex06/main.c | 24 +++++++++++++++++++++--- src/utils.c | 27 ++++++++++++++++++++++++++- src/utils.h | 1 + 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/ex06/main.c b/src/ex06/main.c index 54ea087..f7e60f0 100644 --- a/src/ex06/main.c +++ b/src/ex06/main.c @@ -48,6 +48,11 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } + if (fclose(fp)) { + printf("Error closing file %s\n", filename); + return EXIT_FAILURE; + } + unsigned char buf[BUF_SIZE] = {0}; size_t len = base64_to_bytes(buf, input); if (len == 0) { @@ -67,10 +72,23 @@ int main(int argc, char *argv[]) { printf("keysize = %u, min edit distance = %f\n", keysize, min_edit_dist); - if (fclose(fp)) { - printf("Error closing file %s\n", filename); - return EXIT_FAILURE; + size_t blocks_count = 1 + len / keysize; + unsigned char blocks[keysize][blocks_count]; + memset(blocks, 0, blocks_count * keysize); + + for (size_t i = 0; i < blocks_count; ++i) { + for (size_t j = 0; j < keysize; ++j) { + blocks[j][i] = buf[i * keysize + j]; + } } + char key[keysize]; + for (size_t j = 0; j < keysize; ++j) { + printf("Guessing key character %2zu: ", j); + key[j] = best_single_char_xor_key(blocks_count, blocks[j]); + printf("%c\n", key[j]); + } + printf("key: %s\n", key); + return EXIT_SUCCESS; } diff --git a/src/utils.c b/src/utils.c index 6096518..36439ab 100644 --- a/src/utils.c +++ b/src/utils.c @@ -2,6 +2,7 @@ #include #include #include +#include #define min(a, b) \ ({ \ @@ -39,7 +40,8 @@ size_t hex_to_bytes(unsigned char out[static 1], const char hex[static 1]) { static const char base64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -char *bytes_to_base64(char out[static 4], const unsigned char in[static 3], size_t len) { +char *bytes_to_base64(char out[static 4], const unsigned char in[static 3], + size_t len) { for (size_t i = 0; i < len - 2; i += 3) { size_t j = i / 3 * 4; out[j] = base64_table[in[i] >> 2]; @@ -133,3 +135,26 @@ unsigned int hamming(const char s1[static 1], const char s2[static 1]) { } return res; } + +char best_single_char_xor_key(size_t len, unsigned char buf[static len]) { + char cur[len]; + double min_score = INFINITY; + char key = 'X'; + + for (char c = 32; c < 127; ++c) { + for (size_t i = 0; i < len; ++i) { + cur[i] = buf[i] ^ c; + } + double score = frequency_score(len, cur); + //printf("current character: %c, current score: %f\n", c, score); + if (score < min_score) { + min_score = score; + key = c; + } + if (isfinite(min_score)) { + printf("current best character: %c, current best score: %f\n", key, min_score); + } + } + + return key; +} diff --git a/src/utils.h b/src/utils.h index b39b804..1bdefe1 100644 --- a/src/utils.h +++ b/src/utils.h @@ -9,5 +9,6 @@ char *bytes_to_base64(char out[static 4], const unsigned char in[static 3], size size_t base64_to_bytes(unsigned char out[static 3], const char in[static 4]); double frequency_score(size_t len, const char buf[static len]); unsigned int hamming(const char s1[static 1], const char s2[static 1]); +char best_single_char_xor_key(size_t len, unsigned char buf[static len]); #endif /* UTILS_H */