C++ Caesar Cipher

profileARapSal
demo.docx

================================================================================

Citations for any code used that I did not write:

================================================================================

Purpose of Program:

================================================================================

Data Dictionary:

Local Variables:

Name Type Use Definition

----- --------- ---------------------- ------------------------------

ch char Holds a character ch=[letter|digit|punctuation]

data string Holds word in list data = [string]

head node* Pointer to list head head = [integer|NULL]

ins ifstream Identifies input file ins = [filename]

loop int Holds the loop count loop = [0|posinteger]

outs ofstream Identifies output files outs = [filename]

next node* Holds link to next node next = [integer]

node struct Linked list node node = [data,next]

yn bool Passes yes and not yn = [boolean]

Type Type Definition

------------ -------------------------------------------------------

boolean boolean = [TRUE|FALSE]

digit digit = [0|1|2|...|9]

eos eos = [end of string char]

filename filename = [letter,:,\,\,string]

float float = [integer,.,posinteger]

integer integer = [-infinity|...|-1|0|1|...|infinity]

letter letter = [a|b|...|z|A|B|...|Z]

neginteger neginteger = [-infinity|...|-2|-1]

posinteger posinteger = [1|2|...|infinity]

punctuation punctuation = [ |,|.|/|?|'|+|=|-|)|(|*|&|^|%|$|#|@|!|~|

"|:|;|>|<}|{]

string string = [(letter|number|_|\)n,eos]

==============================================================================*/

//==============================================================================

// Grab some libraries.

#include "global.h"

using namespace std;

//==============================================================================

// Function call definitions for main()

int mgram(vector<bool>&, vector<bool>&, vector<char>&, int, int, int);

int display_keys(vector<bool>, vector<char>, string);

int last_key(vector<bool>);

/*==============================================================================

Data Dictionary for main():

Name Type Use Definition

----- --------- ---------------------- --------------------------------

argc int Holds the number of argc = [0|posinteger]

command line arguments

passed to the program.

argv char** Holds the command line argv = [string]

arguments passed to the

program.

i int Counter for loop. i = [0|posinteger]

cmdarg string Holds a single command cmdarg = [string]

line argument for

evaluation.

==============================================================================*/

// Fire up our main function.

int main(int argc, char* argv[])

{

bool decipher = false;

bool check2grams = false;

bool check3grams = false;

bool check4grams = false;

bool check5grams = false;

bool check6grams = false;

int offset = 0;

int i;

int size;

string symbols = "abcdefghijklmnopqrstuvwxyz";

string key = "abcdefghijklmnopqrstuvwxyz";

string type = "caesar";

string cmdarg;

string ifile = "snark.txt";

string ofile = "cipher.txt";

string cfile = "clean.txt";

vector<char> characters;

vector<char> temp;

char ch;

string word = "";

int loop;

int letters = 3;

size = hash("zz");

vector<bool> bv2grams(size + 1);

size = hash("zzz");

vector<bool> bv3grams(size + 1);

size = hash("zzzz");

vector<bool> bv4grams(size + 1);

size = hash("zzzzz");

vector<bool> bv5grams(size + 1);

size = hash("zzzzzz");

vector<bool> bv6grams(size + 1);

// Create and set a random offset;

offset = random_offset(1, symbols.size() - 1);

// Make all keys, except 0, possible;

if(type == "caesar")

{

size = symbols.size();

}

vector<bool> possible(size);

for(i = 1; i < (int)possible.size(); i++)

{

possible.at(i) = 1;

}

// Set the keyprogress list to a default of 25;

int keyprogress[2000];

for(i = 0; i < 2000; i++)

{

keyprogress[i] = 25;

}

int cntp = bit_count(possible, true);

int lstkey = 0;

// Deal with command line arguments.

for(i = 0; i < argc; i++)

{

cmdarg = argv[i];

// Display help text.

if((cmdarg == "-h") || (cmdarg == "--help"))

{

cout << "\n";

cout << "usage: " << argv[0] << " [options] [commands] [arguments]\n"

<< "options: \n"

<< " -h --help View this help text. \n"

<< " -v --version Display version number. \n"

<< " --debug Enable debug output. \n\n";

cout << "more options: \n"

<< " --use-2grams Use digrams to crack the cipher. \n"

<< " --use-3grams Use trigrams to crack the cipher. \n"

<< " --use-4grams Use quadgrams to crack the cipher. \n"

<< " --use-5grams Use pentagrams to crack the cipher. \n"

<< " --use-6grams Use hexgrams to crack the cipher. \n\n";

cout << "commands: \n"

<< " -i --input File to encrypt / decrypt. \n"

<< " -t --type Type of encryption to use. \n"

<< " -k --key Key to encrypt with. \n"

<< " -n --offset Offset to encrypt with. \n"

<< " -s --symbols Set of symbols to use. \n\n";

exit(1);

}

// Display version info.

if((cmdarg == "-v") || (cmdarg == "--version"))

{

cout << argv[0] << " v0.1 \nLast modified 17 March 2004. \n";

exit(1);

}

// Debug mode?

if(cmdarg == "--debug")

{

debug = true;

}

// Set the m-gram lists to check.

if(cmdarg == "--use-2grams")

{

check2grams = true;

}

if(cmdarg == "--use-3grams")

{

check3grams = true;

}

if(cmdarg == "--use-4grams")

{

check4grams = true;

}

if(cmdarg == "--use-5grams")

{

check5grams = true;

}

if(cmdarg == "--use-6grams")

{

check6grams = true;

}

// Process the input file.

if(cmdarg == "-i" || cmdarg == "--input")

{

ifile = argv[i + 1];

}

// Process all the ecryption variables.

if(cmdarg == "-t" || cmdarg == "--type")

{

type = argv[i + 1];

}

if(cmdarg == "-k" || cmdarg == "--key")

{

key = argv[i + 1];

}

if(cmdarg == "-n" || cmdarg == "--offset")

{

offset = atoi(argv[i + 1]);

}

if(cmdarg == "-s" || cmdarg == "--symbols")

{

symbols = argv[i + 1];

}

}

// Clean and encrypt our input file.

clean(ifile, cfile, symbols);

crypt(cfile, ofile, type, symbols, key, offset, decipher);

// Which m-gram lists should we be using for decryption?

if(!check2grams && !check3grams && !check4grams &&

!check5grams && !check6grams)

{

check2grams = true;

check3grams = true;

check4grams = true;

check5grams = true;

check6grams = true;

}

// Read in the appropriate m-gram lists.

cout << "\n\n";

if(check2grams)

{

cout << "Reading in 2-grams...\n";

bit_read("forbid2.bin", bv2grams);

}

if(check3grams)

{

cout << "Reading in 3-grams...\n";

bit_read("forbid3.bin", bv3grams);

}

if(check4grams)

{

cout << "Reading in 4-grams...\n";

bit_read("forbid4.bin", bv4grams);

}

if(check5grams)

{

cout << "Reading in 5-grams...\n";

bit_read("forbid5.bin", bv5grams);

}

if(check6grams)

{

cout << "Reading in 6-grams...\n";

bit_read("forbid6.bin", bv6grams);

}

cout << "\n\n";

// Reset decipher so we can use it as part of the decryption.

decipher = true;

// Begin the decryption!

ifstream fin;

fin.open("cipher.txt");

for(i = 0; i < letters; i++)

{

fin >> ch;

characters.push_back(ch);

}

while(cntp > 1 && !fin.eof())

{

cout << "Setting up the input file for " << letters << " characters. \n";

for(loop = 1; loop < (int)possible.size(); loop++)

{

if(possible.at(loop) == true)

{

temp = characters;

if(type == "caesar")

{

caesar(temp, symbols, loop, decipher);

}

// Display output.

cout << "\nChecking m-grams for key " << loop << "\n";

for(i = 0; i < (int)characters.size(); i++)

{

cout << characters.at(i);

}

cout << "\n";

for(i = 0; i < (int)temp.size(); i++)

{

cout << temp.at(i);

}

cout << "\n";

// Check m-grams and elminate keys.

if(check2grams)

{

mgram(possible, bv2grams, temp, letters, loop, 2);

}

if(check3grams)

{

mgram(possible, bv3grams, temp, letters, loop, 3);

}

if(check4grams)

{

mgram(possible, bv4grams, temp, letters, loop, 4);

}

if(check5grams)

{

mgram(possible, bv5grams, temp, letters, loop, 5);

}

if(check6grams)

{

mgram(possible, bv6grams, temp, letters, loop, 6);

}

}

}

letters++;

fin >> ch;

characters.push_back(ch);

cntp = bit_count(possible, 26);

keyprogress[letters] = cntp;

display_keys(possible, characters, symbols);

pause("decryption");

}

display_keys(possible, characters, symbols);

for(loop = 2; loop <= letters; loop++)

{

cout << keyprogress[loop] << " ";

}

lstkey = last_key(possible);

cout << "\n\n\n";

cout << "Final letter count is " << letters - 1

<< ". The selected key is " << lstkey << ".\n\n";

if(offset == lstkey)

{

cout << "The decryption was successful. \n";

}

else

{

cout << "The decryption failed. \n";

}

cout << "\n\n\n";

return 0;

}

int mgram(vector<bool>& possible, vector<bool>& bvmgrams, vector<char>& temp,

int letters, int loop, int size)

{

string word = "";

int i;

if((letters >= size) && (possible.at(loop) == true)

&& (temp.size() - size >= 0))

{

for(i = temp.size() - size; i < (int)temp.size(); i++)

{

word.append(1, temp.at(i));

}

if(!bit_check(word, bvmgrams))

{

possible.at(loop) = false;

cout << "Found forbidden m-gram " << word

<< " on list. Elminiating this key. \n";

}

}

return 0;

}

int display_keys(vector<bool> list, vector<char> characters, string symbols)

{

int count;

int i;

vector<char> temp;

cout << "\n\n";

cout << setw(7) << left << "Key" << "Status \n";

cout << setw(7) << left << "=====" << "================= \n";

for(count = 0; count < (int)list.size(); count++)

{

if(list.at(count) == false)

{

cout << setw(7) << left << count << "Key not possible. \n";

}

else

{

cout << setw(7) << left << count << "Possible.";

cout << setw(16) << left << " ";

temp = characters;

caesar(temp, symbols, count, true);

for(i = 0; i < (int)temp.size() - 1; i++)

{

cout << temp.at(i);

}

cout << "\n";

}

}

cout << "\n\n\n";

return 0;

}

int last_key(vector<bool> list)

{

int key = 0;

int i;

for(i = 0; i < (int)list.size(); i++)

{

if(list.at(i) == true)

{

key = i;

}

}

return key;

}