CC=gcc
ODIR=obj
-CFLAGS=-fstack-protector-all
+CFLAGS=-fstack-protector-all -ggdb
all: libs
-libs: io.o xor.o util.o english.o
+libs: io.o xor.o util.o english.o xor_decrypt.o
set1p1.test: set1p1.test.c io.o
$(CC) -o $@ $? $(CFLAGS)
set1p2.test: set1p2.test.c io.o xor.o
$(CC) -o $@ $? $(CFLAGS)
-set1p3.test: set1p3.test.c io.o xor.o util.o english.o
+set1p3.test: set1p3.test.c io.o xor_decrypt.o english.o util.o xor.o
$(CC) -o $@ $? $(CFLAGS)
-test: set1p1.test set1p2.test set1p3.test
+set1p4.test: set1p4.test.c io.o xor_decrypt.o english.o util.o xor.o
+ $(CC) -o $@ $? $(CFLAGS)
+test: set1p1.test set1p2.test set1p3.test set1p4.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"
+ ./set1p4.test >/dev/null || echo "Set 1, Problem 4: Failed"
clean:
rm -f *.o a.out *.test
%.o: %.c
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;
+ case 0: return 0; break;
default: break;
}
if (strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", c) != 0) return 1;
}
return 1;
}
+
+char* printable_buffer(char* buffer, int length) {
+ char* output = malloc(length*3+2);
+ encode_hex(buffer, length, output);
+ memcpy(output + length * 2, ": ", 2);
+ memcpy(output + length * 2 + 2, buffer, length);
+ return output;
+}
+
+void print_buffer(char* buffer, int length) {
+ char* output = printable_buffer(buffer, length);
+ printf("%s\n", output);
+ free(output);
+}
int decode_base64(char* src, char* dest, int* destlen);
void encode_base64(const char* src_bytes, int src_size, char* dest);
void encode_hex(const char* src_bytes, int src_size, char* dest);
+char* printable_buffer(char* buffer, int length);
+void print_buffer(char* buffer, int length);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "english.h"
#include "io.h"
-#include "util.h"
-#include "xor.h"
+#include "xor_decrypt.h"
#define S 34
int main() {
int candidate;
unsigned char xor_byte;
- float scores[256];
unsigned char best_xor_candidate;
- char xor_buffer[S];
- char plaintext_buffer[S+1];
+ float score;
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);
+ best_decryption[S] = '\0'; // Make it a string.
+ find_best_xor_candidate_buf(1, ciphertext_buffer, S, &xor_byte, best_decryption, &score);
+ printf("Best decryption (%hhx => %0.2f): %s\n", xor_byte, score, best_decryption);
if (strcmp("Cooking MC's like a pound of bacon", best_decryption) == 0) {
printf("%s\n", best_decryption);
exit(0);
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include "io.h"
+#include "xor_decrypt.h"
+#define MAX_TEXTS 400
+#define CIPHERTEXT_LENGTH 30
+#define HEX_LENGTH (CIPHERTEXT_LENGTH*2)
+
+int main() {
+ char *ciphertext_buffers[MAX_TEXTS];
+ int candidate_ciphertext_count=0;
+
+ int candidate;
+ unsigned char xor_byte;
+ unsigned char best_xor_candidate;
+ float score, best_score;
+ int best_candidate;
+ char decryption[CIPHERTEXT_LENGTH+1], best_decryption[CIPHERTEXT_LENGTH+1];
+ int i;
+
+ FILE *fd = fopen("problems/set-1/4.txt", "r");
+ for (i=0; i<MAX_TEXTS; i++) ciphertext_buffers[i]=NULL;
+ char *ciphertext_hex = NULL;
+ int read_length, buf_size, decoded_length;
+ while ((read_length=getline(&ciphertext_hex, &buf_size, fd))>0) {
+ switch (read_length-1) {
+ case 60:
+ case 59:
+ ciphertext_hex[HEX_LENGTH]='\0';
+ ciphertext_buffers[candidate_ciphertext_count] = malloc(CIPHERTEXT_LENGTH);
+ memset(ciphertext_buffers[candidate_ciphertext_count], 0, CIPHERTEXT_LENGTH);
+ decode_hex(ciphertext_hex, ciphertext_buffers[candidate_ciphertext_count], &decoded_length);
+ candidate_ciphertext_count++;
+ memset(ciphertext_hex, '0', buf_size);
+ break;
+ case 58:
+ printf("That one line (%d) is wrong length... skipping.\n", candidate_ciphertext_count+1);
+ continue;
+ default:
+ printf("Read line %d from file... wrong length: %d\n", candidate_ciphertext_count+1, read_length-1);
+ exit(1);
+ break;
+ }
+ }
+ printf("Reading from file complete. Read %d lines.\n", candidate_ciphertext_count);
+
+ decryption[CIPHERTEXT_LENGTH] = '\0'; // Make it a string.
+
+ best_score = -1000;
+ for(i=0;i<candidate_ciphertext_count;i++) {
+ find_best_xor_candidate_buf(1, ciphertext_buffers[i], CIPHERTEXT_LENGTH, &xor_byte, decryption, &score);
+ if (score>best_score) {
+ best_score = score;
+ memcpy(best_decryption, decryption, CIPHERTEXT_LENGTH+1);
+ best_candidate=i;
+ }
+ }
+
+ printf("Best decryption (line %d => %0.2f): %s\n", best_candidate+1, score, best_decryption);
+ char* expected = "Now that the party is jumping\n";
+ if (strcmp(expected, best_decryption) == 0) {
+ printf("%s\n", best_decryption);
+ exit(0);
+ } else {
+ printf("Wrong decryption: %s\n", best_decryption);
+ printf(" Expected: %s\n", expected);
+ print_buffer(best_decryption, CIPHERTEXT_LENGTH);
+ print_buffer(expected, CIPHERTEXT_LENGTH);
+ exit(1);
+ }
+}
--- /dev/null
+#include <stdlib.h>
+#include <string.h>
+#include "english.h"
+#include "util.h"
+#include "xor.h"
+
+void select_best_xor_candidate_buf(char** candidates, int num_candidates, int candidate_length, char* ciphertext_buffer, int ciphertext_length, char* best_candidate, char* best_decryption, float* best_score) {
+ int candidate;
+ unsigned char xor_byte;
+ float score;
+ unsigned char best_xor_candidate;
+ char *xor_buffer = malloc(ciphertext_length);
+ char *plaintext_buffer = malloc(ciphertext_length);
+ int ci;
+
+ *best_score = -100;
+ for (ci=0; ci<num_candidates; ci++) {
+ fill(candidates[ci], candidate_length, xor_buffer, ciphertext_length);
+ xor(xor_buffer, ciphertext_buffer, plaintext_buffer, ciphertext_length);
+ score = score_english_buf(plaintext_buffer, ciphertext_length);
+ if (score > *best_score) {
+ *best_score = score;
+ strncpy(best_decryption, plaintext_buffer, ciphertext_length);
+ strncpy(best_candidate, candidates[ci], candidate_length);
+ }
+ }
+}
+
+void find_best_xor_candidate_buf(int length, char* ciphertext, int ciphertext_length, char* best_candidate, char* best_decryption, float* best_score) {
+ int num_candidates = 1;
+ unsigned int i, j, ci;
+ for (i=0; i<length; i++) num_candidates = num_candidates*256;
+ char* candidates = malloc(num_candidates*length);
+ char** candidate_pointers = malloc(num_candidates*sizeof(char*));
+ for (ci=0;ci<num_candidates;ci++) {
+ candidate_pointers[ci] = candidates + length*ci;
+ for (j=0;j<length;j++) {
+ candidate_pointers[ci][j] = (char) (0xFF & (ci >> (j*8)));
+ }
+ }
+ select_best_xor_candidate_buf(candidate_pointers, num_candidates, length,
+ ciphertext, ciphertext_length,
+ best_candidate, best_decryption, best_score);
+}
--- /dev/null
+void select_best_xor_candidate_buf(char** candidates, int num_candidates, int candidate_length, char* ciphertext, int ciphertext_length, char* best_candidate, char* best_decryption, float* best_score);
+void find_best_xor_candidate_buf(int length, char* ciphertext, int ciphertext_length, char* best_candidate, char* best_decryption, float* best_score);