Break the ciphertext in blocks and attempt to decipher it

This commit is contained in:
Dimitri Lozeve 2020-06-09 17:11:07 +02:00
parent 504e6820f2
commit 0bce806ec6
3 changed files with 48 additions and 4 deletions

View file

@ -48,6 +48,11 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (fclose(fp)) {
printf("Error closing file %s\n", filename);
return EXIT_FAILURE;
}
unsigned char buf[BUF_SIZE] = {0}; unsigned char buf[BUF_SIZE] = {0};
size_t len = base64_to_bytes(buf, input); size_t len = base64_to_bytes(buf, input);
if (len == 0) { 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); printf("keysize = %u, min edit distance = %f\n", keysize, min_edit_dist);
if (fclose(fp)) { size_t blocks_count = 1 + len / keysize;
printf("Error closing file %s\n", filename); unsigned char blocks[keysize][blocks_count];
return EXIT_FAILURE; 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; return EXIT_SUCCESS;
} }

View file

@ -2,6 +2,7 @@
#include <ctype.h> #include <ctype.h>
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#define min(a, b) \ #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] = static const char base64_table[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "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) { for (size_t i = 0; i < len - 2; i += 3) {
size_t j = i / 3 * 4; size_t j = i / 3 * 4;
out[j] = base64_table[in[i] >> 2]; 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; 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;
}

View file

@ -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]); 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]); double frequency_score(size_t len, const char buf[static len]);
unsigned int hamming(const char s1[static 1], const char s2[static 1]); 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 */ #endif /* UTILS_H */