Many puzzles use cryptographic techniques to hide information. It is time to join them! Using C++, we will make our own cryptograph to send secret information. For a few reasons described below, we will implement the encryption and decryption within functions. While this scheme could be used to encrypt any data, including audio, video, or other files, for simplicity of demonstration, you should show that your program works by encrypting and decrypting a small piece of text, such as a favorite joke or riddle. Global Variables are Banned on this Assignment.
We will encrypt the data using a very strong technique called a substitution cypher. This is an encoding scheme that shifts each letter in a message by a given amount. For example, shifting A by 2 would result in C. Letters shifted past Z "wrap-around" such that they go back to A. More information on the substitution cipher scheme is described in the Appendix.
One of the reasons this kind of shift substitution is cryptographically weak is because if you figure out how much one letter has shifted, you can quickly shift every other letter in the encoded text by the same amount and recover the original text. To make our encryption stronger, we need a substitution that is less predictable.
We can make this scheme much stronger by having each letter in the message use a different shift value. In other words, the first letter in the message might use a shift value of 3, the second letter might use a value of 25, the third letter might use 10, and so on. As long as the sender and the receiver agree in advance on the sequence of shift values to use, this technique is quick to both encrypt and decrypt, yet remains completely uncrackable by any outside party. The encrypted message could be sent by any meanseven something completely public, like a Twitter feed.
The sequence of shift values should be a series of random integers. We will call this sequence the "encryption pattern." In our work here, we will use the random number generator(4) built into your C++ development environment to generate the encryption pattern. The sender encrypting the message and receiver decrypting that message will use the same seed for the random number generator so that they each have the same encryption pattern. We will call this shared seed the key.
In this project, you will develop codes that perform the encryption and decryption scheme described above. At a minimum, your code only needs to function for capital letters (with words running together as in THISISASECRET).
Specific tasks that should be accomplished by your codes include:
The encryption and decryption operations must be written as separate functions in your code. This will allow us to quickly copy-and-paste these functions into future programs, or to quickly replace these functions with, perhaps, better encryption/decryption functions we write in the future. The functions should each have just one input - either the entire string input by the user or just a single character from the message - and one output - that string or character having been encrypted or decrypted.
For large projects like this, it is usually very beneficial to set intermediate goals. Consider the following as useful milestones. As you work through them, use cout commands often, so that you can see what is happening inside your program as it runs! First, create a program that asks the user for the various inputs, stores them as variables of appropriate type, and then outputs them back to the screen. Second, have your program additionally output to the screen the user's input text one character at a time (hint: if you have a string variable named str, then the 1st character is str[0], the 2nd is str[1], the 3rd is str[2], and so on). Third, have your program send the string one character at a time to an encryption or decryption function as appropriate before outputting to the screen. For now, this can be a "dummy" function that just returns the input without changing it. Fourth, have your encryption/decryption functions perform a constant shift up/down on each character, like the shift-2 described above Note: the numeric value of each character is given in an ASCII table: A = 65, B = 66, etc. This will be useful for your if statement to check if you need to wrap around. Fifth, have your functions shift each character by a random amount. The sequence of random integers should come from the random number generator, seeded with the key input from the user
Cipher
In its simplest form, a substitution cipher is a very weak encryption. The simplest form(1) is what you may have seen in the back of a comic book or cereal box. This method just shifts each letter by a constant number of spots, "rotating" around from the bottom of the alphabet back to the top as needed. For example, a shift of +1 replaces A with B, B with C, and so on until Z is replaced by A. Instead of this +1 shift, the most common shift used with English language communication uses a value of +13 and is called ROT13 (meaning rotate 13 spots). In ROT13, each letter is replaced by the letter 13 spots down, so A gets replaced by N (letter 14), B gets replaced by O (letter 15), and so on until Z gets replaced by M. Since 13 is half the number of letters in the English alphabet, ROT13 has the distinction of being bidirectional: A becomes N, and N becomes A; B becomes O, and O becomes B; Z becomes M, and M becomes Z.
A shift can be represented mathematically. First, each letter is assigned a numerical value. For example, we can start counting at 0 so that A=0, B=1, and so on until Z=25. To shift letters down, we just add a constant value to each number and then convert the numbers back to letters. To demonstrate, in a shift-2 substitution, the word CAT is changed to the numbers (2 0 19), then we add 2 to each number to get (4 2 21), and then we turn these numbers back to letters to get the encoded text ECV.
For our cipher, we will take the shift number and use the mod (%) function to make sure our numbers are never shifted by more than 26. Then, we can "wrap-around" by subtracting 26 if the letter value after shifting is over 25 (Since A = 0, Z = 25). If we effectively wrap around, the number 26 becomes 0, the number 27 becomes 1, and so on. To demonstrate using shift-2: XYZ becomes (23 24 25); You can verify in your head that this worked (25 0 1): shifting each letter down by 2, XYZ -> ZAB.
To decrypt a message, we do basically the same thing as encryption, but we subtract the shift value instead of add it. We can use the same mod 26 to the random number used to shift and then add 26 to stay within 0 to 26!
As an example of decryption, the shift-28 encrypted message VQA becomes (21 16 0), we mod 28 and get 2. Then we subtract 2 from each to get (19 14 -2), we take each number less than 0 and add 26 to get (19 14 24), and we convert back to our original message: TOY. You can verify in your head that our math worked again: shifting each letter back 28 (or 2) from the encrypted message VQA -> TOY.