C++ Caesar Cipher
================================================================================
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);
/*==============================================================================
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;
}