################################# ## Simple Cryptography in C ## ## ## ## By Feky, 2007 ## ## ## ################################# ## [0] - TABLE OF CONTENTS ## ############################# 0 - Intro 1 - Shift cipher 2 - Polyalphabetic substitution ## [0] - INTRO ## ############################# I assume you have a basic knowledge of the C language. In this tutorial, I'll describe some fairly simple encryption algorithms as well as show you how to implement them in C. We'll begin with the shift cipher, since it's the easiest to understand, implement and break. Polyalphabetic substitution, describing and implementing the Vigenère cipher is the topic of the 2nd part of this tutorial. ## [1] - SHIFT CIPHER ## ############################# Shift cipher is a simple substitution cipher, in which we get the encrypted text (ciphertext) by replacing a letter with another. For example, if the text we want to encrypt (plaintext) is: "APPLE", and we the key is 3, we'll replace each letter with another one that is 3 letters in front of it. The key decides how much the letters will be shifted. So, this way plaintext "APPLE", if the key is 3, will become "DSSOH". Simple, right? Caesar, the roman emperor, used a shift of 3. People at experts-exchange.com use ROT-13 (a shift of 13), to encrypt the answers. Stupid noobs. The fact is that this method can be easily broken, by searching for frequent letters. In the standard english alphabet, the most frequent letters are E, T, A, O, I, N. Note that, for example, all "D" letters in a ciphertext will are "A", if we used a shift of 3. Also, the shift cipher can be easily broken by the brute-force method (trying all possible combinations (shifts)). Since the key can't be larger then 25 (because the english alphabet has 25 letters), it's would take less than a second to crack the cipher using the appropriate programs. Now, here's some C code we will examine: #include #include int main(int argc, char *argv[]){ int i=0, n, pos; if(argc != 3){ printf("Usage: %s [string] [shift]\n", argv[0]); return 1; } n = atoi(argv[2]); /* convert char to int */ if(n > 26){ printf("Shift larger than 26?! Idiot.\n"); return 1; } while (argv[1][i] != '\0'){ /* while not at the end of the array */ pos = argv[1][i]; if(isupper(pos)){ /* it's upper case */ pos+=n; if(pos > 'Z') pos-=26; } if(islower(pos)){ /* it's lower case */ pos+=n; if(pos > 'z') pos-=26; } printf("%c", pos); /* print each character, one-by-one */ i++; } printf("\n"); return 0; } OK. So how does it work? The integer "i" stores our position in the plaintext string (argv[1]), "pos" also, but we modify it, and "n" is the key which decides how many places will the letters be shifted. After we are sure we have enough parameters, we convert the char argv[2] to an int, so we can do maths with it. Next, we start a while loop which contains all the stuff we need, and will repeat until we reach the end of the array. Each time the while loop is near it's end, 1 is added to "i", so we continue with the next character of the plaintext. We need to check if the character we are currently processing is upper or lower case. We won't use the isalpha() function from string.h, because there are some characters between the upper and lower case letters in the ASCII table, which we don't want in our results. So we use isupper() and islower(), their name explains what they do. Now we add the value of "n" (the key) to "pos" -- this is the main thing, the shift. Of course, we don't want some silly characters in our results, so we will check if "pos" is larger than 'Z'/'z', so if it is, we substract 26 from it to get 'A'/'a' and start over. Finally, we display the resulting character. ## [2] - POLYALPHABETIC SUBSTITUTION ## ######################################## Polyalphabetic substitution is, as it name says, a substitution cipher (letters are replaces by other letters) where multiple alphabets are used, unlike the simple shift cipher, where we use only one alphabet. I'll show you an example of the Vigenère cipher, since it's the most well-known among all polyalphabetic substitution ciphers. The Vigenère cipher is harder to crack than a standard shift cipher, since we can't break it using standard letter frequency analysis. Check out Wikipedia, for the Charless Babbage and Friedrich Kasiski cryptoanalysis. Let's see an example: The plaintext "APPLE IS RED", encrypted with the key "MANGO" will become "MPCRS US EKR". As you can see, the the letters "PP" from "APPLE" will become "PC" when encrypted using the key "MANGO". Why? Here's a small scheme: Plaintext: APPLEISRED Key: MANGOMANGO Ciphertext: MPCRSUSEKR So, the key decides how many places will the letters be shifted. The letter "A" has the value 0, "B" is 1, and so on. When we add 0 to "P" it will be "P" in the ciphertext, because nothing has changed. But, if we would add "B" to "P", it would result in "Q", the next letter to "P" in the alphabet. I think you get the idea of the Vigenère cipher now. If the key is not long as the plaintext itself (like in this example), it is repeated. However, if you want better security, your key should be as long as the plaintext. Now, enough of "blablabla", let's see the code: #include #include int main(int argc, char * argv[]){ int pos, i=0, key, r; char key_buff[255]; if(argc != 3){ printf("Usage: %s [text] [key]\n", argv[0]); return 1; } while(strlen(argv[2]) < strlen(argv[1])){ /* Extend the key */ strcpy(key_buff, argv[2]); strcat(argv[2], key_buff); } while(argv[1][i] != '\0'){ pos = argv[1][i]; key = argv[2][i] - 65; /* Make the key */ if(isupper(pos)){ r = pos + key; if(r > 'Z') r-=26; printf("%c", r); /* Main stuff */ } i++; } return 0; } The int "pos" stores the ASCII code of the plaintext array's current character. "i" stores the position in the plaintext string and in the key. The value of "key" decides how many places will the characters will be shifted. "r" is the resulting character's ASCII code. "key_buff" is needed to extend the key if it's shorter than plaintext. Two parameters are required, the plaintext and the key. After we get them, we need to check if the key is shorter than the plaintext. If it is, we need to extend it by doubling it. This means, that "MANGO" will become "MANGOMANGO". If the key is longer than the plaintext, we simply won't use the uneeded characters from the key. Now we enter a while loop and sum "pos" with "key" to get the ciphertext "r". 65 is substracted from the ASCII code of the key character, because in this code we work only with upper case letters - the smallest upper case letter is "A", with the ASCII value of 65. And since we want our ciphertext in upper case letters, we can't add more than 25 to "pos". Note that in this example I only showed you how to encrypt. Feel free to figure out how to write a decryption routine (it's simple).