# Overview

In this project, you will move on to cryptography and you’ll be asked to encrypt and decrypt messages using three different encryption algorithms. The S’more part of this project will challenge you to “crack” others’ secret messages in ciphertext and convert them back to plaintext.

## Objectives

• To have fun.

• To practice loops.

• To gain experience with strings.

• To become better acquainted with functions and libraries.

• To allow you to dabble in cryptography.

WARNING: Beware the autograder’s ability to detect cheating, see Honor Code for further information.

## Collaboration Policy and the Honor Code

All students in the class are presumed to be decent and honorable, and all students in the class are bound by the College of Engineering Honor Code.

We want students to learn from and with each other, and we encourage you to collaborate. We also want to encourage you to reach out and get help when you need it.

### You are encouraged to:

• Give or receive help in understanding course concepts covered in lecture or lab.
• Practice and study with other students to prepare for assessments or exams.
• Consult with other students to better understand project specifications.
• Discuss general design principles or ideas as they relate to projects.
• Help others understand compiler errors or how to debug parts of their code.

To clarify the last item, you are permitted to look at another student’s code to help them understand what is going on with their code. You are not allowed to tell them what to write for their code, and you are not allowed to copy their work to use in your own solution. If you are at all unsure whether your collaboration is allowed, please contact the course staff via the admin form before you do anything. We will help you determine if what you’re thinking of doing is in the spirit of collaboration for EECS 183.

### The following are considered Honor Code violations:

• Submitting others’ work as your own.
• Copying or deriving portions of your code from others’ solutions.
• Collaborating to write your code so that your solutions are identifiably similar.
• Sharing your code with others to use as a resource when writing their code.
• Receiving help from others to write your code.
• Sharing test cases with others if they are turned in as part of your solution.
• Sharing your code in any way, including making it publicly available in any form (e.g. a public GitHub repository or personal website).

The full collaboration policy can be found in the syllabus.

We run every submission against every other submission and determine similarities. All projects that are “too similar” are forwarded to the Engineering Honor Council. This happened to numerous students last semester. Also know that it takes months to get a resolution from the Honor Council. Discussing the project with other students will NOT be an issue. Sharing code between students, even if it’s just one function, will likely cause the cheating detector to identify both programs as “too similar”. We also search the web for solutions that may be posted online and add these into the mix of those checked for similarities. Searching the web, by the way, is something that we are very good at.

Any violation of the honor policies appropriate to each piece of course work will be reported to the Honor Council, and if guilt is established, penalties may be imposed by the Honor Council and Faculty Committee on Discipline. Such penalties can include, but are not limited to, letter grade deductions or expulsion from the University.

Also note that on all cases forwarded to the Engineering Honor Council the LSA Dean of Academic Affairs is also notified. Furthermore, the LSA rule is students involved in honor violations cannot withdraw from nor drop the course.

• 10 points testing. Write a test suite in test.cpp.

• 60 points correctness. Implement functions in utility.cpp, caesar.cpp, vigenere.cpp,polybius.cpp, and ciphers.cpp. To what extent does your code implement the features required by our specification? To what extent is your code consistent with our specifications and free of bugs?

• 10 points style. To what extent is your code written well? To what extent is your code readable? Consult EECS 183 Style Guide and check the Style Checklist at the end of this project’s specification for some tips!

## Submission Rules

• NOTE: There are NO BLIND SUBMISSIONS for Project 3. The reason we are not allowing blind submits for Project 3 and beyond is that when students use loads of blind submits to try to maximize their best score, all those submissions can (collectively) bring down the autograder, creating a situation where students who are not using blind submits can’t submit either.

• You get 4 submissions to the autograder per day, with feedback. Beyond that, you get one additinal “wildcard” submission per project, meaning that you get one extra submission with feedback, one time during the project period.

• You have 3 late days that you can use any time during the semester for projects. There are 3 late days total, not 3 per project. To use a late day, submit to the autograder after the deadline. It will prompt you about using one of your late day tokens. There are more details about late days in the syllabus.

The deadline is Friday, March 26 at 11:59PM Eastern. If your last submission is on Wednesday, March 24 by 11:59PM, you will receive a 5% bonus. If your last submission is on Thursday, March 25 by 11:59PM, you will receive a 2.5% bonus.

Remember that we grade your BEST submission for style. If multiple submissions are tied in score, we take the last of those.

WARNING: Beware the autograder’s ability to detect cheating! See Collaboration Policy for further information.

## Working with a Partner

• For Projects 3, 4, and 5, you may choose to work with one other student who is currently enrolled in EECS 183.
• Although you are welcome to work alone if you wish, we encourage you to consider partnering up for Project 3. If you would like a partner but don’t know anyone in the class, we encourage you to use the Search for Teammates post on Piazza if you want to find someone! Please make sure to mark your search as Done once you’ve found a partner.
• As a further reminder, a partnership is defined as two people. Outside of your partnership, you are encouraged to help each other and discuss the project in English (or in some other human language), but don’t share project code with anyone but your partner.
• To register a partnership on the autograder, go to the autograder link for the project and select “Send group invitation”. Then, add your partner to the group by entering their email when prompted. They will receive a confirmation after registration, and must accept the invitation before the partnership can submit. You must choose whether or not to register for a group on the autograder before you can submit. If you select the option to work alone, you will not be able to work with a partner later in the project. If a partnership needs to be changed after you register, you may submit an admin request.
• The partnership will be treated as one student for the purpose of the autograder, and you will not receive additional submits beyond the given four submits per day.
• If you decide to work with a partner, be sure to review the guidelines for working with a partner.
• If you choose to use late days and you are working in a partnership, review this document for how late days will be charged against each partner.

## Distribution Code

utility.h A header file with declarations (aka prototypes) of the helper functions you’ll have to implement.

utility.cpp
Implementations of functions declared in utility.h.

caesar.h
A header file with declarations of the functions related to caesar cipher you’ll have to implement.

caesar.cpp
Implementations of functions declared in caesar.h.

vigenere.h
A header file with declarations of the functions related to vigenere cipher you’ll have to implement.

vigenere.cpp
Implementations of functions declared in vigenere.h.

polybius.h
A header file with declarations of the functions related to polybius cipher you’ll have to implement.

polybius.cpp
Implementations of functions declared in polybius.h.

ciphers.cpp
A function that allows the user to encrypt and decrypt messages. This file uses functions from utility.h, caesar.h, vigenere.h, polybius.h.

start.cpp
A program that allows you to select between executing your tests in test.cpp and using the ciphers you have created.

Additionally, you’ll be working with this file that you’ll have to create yourself:

test.cpp
A test suite for functions declared in utility.h, caesar.h, vigenere.h, polybius.h. Its job is to reveal bugs that someone (e.g. you or staff) could have made while implementing those functions. All testing should be done by printing to the standard output. Note that there will be no main function in this file.

NOTE: The starter code will not compile until you:

• Stub all functions that are not yet stubbed. The starter code provides function stubs for all functions declared in utility.h; the stubs for those functions appear in utility.cpp. You’ll need to write function stubs for all of the functions declared in caesar.h, vigenere.h, and polybius.h– those stubs go in caesar.cpp, vigenere.cpp, and polybius.cpp, respectively.
• Create a test.cpp file with a function named startTests(). Your project will not compile until you have created your test.cpp. More details can be found in the section Creating test.cpp.

# Suggested Timeline

As an approximate timeline, you will be on track if by:

• March 4: Starter code downloaded and new project set up in IDE. All necessary file(s) created. All necessary function stubs added according to the header files. Code compiles on your IDE. Code compiles on the autograder (submit to verify). You’ve read through the spec.
• March 6: Functions in utility.cpp implemented, fully tested, and passed on the autograder. Associated testing functions in test.cpp implemented, working, and catching the associated bugs on the autograder. Suggested order: toUpperCase(), removeNonAlphas(), charToInt(), removeDuplicate().
• March 8 - 12: Gap week - no class!
• March 14: Functions in caesarCipher.cpp implemented, fully tested, and passed on the autograder. Associated testing functions in test.cpp implemented, working, and catching the associated bugs on the autograder. Necessary order: shiftAlphaCharacter(), caesarCipher()
• March 16: vigenereCipher() implemented, fully tested, and passed on the autograder. Associated testing function in test.cpp implemented, working, and catching the associated bug(s) on the autograder.
• March 18: Functions in polybius.cpp implemented, fully tested, and passed on the autograder. Associated testing functions in test.cpp implemented, working, and catching the associated bugs on the autograder. Suggested order: mixKey(), fillGrid(), findInGrid(), polybiusSquare(). Began working on ciphers().
• March 21: ciphers() and all other code should be completed. Debugging in progress. Passing all individual function tests, 80% or higher on autograder.
• March 23: Wellness day - relax and try not worry too much about work :)
• March 24: Last day to still get 5% extra credit for your project 3 submission!
• If at any point your code is not working as intended checkout the troubleshooting checklist

# Warm-up

To make working on this project easier and more fun, be sure you’re able to answer the following questions:

• Recall our friend modulo, %. What does it do?

• What’s the difference between a char and a string?

• How can you figure out the length of a given string?

• Suppose you have a variable of type string called word, and that word is of some positive length.

• Without knowing word’s length in advance, how could you print its first character?

• How about the last character?

• How would you print word’s nth character?

• How can you represent an empty string, i.e. a string of length 0?

• Suppose you somehow ended up with this code:

string firstName = "Julius";
string lastName = "Caesar";
// ...


and that you’d like to have another string, fullName that would join (i.e. concatenate) firstName and lastName, so as to get "Julius Caesar". How best to do this?

• Surf on over to http://www.asciitable.com and make note of Dec and Char columns.

• Recall from lecture that characters, such as letters, punctuation marks and digits are represented by a number in the computer. So to store the character A, the computer is really storing the number 65. Similarly it stores 97 to represent a. Because of this property, you can increment chars and do arithmetic with them just like you can with ints.

• Note You should never refer to ASCII values when working with chars. Instead, always use the alphanumeric or symbol representation. For example
// do NOT use numerical ASCII values in your code, like below
char ch = 65;
if (ch == 66) {
....
}

// Instead, use the alphanumeric representation, like below
char ch = 'A';
if (ch == 'B') {
....
}

• What is the value of character at the end of this code’s execution?

char character = 'A';
character += 1;
character += 'A' - 'a';

• How would you print all the letters in the alphabet, A through Z, with just a couple lines of code (without hardcoding all those letters)?

• What’s the difference between 0 and '0'?

• How can you determine if a character is a lowercase letter?

• How can you determine if a character is an uppercase letter?

• How can you determine if a character is alphanumeric or alphabetical?

# Getting Started

## Multiple Files

• Most programs in the real world are written in more than just one file, to break down the functionality into smaller parts and to keep the program’s organization clean.

• For Projects 1 and 2, you worked with just one file, such as rps.cpp. It had a main() function, where the execution began, and then some other functions that were called from main() or from other functions. But as a program gets more complicated, the file becomes longer and it becomes difficult to organize and test the program.

• And so a common practice is to put (at least some) functions into separate files. The functions’ declarations (aka prototypes) go in what’s known as a header files that end in .h and the functions’ definitions (aka implementations) go in .cpp files. Each .cpp file that implements functions will #include its respective .h file that contains the functions’ declarations.

Then the program will contain one other .cpp file (without a header file) that will contain a main function that drives the program. This .cpp file will #include any header files that contain the definition of any functions that it might need.

## Creating a Project

• In the Distribution Code you’ll find utility.h, caesar.h, vigenere.h, and polybius.h that has declarations for some functions. You’ll also find caesar.cpp, vigenere.cpp, polybius.cpp, and utility.cpp whose job is to implement those functions. You will also find ciphers.cpp which is the driver that makes use of the ciphers you have implemented. Finally, there is a file start.cpp which contains the main() function for the project. This function will allow you to select executing your test cases or using the ciphers you have written.

NOTE: Your project will not compile or run until you have written all necessary function stubs, and created a test.cpp with a startTests() function. You can see how to do this in the next two Sections, Writing Function Stubs and Test Suite.

• As usual, the code in start.cpp will print the project menu with options to either run the tests in test.cpp or call driver function for the project, ciphers(). Enter 1 to select executing your test cases starting with the startTests() function in test.cpp, enter 2 to select executing your ciphers starting with the ciphers() function in ciphers.cpp. Once you have written all the function stubs and test_toUpperCase(), your program might run as follows (bold text represents your input):

-------------------------------
EECS 183 Project 3 Menu Options
-------------------------------
1) Execute testing functions in test.cpp
2) Execute ciphers() function to use ciphers
Choice --> 1

Now testing function toUpperCase()
Expected: "HELLO WORLD!", Actual: "HELLO WORLD!"
Expected: "HI THERE 123", Actual: "HI THERE 123"
Expected: "&&GO BLUE**", Actual: "&&GO BLUE**"

• To begin, create a new project in Xcode or in Visual Studio and add caesar.h, vigenere.h, polybius.h, utility.h, caesar.cpp, vigenere.cpp, polybius.cpp, utility.cpp, and ciphers.cpp to your project. Be sure that the files are copied and stored in the project directory.

WARNING: When adding files to your project, be sure that the files are copied and stored in the project directory!

## Writing Function Stubs

• Stubbing functions means adding the minimal necessary code to make a function compile. In Project 2, we provided all necessary function stubs. In Project 3, you will need to write some function stubs of your own before your code will compile. For each function declared in one of the .h files, you need a to have a corresponding function stub in the associated .cpp file in order for your code to compile.

• You might be wondering what exactly is the “minimum necessary code to make a function compile”? In general, function stubs will include the function header, and an almost-empty function body that consists of a single return statement that returns a placeholder item of the necessary return type. The compiler doesn’t need the function to actually do anything, but it does require that the function returns a value of the type indicated in the function header.

• For example, caesar.h contains the following function declaration:

char shiftAlphaCharacter(char c, int n);

• This means that caesar.cpp needs a function definition for shiftAlphaCharacter(). We will postpone thinking about how to actually implement this function until later. For now, we just want the code to compile. So, in caesar.cpp, we should write a placeholder implementation for shiftAlphaCharacter() (i.e., the stub) that returns a char, as the function header indicates, and nothing else:

char shiftAlphaCharacter(char c, int n) {
// to do: Implement this function!
// returning a space to avoid a compiler error
return ' ';
}

• Note that you could return any char and the code would compile. However, it is standard practice to return “default” values for particular return types: for chars: return ' ';, strings return "";, ints or doubles: return 0;, and for bools: return false;.

• The starter code provides function stubs for all functions declared in utility.h. The stubs for those functions appear in utility.cpp. You’ll need to write function stubs for all of the functions declared in caesar.h, vigenere.h, and polybius.h – those stubs go in caesar.cpp, vigenere.cpp, and polybius.cpp, respectively. You also need to write a stub for the ciphers() function, which is declared in start.cpp; the stub for this function should go in ciphers.cpp.

# Test Suite

## Creating test.cpp

• As you write code, it’s important to test it! Catching and fixing bugs early is much easier than later on; this will save you hours when you work. So you’ll be required to create and submit a test suite for this project.

NOTE: The best practice is to write tests before even implementing functions. Writing tests will make implementing the function faster/easier, PLUS it is infinitely satisfying to be able to test a function immediately once you’ve implemented it.

• Create a new file and call it test.cpp. At the top of the file, put a multiline comment with the project’s name, your name and uniqname, your partner’s name and uniqname, if you have one, and a short description for this test file. This file will in fact test the functions declared in utility.h, caesar.h, vigenere.h, and polybius.h so be sure to add these lines:

#include "utility.h"
#include "caesar.h"
#include "vigenere.h"
#include "polybius.h"


after the multiline comment. Note that the filename is enclosed in double quotes "" and not angle brackets <>, which means that it’s a local file and not a system library.

WARNING: Make sure that it’s #include "utility.h". Don’t #include "utility.cpp".

NOTE: If you’re using Xcode and it gave you main.cpp with a main function, you won’t need it! So be sure to delete it. Or just rename main.cpp (from Xcode) to test.cpp; this way you don’t have to create a new file.

• Next, write a startTests function in test.cpp. This file will test functions declared in utility.h, caesar.h, vigenere.h, and polybius.h via standard output, so you’ll be calling those functions many times. Here’s a good way to start it:

#include "utility.h"
#include "caesar.h"
#include "vigenere.h"
#include "polybius.h"
#include <iostream>
#include <string>

using namespace std;

void testShiftAlphaCharacter();

void startTests() {
testShiftAlphaCharacter();
// Repeat for all other functions to be tested

return;
}

void testShiftAlphaCharacter() {
cout << "Now testing function ShiftAlphaCharacter()" << endl;
cout << "Expected: 'a', Actual: '" << shiftAlphaCharacter('a', 0) << "'" << endl;
cout << "Expected: 'b', Actual: '" << shiftAlphaCharacter('a', 1) << "'" << endl;
cout << "Expected: 'd', Actual: '" << shiftAlphaCharacter('b', 2) << "'" << endl;
return;
}

• shiftAlphaCharacter does not print anything, it just returns a character. If you were to just call this function, nothing would be printed to the console. But shiftAlphaCharacter does return a char. And so in order to check the correctness of this function’s implementation, you have to print its return value.

• When you test these functions, you may wish to pay close attention to the Requires clause of each function. For example, the Requires clause for shiftAlphaCharacter functions “requires” that c is an alphabetical character. This means that you can assume that this function will always receive an argument that is an alphabetical character. Furthermore, you should not be calling it from the test suite with a value that violates the Requires clause. Doing so will cause your test suite to fail the autograder. For example, don’t call shiftAlphaCharacter with an argument of '@'.

WARNING:

If you submit a test case that violates the Requires clause, we will stop grading that submission and you will receive a very low score.

• As you work on the functions in utility.cpp, you should write some test cases first, then write the implementation, and then run the program to check if the implementation is correct. You should repeat this with functions in caesar.cpp, vigenere.cpp, and polybius.cpp.

## List of Functions to Test

Here the a list of functions you will need to test in test.cpp.

• toUpperCase()

• removeNonAlphas()

• removeDuplicate()

• charToInt()

• shiftAlphaCharacter()

• caesarCipher()

• vigenereCipher()

• fillGrid()

• mixKey()

• findInGrid()

• polybiusSquare()

## Submit Frequently

• As you progress through the project, we encourage you to submit after completing each section of the project. Doing so will help to ensure that you have written each part correctly before moving onto building the next.

• When you submit test.cpp, we will compile and run it with our correct implementation of utility.cpp, caesar.cpp, vigenere.cpp, and polybius.cpp and with our buggy implementation of utility.cpp, caesar.cpp, vigenere.cpp, and polybius.cpp so as to generate two different outputs. We’ll then compare two outputs. If there is any difference, you’ve successfully exposed a bug! The autograder does not go into the details of what the difference is, it only sees if there exists a difference.

• Remember that some functions don’t print anything on their own; we have to print their return value, as with the function shiftAlphaCharacter():

cout << shiftAlphaCharacter('a', 0) << endl;
cout << shiftAlphaCharacter('b', 2) << endl;
cout << shiftAlphaCharacter('X', 5) << endl;
cout << shiftAlphaCharacter('X', 50) << endl;

• After you submit your test suite, you might see output that looks like this:

Score: 6.3/10

# of exposed bugs:  7
Bugs exposed:     CAESAR_SHIFTALPHACHARACTER1
CAESAR_SHIFTALPHACHARACTER2
CAESARCIPHER
POLYBIUS_FILLGRID
POLYBIUS_FINDINGRID
POLYBIUS_MIXKEY
POLYBIUSSQUARE
UTILITY_CHARTOINT
UTILITY_REMOVEDUPLICATE
UTILITY_REMOVENONALPHAS1
UTILITY_REMOVENONALPHAS2
UTILITY_TOUPPERCASE
VIGENERECIPHER


That means that your test suite exposed 7 out of 13 bugs in the staff’s “buggy” implementations of utility.cpp, caesar.cpp, vigenere.cpp, and polybius.cpp and your score for the test suite is 6.3 out of 10 points. Each bug discovered is worth 0.9 points. The total points you can earn on test.cpp is capped at 10 points. You can earn all 10 points if you discover 12 of the 13 bugs.

### Bugs To Expose

There are a total of 13 unique bugs to find in our implementations. Your tests do not need to expose all of the bugs to receive full points for the lab. The autograder will tell you the names of the bugs that you have exposed, from the following set:

• UTILITY_TOUPPERCASE

• UTILITY_REMOVENONALPHAS1

• UTILITY_REMOVENONALPHAS2

• UTILITY_REMOVEDUPLICATE

• UTILITY_CHARTOINT

• CAESAR_SHIFTALPHACHARACTER1

• CAESAR_SHIFTALPHACHARACTER2

• CAESARCIPHER

• VIGENERECIPHER

• POLYBIUS_FILLGRID

• POLYBIUS_MIXKEY

• POLYBIUS_FINDINGRID

• POLYBIUSSQUARE

# Helper functions

After your code compiles, your next task in this project is to indulge in writing functions in utility.cpp. These functions will serve as helper functions in caesar.cpp, vigenere.cpp, and polybius.cpp Remember to write your testing function for each function before you write the function itself. For example, write test_toUppercase() (in test.cpp) before you write the implementation of toUpperCase().

## toUpperCase()

string toUpperCase(string original);

• This function converts all alphabetical characters in the string original to uppercase.

• As an example of how this function works, suppose in test.cpp you call it and print its return value like this:

cout << toUpperCase("Diag @ 11 p.m.") << endl;


Then the following should print:

DIAG @ 11 P.M.


## removeNonAlphas()

string removeNonAlphas(string original);

• This function removes all non-alphabetical characters from the string original.

• As an example of how this function works, suppose in test.cpp you call it and print its return value like this:

cout << removeNonAlphas("Diag @ 11 p.m.") << endl;


Then the following should print:

Diagpm


## removeDuplicate()

string removeDuplicate(string original);

• This function removes all duplicate characters except the first occurrence of it from the string original.

• As an example of how this function works, suppose in test.cpp you call it and print its return value like this:

cout << removeDuplicate("HELLOWORLD") << endl;


Then the following should print:

HELOWRD


## charToInt()

int charToInt(char original);

• This function converts the character original to its integer representation.

• As an example of how this function works, suppose in test.cpp you call it and print its return value like this:

cout << charToInt('1') << endl;


Then the following should print:

1


# Ciphers

IMPORTANT: As you implement the functions in the next section, you will find it helpful to refer to the Function Table linked at the bottom of the spec. The table contains the relationship between the functions below, i.e., which functions are called by others.

## Art of Cryptography

• This type of “art” deals with scrambling information, so that passwords, credit cards and other sensitive data are all the more secure. An example with which you might already be somewhat familiar is HTTPS, a secure version of HTTP (a protocol that web browsers use to communicate with servers). When a browser requests a webpage from a server via HTTPS (and the address of that webpage will begin with https://), all the data flowing between the browser and the server is encrypted (i.e. converted into seemingly meaningless characters). This is useful for logging into websites like Facebook, for credit card purchases on online stores such as Amazon, and especially so for accessing account information on banks’ websites.

## caesar.cpp

### Cæsar

• History holds that Julius Caesar protected sensitive messages by “rotating” each letter by 3 positions, so A became D, B became E, …​, Z became C:

• This type of cipher is know as a substitution cipher, i.e. each letter is substituted with another. In the case of Caesar’s cipher, we have a secret key that’s known only by those who are supposed to know the information that is shared. This secret key (k) is used to rotate (i.e. shift) each letter by k places, wrapping A to Z and a to z as needed.

• For example, suppose that the secret key is 10 and the plaintext message is Meet me at the Diag at 11 p.m. We would encrypt this message by shifting each letter 10 places:

Meet me at the Diag at 11 p.m.
Wood wo kd dro Nskq kd 11 z.w.


Notice how M became W, since W is 10 characters away from M. Similarly, t became d. t is the 20th letter in the alphabet (and the English alphabet has just 26 letters), so after we get to z (26th letter), we go back to a and go through three more letters to find d.

• A negative key would shift the letters back. So if the key were -3, E would become B and A would become X.

• Because the English alphabet has just 26 letters, keys of -25, 1, 27, 53, etc. are equivalent.

• This cipher will encrypt only uppercase and lowercase letters. This means that only alphabetical characters are shifted. Furthermore, uppercase letters will remain uppercase and lowercase letters will remain lowercase after shifting. All other characters will remain the same.

• Decrypting Caesar cipher is fairly simple: it suffices to shift the letters the other way.

NOTE: Most of this project’s specification has been encrypted with a key of 26, which is twice as secure as a key of 13.[1]

• And now, an overview of functions that you must implement in caesar.cpp. Note that the functions that follow do not print anything on its own; instead they return the result.

### shiftAlphaCharacter()

char shiftAlphaCharacter(char c, int n);

• This function “requires” that the first argument that’s passed in, c, be a letter. So you may assume that it will only be called with an uppercase or a lowercase letter. And remember not to call this function with anything but alphabetical characters, not even in your test suite!

• Shifting a character is illustrated by the same diagram you saw earlier. Suppose that you’re working with uppercase characters and n is 3. Then the characters would be shifted like this:

• Note that the letter must remain in the same case after you shift it. So if c is lowercase, it will remain lowercase when this function returns it; if c is uppercase, it will remain uppercase.

• And this is how you can test shiftAlphaCharacter in test.cpp. Since the function itself does not print anything, we have to print its return value:

cout << shiftAlphaCharacter('a', 0) << endl;
cout << shiftAlphaCharacter('b', 2) << endl;
cout << shiftAlphaCharacter('X', 5) << endl;
cout << shiftAlphaCharacter('X', 50) << endl;


You should get this output:

a
d
C
V


### caesarCipher()

string caesarCipher(string original, int key, bool encrypt);

• As its name suggests, this function encrypts or decrypts the string that’s passed in using the algorithm described above.

• For example, suppose original is the string "Meet me at the Diag at 11 p.m.", key is 42 and encrypt is true. Then calling caesarCipher and printing its return value in test.cpp

cout << caesarCipher("Meet me at the Diag at 11 p.m.", 42, true) << endl;


would cause the following to be printed:

Cuuj cu qj jxu Tyqw qj 11 f.c.


To decrypt a message, call caesarCipher with encrypt set to false:

cout << caesarCipher("Cuuj cu qj jxu Tyqw qj 11 f.c.", 42, false) << endl;


which would print

Meet me at the Diag at 11 p.m.


IMPORTANT: Don’t forget to keep writing tests in test.cpp for functions we declared in caesar.h!

## vigenere.cpp

### Vigenère

• As you might imagine, Caesar cipher is not all that strong, since it only takes to go through at most 25 different keys to break it. (Interested in breaking the Caesar cipher? Check out this project’s S’more!) For this reason, the world (or the French?) came up with Vigenère cipher. It dates to the fifteenth century and is one of the truly great breakthroughs in the development of cryptography. For more information, check out http://en.wikipedia.org/wiki/Vigenère_cipher.

• Vigenère cipher improves upon Caesar cipher by shifting letters using different keys. This sequence of keys is known as a keyword. Each letter in the keyword represents by how far the corresponding letter in the original message will be shifted (A and a represent 0, B and b represent 1, Z and z represent 25).

• For example, suppose you still want to send that same secret message, Meet me at the Diag at 11 p.m. But this time, you’re more careful and are using Vigenère cipher with the key Squirrel! Here’s how to encrypt:

 plaintext:  Meet me at the Diag at 11 p.m.
key:  SQUI RR EL SQU IRRE LS    Q U
ciphertext:  Euyb dv ee lxy Lzrk ll 11 f.g.

• We first converted each letter of the keyword to uppercase and removed all non-alphabetic characters. We also applied the key just to letters and repeated the keyword after its last letter. Since S is 18 characters away from A, M is shifted by 18.

• So putting it all together, you will need to do the following:

• Convert all letters in the keyword to uppercase.

• Remember to strip all non-alphabetic characters from the keyword.

• The keyword can be of any length greater than 0 and repeats after its last character.

• Apply the keyword only to alphabetical characters in the original message.

• As in the Caesar cipher, Z wraps to A and z wraps to a.

• Decrypting would shift the letters backward.

• This cipher will encrypt and decrypt only uppercase and lowercase letters. This means that only alphabetic characters will be shifted. Furthermore, uppercase letters will remain uppercase and lowercase letters will remain lowercase after shifting. All other characters will remain the same.

### vigenereCipher()

string vigenereCipher(string original, string keyword, bool encrypt);

• Notice that this function “requires” that keyword contain at least one alphabetical character. This means that you every time you call this function the string you provide as the second argument needs to have at least one letter in it. Make sure this is true for you function calls when testing the function, as well as anywhere else in your code.

• When you implement this function, be sure to follow the rules outlined above.

• As an example of how this function works, suppose in test.cpp you try to encrypt the string "Meet me at the Diag at 11 p.m." with the keyword "Squirrel!" call it and print its return value like this:

cout << vigenereCipher("Meet me at the Diag at 11 p.m.", "Squirrel!", true) << endl;


Then the following ciphertext should print:

Euyb dv ee lxy Lzrk ll 11 f.g.


Remember that decrypting shifts the letters backward! As an example:

cout << vigenereCipher("Euyb dv ee lxy Lzrk ll 11 f.g.", "Squirrel!", false) << endl;


And this is the output:

Meet me at the Diag at 11 p.m.


## polybius.cpp

### Polybius Square

• While shifting characters based on a key is common in ciphers, another common approach is to construct a grid as a cipher. As the name may suggest, the Polybius Square is a device invented by the Ancient Greek historian and scholar Polybius.

• Although Polybius did not intend for his device to be used as a cipher, the Polybius Square is said to have been used in the form of the “knock code” to signal messages between cells in prisons by tapping the numbers on pipes or walls.

• The original grid consists of the English alphabet and the digits 0 through 9.

Each letter is then represented by its coordinates in the grid, with the row number first and then the column number. For example, "EECS" becomes "04040230" in the original grid above.

• The encryption process using a Polybius Square begins with generating a Mixed Square, using a keyword. Once the Mixed Square is generated, we replace each letter with the “coordinates” of the letter within the grid, reading across first and then down (i.e. row and then column).

• As an example, we shall encrypt the plaintext “EECS” with the keyword “POLYBIUS”.

• First we make the Mixed Square using the keyword. We start by filling in the squares in the grid with the letters of the keyword, ignoring repetitions, and then continue with the rest of the alphanumerical letters in its original order.

• With the Square complete, we simply find each plaintext letter in the grid, and replace it with its coordinates. So “E” becomes “15”, “C” becomes “13”, and “S” becomes “11”. With this, we get the ciphertext “15151311”. Note that each alphanumeric character is always represented by a pair of digits.

• Decryption works in the reverse order, by translating the coordinates to its corresponding letter in the grid.

• The Mixed square is generated in exactly the same way as we did before.

• Imagine we received the ciphertext “435445” and the key is “POLYBIUS” again. Then “43” becomes “1”, “54” becomes “8”, and “45” becomes “3”. With this, we get the plaintext “183”.

IMPORTANT: Note that the grid does not represent any non-alphanumerical character. This means that such characters cannot be encrypted, unlike the Caeser and Vigenere cipher. However spaces are allowed in the plaintext, and should be represented as spaces in the ciphertext.

### fillGrid()

void fillGrid(char grid[SIZE][SIZE], string content);

• Notice that this function “requires” that content be of length of 36. This means that you should never be passing a string that has a length that does not equal 36.

• As an example of how this function works, suppose in test.cpp you try to fill the grid with the constant string ALNUM defined in utility.cpp. To test that your grid has been filled correctly, you should call the printGrid function implemented for you in utility.cpp.

NOTE: SIZE is a constant in utility.h that represents the maximum dimension of the grid, which has the value 6.

char grid[SIZE][SIZE];
fillGrid(grid, ALNUM);
printGrid(grid);


Then the following content should print:

 --- --- --- --- --- ---
| A | B | C | D | E | F |
--- --- --- --- --- ---
| G | H | I | J | K | L |
--- --- --- --- --- ---
| M | N | O | P | Q | R |
--- --- --- --- --- ---
| S | T | U | V | W | X |
--- --- --- --- --- ---
| Y | Z | 0 | 1 | 2 | 3 |
--- --- --- --- --- ---
| 4 | 5 | 6 | 7 | 8 | 9 |
--- --- --- --- --- ---


We have implemented printGrid() for you, and its RME can be found in utility.h. Feel free to use this helper function when testing other functions in polybius.h.

### mixKey()

string mixKey(string key);

• Notice that this function “requires” that key does not contain duplicate characters and consists of only uppercase alphabet and numbers. This means that you do not have to handle duplicate characters or lowercase alphabet. You will later handle duplicate characters and lowercase alphabet in ciphers.cpp.

• As an example of how this function works, suppose in test.cpp you try to mix the key "POLYBIUS", call it, and print its return value like this:

cout << mixKey("POLYBIUS") << endl;


Then the following content should print:

POLYBIUSACDEFGHJKMNQRTVWXZ0123456789


NOTE: Make use of the constant string ALNUM defined in utility.h. You should always begin with the alphabet and digits in their original order.

### findInGrid()

string findInGrid(char c, char grid[SIZE][SIZE]);

• Notice that this function “requires” that c is an uppercase alphabet or a digit. This means that you do not have to handle lowercase alphabet.

• As an example of how this function works, suppose in test.cpp you call findInGrid with 'A' as c, a grid filled as follows, and printing its return value like this:

char grid[SIZE][SIZE];
fillGrid(grid, ALNUM);
cout << findInGrid('A', grid) << endl;


Then the following content should print:

00


### polybiusSquare()

string polybiusSquare(char grid[SIZE][SIZE], string key, string original, bool encrypt);

• Notice that this function “requires” that key does not contain duplicate characters and consists of only uppercase alphabet and numbers. This means that you do not have to handle duplicate characters or lowercase alphabet. You will later handle duplicate characters and lowercase alphabet in ciphers.cpp.

• When you implement this function, be sure to follow the rules outlined above.

• As an example of how this function works, suppose in test.cpp you try to encrypt the string "EECS 183 is the best" with the keyword "183" call it and print its return value like this:

char grid[SIZE][SIZE];
cout << polybiusSquare(grid, "183", "EECS 183 IS THE BEST", true) << endl;


Then the following ciphertext should print:

11110533 000102 1533 341411 04113334


Remember that decrypting uses the same grid as encrypting! As an example:

char grid[SIZE][SIZE];
cout << polybiusSquare(grid, "183", "11110533 000102 1533 341411 04113334", false) << endl;


And this is the output:

EECS 183 IS THE BEST


IMPORTANT: Note that spaces are allowed in the original message, and they must stay as spaces in the encrypted message as well.

## ciphers.cpp

WARNING: Sanity check! At this point, utility.cpp, caesar.cpp, vigenere.cpp, and polybius.cpp should have implementations of all functions that we declared in utility.h, caesar.h, vigenere.h, and polybius.h, and test.cpp should have a test suite for those functions. If you have not yet submitted, we highly encourage you to do so, unless you are starting late and it is close to the deadline so you have few submissions remaining.

### Overview

• As your last task involving ciphers, create a program that asks the user for a cipher (Caesar, Vigenere, or Polybius), whether the user would like to encrypt or decrypt a message, asks for the message and then for a key. Finally, the program should print the encrypted or decrypted message, as specified by the user.

• At the top of the file, you’ll notice this line that lets ciphers.cpp use functions that are declared in utility.h, caesar.h, vigenere.h, and polybius.h:

#include "utility.h"
#include "caesar.h"
#include "vigenere.h"
#include "polybius.h"


after the multiline comment.

• Implement the ciphers function in ciphers.cpp. Let us recommend this structure:

void ciphers() {

// ask user for cipher (Caesar, Vigenere, or Polybius)

// ask user to encrypt or decrypt

// get message from user

// get key or keyword from user

// encrypt or decrypt message using selected cipher and key(word)

// print encrypted/decrypted message
}

• When you ask the user for input be sure to use these prompts, followed by a single space, in this order:

When encrypting,

Choose a cipher (Caesar, Vigenere, or Polybius):
Encrypt or decrypt:
Enter a message:
The encrypted message is:


Or when decrypting,

Choose a cipher (Caesar, Vigenere, or Polybius):
Encrypt or decrypt:
Enter a message:
The decrypted message is:


Expect the user to be bad at capitalization and accept input ignoring the case, such as

cAEsar
vigenEre
POLYBIus
ENCRYPT
decrypt


You must also accept c, v, p, e and d as valid input. If an invalid cipher type or mode (encrypt or decrypt) is entered, you must print out the message Invalid cipher! or Invalid mode!.

We recommend using getline to read strings, so as to read more than just the first word of the keyword or message.

NOTE: For the caesar cipher, you can assume the user will always enter a key that is an integer when they have selected to use a Caesar cipher.

• Then print the encrypted/decrypted message on a new line.

• Because you’ll probably be repeating some code in ciphers.cpp, like prompting the user for a string and reading that string, it’s a good idea to factor out common functionality into separate functions. Declare those functions in ciphers.cpp (not in utility.h) above main and implement them below main. Be sure to write RME comments above those functions’ declarations to maximize style points.

WARNING: Be sure not to modify any of the header files, since we’ll be using the original version when grading your project.

• So that we can automate some tests of your code, your program must behave per the examples below. Assumed that the red underlined text is what some user has typed.

### Error handling

Here are the errors you must handle:

• If the user enters an invalid cipher type (anything other than what is defined above), print Invalid cipher!, and exit the program, i.e., return; from ciphers().

• If the user enters an invalid mode (anything other than what is defined above), print Invalid mode!, and exit the program, i.e., return; from ciphers().

• For the Vigenere Cipher, you must ensure that the keyword contains at least one alphabetical character. If not, print Invalid key!, and exit the program, i.e., return; from ciphers().

• For Polybius Square, you must ensure that message is valid. That is, you must verify that all characters are alphanumeric characters or a space. If an invalid message is entered, you must print Invalid message!, and exit the program, i.e., return; from ciphers().

• For Polybius Square, the user-entered key may contain duplicate characters, lowercase letters, and non-alphanumeric letters. To ensure the requires clause is fulfilled for the polybiusSquare(), you need to handle these cases by converting both the key and message to uppercase, and remove duplicate characters in the key only (HINT: think of which functions in utility.h you can use).

• For Caesar Cipher, you can assume that the user will always enter an integer-valued key when they have selected to use the Caesar Cipher. You do not need to handle the case where they enter a non-integer key.

### Sample Output

When you run ciphers.cpp, it should behave per the examples below. Assume that the red underlined text is what some user has typed.

NOTE: The following sample runs do not include the menu selection detailed in Creating a Project.

Choose a cipher (Caesar, Vigenere, or Polybius): caesar
Encrypt or decrypt: encrypt
Enter a message: I solemnly swear that I am up to no good.
The encrypted message is: P zvsltusf zdlhy aoha P ht bw av uv nvvk.

Choose a cipher (Caesar, Vigenere, or Polybius): c
Encrypt or decrypt: e
Enter a message: I solemnly swear that I am up to no good.
The encrypted message is: P zvsltusf zdlhy aoha P ht bw av uv nvvk.

Choose a cipher (Caesar, Vigenere, or Polybius): vigenere
Encrypt or decrypt: decrypt
Enter a message: U lgp'a os qaoxitk iaz ltvcfqq. Teoafoq ckwhtpd riady qh.
What is your key: Mischief managed.
The decrypted message is: I don't go looking for trouble. Trouble usually finds me.

Choose a cipher (Caesar, Vigenere, or Polybius): ViGenere
Encrypt or decrypt: DECrypt
Enter a message: U lgp'a os qaoxitk iaz ltvcfqq. Teoafoq ckwhtpd riady qh.
What is your key: Mischief managed.
The decrypted message is: I don't go looking for trouble. Trouble usually finds me.

Choose a cipher (Caesar, Vigenere, or Polybius): polybius
Encrypt or decrypt: encrypt
Enter a message: EECS 183 is the best
The encrypted message is: 15151311 435445 0511 332215 04151133

Choose a cipher (Caesar, Vigenere, or Polybius): P
Encrypt or decrypt: E
Enter a message: EECS 183 is the best
The encrypted message is: 15151311 435445 0511 332215 04151133

Choose a cipher (Caesar, Vigenere, or Polybius): hello
Invalid cipher!

Choose a cipher (Caesar, Vigenere, or Polybius): C
Encrypt or decrypt: V
Invalid mode!

Choose a cipher (Caesar, Vigenere, or Polybius): v
Encrypt or decrypt: e
Enter a message: EECS 183 is the best
Invalid key!

Choose a cipher (Caesar, Vigenere, or Polybius): p
Encrypt or decrypt: e
Enter a message: EECS 183 is the best!
Invalid message!

• Now you can send secret messages to your friends. (Although they’ll need the same program to decrypt your messages!) Feel free to modify ciphers.cpp as you wish to suit your needs.

IMPORTANT: Note that when selecting Polybius Square, the decrypted message is all uppercase, while the original message contained lower case letters. This is fine, as the grid we construct only supports uppercase letters.

# Function Table

• The table below provides an outline of which other functions each function should call, if any.

WARNING: The table below does not include all cases of where to use the helper functions from utility.cpp. There are hints in the specification where to use your helper functions, and you should consider implementing these functions first.

File Function Other functions it should call
utility.cpp toUpperCase() Does not utilize any other functions
utility.cpp removeNonAlphas() Does not utilize any other functions
utility.cpp charToInt() Does not utilize any other functions
utility.cpp removeDuplicate() Does not utilize any other functions
caesar.cpp shiftAlphaCharacter() Does not utilize any other functions
caesar.cpp caesarCipher() shiftAlphaCharacter()
vigenere.cpp vigenereCipher() toUpperCase(), removeNonAlphas(), shiftAlphaCharacter()
polybius.cpp mixKey() removeDuplicate()
polybius.cpp fillGrid() Does not utilize any other functions
polybius.cpp findInGrid() Does not utilize any other functions
polybius.cpp polybiusSquare() mixKey(), fillGrid(), findInGrid(), charToInt()

Here is an example of how to read the table:

• caesarCipher() should call shiftAlphaCharacter()

NOTE: Note that the functions under “Other functions it should call” only refer to the functions you will implement. Feel free to use library functions anywhere.

# Style Checklist

To maximize your style points, be sure to follow this non-exhaustive checklist:

• ❏ Review EECS 183 Style Guide and P3 Style Guide. While all sections are relevant to this project, pay particular attention to Loops and Functions.

• ❏ Be sure that your code is well-commented. It might at first seem that the algorithm is straight-forward and self-explanatory, but would you remember all the details a month from now? And it’s much easier for the staff to help you with your code if you have comments!

• ❏ The RME comments must go above functions’ declarations (prototypes). This means that RMEs for functions declared in utility.h should stay in utility.h. The “required” functions in utility.cpp must have no RMEs. If you did, however, add you own helper functions in ciphers.cpp, be sure to include their RMEs above those functions’ declarations. However, you must not add any additional function definitions in the header files provided.

• ❏ Make sure that you’re not redundantly repeating code. If you have large blocks of code that appear in several places, it might make sense to create a helper function. And certainly utilize functions such as shiftAlphaCharacter inside others.

• ❏ Don’t use break or continue in loops. Loops should be controlled by a condition and should terminate when that condition is met.

• ❏ Remember to avoid magic numbers. Be sure that you don’t have numbers like 26, 32, 65 or 97 in your code!

• ❏ And certainly don’t use global variables.

• ❏ Remember that all lines must be 80 characters or less.

NOTE: We will not be grading style in test.cpp.

# How to Submit

• To submit the project and its tests, select Project 3 Ciphers https://autograder.io/web/project/982 and submit all of the following files:

• caesar.cpp

• ciphers.cpp

• polybius.cpp

• utility.cpp

• vigenere.cpp

• test.cpp

NOTE: The file names must match exactly as listed above.

IMPORTANT: Be sure to submit all parts of the project (including test.cpp).

IMPORTANT: Both partners’ names and uniqnames must be in the header comments in all files submitted.

NOTE: Differences in whitespace will fail the autograder.

• If confident that you’ve selected correct files, click Submit to submit to the Autograder.

• You have four submissions to the autograder per day with feedback, and one additional “wildcard” submission to use once during the project.

• There are NO blind submissions for this project.

OPTIONAL: For more practice and fun, check out the S’More for Project 3. With this optional challenge you can implement the functions in decrypt.cpp to break encryption.