**BEGINNER C++ CRYPTOGRAPHY TUTORIAL**

**CONTENTS**

• I. ASSUMPTIONS

• II. INTRODUCTION – CRYPTOGRAPHY VOCABULARY

• III. ALGORITHM

• IV. PASSING A TWO DIMENSIONAL ARRAY TO A FUNCTION BY REFERENCE

• V. C++ STANDARD LIBRARY PSEUDO RANDOM NUMBER GENERATOR.

• VI. PROGRAM.ANALYSIS

• VII. CONTACT ME

**WHAT YOU WILL LEARN IN THIS TUTORIAL**

1. You will learn the basic vocabulary of cryptography.

2. You will learn how to pass a two dimensional array to a function by reference.

3. You will learn the syntax for passing variables to functions by reference.

4. You will learn how to use the C++ standard library pseudo random number generator.

5. You will learn how to write a beginner level C++ encryption program.

**• I. ASSUMPTIONS**

Hello; nice to meet you. Welcome to the Beginner C++ Cryptography Tutorial.

This tutorial assumes you understand the fundamentals of the C++ language and are interested in Cryptography

**• II. INTRODUCTION – Cryptography vocabulary.**

What is cryptography? Cryptography is the practice and study of hiding information.

What is encryption? Encryption is using an algorithm to change readable information into information that is not readable. If a recipient wants to read an encrypted message the recipient has to have a decryption algorithm to change the encrypted information back to readable information.

What is an algorithm? An algorithm is an ordered sequence of unambiguous and well-defined instructions that perform a task.

What is a cipher? A cipher is a “key” for performing encryption and decryption.

What is a “key?” In order to use a cipher you have to know the key. For encrypted information to remain hidden, the key must be known to the recipient and sender and to no one else. A “symmetric key algorithm” is used for both encryption and decryption. An “asymmetric key algorithm” is when the sender uses one key to encrypt messages and the recipient uses a different key to decrypt those messages. When using an “asymmetric key algorithm,” each user has a pair of cryptographic keys; a public key and a private key. One or more people can encrypt messages using the public key. Security depends on the secrecy of the private key. Therefore the private key is normally kept secret by only one person, the recipient who decrypts received messages.

**• III. ALGORITHM**

We will use the following scenario to demonstrate examples of how C++ can be used in cryptography to change readable information into information that is not readable:

One of your clients has been having problems controlling access to their research and development facility. Their associates use a plastic card the size of a credit card to gain entrance to the facility by swiping the card through a door card reader. Each card has a magnetic strip containing a four digit number. Occasionally the associate cards are lost or stolen. Your client is concerned that these lost or stolen cards could be used by competitors to gain access to the facility and steal trade secrets. You have been asked to encrypt the four digit numbers in a manner that will permit electronic reissuance of the four digits. Your client is confident, that with the right software, his door card readers can both read the four digits from the card and write new digits to the card as the card is read. An alarm would sound, and security guards would intervene when the card reader did not read the correct updated four digits.

After careful thought you have decided to use the following six step symmetric key algorithm:

Step 1. Read in a four digit number.

Step 2. Perform a random number selection of addition, subtraction, multiplication, or division on each of the four digits. For example, add 7 to each digit of the four digit number.

Step 3. Perform a random number selection of addition, subtraction, multiplication, or division on each of the four digits. For example, divide each digit of the four digit number by 9.

Step 4. Perform a random number swap. For example, swap the first digit of the four digit number with the third digit.

Step 5. Perform a random number swap. For example, swap the second digit of the four digit number with the fourth digit.

Step 6. Round up each of the four digits.

You have decided to use the elements of an array and a vector to create an audit trail of each step of the encryption. You will use these audit trails to create the symmetric key algorithm for decryption.

**• IV. PASSING A TWO DIMENSIONAL ARRAY TO A FUNCTION BY REFERENCE**

Since your client plans to periodically update his security, you know your program has to be designed for easy maintenance. Therefore, you have decided to have your program include passing a two dimensional array to functions by reference.

First, let’s talk about functions. Functions have two limitations: Arguments are passed by value, and the return statement can return only one value. Passing values to a function by reference can overcome both of these limitations. Passing an object by reference enables the function to change the object being referenced. This approach bypasses the return value of the function, which can be reserved for reporting errors. A reference as a function parameter is created and initialized each time the function is called and is destroyed when the function ends, so you get a completely new reference created each time you use the function.

Second, let’s talk about arrays. We have a special case because we are using a two dimensional array. Multidimensional arrays are arrays of arrays. Our array name is f, and our first function name is ff1. Arrays count from zero, not from one. C++ arrays are row major order, which means when we code “void ff1(float (&f)[8][6]);” the first [8] means eight rows, and the second [8] means eight columns. Each intersection of a row and a column is called an array element. We have 8 x 8 or 64 array elements of type float in our f array. The amount of memory required to store each element of an array is determined by its type, and all the elements of an array are stored in a contiguous block of memory. Which leads us to the question why is the function call coded as “ff1(f);” and the answer is because the name of an array is a pointer pointing to the first element of the array. f is a pointer to &f[0][0], which is the address of the first element of the array f.

Third, let’s talk about references. What is a reference? A reference is an alias. When you create a reference, you initialize it with the name of another object, the target. The reference is then another name for the target. Anything you do to the reference you are also doing to the target. You create a reference by writing the type of the target object, followed by a space, followed by the reference operator (&), followed by the name of the reference, followed by an equal sign (=), followed by the name of the target object. For example, if we have a float variable named ourFloat, we can make a reference to that variable by writing:

float &rOurReference = ourFloat;

The space between the type and the reference operator is required. The reference operator (&) and the address-of operator (&) are not the same. They both use the same (&) symbol; however, they are two different operators.

It is a good idea to use the letter r as a prefix for reference names. And, references must be initialized when they are declared. In the above reference declaration example we initialized &rOurReference with ourFloat.

We are working with an array; therefore, in our encryption scenario we have a special case in regards to creating a reference because the name of our reference and the name of our target object is the same:

float &f[8][8] = f[8][8];

Therefore, in our encryption scenario, when referring to the array you will use the following function prototype definition syntax:

type function_name (type (&array_name) [row_elements][column_elements]);

For example, in the attached program we will use:

void ff1(float (&f)[8][8]);

And, the following array function call syntax:

function_name(array_name);

For example, in the attached program we will use:

ff1(f);

**• V. C++ STANDARD LIBRARY PSEUDO RANDOM NUMBER GENERATOR.**

The C++ standard library includes a pseudo random number generator for generating random numbers. In order to use it we need to include the #include <cstdlib> header. To generate a random number we use the rand() function. This will produce a result in the range 0 to RAND_MAX. The value of RAND_MAX varies between compilers and can be as low as 32767. This gives a range from 0 to 32767 for rand() which is not suitable for cryptography. However, it is more than adequate for our tutorial. We will only be working with random integers in a range of zero to nine. To keep everything realistic we will seed the generator with the srand() function. This will start the generator from a point in the sequence that is dependent on the value we pass as an argument. We will seed the generator with the system time. Therefore, we will need to include the #include <ctime> header.

We will generate a random number named rndInt1 which will have a range of zero to three. The value of rndInt1 will determine if we will add, subtract, multiply, or divide each of the original four digits. Zero will represent addition. One will represent subtraction. Two will represent multiplication. And, three will represent division. The value of rndInt1 will be stored in element f[1][4] of our array to establish an audit trail which will later be used to create the symmetric key algorithm for decryption.

We will generate a random number named rndInt2 which will have a range of one to nine. We will use the value of rndInt2 as the number we will add, subtract, multiply, or divide each of the original four digits by. The value of rndInt2 will be stored in element f[1][5] of our array to establish an audit trail which will later be used to create the symmetric key algorithm for decryption.

We will generate a random number named rndInt3 and a random number named rndInt4. They which each have a range of zero to three and their values will determine the swap order of the original four digits. For example, if rndInt3 equals 0 and rndInt4 equals 3 it would mean swap digit 0 with digit 3. The value of rndInt3 will be stored in element f[1][6] of our array. The value of rndInt4 will be stored in element f[1][7] of our array. These two values will later be used to create the symmetric key algorithm for decryption.

**• VI. PROGRAM ANALYSIS.**

Please copy and paste the attached program into a file your compiler can read. Then build, compile, and debug the program. Following along, back and forth, between the tutorial and your copy of the program will help you understand the program functionality.

//************************************ //Beginner C++ Encryption Tutorial. //************************************ #include <algorithm> //Sort, lower_bound. #include <cmath> #include <cstdlib> //Random number generator. #include <cstring> #include <ctime> // system time. #include <fstream> //File-based input and output. #include <functional> #include <iomanip> //Output formatting. #include <iosfwd> #include <iostream> //Input and output. #include <istream> #include <limits> //Limits. #include <math.h> #include <ostream> #include <string> //String. #include <vector> //Vector. using std::cerr; //STL classes. using std::cin; //STL classes. using std::cout; //STL classes. using std::ifstream; //STL classes. using std::istringstream; //STL classes. using std::string; //STL classes. using namespace std; enum types { DELIMITER = 1, VARIABLE, NUMBER}; //DEL = 1; VAR = 2; NUM = 3. //************************************ //Class. //************************************ class CCryptography //Declares the Cryptography class. { public: //Members that follow are public. CCryptography(); //CCryptography constructor. double m_sniff(char *exp); //Parser entry point. void m_Pause(); //Prompts the user to continue. void m_WriteFile(); //Write file, output file. void m_ReadFile(); //Read file, input file. void m_ParseFile(); //Parse file. void m_ff1(float(&f)[8][8]); //Initializes two dimension array to zero. void m_ff2(float(&f)[8][8]); //Passes two dimension array by reference. void m_ff3(float(&f)[8][8]); //Prints contents of two dimensional array. void m_S2rnd0To3(float(&f)[8][8]); //Generates a random number from 0 to 3 Step 2. void m_S2rnd1To9(float(&f)[8][8]); //Generates a random number from 1 to 9 Step 2. void m_S3rnd0To3(float(&f)[8][8]); //Generates a random number from 0 to 3 Step 3. void m_S3rnd1To9(float(&f)[8][8]); //Generates a random number from 1 to 9 Step 3. void m_S4rnd0To3(float(&f)[8][8]); //Generates a random number from 0 to 3 Step 4. void m_S5rnd0To3(float(&f)[8][8]); //Generates a random number from 0 to 3 Step 5. ~CCryptography(); //CCryptography destructor. private: //Members that follow are private. char *pm_Expresion; // Points to the expression. char m_token[80]; // Holds current token. char m_tokenType; // Holds token's type. void m_recursive1(double &culmination); void m_recursive2(double &culmination); void m_recursive3(double &culmination); void m_recursive4(double &culmination); void m_recursive5(double &culmination); void m_bomb(double &culmination); void m_nextToken(); void m_serror(int error); int m_isdelim(char c); }; //************************************ //CCryptography constructor. //************************************ CCryptography::CCryptography() { pm_Expresion = NULL; } //************************************ //CCryptography entry point. //************************************ double CCryptography::m_sniff(char *exp) { double culmination; pm_Expresion = exp; m_nextToken(); if(!*m_token) { m_serror(2); // No expression present. return 0.0; } m_recursive1(culmination); if(*m_token) m_serror(0); // Last token must be null. return culmination; } //************************************ //Add or subtract two terms. //************************************ void CCryptography::m_recursive1(double &culmination) { register char beer; double bucket; m_recursive2(culmination); while((beer = *m_token) == '+' || beer == '-') { m_nextToken(); m_recursive2(bucket); switch(beer) { case '-': culmination = culmination - bucket; break; case '+': culmination = culmination + bucket; break; } } } //************************************ //Multiply or divide two factors. //************************************ void CCryptography::m_recursive2(double &culmination) { register char beer; double bucket; m_recursive3(culmination); while((beer = *m_token) == '*' || beer == '/' || beer == '%') { m_nextToken(); m_recursive3(bucket); switch(beer) { case '*': culmination = culmination * bucket; break; case '/': culmination = culmination / bucket; break; case '%': culmination = (int) culmination % (int) bucket; break; } } } //************************************ //Process an exponent. //************************************ void CCryptography::m_recursive3(double &culmination) { double bucket, ex; register int t; m_recursive4(culmination); if(*m_token == '^') { m_nextToken(); m_recursive3(bucket); ex = culmination; if(bucket == 0.0) { culmination = 1.0; return; } for(t=(int)bucket-1; t>0; --t) culmination = culmination * (double)ex; } } //************************************ //Evaluate a unary + or -. //************************************ void CCryptography::m_recursive4(double &culmination) { register char beer; beer = 0; if((m_tokenType == DELIMITER) && *m_token == '+' || *m_token == '-') { beer = *m_token; m_nextToken(); } m_recursive5(culmination); if(beer == '-') culmination = -culmination; } //************************************ //Process a parenthesized expression. //************************************ void CCryptography::m_recursive5(double &culmination) { if((*m_token == '(')) { m_nextToken(); m_recursive1(culmination); if(*m_token != ')') m_serror(1); m_nextToken(); } else m_bomb(culmination); } //************************************ //Get the value of a number. //************************************ void CCryptography::m_bomb(double &culmination) { switch(m_tokenType) { case NUMBER: culmination = atof(m_token); m_nextToken(); return; default: m_serror(0); } } //************************************ //Display a syntax error. //************************************ void CCryptography::m_serror(int error) { static char *e[]= { "Syntax Error", "Unbalanced Parentheses", "No expression Present" }; cout << e[error] << endl; } //************************************ //Obtain the next token. //************************************ void CCryptography::m_nextToken() { register char *bucket; m_tokenType = 0; bucket = m_token; *bucket = '\0'; if(!*pm_Expresion) return; // At end of expression. while(isspace(*pm_Expresion)) ++pm_Expresion; // Skip over white space. if(strchr("+-*/%^=()", *pm_Expresion)) { m_tokenType = DELIMITER; *bucket++ = *pm_Expresion++; } else if(isalpha(*pm_Expresion)) { while(!m_isdelim(*pm_Expresion)) *bucket++ = *pm_Expresion++; m_tokenType = VARIABLE; } else if(isdigit(*pm_Expresion)) { while(!m_isdelim(*pm_Expresion)) *bucket++ = *pm_Expresion++; m_tokenType = NUMBER; } *bucket = '\0'; } //************************************ //Return true if c is a delimiter. //************************************ int CCryptography::m_isdelim(char c) { if(strchr(" +-/*%^=()", c) || c == 9 || c == '\r' || c == 0) return 1; return 0; } //************************************ //CCryptography destructor. //************************************ CCryptography::~CCryptography() { } //************************************ //Pause function. //************************************ void CCryptography::m_Pause() { cout << endl << endl << endl; cout << " "; system("PAUSE"); } //************************************ //WRITE TO FILE //Creates file received from customer. //************************************ void CCryptography::m_WriteFile() { ofstream myfile; //ofstream class initialization of object myfile. myfile.open("FourDigits.dat"); //Opens myfile. float digit[4] = {9.0,8.0,7.0,6.0}; if (myfile.is_open()) //Checks to see if file is open. { for (int i = 0; i <= 3; i++) { myfile << digit[i]; } myfile.close(); //Closes file. } else cout << " Unable to open file"; } //************************************ //READ FROM FILE //Reads file received from customer. //************************************ void CCryptography::m_ReadFile() { //We already declared myfile to be an ofstream class object //when we created the output file in the //void CCryptography::m_WriteFile() member function. ifstream myfile; //input file myfile.open("FourDigits.dat"); //Opens myfile. float line = 0.0; //Instantiates line as an object of class type float. if (myfile.is_open()) //Checks to see if file is open. { while (! myfile.eof()) //eof(); returns true when end of file has been reached, { //otherwise it returns false. myfile >> line; cout << " " << line << endl << endl; } myfile.close(); //Closes file. } else { if(!myfile) { cout << " Unable to open file.\n"; } } } //************************************ //Parser used to read the customer's //standard ASCII null terminated string //pointed to by expstr. //************************************ void CCryptography::m_ParseFile() { char expstr[80]; ifstream myfile; //input file myfile.open("FourDigits.dat"); //Opens myfile. if (myfile.is_open()) //Checks to see if file is open. { while (! myfile.eof()) //eof(); returns true when end of file //has been reached, otherwise it returns false. { myfile >> expstr; } myfile.close(); //Closes file. } else { if(!myfile) { cout << " Unable to open file.\n"; } } //************************************ cout << endl << endl << " The parsed verification of the four digit number is: "; cout << m_sniff(expstr) << "\n\n"; } //************************************ //Definition of function to initialize array to zero. //Easy way is just "void ff3(float(&f)[8][8])= {0};" //however, this is a demonstration //of how to loop through a multidemtional array. //NOTE: Arrays count from zero, not one. //Eight rows count as 0, 1, 2, 3, 4, 5, 6, 7 which //equals eight elements. //Eight columns count as 0, 1, 2, 3, 4, 5, 6, 7 which //equals eight elements. //f[8][8] means an array f of 8 rows of elements by //eight columns of elements. A total of 64 elements. //************************************ void CCryptography::m_ff1(float(&f)[8][8]) { for (int row = 0; row <= 7; row++) { for (int column = 0; column <= 7; column++) { f[row][column] = 0; } } } //************************************ //Passes two dimension array by reference. //************************************ void CCryptography::m_ff2(float(&f)[8][8]) { if((f[0][4]) <= 9) { (f[0][0]) = (f[0][4]); //9 or less } //************************************ else if(((f[0][4]) > 9) && ((f[0][4]) <= 99)) { float loop1 = 0; float temp1 = (f[0][4]); do { temp1 = (temp1 - 10); (f[0][1]) = ++loop1; } while(temp1 > 9); //99 or less (f[0][0]) = temp1; } //************************************ else if (((f[0][4]) > 99) && ((f[0][4]) <= 999)) { float loop2 = 0; float temp2 = (f[0][4]); do { temp2 = (temp2 - 100); (f[0][2]) = ++loop2; } while(temp2 > 99); //999 or less float loop1 = 0; float temp1 = temp2; do { temp1 = (temp1 - 10); (f[0][1]) = ++loop1; } while(temp1 > 9); //99 or less (f[0][0]) = temp1; } //************************************ else if (((f[0][4]) > 999) && ((f[0][4]) <= 9999)) { float loop3 = 0; float temp3 = (f[0][4]); do { temp3 = temp3 - 1000; (f[0][3]) = ++loop3; } while(temp3 > 999); //9999 or less float loop2 = 0; float temp2 = temp3; do { temp2 = (temp2 - 100); (f[0][2]) = ++loop2; } while(temp2 > 99); //999 or less float loop1 = 0; float temp1 = temp2; do { temp1 = (temp1 - 10); (f[0][1]) = ++loop1; } while(temp1 > 9); //99 or less (f[0][0]) = temp1; } } //************************************ //Displays two dimensional array. //************************************ void CCryptography::m_ff3(float(&f)[8][8]) { cout << endl << endl << endl; cout << " The array verification of the four digit number is:" << endl << endl; cout << " Reading the digits <== from right to left." << endl << endl; cout << " f[0][0] the 1st digit is " << f[0][0] << endl; //6 cout << " f[0][1] the 2nd digit is " << f[0][1] << endl; //7 cout << " f[0][2] the 3rd digit is " << f[0][2] << endl; //8 cout << " f[0][3] the 4th digit is " << f[0][3] << endl; //9 cout << " " << endl; cout << " f[0][4] the original number is " << f[0][4] << endl; //9876 } //************************************ //Generates one random number //with a value range from //0 to 3 for Encryption Step 2. //************************************ void CCryptography::m_S2rnd0To3(float(&f)[8][8]) { srand((unsigned)time(0)); // void srand ( unsigned int seed ); time() function int rndInt1; int left = 0; // Starting number for range of random numbers int right = 3; // Ending number for range of random numbers int vector = (right - left) + 1; for(int i = 0; i < 1; i++) // Number of random numbers generated { rndInt1 = left + int(vector * rand()/(RAND_MAX + 1.0)); } f[1][4] = rndInt1; } //************************************ //Generates one random number //with a value range from //1 to 9 for Encryption Step 2. //************************************ void CCryptography::m_S2rnd1To9(float(&f)[8][8]) { srand((unsigned)time(0)); // void srand ( unsigned int seed ); time() function int rndInt2; int left = 1; // Starting number for range of random numbers int right = 9; // Ending number for range of random numbers int vector = (right - left) + 1; for(int i = 0; i < 1; i++) // Number of random numbers generated { rndInt2 = left + int(vector * rand()/(RAND_MAX + 1.0)); } f[1][5] = rndInt2; } //************************************ //Generates one random number //with a value range from //0 to 3 for Encryption Step 3. //************************************ void CCryptography::m_S3rnd0To3(float(&f)[8][8]) { srand((unsigned)time(0)); // void srand ( unsigned int seed ); time() function int rndInt1; int left = 0; // Starting number for range of random numbers int right = 3; // Ending number for range of random numbers int vector = (right - left) + 1; for(int i = 0; i < 1; i++) // Number of random numbers generated { rndInt1 = left + int(vector * rand()/(RAND_MAX + 1.0)); } f[2][4] = rndInt1; } //************************************ //Generates one random number //with a value range from //1 to 9 for Encryption Step 3. //************************************ void CCryptography::m_S3rnd1To9(float(&f)[8][8]) { srand((unsigned)time(0)); // void srand ( unsigned int seed ); time() function int rndInt2; int left = 1; // Starting number for range of random numbers int right = 9; // Ending number for range of random numbers int vector = (right - left) + 1; for(int i = 0; i < 1; i++) // Number of random numbers generated { rndInt2 = left + int(vector * rand()/(RAND_MAX + 1.0)); } f[2][5] = rndInt2; } //************************************ //Generates one random number //with a value range from //0 to 3 for Encryption Step 4. //************************************ void CCryptography::m_S4rnd0To3(float(&f)[8][8]) { srand((unsigned)time(0)); // void srand ( unsigned int seed ); time() function int rndInt1; int left = 0; // Starting number for range of random numbers int right = 3; // Ending number for range of random numbers int vector = (right - left) + 1; for(int i = 0; i < 1; i++) // Number of random numbers generated { rndInt1 = left + int(vector * rand()/(RAND_MAX + 1.0)); } f[3][4] = rndInt1; } //************************************ //Generates one random number //with a value range from //0 to 3 for Encryption Step 5. //************************************ void CCryptography::m_S5rnd0To3(float(&f)[8][8]) { srand((unsigned)time(0)); // void srand ( unsigned int seed ); time() function int rndInt1; int left = 0; // Starting number for range of random numbers int right = 3; // Ending number for range of random numbers int vector = (right - left) + 1; for(int i = 0; i < 1; i++) // Number of random numbers generated { rndInt1 = left + int(vector * rand()/(RAND_MAX + 1.0)); } f[4][4] = rndInt1; } //************************************ // MAIN() FUNCTION. //************************************ int main(int argc, char* argv[]) { int choice = 0; bool exitt = false; CCryptography OEquation; // Instantiates OEquation as an object of type CCryptography. vector<float> myVector(0); //Declares a vector. float f[8][8]; //Declare f[8][8] array. OEquation.m_ff1(f); //Initializes f[8]