analysis.c (2470B)
1 #include "cryptanalysis.h" 2 3 unsigned long score_letter(char c) 4 { 5 /* this is approximate, however this shouldnt really make a difference 6 * unless you have multiple ciphertexts very close to each other as 7 * far as the score is concerned - meaning this is enough to weed out 8 * junk (nonenglish) byte sequences */ 9 unsigned long freqs[] = { 10 82, 15, 28, 43, 130, 11 22, 20, 61, 70, 1, 12 8, 40, 24, 67, 75, 13 19, 1, 60, 63, 91, 14 28, 10, 24, 2, 20, 15 1}; 16 17 c = tolower(c); 18 if (c == ' ') 19 return 200; 20 21 if (isalpha(c)) 22 return freqs[c-'a']; 23 24 return 0; 25 } 26 27 unsigned long score_english(ba *text) 28 { 29 unsigned long res; 30 int i; 31 32 res = 0; 33 for (i = 0; i < text->len; i++) 34 res += score_letter((text->val)[i]); 35 return res; 36 } 37 38 ba *decrypt_scxor(ba *ct) 39 { 40 char buf[2*(ct->len)]; 41 uint8_t best_key; 42 uint16_t i; 43 ba *key; 44 int max; 45 46 max = 0; 47 for (i = 0; i < 0xff; i++) { 48 char buf[2*(ct->len)]; 49 snprintf(buf, 16, "%2x", i); 50 key = ba_from_hex_n(buf, ct->len); 51 ba_xor(key, ct); 52 unsigned long sc = score_english(key); 53 if (sc > max) { 54 max = sc; 55 best_key = i; 56 } 57 } 58 59 snprintf(buf, 16, "%2x", best_key); 60 key = ba_from_hex_n(buf, ct->len); 61 ba_xor(ct, key); 62 ba_free(key); 63 return ct; 64 } 65 66 void encrypt_rkxor(ba *pt, ba *key) 67 { 68 ba *key_exp; 69 int i; 70 71 key_exp->len = pt->len; 72 key_exp->val = (uint8_t *) malloc(sizeof(uint8_t) * key_exp->len); 73 for (i = 0; i < key_exp->len; i++) 74 key_exp->val[i] = key->val[i % (key->len)]; 75 ba_xor(pt, key_exp); 76 } 77 78 float index_of_coincidence(ba *ct) 79 { 80 unsigned int occur[256]; 81 unsigned int i; 82 unsigned int t; 83 float res; 84 85 res = 0; 86 memset(occur, 0, sizeof(occur)); 87 88 for (i = 0; i < ct->len; i++) 89 occur[ct->val[i]]++; 90 91 t = 0; 92 for (i = 0; i < 256; i++) 93 t += occur[i] * (occur[i] - 1); 94 95 res = t / (float) (ct->len * (ct->len - 1)); 96 return res; 97 } 98 99 static float get_i_c_m(ba *ct, unsigned int m) 100 { 101 float res; 102 int i; 103 res = 0; 104 for (i = 0; i < m; i++) { 105 ba *chunk = (ba *) malloc(sizeof(ba)); 106 int j; 107 int k; 108 109 chunk->len = ct->len / m; 110 chunk->val = (uint8_t *) malloc(sizeof(uint8_t) * chunk->len); 111 112 for (j = 0, k = 0; j < chunk->len && k + i < ct->len; j++, k += m) 113 chunk->val[j] = ct->val[k + i]; 114 res += index_of_coincidence(chunk); 115 } 116 return res / m; 117 } 118 119 unsigned int guess_vigenere_keylen(ba *ct) 120 { 121 unsigned int best; 122 float max; 123 int m; 124 125 max = 0; 126 for (m = 1; m < 40; m++) { 127 float avg; 128 129 avg = get_i_c_m(ct, m); 130 if (avg > max) { 131 max = avg; 132 best = m; 133 } 134 } 135 return best; 136 }