summaryrefslogtreecommitdiff
path: root/break_repeating_key_xor_s1.c
diff options
context:
space:
mode:
Diffstat (limited to 'break_repeating_key_xor_s1.c')
-rw-r--r--break_repeating_key_xor_s1.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/break_repeating_key_xor_s1.c b/break_repeating_key_xor_s1.c
new file mode 100644
index 0000000..322829b
--- /dev/null
+++ b/break_repeating_key_xor_s1.c
@@ -0,0 +1,87 @@
+#include "util/base64.h"
+#include "util/hamming.h"
+#include "util/io.h"
+#include "util/score.h"
+#include "util/xor.h"
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define DEBUG
+
+static double average(double *xs, size_t len) {
+ size_t count = 0;
+ double total = 0;
+ for (size_t i = 0; i < len; i++) {
+ count++;
+ total += xs[i];
+ }
+ return total / count;
+}
+
+static void print_key(uint8_t *key, size_t len) {
+ printf("key=\"");
+ for (size_t i = 0; i < len; i++)
+ printf("%c", key[i]);
+ printf("\"\n");
+}
+
+int main() {
+ FILE *stream = stdin;
+ char *b64text = read_non_space(stream);
+ if (b64text == NULL) {
+ printf("read_non_space() failed\n");
+ exit(1);
+ }
+ size_t byte_len;
+ uint8_t *cyphertext = base64_decode(b64text, &byte_len);
+ if (cyphertext == NULL) {
+ printf("base64_decode() failed\n");
+ exit(1);
+ }
+ size_t key_size, best_size = 0;
+ double best_dist = 1e9;
+ int n = 15;
+ for (key_size = 2; key_size <= 40; key_size++) {
+ double dist[n];
+ uint8_t *curr = cyphertext;
+ for (int i = 0; i < n; i++) {
+ dist[i] =
+ ((double)hamming_distance_bytes(curr, curr + key_size, key_size)) /
+ key_size;
+ curr += 2 * key_size;
+ }
+ double norm_dist = average(dist, n);
+#ifdef DEBUG
+ printf("key size: %zu, norm dist: %f\n", key_size, norm_dist);
+#endif
+ if (norm_dist < best_dist) {
+ best_dist = norm_dist;
+ best_size = key_size;
+ }
+ }
+#ifdef DEBUG
+ printf("best size: %zu, best dist: %f\n", best_size, best_dist);
+#endif
+ uint8_t *key = malloc(best_size);
+ for (size_t i = 0; i < best_size; i++) {
+ uint8_t k = best_key_step(cyphertext, byte_len, i, best_size);
+ key[i] = k;
+ }
+ print_key(key, best_size);
+ printf("\ndecoded message:\n");
+ uint8_t *decoded =
+ xor_with_repeating_key(cyphertext, byte_len, key, best_size);
+ if (fwrite(decoded, 1, byte_len, stdout) != byte_len) {
+ printf("frwrite() failed\n");
+ exit(1);
+ }
+ free(key);
+ free(decoded);
+ free(b64text);
+ free(cyphertext);
+ fclose(stream);
+ return 0;
+}