Shift Cipher

In UMD professor Jonathan Katz' Introduction to Cryptography text, one of the classical encryption methods, the shift cipher, is described, including a method to crack the cipher. The shift cipher is a simple encryption method as all that is necessary to encrypt the message is to select a "key" value, and shift each letter by that key value. For example, if the key is 4, then the letter 'a' is mapped to 'e', 'b' to 'f', etc.

The gist of the cracking algorithm is that one has to compare the given cipher text to the letter frequencies of a dictionary. By iterating through all possible cipher texts (of which, if only using lowercase letters, is 26), one can compare each possible cipher text letter frequency distribution to that of plain text, and the iteration that has the closest letter frequency distribution is the cracked plain text.

Project repository: Git

The relevant bits of the code to crack the cipher are as follows:

    /*The crack function decrypts a ciphertext by comparing the letter frequencies of 
the ciphertext to those that are standard in English. This function works
quite well for even single sentence messages.*/
char *crack(char *ciphertext, int message_len) {
    /*frequencies of letters a-z in english dictionary*/
    float dic_freq[] = {0.08167, 0.01492, 0.02782, 0.04253, 0.12702, 0.02228,
    0.02015, 0.06094, 0.06996, 0.00153, 0.00772, 0.04025, 0.02406, 0.06749,
    0.07507, 0.01929, 0.00095, 0.05987, 0.06327, 0.09056, 0.02758, 0.00978, 
    0.02361, 0.00150, 0.01974, 0.00074}, freq[26]={0},  I_j[26] ={0};
    char *c = ciphertext;
    int key = 0, i, j;

    /*determining frequency of letters in the ciphertext*/
    while (*c != '\0') {
        /*only care about lowercase*/
        if (*c >=97 && *c <= 122)
            /*accounting for ACII values in array indexing*/
            freq[(*c) -97]++;
        c++;
    }

    /*Using attack on shift cipher described in chapter 1.3 of text described in 
    main.c*/
    for (j = 0; j < 26; j++) {
        for (i = 0; i < 26; i ++)
            I_j[j]+=freq[(i+j) % 26]/message_len*dic_freq[i];
        I_j[j] -= 0.065539;
        if (I_j[j] < 0) 
            I_j[j] = -I_j[j];
        /*find the sum value that is closest to 0.065 (by using various shifts)*/
        if (I_j[j] <I_j[key])
            key = j;
    }
    /*decrypt using the found key*/
    return dec(ciphertext, key);
}

Moral of the story: stick to 256-bit AES encryption...