]> git.za3k.com Git - cryptopals.git/commitdiff
Solve Set 1, Problem 3
authorZachary Vance <za3k@za3k.com>
Sun, 14 May 2017 08:54:21 +0000 (01:54 -0700)
committerZachary Vance <za3k@za3k.com>
Sun, 14 May 2017 08:54:21 +0000 (01:54 -0700)
Makefile
english.c [new file with mode: 0644]
english.h [new file with mode: 0644]
set1p3.test.c [new file with mode: 0644]
util.c [new file with mode: 0644]
util.h [new file with mode: 0644]

index 5bbfa628e4e07e3d7eded898da9298345b818ef6..71f7f4bec2f9c2f8fc9b63fccdc59351a17f20b8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,16 +1,19 @@
 CC=gcc
 ODIR=obj
-CFLAGS=
+CFLAGS=-fstack-protector-all
 
 all: libs
-libs: io.o xor.o
+libs: io.o xor.o util.o english.o
 set1p1.test: set1p1.test.c io.o
        $(CC) -o $@ $? $(CFLAGS)
 set1p2.test: set1p2.test.c io.o xor.o
        $(CC) -o $@ $? $(CFLAGS)
-test: set1p1.test set1p2.test
+set1p3.test: set1p3.test.c io.o xor.o util.o english.o
+       $(CC) -o $@ $? $(CFLAGS)
+test: set1p1.test set1p2.test set1p3.test
        ./set1p1.test >/dev/null || echo "Set 1, Problem 1: Failed"
        ./set1p2.test >/dev/null || echo "Set 1, Problem 2: Failed"
+       ./set1p3.test >/dev/null || echo "Set 1, Problem 3: Failed"
 clean:
        rm -f *.o a.out *.test
 %.o: %.c
diff --git a/english.c b/english.c
new file mode 100644 (file)
index 0000000..184f97b
--- /dev/null
+++ b/english.c
@@ -0,0 +1,25 @@
+#include <string.h>
+
+float score_english_character(char c) {
+    switch (c) {
+      case 'E': case 'T': case 'A': case 'O': case 'I': case 'N': return 3; break;
+      case 'e': case 't': case 'a': case 'o': case 'i': case 'n': return 3; break;
+      case 'S': case 'H': case 'R': case 'D': case 'L': case 'U': return 2; break;
+      case 's': case 'h': case 'r': case 'd': case 'l': case 'u': return 2; break;
+      default: break;
+    }
+    if (strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", c) != 0) return 1;
+    if (strchr("0123456789 .:?,-![]()'", c) != 0) return 1;
+    return 0;
+}
+float score_english_buf(char* possible_plaintext, int length) {
+    int i;
+    float score=0;
+    for (i=0;i<length;i++) {
+      score = score + score_english_character(possible_plaintext[i]);
+    }
+    return score;
+}
+float score_english_str(char* possible_plaintext) {
+    return score_english_buf(possible_plaintext, strlen(possible_plaintext));
+}
diff --git a/english.h b/english.h
new file mode 100644 (file)
index 0000000..16823fa
--- /dev/null
+++ b/english.h
@@ -0,0 +1,3 @@
+float score_english_character(char c);
+float score_english_str(char* possible_plaintext);
+float score_english_buf(char* possible_plaintext, int length);
diff --git a/set1p3.test.c b/set1p3.test.c
new file mode 100644 (file)
index 0000000..1f85d9d
--- /dev/null
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "english.h"
+#include "io.h"
+#include "util.h"
+#include "xor.h"
+#define S 34
+
+int main() {
+  char ciphertext_hex[] = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736";
+  char ciphertext_buffer[S];
+  int ciphertext_byte_length;
+  decode_hex(ciphertext_hex, ciphertext_buffer, &ciphertext_byte_length);
+  if (ciphertext_byte_length != S) {
+    printf("Wrong length.\n");
+    exit(1);
+  }
+  
+  int candidate;
+  unsigned char xor_byte;
+  float scores[256];
+  unsigned char best_xor_candidate;
+  char xor_buffer[S];
+  char plaintext_buffer[S+1];
+  char best_decryption[S+1];
+  plaintext_buffer[S] = 0; // Look like a string for score_english
+  for (candidate=0; candidate<256; candidate++) {
+    xor_byte=candidate & 0xFF; // Avoid an infinite loop
+
+    fill(&xor_byte, 1, xor_buffer, S);
+    xor(xor_buffer, ciphertext_buffer, plaintext_buffer, S);
+    scores[xor_byte] = score_english_buf(plaintext_buffer, S);
+    if (scores[xor_byte] > scores[best_xor_candidate]) {
+      best_xor_candidate=xor_byte;
+      strncpy(best_decryption, plaintext_buffer, S+1);
+    }
+  }
+  //printf("Best decryption (%hhx => %0.2f): %s\n", best_xor_candidate, scores[best_xor_candidate], best_decryption);
+  if (strcmp("Cooking MC's like a pound of bacon", best_decryption) == 0) {
+    printf("%s\n", best_decryption);
+    exit(0);
+  } else {
+    printf("Wrong decryption: %s", best_decryption);
+    exit(1);
+  }
+}
diff --git a/util.c b/util.c
new file mode 100644 (file)
index 0000000..d3f3207
--- /dev/null
+++ b/util.c
@@ -0,0 +1,5 @@
+void fill(char* buffer1, int buf1_length, char* buffer2, int buf2_length) {
+    int i;
+    for (i=0;i<buf2_length;i++)
+      buffer2[i] = buffer1[i%buf1_length];
+}
diff --git a/util.h b/util.h
new file mode 100644 (file)
index 0000000..67aa1c8
--- /dev/null
+++ b/util.h
@@ -0,0 +1 @@
+void fill(char* buffer1, int buf1_length, char* buffer2, int buf2_length);