cryptopals_c

cryptopals crypto challenges solutions in pure c
git clone git://git.superpozycja.net/cryptopals_c
Log | Files | Refs | README

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 }