| Previous | Table of Contents | Next |
Program Execution
To illustrate the use of CIPHER4.BAS, execute the program just developed. The top portion of Figure 2.6 illustrates the execution of the program which displays program information and enables the user to enter his or her message. In this example, the first two lines of the message were entered with the forward slash as a prefix character to ensure those lines remained in cleartext. After the two-line heading, the next four lines required encipherment and were entered without a forward slash character used as a prefix. Finally, the backslash character was entered by itself on a separate line to indicate the termination of the message.
Figure 2.6 The execution of CIPHER4.BAS
The lower portion of Figure 2.6 illustrates the resulting enciphered message printed in groups of five characters. Note that the first two lines of heading information are simply printed without alteration, while the body of the message is both enciphered and printed in groups of five characters. Also note that the last group contained three characters and required the addition of two Xs to complete the group of five. You can easily confirm this visually by noting that the message ended with the word STOP. Because a simple alphabetic shift was used for enciphering using the character B as the shift key, each character of plaintext is shifted up two positions in the alphabet. Thus, STOP becomes UVQR. Because VQR are the last three characters in the message, two Xs were added to complete the group.
Program Default Files
To understand the contents of the default files created by CIPHER4.BAS, let us examine their contents after the program is executed. Figure 2.7 lists the contents of MESSAGE.DAT and CIPHERTX.DAT based upon the message illustrated in Figure 2.6 being entered when CIPHER4.BAS was executed. As indicated in Figure 2.7, the heading is placed on a file as is, while the body of the message is placed on each file with spaces between words being removed.
Figure 2.7 The CIPHER4.BAS file contents.
The C++ version of CIPHER4.BAS contains a number of programming improvements which facilitate the use of the program. The program listing of CIPHER4.CPP is contained in Listing 2.15.
Listing 2.15 The CIPHER4.CPP program listing.
/*
Cipher4.cpp
C++ Code written by Jonathan Held, January 23, 1998, using
Microsoft Visual C++, version 5.0.
486 total lines of code.
*/
//standard include files
#include <iostream.h> //standard i/o operations
#include <string.h> //used to find the length of a string
#include <ctype.h> //for character handling
#include <fstream.h> //file stream processing
#include <stdlib.h> //standard library functions
//function prototypes - see function headers for more information
void getFileNames(char* &, char* &);
int getInputType(void);
void getShiftKey(char &);
void createCipher(const char [], char[], const char);
bool getMessage(char*, char*, char [], const char[],
const char[]); char* formCipheredMessage(const char[],
const char [], char []); void printResults(const char[],
const char[], const char[], const char [],
const int);
void printCipherToFile(ofstream, const char[]);
bool encryptText(char *, char *, const char [],
const char[], char[]);
//-----------------------------------------------------
//Function: main()
//Parameters: argc - the number of command line arguments passed to
// main
//Return Type: int - 0 execution is normal, 1 abnormal termination
//Purpose: Runs the main part of the program.
//-----------------------------------------------------
int main(int argc, char *argv[]){
//initialize plaintext
char plaintext[26] = {'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'};
//other variables we will use
char ciphertext[26], message_to_cipher[256],
enciphered_message[256], key;
char *infile, *outfile;
int input_type;
bool success = false;
//function calls
//this code allows the user to run the program from the
//dos prompt with command line arguments, i.e. the user
//can run the program at the dos prompt by typing
//cipher <input filename> <output filename> <key>
if (argc >= 4){
infile = new char[strlen(argv[1])+1];
strcpy(infile,argv[1]);
outfile = new char[strlen(argv[2])+1];
strcpy(outfile,argv[2]);
key = toupper(*argv[3]);
int key_value = static_cast<int>(key);
if ((key_value < 65) || (key_value > 90)){
//print error message
cerr << "Error: Invalid key used. Goodbye." << endl;
//force the program to terminate due to error
exit(EXIT_FAILURE);
}
input_type = 1;
}
//user tried to run from the dos prompt but made a mistake
else if (argc >=2 && argc <4){
cout << "Usage: cipher10 <inputfile> <outputfile> <key>";
//force the program to terminate due to error
exit(EXIT_FAILURE);
}
else {
//user wants to manually enter information
//get file information
getFileNames(infile, outfile);
input_type = getInputType();
//get the uppercase key
getShiftKey(key);
}
//create the cipher key
createCipher(plaintext, ciphertext, key);
//process file input
if (input_type){
success = encryptText(infile, outfile, plaintext, ciphertext,
enciphered_message);
}
else {
cout << "Use a \'\\' to leave a line in plaintext." << endl
<< "Use a \'\\' to indicate end of message input. " << endl;
success = getMessage(infile, outfile, message_to_cipher, plaintext,
ciphertext);
}
//report success of operation
if (!success){
cerr << "Error: Invalid filename specified. Goodbye." << endl;
}
//delete dynamically allocated memory
delete [] infile;
delete [] outfile;
return (EXIT_SUCCESS);
}//end main()
//-----------------------------------------------------
//Function: getFileNames()
//Parameters: infile_name - the input file
// outfile_name - the output file we will write the
// enciphered text to
//Return Type: None
//Purpose: Get file information from the user.
//-----------------------------------------------------
void getFileNames(char * &infile_name, char * &outfile_name)
{
char buffer[256];
int length;
cout << "Enter filename to store/retrieve plaintext message: ";
cin >> buffer;
length = strlen(buffer);
infile_name = new char[length + 1];
strcpy(infile_name, buffer);
cout << "\nEnter filename to store enciphered message: ";
cin >> buffer;
length = strlen(buffer);
outfile_name = new char[length + 1];
strcpy(outfile_name, buffer);
cout << endl;
return;
}//end getFileNames()
//-----------------------------------------------------
//Function: getInputType()
//Parameters: None
//Return Type: int - 0 indicated keyboard input, 1 indicates file
input
//Purpose: Determines if the user will be manually entering text to
//be enciphered or if the user wants a file to be enciphered.
//-----------------------------------------------------
int getInputType(void)
{
char type;
bool error = false;
int value;
do {
//prompt user for input from file or keyboard
cout << "Is file input from keyboard (K, k) or file (F, f): ";
cin >> type;
//make type an uppercase letter
type = static_cast<char>(toupper(static_cast<int>(type)));
//check for an invalid character
if ((type != 'K') && (type != 'F')){
cerr << "You have entered an invalid character!" << endl << endl;
error = true;
}
else {
if (type == 'K')
value = 0; //value of 0 represents keyboard input
else value = 1; //value of 1 represents file input
error = false;
}
} while (error);
cout << endl;
return value;
}//end getInputType()
//-----------------------------------------------------
//Function: encryptText()
//Parameters: inp_file - the name of the input plaintext file
// outp_file - the name of the output ciphertext file
// PTEXT[] - the plaintext alphabet
// CTEXT[] - the ciphertext alphabet
// encoded_msg[] - the message to be encoded
//Return Type: bool, indicating success of operation
//Purpose: Used to encrypt file input. Takes each line of the input
//file, encrypts it, and saves the result to the specified output
//file.
//-----------------------------------------------------
bool encryptText(char * inp_file, char * outp_file, const char PTEXT[],
const char CTEXT[], char encoded_msg[])
{
bool success = false;
char buffer[256];
char nextChar;
//declare file stream objects
ifstream input(inp_file, ios::in);
ofstream output(outp_file, ios::app);
if ((!input) || (!output)){
//do nothing - I/O error; user will be notified upon
//procedure's return to main()
}
else {
success = true;
//print plaintext and ciphertext alphabets to the
//output file
output << "PLAINTEXT: " << PTEXT << endl;
output << "CIPHERTEXT: " << CTEXT << endl << endl;
while (input.getline(buffer, 256, '\n')){
//look at the next character
nextChar = input.peek();
//if we've grabbed 256 characters, and the very next character
//is the newline delimeter, we want to ignore it
if (nextChar == '\n')
input.ignore();
//check to see if the user wants the line to appear in plain text
if (buffer[0] == '/'){
output << buffer << endl;
}
else {
//encipher the line
char *msg = formCipheredMessage(CTEXT, buffer, encoded_msg);
//print the cipher in groups of five to the ouput file
printCipherToFile(output, msg);
} }
//notify user where plaintext and ciphertext files are
cout << "Plaintext file is: " << inp_file << endl;
cout << "Encrypted file is: " << outp_file << endl << endl;
}
//don't forget to close the files
input.close();
output.close();
//return success of the operation
return success;
}//end encryptText()
//-----------------------------------------------------
//Function: getShiftKey()
//Parameters: key_desired - uppercase key entered by the user
//Return Type: None
//Purpose: Get the key the user enters; error checking performed
//until user enters a valid value.
//-----------------------------------------------------
void getShiftKey(char &key_desired){
bool error = true;
do {
//prompt user to enter an uppercase shift key
cout << "Enter UPPERCASE Alphabetic Shift Key (CTRL-C to quit): ";
cin >> key_desired;
int key_value = static_cast<int>(key_desired);
//do some error checking
if ((key_value < 65) || (key_value > 90)){
cerr << "\nYou must enter a letter from A to Z!" << endl << endl;
}
else {
error = false;
}
} while (error);
cout << endl;
return;
}//end getShiftKey()
//-----------------------------------------------------
//Function: createCipher()
//Parameters: PTEXT - the plaintext alphabet
// ctext - the cipher alphabet we are going to create
// user_key - the key the user entered
//Return Type: None
//Purpose: Create the cipher stream we will use later to encode the
//user's message.
//-----------------------------------------------------
void createCipher(const char PTEXT[], char ctext[], const char user_key){
int location;
//find the location of the key in the plaintext
for (int ix=0; ix<26; ix++){
if (user_key == PTEXT[ix]){
//location is one more than ix
location = ix + 1;
break;
}
}
//create the cipher text
for (int jx=0; jx<26; jx++){
ctext[jx] = PTEXT[(jx + location) % 26];
}
return;
}//end createCipher();
//-----------------------------------------------------
//Function: getMessage()
//Parameters: input - the name of the input plaintext file
// output the name of the output ciphertext file
// msg_to_cipher - the essage to be encoded
// PTEXT[] - the plaintext alphabet
// CTEXT[] - the ciphertext alphabet
//Return Type: bool, indicating success of operation
//Purpose: Allow the user to manually input text from the keyboard.
//Save the text in plaintext to the input file; encrypt the text
//and save it to the specified output file for later retrieval.
//-----------------------------------------------------
bool getMessage(char* input, char* output,
char msg_to_cipher[], const char
PTEXT[], const
char CTEXT[]){
bool go_on = true, success = false;
ofstream textFile(input, ios::app);
ofstream cipherFile(output, ios::app);
if ((!textFile) || (!cipherFile)){
//do nothing - error will be noted to user later
}
else {
success = true;
textFile << "PLAINTEXT: " << PTEXT << endl;
textFile << "CIPHERTEXT: " << CTEXT << endl << endl;
//get the newline character off of the input stream
cin.get();
cout << "Enter the message in UPPERCASE characters: " << endl;
while (go_on) {
//get the entire line, up to 256 characters
cin.getline(msg_to_cipher, 256, '\n');
//case user doesn't want the text to be encrypted
if (msg_to_cipher[0] == '/'){
textFile << msg_to_cipher << endl;
cipherFile << msg_to_cipher << endl;
}
//case user is done entering text (ASCII value is 92
//for the newline delimeter
else if (static_cast<int>(msg_to_cipher[0]) == 92){
go_on = false;
}
//encrypt the text
else {
textFile << msg_to_cipher << endl;
char enciphered_msg[256];
formCipheredMessage(CTEXT,msg_to_cipher,enciphered_msg);
printCipherToFile(cipherFile,enciphered_msg);
}
}
}
//close the files
textFile.close();
cipherFile.close();
//notify user where plaintext and ciphertext files are
cout << "\nPlaintext file is: " << input << endl;
cout << "Encrypted file is: " << output << endl << endl;
return success;
}//end getMessage()
//-----------------------------------------------------
//Function: formCipheredMessage()
//Parameters: CTEXT - the cipher alphabet we will use for substitution
// MESSAGETOCIPHER - the user's message
// enc_message - the enciphered message to be determined
//Return Type: char* - a pointer to the encoded information.
//Purpose: Encipher the user's message.
//-----------------------------------------------------
char* formCipheredMessage(const char CTEXT[], const char MESSAGETOCIPHER[],
char enc_message[]){
int length = strlen(MESSAGETOCIPHER)+1;
int encode_value;
for (int ix=0; ix<length; ix++){
//test to see if we have an alphabetic charac‚ter; if not,
//simply copy it to our encrypted message - this preserves
//characters such as ', ! etc...
if (!isalpha(static_cast<int>(MESSAGETOCIPHER[ix]))){
enc_message[ix] = MESSAGETOCIPHER[ix];
}
els{
//valid character - the easy way to calculate the ciphered
//character is based on the plain text's ascii character value;
//since it has to be a capital letter, it must be in the range
//from 65 to 90, with A represented by 65, Z by 90. By simply
//subtracting 65 from the encode_value (the integer representation
//of the plaintext character), we now know what cipher character
//to use.
encode_value = toupper(static_cast<int>(MESSAGETOCIPHER[ix]));
enc_message[ix] = CTEXT[encode_value-65];
}
}
//return a reference to the encoded message
return enc_message;
}//end formCipheredMessage()
//-----------------------------------------------------
//Function: printCipherToFile()
//Parameters: op - the output file we are writing to
// MSG - the cipher text we are displaying
//Return Type: None
//Purpose: Group the cipher in 5-character blocks in the
//specified output file.
//-----------------------------------------------------
void printCipherToFile(ofstream op, const char MSG[]){
int len = strlen(MSG) + 1;
//keep track of number of characters
int counter = 0;
for (int kx=0;kx<len;kx++){
if (*(MSG+kx) != ' '){
//test to see if we need to print a space
if ((counter != 0) && (counter%5 == 0)) {
op << " ";
}
//if not, we have a character to print
op << *(MSG+kx);
//increment the count of characters
counter++;
}
}
//force a carriage return in the output file
op << endl;
return;
}//end printCipherToFile()
//end file cipher4.cpp
| Previous | Table of Contents | Next |