summaryrefslogtreecommitdiff
path: root/task6.c
blob: 949d0ec615069a11b442d65116000ff4a4b89ff0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "lib.h"

/**
 * split ciphertext in blocks of size blocksize
 * @return returns an array of string of size with blocksize elements
 */


char **transpose_blocks(char *ciphertext, int blocksize, int length)
{
	char **blocks;
	int i, j;
	int number_blocks = length / blocksize;

	blocks = malloc(blocksize*(sizeof(char*)));

	for(i=0;i<blocksize;i++) {
		blocks[i] = malloc(number_blocks+1);
	}

	for(j=0;j<blocksize;j++) {
		for(i=0;i<number_blocks;i++) {
			blocks[j][i] = ciphertext[(i*blocksize)+j];
		}
	}

	return blocks;
}

int main()
{
	FILE *fp;
	int keysize;
	char ch;
	char *file_content, *new_file_content, *chiphertext, *block1, *block2;
	int file_size = 60, file_pos = 0;
	int i; 
	double min_hamming_distance, tmp;
	
	fp = fopen("6.txt", "r");

	if (fp == NULL) {
		printf("Error open file\n");
		exit(1);
	}
	
	file_content = malloc(file_size);

	if (file_content == NULL) {
		perror("out of memory");
		exit(1);
	}

	// read data and decode it from base64
	// result is not a hex strin or?

	while ( (ch = fgetc(fp)) != EOF) {
		// ignore new lines as this is part of base64
		if (ch == '\n' || ch == '\r')
			continue;

		if (file_pos+1 >= file_size) {
			new_file_content = realloc(file_content, (file_size+60));
			if (new_file_content != NULL) {
				file_content = new_file_content;
				file_size += 60;
			}
			else {
				printf("error allocating memory\n");
				exit(1);
			}
		}
		file_content[file_pos++] = ch;
	}
	file_content[file_pos] = '\0';

	int ciphertext_len = 0;

	chiphertext = malloc(file_pos+1);
	ciphertext_len = decode_base64(file_content, chiphertext);

	block1 = malloc(41);
	block2 = malloc(41);

	// max. hamming distacne is 100.
	min_hamming_distance = 101;

	int j=0;
	// split ciphertext in 4 blocks of size 2 to 40
	// and compute hamming distance of these blocks
	for(i=2; i <= 40; i++) {
		for(j=0;j< ciphertext_len/i;j++) {
			memcpy(block1, &chiphertext[j], i);
			block1[i+1] = '\0';
			memcpy(block2, &chiphertext[j+i], i);
			block2[i+1] = '\0';
		
			tmp += (double) hamming_distance_equal_length(block1, block2, i);
		}
		tmp = ((double)tmp / (double) (ciphertext_len/i)/ (double)i);
		if (tmp <= min_hamming_distance) {
			min_hamming_distance = tmp;
			keysize = i;
		}
	}
	
	int number_blocks = ciphertext_len/keysize;
	printf("use keysize: %i with hammind_distance: %f, number of blocks:%i\n", keysize, min_hamming_distance, number_blocks);
	// split into keysize blcoks and transpose them 
	char **transposed_blocks = transpose_blocks(chiphertext, keysize, ciphertext_len);

	char key[keysize+1];
	struct key_and_freq tmp_NOT_USED_HERE;

	for(i=0;i<keysize;i++) {
		key[i] = brute_force_single_byte_xor(transposed_blocks[i],
					number_blocks, &tmp_NOT_USED_HERE);
	}

	key[keysize+1] = '\0';	
	char *cleartext = malloc(ciphertext_len+1);
	// xor with all single byte keys on the whole data
	cleartext[ciphertext_len] = '\0';
	xor_string(chiphertext, key, cleartext, keysize, ciphertext_len);

	printf("%s\n", cleartext);
	printf("used key: %s\n", key);
	return 0;
}