@@ -1,9 +1,11 @@ | |||
INC=. | |||
all: | |||
mkdir -p obj | |||
g++ -g -I${INC} -c utils/hex_to_base64.cpp -o obj/hex_to_base64.o | |||
g++ -g -I${INC} -c utils/utils_tester.cpp -o obj/utils_tester.o | |||
g++ -g -I${INC} -c utils/xor.c -o obj/xor.o | |||
g++ -g -I${INC} -c set1/xor_char_finder.cpp -o obj/xor_char_finder.o | |||
g++ -g -I${INC} -c utils/hamming.c -o obj/hamming.o | |||
g++ -g -lpthread -o utils_tester obj/hex_to_base64.o obj/utils_tester.o obj/xor_char_finder.o obj/xor.o obj/hamming.o | |||
clean: | |||
rm -rf obj utils_tester |
@@ -3,8 +3,6 @@ | |||
#include "utils/hex_to_base64.h" | |||
#include "set1/xor_char_finder.h" | |||
#define FREQUENT_LETTERS_AMOUNT 5 | |||
int char_in_array(const unsigned char iX, const char* const iArray, const int iSize ) | |||
{ | |||
int found = 0; | |||
@@ -22,32 +20,12 @@ int char_in_array(const unsigned char iX, const char* const iArray, const int iS | |||
static void fill_frequency(struct frequency_t (&i_frequency_array)[FREQUENT_LETTERS_AMOUNT]) | |||
{ | |||
// Most frequent letters in english "etaoinshr", | |||
i_frequency_array[0].letter='e'; | |||
i_frequency_array[0].frequency=12; | |||
i_frequency_array[0].score=0; | |||
i_frequency_array[1].letter='t'; | |||
i_frequency_array[1].frequency=9; | |||
i_frequency_array[1].score=0; | |||
i_frequency_array[2].letter='a'; | |||
i_frequency_array[2].frequency=8; | |||
i_frequency_array[2].score=0; | |||
i_frequency_array[3].letter='o'; | |||
i_frequency_array[3].frequency=8; | |||
i_frequency_array[3].score=0; | |||
i_frequency_array[4].letter='i'; | |||
i_frequency_array[4].frequency=7; | |||
i_frequency_array[4].score=0; | |||
} | |||
void xor_char_finder(const char* const ciphertext, struct frequency_t& o_frequency) | |||
void xor_char_finder(const unsigned char* const p_ciphertext_xor, struct frequency_t& o_frequency, unsigned ciphertext_len) | |||
{ | |||
static const int ciphertext_len = strlen(ciphertext) / 2; | |||
unsigned char ciphertext_xor[ciphertext_len]; | |||
static const char printable_ascii[] =" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,-'+_`?!*:;$<>[]@#$%^&*()?><MZ}|\"{:P"; | |||
static const unsigned printable_ascii_len = sizeof(printable_ascii)/sizeof(char); | |||
@@ -57,8 +35,7 @@ void xor_char_finder(const char* const ciphertext, struct frequency_t& o_frequen | |||
// ordered from most frequent to least frequent | |||
// | |||
// ----------------------------------------------------------------------------- | |||
struct frequency_t frequency[FREQUENT_LETTERS_AMOUNT]; | |||
fill_frequency(frequency); | |||
frequency_set frequency; | |||
/* | |||
printf("Frequencies "); | |||
@@ -76,13 +53,6 @@ void xor_char_finder(const char* const ciphertext, struct frequency_t& o_frequen | |||
int xorable = 0; | |||
char xorable_chars[printable_ascii_len]; | |||
// ----------------------------------------------------------------------------- | |||
// | |||
// 1. Convert ASCII ciphertext to HEX | |||
// | |||
// ----------------------------------------------------------------------------- | |||
unsigned char* p_ciphertext_xor = ciphertext_xor; | |||
convert_string_to_hex(ciphertext, ciphertext_len*2, p_ciphertext_xor); | |||
// ----------------------------------------------------------------------------- | |||
// | |||
@@ -98,7 +68,7 @@ void xor_char_finder(const char* const ciphertext, struct frequency_t& o_frequen | |||
int fully_coppied=1; | |||
for(int j=0; j<ciphertext_len; ++j) | |||
{ | |||
const unsigned char X = ciphertext_xor[j]^aXorChar; | |||
const unsigned char X = p_ciphertext_xor[j]^aXorChar; | |||
if( char_in_array(X, printable_ascii, printable_ascii_len) == 0) | |||
{ | |||
fully_coppied=0; | |||
@@ -130,7 +100,7 @@ void xor_char_finder(const char* const ciphertext, struct frequency_t& o_frequen | |||
{ | |||
for(int k=0; k<FREQUENT_LETTERS_AMOUNT; ++k) | |||
{ | |||
if(frequency[k].letter == (ciphertext_xor[j]^xorable_chars[i])) | |||
if(frequency[k].letter == (p_ciphertext_xor[j]^xorable_chars[i])) | |||
{ | |||
score += frequency[k].frequency; | |||
} | |||
@@ -1,9 +1,43 @@ | |||
#define FREQUENT_LETTERS_AMOUNT 5 | |||
struct frequency_t { | |||
char letter; | |||
unsigned long frequency; | |||
unsigned long score; | |||
unsigned long score; | |||
}; | |||
void xor_char_finder(const char* const ciphertext, struct frequency_t& o_frequency); | |||
struct frequency_set { | |||
static const unsigned Size = FREQUENT_LETTERS_AMOUNT; | |||
frequency_t frequencies[FREQUENT_LETTERS_AMOUNT]; | |||
frequency_set() | |||
{ | |||
// Most frequent letters in english "etaoinshr", | |||
frequencies[0].letter='e'; | |||
frequencies[0].frequency=12; | |||
frequencies[0].score=0; | |||
frequencies[1].letter='t'; | |||
frequencies[1].frequency=9; | |||
frequencies[1].score=0; | |||
frequencies[2].letter='a'; | |||
frequencies[2].frequency=8; | |||
frequencies[2].score=0; | |||
frequencies[3].letter='o'; | |||
frequencies[3].frequency=8; | |||
frequencies[3].score=0; | |||
frequencies[4].letter='i'; | |||
frequencies[4].frequency=7; | |||
frequencies[4].score=0; | |||
} | |||
const frequency_t& operator[](const unsigned idx) { | |||
return frequencies[idx]; | |||
} | |||
}; | |||
void xor_char_finder(const unsigned char* const p_ciphertext_xor, struct frequency_t& o_frequency, unsigned ciphertext_len); |
@@ -31,12 +31,12 @@ int block_distance(const char* const s1, const char* const s2, const unsigned i_ | |||
return ret; | |||
} | |||
int choose_min_block_size(const char* i_string, const unsigned i_size) | |||
int choose_min_block_size(const char* const i_string, const unsigned i_size, unsigned i_start_with) | |||
{ | |||
unsigned block_size = 2; | |||
unsigned block_size = i_start_with; | |||
double min_dist=40; // max block is 40 => max dist is 40 | |||
double tmp_dist1, tmp_dist2; | |||
int min_block_size=2; | |||
int min_block_size=40; | |||
tmp_dist1 = tmp_dist2 = 0; | |||
@@ -58,6 +58,3 @@ int choose_min_block_size(const char* i_string, const unsigned i_size) | |||
} | |||
return min_block_size; | |||
} | |||
// break in blocks | |||
// |
@@ -1,2 +1,2 @@ | |||
int block_distance(const char* const s1, const char* const s2, const unsigned i_size); | |||
int choose_min_block_size(const char* i_string, const unsigned i_size); | |||
int block_distance(const char* const s1, const char* const s2, const unsigned i_size); | |||
int choose_min_block_size(const char* const i_string, const unsigned i_size, unsigned i_start_with); |
@@ -229,14 +229,10 @@ int base64_to_hex(const char* const i_string, int i_string_len, unsigned char*& | |||
struct int24 tmp; | |||
while(pointer<i_string_len) | |||
{ | |||
array[pointer] = *(i_string+pointer); | |||
pointer++; | |||
array[pointer] = *(i_string+pointer); | |||
pointer++; | |||
array[pointer] = *(i_string+pointer); | |||
pointer++; | |||
array[pointer] = *(i_string+pointer); | |||
pointer++; | |||
array[pointer%4] = i_string[pointer]; pointer++; | |||
array[pointer%4] = i_string[pointer]; pointer++; | |||
array[pointer%4] = i_string[pointer]; pointer++; | |||
array[pointer%4] = i_string[pointer]; pointer++; | |||
tmp = base64_3char_to_hex(array); | |||
o_hex_array[hex_pointer++] = tmp.data >> 16; | |||
@@ -244,6 +240,6 @@ int base64_to_hex(const char* const i_string, int i_string_len, unsigned char*& | |||
o_hex_array[hex_pointer++] = tmp.data; | |||
} | |||
return 0; | |||
return hex_pointer; | |||
} | |||
@@ -116,7 +116,18 @@ void set1_challenge3_test() | |||
{ | |||
static const char ciphertext[] = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736"; | |||
struct frequency_t max_score; | |||
xor_char_finder(ciphertext, max_score); | |||
// ----------------------------------------------------------------------------- | |||
// | |||
// 1. Convert ASCII ciphertext to HEX | |||
// | |||
// ----------------------------------------------------------------------------- | |||
const int ciphertext_len = strlen(ciphertext) / 2; | |||
unsigned char ciphertext_xor[ciphertext_len]; | |||
unsigned char* p_ciphertext_xor = ciphertext_xor; | |||
convert_string_to_hex(ciphertext, ciphertext_len*2, p_ciphertext_xor); | |||
xor_char_finder(p_ciphertext_xor, max_score, ciphertext_len); | |||
assert(max_score.letter == 'X'); | |||
} | |||
@@ -143,7 +154,19 @@ void set2_challange4_test() | |||
struct frequency_t max_score; | |||
max_score.letter=0x0; | |||
max_score.score = 0; | |||
xor_char_finder(line, max_score); | |||
// ----------------------------------------------------------------------------- | |||
// | |||
// 1. Convert ASCII ciphertext to HEX | |||
// | |||
// ----------------------------------------------------------------------------- | |||
const int ciphertext_len = strlen(line) / 2; | |||
unsigned char ciphertext_xor[ciphertext_len]; | |||
unsigned char* p_ciphertext_xor = ciphertext_xor; | |||
convert_string_to_hex(line, ciphertext_len*2, p_ciphertext_xor); | |||
xor_char_finder(p_ciphertext_xor, max_score, ciphertext_len); | |||
if(max_score.letter != 0x00) | |||
{ | |||
// printf("%d -> %c\n", line_nb, max_score.letter); | |||
@@ -199,6 +222,40 @@ void base64_to_hex_test() | |||
assert( memcmp(expected, out, 6) == 0 ); | |||
} | |||
void set2_challenge_6_test() | |||
{ | |||
char buf[1024*1024]; // 1 MB | |||
unsigned char hex_buf[1024*1024]; | |||
char* pbuf=buf; | |||
unsigned char* p_hex_buf=hex_buf; | |||
unsigned long len=read_file_to_buffer("etc/set1_t6.txt", pbuf); | |||
buf[len]='\0'; | |||
len=base64_to_hex(buf, len, p_hex_buf); | |||
for(int i=0; i<len; ++i) | |||
buf[i]=hex_buf[i]; | |||
buf[len]='\0'; | |||
// guess keysize | |||
int keysize = choose_min_block_size(buf, strlen(buf), 2); | |||
unsigned char* slide = new unsigned char[strlen(buf)/keysize]; | |||
for(int j=0; j<keysize; ++j) | |||
{ | |||
memset(slide, '\0', strlen(buf)/keysize); | |||
int counter = 0; | |||
for(int i=0; i+j<strlen(buf); i+=keysize, counter++) | |||
{ | |||
slide[counter] = hex_buf[i+j]; | |||
} | |||
struct frequency_t max_score; | |||
xor_char_finder(slide, max_score, counter); | |||
printf("> %c %x\n", max_score.letter, max_score.letter); | |||
} | |||
// delete [] slide; | |||
} | |||
int main() { | |||
hex_to_base64_text(); | |||
convert_string_to_hex_test(); | |||
@@ -208,11 +265,6 @@ int main() { | |||
set2_challenge_5_test(); | |||
hamming_test(); | |||
base64_to_hex_test(); | |||
char buf[1024*1024]; // 1 MB | |||
char* pbuf=buf; | |||
unsigned long l=read_file_to_buffer("etc/set1_t6.txt", pbuf); | |||
buf[l]='\0'; | |||
printf("%s\n", buf); | |||
set2_challenge_6_test(); | |||
} | |||