|
- #include <stdio.h>
- #include <string.h>
- #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;
- for(int i=0; i<iSize; ++i)
- {
- if(iX==iArray[i])
- {
- found = 1;
- break;
- }
-
- }
- return found;
- }
-
- 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)
- {
- 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);
-
- // -----------------------------------------------------------------------------
- //
- // Array keeps letters that occure most frequently in english language. They are
- // ordered from most frequent to least frequent
- //
- // -----------------------------------------------------------------------------
- struct frequency_t frequency[FREQUENT_LETTERS_AMOUNT];
- fill_frequency(frequency);
-
- /*
- printf("Frequencies ");
- for(int i=0; i<FREQUENT_LETTERS_AMOUNT; ++i)
- printf("%c %d, ",frequency[i].letter, frequency[i].frequency);
- printf("\n");
- */
-
- // -----------------------------------------------------------------------------
- //
- // Keeps xorable characters - those which produce valid ascii text after xoring
- // with ciphertext.
- //
- // -----------------------------------------------------------------------------
- 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);
-
- // -----------------------------------------------------------------------------
- //
- // 2. Check if Xorable. Get those characters for which XOR of ciphertext and
- // each byte from cipher text produces some valid text.
- //
- // -----------------------------------------------------------------------------
- unsigned char tmp[printable_ascii_len][printable_ascii_len];
- for(int i=0; i<printable_ascii_len; ++i)
- {
- char tmp_hex[ciphertext_len];
- char aXorChar = printable_ascii[i];
- int fully_coppied=1;
- for(int j=0; j<ciphertext_len; ++j)
- {
- const unsigned char X = ciphertext_xor[j]^aXorChar;
- if( char_in_array(X, printable_ascii, printable_ascii_len) == 0)
- {
- fully_coppied=0;
- break;
- }
- tmp[xorable][j] = X;
- }
- if(fully_coppied)
- {
- xorable_chars[xorable] = aXorChar;
- xorable++;
- }
- }
- // -----------------------------------------------------------------------------
- //
- // 3. Calculate best score - get this text from xorables that has most occurences
- // of letters from frequency list.
- //
- // -----------------------------------------------------------------------------
- o_frequency.frequency=0;
- o_frequency.letter=0x00; // > is not in the set
- o_frequency.score = 0;
- if( xorable > 1 )
- {
- for(int i=0; i<xorable; ++i)
- {
- unsigned long score=0;
- for(int j=0; j<ciphertext_len; ++j)
- {
- for(int k=0; k<FREQUENT_LETTERS_AMOUNT; ++k)
- {
- if(frequency[k].letter == (ciphertext_xor[j]^xorable_chars[i]))
- {
- score += frequency[k].frequency;
- }
- }
- }
- if(o_frequency.score > 0 && (score == o_frequency.score) )
- {
- printf("Two results with equal scores. Extend number of frequent letters.\n");
- return;
- }
- else if(score > o_frequency.score)
- {
- o_frequency.score = score;
- o_frequency.letter = xorable_chars[i];
- }
- }
- }
- else if(xorable == 1)
- {
- o_frequency.letter = xorable_chars[0];
- o_frequency.frequency=0;
- o_frequency.score = 0;
- }
-
- }
|