Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 

158 řádky
4.5 KiB

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "utils/hex_to_base64.h"
  4. #include "set1/xor_char_finder.h"
  5. #define FREQUENT_LETTERS_AMOUNT 5
  6. int char_in_array(const unsigned char iX, const char* const iArray, const int iSize )
  7. {
  8. int found = 0;
  9. for(int i=0; i<iSize; ++i)
  10. {
  11. if(iX==iArray[i])
  12. {
  13. found = 1;
  14. break;
  15. }
  16. }
  17. return found;
  18. }
  19. static void fill_frequency(struct frequency_t (&i_frequency_array)[FREQUENT_LETTERS_AMOUNT])
  20. {
  21. // Most frequent letters in english "etaoinshr",
  22. i_frequency_array[0].letter='e';
  23. i_frequency_array[0].frequency=12;
  24. i_frequency_array[0].score=0;
  25. i_frequency_array[1].letter='t';
  26. i_frequency_array[1].frequency=9;
  27. i_frequency_array[1].score=0;
  28. i_frequency_array[2].letter='a';
  29. i_frequency_array[2].frequency=8;
  30. i_frequency_array[2].score=0;
  31. i_frequency_array[3].letter='o';
  32. i_frequency_array[3].frequency=8;
  33. i_frequency_array[3].score=0;
  34. i_frequency_array[4].letter='i';
  35. i_frequency_array[4].frequency=7;
  36. i_frequency_array[4].score=0;
  37. }
  38. void xor_char_finder(const char* const ciphertext, struct frequency_t& o_frequency)
  39. {
  40. static const int ciphertext_len = strlen(ciphertext) / 2;
  41. unsigned char ciphertext_xor[ciphertext_len];
  42. static const char printable_ascii[] =" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,-'+_`?!*:;$<>[]@#$%^&*()?><MZ}|\"{:P";
  43. static const unsigned printable_ascii_len = sizeof(printable_ascii)/sizeof(char);
  44. // -----------------------------------------------------------------------------
  45. //
  46. // Array keeps letters that occure most frequently in english language. They are
  47. // ordered from most frequent to least frequent
  48. //
  49. // -----------------------------------------------------------------------------
  50. struct frequency_t frequency[FREQUENT_LETTERS_AMOUNT];
  51. fill_frequency(frequency);
  52. /*
  53. printf("Frequencies ");
  54. for(int i=0; i<FREQUENT_LETTERS_AMOUNT; ++i)
  55. printf("%c %d, ",frequency[i].letter, frequency[i].frequency);
  56. printf("\n");
  57. */
  58. // -----------------------------------------------------------------------------
  59. //
  60. // Keeps xorable characters - those which produce valid ascii text after xoring
  61. // with ciphertext.
  62. //
  63. // -----------------------------------------------------------------------------
  64. int xorable = 0;
  65. char xorable_chars[printable_ascii_len];
  66. // -----------------------------------------------------------------------------
  67. //
  68. // 1. Convert ASCII ciphertext to HEX
  69. //
  70. // -----------------------------------------------------------------------------
  71. unsigned char* p_ciphertext_xor = ciphertext_xor;
  72. convert_string_to_hex(ciphertext, ciphertext_len*2, p_ciphertext_xor);
  73. // -----------------------------------------------------------------------------
  74. //
  75. // 2. Check if Xorable. Get those characters for which XOR of ciphertext and
  76. // each byte from cipher text produces some valid text.
  77. //
  78. // -----------------------------------------------------------------------------
  79. unsigned char tmp[printable_ascii_len][printable_ascii_len];
  80. for(int i=0; i<printable_ascii_len; ++i)
  81. {
  82. char tmp_hex[ciphertext_len];
  83. char aXorChar = printable_ascii[i];
  84. int fully_coppied=1;
  85. for(int j=0; j<ciphertext_len; ++j)
  86. {
  87. const unsigned char X = ciphertext_xor[j]^aXorChar;
  88. if( char_in_array(X, printable_ascii, printable_ascii_len) == 0)
  89. {
  90. fully_coppied=0;
  91. break;
  92. }
  93. tmp[xorable][j] = X;
  94. }
  95. if(fully_coppied)
  96. {
  97. xorable_chars[xorable] = aXorChar;
  98. xorable++;
  99. }
  100. }
  101. // -----------------------------------------------------------------------------
  102. //
  103. // 3. Calculate best score - get this text from xorables that has most occurences
  104. // of letters from frequency list.
  105. //
  106. // -----------------------------------------------------------------------------
  107. o_frequency.frequency=0;
  108. o_frequency.letter=0x00; // > is not in the set
  109. o_frequency.score = 0;
  110. if( xorable > 1 )
  111. {
  112. for(int i=0; i<xorable; ++i)
  113. {
  114. unsigned long score=0;
  115. for(int j=0; j<ciphertext_len; ++j)
  116. {
  117. for(int k=0; k<FREQUENT_LETTERS_AMOUNT; ++k)
  118. {
  119. if(frequency[k].letter == (ciphertext_xor[j]^xorable_chars[i]))
  120. {
  121. score += frequency[k].frequency;
  122. }
  123. }
  124. }
  125. if(o_frequency.score > 0 && (score == o_frequency.score) )
  126. {
  127. printf("Two results with equal scores. Extend number of frequent letters.\n");
  128. return;
  129. }
  130. else if(score > o_frequency.score)
  131. {
  132. o_frequency.score = score;
  133. o_frequency.letter = xorable_chars[i];
  134. }
  135. }
  136. }
  137. else if(xorable == 1)
  138. {
  139. o_frequency.letter = xorable_chars[0];
  140. o_frequency.frequency=0;
  141. o_frequency.score = 0;
  142. }
  143. }