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
--- /dev/null
+#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));
+}
--- /dev/null
+float score_english_character(char c);
+float score_english_str(char* possible_plaintext);
+float score_english_buf(char* possible_plaintext, int length);
--- /dev/null
+#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);
+ }
+}
--- /dev/null
+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];
+}
--- /dev/null
+void fill(char* buffer1, int buf1_length, char* buffer2, int buf2_length);