From: Zachary Vance Date: Sun, 14 May 2017 08:54:21 +0000 (-0700) Subject: Solve Set 1, Problem 3 X-Git-Url: https://git.za3k.com/?a=commitdiff_plain;h=cf8835524d6b16eb97abe6b2a6f793575eeeb9d1;p=cryptopals.git Solve Set 1, Problem 3 --- diff --git a/Makefile b/Makefile index 5bbfa62..71f7f4b 100644 --- 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 index 0000000..184f97b --- /dev/null +++ b/english.c @@ -0,0 +1,25 @@ +#include + +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 +#include +#include +#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 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