-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcracker.c
129 lines (87 loc) · 2.5 KB
/
cracker.c
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 <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <assert.h>
#include "misc.h"
#include "filtered_string.h"
#include "mfreq_analysis.h"
#include "kasiski.h"
#include "cracker.h"
/* Initialize a struct cracker. */
void ck_init(struct cracker *state, struct fs_ctx *str) {
memset(state, 0, sizeof(*state));
state->str = str;
state->ka_minlen = 3;
}
/* Free everything one of the ck_* function allocated */
void ck_fini(struct cracker *state) {
if (state->key != NULL)
free(state->key);
if (state->ka_done)
ka_fini(&state->ka);
if (state->mfa_done)
mfa_fini(&state->mfa);
memset(state, 0, sizeof(*state));
}
void ck_set_length(struct cracker *state, size_t len) {
state->klen = len;
if (state->key != NULL)
free(state->key);
state->key = malloc((len + 1) * sizeof(*state->key));
if (state->key == NULL)
system_error("malloc");
memset(state->key, 0, (len + 1) * sizeof(*state->key));
}
void ck_length(struct cracker *state) {
size_t i, nlen;
size_t bestlength, bestscore;
nlen = strlen(state->str->norm);
if (nlen < 3)
custom_error("Can't break key length of a text with only %lu "
"signficant characters", nlen);
/* Restart the kasiski analysis if specifically asked to. */
if (state->ka_done)
ka_fini(&state->ka);
ka_init(&state->ka, state->str->norm, state->ka_minlen);
ka_analyze(&state->ka);
bestlength = 2;
bestscore = state->ka.score[bestlength];
for (i = 3; i < nlen; i++) {
size_t score = state->ka.score[i];
if (score > bestscore) {
bestscore = score;
bestlength = i;
}
}
ck_set_length(state, bestlength);
state->ka_done = 1;
}
static void key_from_mfa_shift(struct cracker *state) {
size_t i;
const struct charset *cs;
assert(state->mfa_done);
cs = state->str->charset;
for (i = 0; i < state->klen; i++) {
/* Substract because we're undoing a Vigenère. */
size_t j = cs->length - state->mfa.shift[i];
state->key[i] = cs_chr(cs, j % cs->length);
}
}
void ck_freq(struct cracker *state) {
if (state->klen == 0)
custom_error("Call either ck_length or ck_set_length "
"before calling ck_freq.");
/* Restart the multi-freq analysis if specifically asked to. */
if (state->mfa_done)
mfa_fini(&state->mfa);
mfa_init(&state->mfa, state->str->norm, state->klen, state->str->charset, freq_en);
state->mfa_done = 1;
mfa_analyze(&state->mfa);
key_from_mfa_shift(state);
}
void ck_crack(struct cracker *state) {
if (state->klen == 0)
ck_length(state);
if (!state->mfa_done)
ck_freq(state);
}