//*********************************************************************** // vigenere.h // // this is an implementation of the vigenere polyalphabetic cipher // // the cipher is controlled by the Vigenere_cipher object class // it reads and writes file data (key, plaintext, ciphertext) // and resizes the key to match the plaintext or ciphertext length // it uses the vigenere class to encrypt and decrypt // // the vigenere tableau is implemented as a object class // the class constructor creates the tableau // a default constructor uses the full alphabet // an overloaded constructor creates a tableau for any alphabet // the vigenere class has methods to encrypt and decrypt single characters // //*********************************************************************** // INPUTS: (from disk file) // encryption: key, plaintext // // decryption: key, ciphertext // // OUTPUTS: (to disk file) // encryption: ciphertext // // decryption: plaintext // //*********************************************************************** // WARNING: // this program requires 4 disk files on the A drive: key.txt, // plaintext_in.txt, plaintext_out.txt. and ciphertext.txt // //*********************************************************************** // IMPLEMENTATION NOTE: // this program compiles with 4 instances of compiler warning C4786 // when compiled in DEBUG mode // // these warnings DO NOT affect the program - ignore them // //*********************************************************************** // created by: j. aleshunas // created on: 8 may 02 // modified on: 22 mar 04 // // Copyright 2004 john aleshunas // //*********************************************************************** #include #include #include #include using namespace std; //*********************************************************************** // class Vigenere declaration //*********************************************************************** class Vigenere { // private class variables vector vsTableau; // private methods string Left_circular_rotate(string sIn_string); public: // public methods Vigenere(void); // constructor Vigenere(string sAlphabet); // constructor char Encrypt(char cKey, char cPlaintext); char Decrypt(char cKey, char cCiphertext); }; // class Vigenere //*********************************************************************** // class Vigenere_cipher method declarations //*********************************************************************** // private class method string Vigenere::Left_circular_rotate(string sIn_string) { // this function performs a left circular rotation of the input string string sLocal_string; // a work space int index; // loop index int iMax_index; // loop limit // get the loop limit iMax_index = sIn_string.size(); // shift the input string one character to the left for(index = 1; index < iMax_index; index++) { sLocal_string += sIn_string[index]; } // circularly rotate the first character of the input string sLocal_string += sIn_string[0]; return sLocal_string; } // Vigenere::Left_circular_rotate() //*********************************************************************** // the class constructor Vigenere::Vigenere(void) { // the base string string sAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int iIndex; // the loop index int iMax_index; // the loop limit // get the loop limit - done for code generalization iMax_index = sAlphabet.size(); // populate the tableau for (iIndex = 0; iIndex < iMax_index; iIndex++) { // store the string in the tableau vsTableau.push_back(sAlphabet); // do a circular rotation on the string sAlphabet = Left_circular_rotate(sAlphabet); } return; }// Vigenere::Vigenere(void) //*********************************************************************** // the class constructor - OVERLOAD - allows input string specification Vigenere::Vigenere(string sAlphabet) { int iIndex; // the loop index int iMax_index; // the loop limit // get the loop limit - done for code generalization iMax_index = sAlphabet.size(); // populate the tableau for (iIndex = 0; iIndex < iMax_index; iIndex++) { // store the string in the tableau vsTableau.push_back(sAlphabet); // do a circular rotation on the string sAlphabet = Left_circular_rotate(sAlphabet); } return; }// Vigenere::Vigenere(string sAlphabet) //*********************************************************************** char Vigenere::Encrypt(char cKey, char cPlaintext) { int iKey_row; int iPlain_column; char cCipher; // convert the input characters to integers iKey_row = toupper(cKey); iPlain_column = toupper(cPlaintext); // correct the row and column numbers iKey_row = iKey_row - 65; iPlain_column = iPlain_column - 65; // get the cipher character cCipher = vsTableau[iKey_row][iPlain_column]; return cCipher; }// Vigenere::Encrypt() //*********************************************************************** char Vigenere::Decrypt(char cKey, char cCiphertext) { int iKey_row; int iPlain_Column; char cPlain; string sCipher_string; // convert the input characters to integers iKey_row = toupper(cKey); // correct the row number iKey_row = iKey_row - 65; // convert the input character to a string sCipher_string = toupper(cCiphertext); // get the cipher character iPlain_Column = vsTableau[iKey_row].find(sCipher_string); // convert the result to a character cPlain = vsTableau[0][iPlain_Column]; return cPlain; }// Vigenere::Decrypt() //*********************************************************************** // class Vigenere_cipher declaration //*********************************************************************** class Vigenere_cipher { // private methods string Get_key(void); string Get_plaintext(void); void Write_plaintext(string sPlaintext); string Get_ciphertext(void); void Write_ciphertext(string sCiphertext); string Resize_key(string sKey, int iSize); public: // public methods void Encryption(void); void Decryption(void); }; // class Vigenere_cipher //*********************************************************************** // class Vigenere_cipher method declarations //*********************************************************************** string Vigenere_cipher::Get_key(void) { string sKey; // declare an input stream to read the key ifstream strKey_stream; // open the input stream to read the key strKey_stream.open("A:Key.txt"); // check if the file was OK if (strKey_stream.is_open()) // get the key strKey_stream >> sKey; else cout << "Error reading the key file!" << endl << endl; // print error message strKey_stream.close(); // close filestream return sKey; }// Vigenere_cipher::Get_key() //*********************************************************************** string Vigenere_cipher::Get_plaintext(void) { string sPlaintext; // declare an input stream to read the input plaintext ifstream strPlaintext_in_stream; // open the input stream to read the input plaintext strPlaintext_in_stream.open("A:Plaintext_in.txt"); // check if the file was OK if (strPlaintext_in_stream.is_open()) // get the plaintext strPlaintext_in_stream >> sPlaintext; else cout << "Error reading the plaintext file!" << endl << endl; // print error message strPlaintext_in_stream.close(); // close filestream return sPlaintext; }// Vigenere_cipher::Get_plaintext() //*********************************************************************** void Vigenere_cipher::Write_plaintext(string sPlaintext) { // declare an output stream to write the output plaintext ofstream strPlaintext_out_stream; // open the stream to write the output plaintext strPlaintext_out_stream.open("A:Plaintext_out.txt"); // write the plaintext to the output file stream strPlaintext_out_stream << sPlaintext; strPlaintext_out_stream.close(); return; }// Vigenere_cipher::Write_plaintext() //*********************************************************************** string Vigenere_cipher::Get_ciphertext(void) { string sCiphertext; // declare a stream to read the ciphertext ifstream strCipher_in_stream; // open the stream to read the ciphertext strCipher_in_stream.open("A:Ciphertext.txt"); // check if the file was OK if (strCipher_in_stream.is_open()) // get the ciphertext message strCipher_in_stream >> sCiphertext; else cout << "Error reading the ciphertext file!" << endl << endl; // print error message strCipher_in_stream.close(); return sCiphertext; }// Vigenere_cipher::Get_ciphertext() //*********************************************************************** void Vigenere_cipher::Write_ciphertext(string sCiphertext) { // declare a stream to write the ciphertext ofstream strCipher_out_stream; // open the stream to write the ciphertext strCipher_out_stream.open("A:Ciphertext.txt"); // write the ciphertext to the output file stream strCipher_out_stream << sCiphertext; strCipher_out_stream.close(); // close filestream return; }// Vigenere_cipher::Write_ciphertext() //*********************************************************************** string Vigenere_cipher::Resize_key(string sKey, int iSize) { int iKey_length; int iKey_expansion_loops; int iLoop_index; string sExpanded_key; iKey_length = sKey.size(); // calculate the number of repetitions to resize the key iKey_expansion_loops = (int)(iSize/iKey_length); // expand the key sExpanded_key = sKey; for(iLoop_index = 0; iLoop_index < iKey_expansion_loops; iLoop_index++) { sExpanded_key += sKey; }// for // remove enough characters from the expanded key to equal the desired length sExpanded_key.resize(iSize); return sExpanded_key; }// Vigenere_cipher::Resize_key //*********************************************************************** void Vigenere_cipher::Encryption(void) { // declare an instance of Class Vigenere Vigenere vclWorking_tableau; // the function storage strings string sKey; string sPlaintext; string sCiphertext; // string length measurements int iPlaintext_length; int iLoop_index; // get the key sKey = Get_key(); // get the plaintext message sPlaintext = Get_plaintext(); iPlaintext_length = sPlaintext.size(); // resize the key to match the plaintext length sKey = Resize_key(sKey, iPlaintext_length); // encrypt the plaintext message one letter at a time and append it // to the ciphertext string for(iLoop_index = 0; iLoop_index < iPlaintext_length; iLoop_index++) { sCiphertext += vclWorking_tableau.Encrypt(sKey[iLoop_index] , sPlaintext[iLoop_index]); }// for // write the ciphertext to the file Write_ciphertext(sCiphertext); return; }// Vigenere_cipher::Encryption() //*********************************************************************** void Vigenere_cipher::Decryption(void) { // declare an instance of Class Vigenere Vigenere vclWorking_tableau; // the function storage strings string sKey; string sPlaintext; string sCiphertext; // string length measurements int iCiphertext_length; int iLoop_index; // get the key sKey = Get_key(); // get the ciphertext message sCiphertext = Get_ciphertext(); iCiphertext_length = sCiphertext.size(); // resize the key to match the ciphertext length sKey = Resize_key(sKey, iCiphertext_length); // encrypt the plaintext message one letter at a time and append it // to the ciphertext string for(iLoop_index = 0; iLoop_index < iCiphertext_length; iLoop_index++) { sPlaintext += vclWorking_tableau.Decrypt(sKey[iLoop_index] , sCiphertext[iLoop_index]); }// for // write the plaintext to the file Write_plaintext(sPlaintext); return; }// Vigenere_cipher::Decryption() //***********************************************************************