commit d6af37147d971612c349a27bc26f7fb8ba44b34d
parent 8a74c314a49ab1632f88a21970241dff0384e127
Author: superpozycja <anna@superpozycja.net>
Date: Sun, 1 Sep 2024 19:42:58 +0200
add vigenere related functions and truly rename to analysis
Diffstat:
2 files changed, 64 insertions(+), 2 deletions(-)
diff --git a/lib/analysis.c b/lib/analysis.c
@@ -74,3 +74,63 @@ void encrypt_rkxor(ba *pt, ba *key)
key_exp->val[i] = key->val[i % (key->len)];
ba_xor(pt, key_exp);
}
+
+float index_of_coincidence(ba *ct)
+{
+ unsigned int occur[256];
+ unsigned int i;
+ unsigned int t;
+ float res;
+
+ res = 0;
+ memset(occur, 0, sizeof(occur));
+
+ for (i = 0; i < ct->len; i++)
+ occur[ct->val[i]]++;
+
+ t = 0;
+ for (i = 0; i < 256; i++)
+ t += occur[i] * (occur[i] - 1);
+
+ res = t / (float) (ct->len * (ct->len - 1));
+ return res;
+}
+
+static float get_i_c_m(ba *ct, unsigned int m)
+{
+ float res;
+ int i;
+ res = 0;
+ for (i = 0; i < m; i++) {
+ ba *chunk = (ba *) malloc(sizeof(ba));
+ int j;
+ int k;
+
+ chunk->len = ct->len / m;
+ chunk->val = (uint8_t *) malloc(sizeof(uint8_t) * chunk->len);
+
+ for (j = 0, k = 0; j < chunk->len && k + i < ct->len; j++, k += m)
+ chunk->val[j] = ct->val[k + i];
+ res += index_of_coincidence(chunk);
+ }
+ return res / m;
+}
+
+unsigned int guess_vigenere_keylen(ba *ct)
+{
+ unsigned int best;
+ float max;
+ int m;
+
+ max = 0;
+ for (m = 1; m < 40; m++) {
+ float avg;
+
+ avg = get_i_c_m(ct, m);
+ if (avg > max) {
+ max = avg;
+ best = m;
+ }
+ }
+ return best;
+}
diff --git a/lib/analysis.h b/lib/analysis.h
@@ -1,5 +1,5 @@
-#ifndef CRYPTANALYSIS_H
-#define CRYPTANALYSIS_H
+#ifndef ANALYSIS_H
+#define ANALYSIS_H
#include <ctype.h>
#include <string.h>
@@ -12,5 +12,7 @@ unsigned long score_letter(char c);
unsigned long score_english(ba *text);
ba *decrypt_scxor(ba *ct);
void encrypt_rkxor(ba *pt, ba *key);
+float index_of_coincidence(ba *ct);
+unsigned int guess_vigenere_keylen(ba *ct);
#endif