2
CLASSICAL CRYPTOGRAPHIC ALGORITHMS

SHEIKH SHAUGAT ABDULLAH AND SAIFUL AZAD

Contents

Keywords

2.1 Caesar Cipher

2.1.1 Algorithm

2.1.2 Implementation

2.1.3 Limitations

2.2 Monoalphabetic Cipher

2.2.1 Algorithm

2.2.2 Implementation

2.2.3 Limitations

2.3 Playfair Cipher

2.3.1 Algorithm

2.3.2 Implementation

2.3.3 Limitations

2.4 Polyalphabetic Cipher

2.4.1 Algorithm

2.4.2 Implementation

2.4.3 Limitations

Keywords

Caesar ciphe

Monoalphabetic cipher

Playfair cipher

Polyalphabetic cipher

The history of cryptography starts from the ancient era when it was practiced by the secret societies or by the troops on the battlefield. The necessity of such an approach has increased with time. In the current information era, there is indeed no time at which information security is not necessary, and hence cryptography. From military to civilian, or from government to individual, information security is tremendously necessary. Consequently, several algorithms are proposed, and they are implemented with various hardware. In this chapter, we discuss a couple of renowned classical encryption techniques.

2.1 Caesar Cipher

Caesar cipher or Caesar’s shift cipher is an extensively known and the easiest encryption technique, named after Julius Caesar, who used it in his military campaigns. Julius Caesar replaced each letter in the plaintext by the letter three positions further down the alphabet. It was the first recorded use of encryption for the sake of securing messages. Hence, it has become so important that it is still included in more advanced encryption technique at times (e.g., Vigenère cipher).

Actually, Caesar cipher is a type of substitution cipher in which each letter of the alphabet is substituted by a letter a certain distance away from that letter (Table 2.1). When the last letter, Z, is reached, it wraps back around to the beginning. For example, with a shift of three (i.e., key = 3) to the right, A would be replaced by D, B would become E, and so on.

2.1.1 Algorithm

Step 0: Mathematically, map the letters to numbers (i.e., A = 1, B = 2, and so on).

Step 1: Select an integer key K in between 1 and 25 (i.e., there are total 26 letters in the English language).

Step 2: The encryption formula is “Add k mod 26”; that is, the original letter L becomes (L + k)%26.

Step 3: The deciphering is “Subtract k mod 26”; that is, the encrypted letter L becomes (Lk)%26.

Table 2.1 Caesar Cipher, Plaintext–Ciphertext Conversion for Key Value 3 to the Right

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

d

e

f

g

h

i

j

k

l

m

n

o

p

q

r

s

t

u

v

w

x

y

z

a

b

c

2.1.2 Implementation

#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;

charcaesar(char c, int k)//'c' holds the letter to be
   encrypted or decrypted and 'k' holds the key
{
if(isalpha(c) && c ! = toupper(c))
   {
      c = toupper(c);//use upper to keep from having
          to use two separate for A..Z a..z
      c = (((c-65)+k)% 26) + 65; //Encryption, (add k
          with c) mod 26
   }
else
   {
      c = ((((c-65)-k) + 26)% 26) + 65; //Decryption,
          (subtract k from c) mod 26
      c = tolower(c);//use lower to keep from having
          to use two separate for A..Z a..z
   }
return c;
}

int main()
{
string input, output;
int choice = 0;


while (choice ! = 2) {
cout<<endl<< "Press 1: Encryption/Decryption; Press 2:
quit: " ;

try {
cin>> choice;
if (choice ! = 1 && choice ! = 2) throw "Incorrect
Choice";
      }
catch (const char* chc) {
cerr<< "INCORRECT CHOICE !!!!" <<endl;
return 1;
     }
if (choice = = 1) {
int key;
try {
cout<<endl<< "Choose key value (choose a number
   between 1 to 26): ";
cin>> key;
cin.ignore();
if (key < 1 || key > 26) throw "Incorrect key";
        }
catch (const char* k) {
cerr<< "INCORRECT KEY VALUE CHOSEN !!!" <<endl;
return 1;
        }

try {
cout<<endl<< "NOTE: Put LOWER CASE letters for
encryption and" <<endl;
cout<< "UPPER CASE letters for decryption" <<endl;
cout<<endl<< "Enter cipertext (only alphabets) and
press enter to continue: ";
getline(cin, input);

for (inti = 0; i<input.size(); i++) {
if ((!(input[i] > = 'a' && input[i] < = 'z')) &&
(!(input[i] > = `A' && input[i] < = `Z'))) throw
"Incorrect string";
       }
     }
catch (const char* str) {
cerr<< "YOUR STRING MAY HAVE DIGITS OR SPECIAL SYMBOLS
!!!" <<endl;
cerr<< "PLEASE PUT ONLY ALPHABETS !!! " <<endl;
return 1;
     }

for(unsigned int x = 0; x <input.length(); x++) {
output + = caesar(input[x], key); //calling the Caesar
function, where the actual encryption and decryption
takes place
       }

cout<< output <<endl;
output.clear();
    }
  }
}

2.1.3 Limitations

The Caesar cipher was reasonably secure in earlier days (until the ninth century) because most of the enemies of Julius Caesar were illiterate. They thought the encrypted text was written in some foreign language. However, there are several techniques to break Caesar cipher these days.

Caesar cipher is vulnerable to brute-force attack because it depends on a single key with 25 possible values if the plaintext is written in English. Therefore, by trying each option and checking which one results in a meaningful word, it is possible to find out the key. Once the key is found, the full ciphertext can be deciphered accurately.

Frequency analysis is another way to break Caesar cipher, which is smarter and faster than brute force. We will learn more about frequency analysis later in this chapter.

2.2 Monoalphabetic Cipher

Another type of substitution cipher is monoalphabetic cipher, where the same letters of the plaintext are always replaced by the same letters in the ciphertext. The word mono means “one,” and therefore, each letter is one-to-one mapped with a single ciphertext letter. A sample plaintext–ciphertext alphabet mapping is given in Table 2.2. Here, A in the plaintext will be replaced by q in the ciphertext, and so on.

Unlike Caesar cipher, this technique uses a random key for every single letter (i.e., total of 26 keys). So breaking the code for a single letter doesn’t necessarily decipher the whole encrypted text, which makes the monoalphabetic cipher secure against brute-force attack.

2.2.1 Algorithm

Step 0: Generate plaintext–ciphertext pair by mapping each plaintext letter to a different random ciphertext letter.

Step 1: To encipher, for each letter in the original text, replace the plaintext letter with a ciphertext letter.

Step 2: For deciphering, reverse the procedure in step 1.

Table 2.2 Sample Plaintext–Ciphertext Letters Mapping in Monoalphabetic Cipher

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

q

w

E

r

t

y

u

I

o

p

a

s

d

f

g

h

j

k

L

z

x

c

v

b

n

m

2.2.2 Implementation

#include <iostream>
#include <vector>
#include <string>
#include <stdlib.h>
using namespace std;


typedef vector <char>CharVec;
CharVec Plain;
CharVec Cipher;


voidPutCharInVec ()
{
cout<< "Plain: " <<endl;
for(inti = 0; i< 26; i++) {
Plain.push_back(i+97); //Assigning the plain
characters in Vector
  }


for(inti = 0; i< 26; i++) {
cout<< Plain[i] << " " ;
  }
cout<<endl;
  //Assigning the random characters in Vector to use
as key
cout<< "Cipher: " <<endl;
bool exist;
intnum;
for(inti = 0; i< 26; i++) {
  // Generating unique random numbers as keys
while (exist) {
exist = false;
num = rand()% 26 + 1;
for (vector <char> :: iterator it = Cipher.begin(); it
! = Cipher.end(); it++) {
if ((*it) = = num) {
exist = true;
break;
           }
      }
    }
Cipher.push_back(((i + num)% 26) + 65);
  }
for(inti = 0; i< 26; i++) {
cout<< Cipher[i] << " " ;
  }
cout<<endl;
}

charMonoalphabetic (char c)
{
  //Encryption
if (c ! = toupper(c)) {
for (inti = 0; i< 26; i++) {
if (Plain[i] = = c) {
return Cipher[i];
       }
     }
   }
  //Decryption
else {
for (inti = 0; i< 26; i++) {
if (Cipher[i] = = c) {
return Plain[i];
        }
     }
  }
return 0;
}

int main ()
{
string input, output;

PutCharInVec();
int choice = 0;
while (choice ! = 2) {
cout<<endl<< "Press 1: Encryption/Decryption; Press 2:
quit: " ;

try {
cin>> choice;
cin.ignore();
if (choice ! = 1 && choice ! = 2) throw "Incorrect
Choice";
      }
catch (const char* chc) {
cerr<< "INCORRECT CHOICE !!!!" <<endl;
return 1;
     }
if (choice = = 1) {
try {
cout<<endl<< "NOTE: Put LOWER CASE letters for
encryption and" <<endl;
cout<< "UPPER CASE letters for decryption" <<endl;
cout<<endl<< "Enter cipertext (only alphabets) and
press enter to continue: ";
getline(cin, input);

for (inti = 0; i<input.size(); i++) {
if ((!(input[i] > = 'a' && input[i] < = 'z')) &&
(!(input[i] > = 'A' && input[i] < = 'Z'))) throw
"Incorrect string";
       }
    }
catch (const char* str) {
cerr<< "YOUR STRING MAY HAVE DIGITS OR SPECIAL SYMBOLS
!!!" <<endl;
cerr<< "PLEASE PUT ONLY ALPHABETS !!! " <<endl;
return 1;
       }

for(unsigned int x = 0; x <input.length(); x++) {
output + = Monoalphabetic(input[x]);
       }
cout<< output <<endl;
output.clear();
     }

  }
return 0;
}

2.2.3 Limitations

Despite its advantages, the random key for each letter in monoalphabetic substitution has some downsides too. It is very difficult to remember the order of the letters in the key, and therefore, it takes a lot of time and effort to encipher or decipher the text manually.

On the other hand, monoalphabetic substitution is vulnerable to frequency analysis because it does not change the relative letter frequencies. As human language is not random, so frequencies of different letters are different in the regular text (e.g., e and t are most frequent; the, and, a, and an are very common). The frequency distribution of each letter in the ciphertext can be calculated by using the statistical analyzer. Then, the distribution result is compared to the standard letter frequency statistics to make assumptions at possible letter replacements. Sometimes backtracking is necessary to confirm the assumptions.

To improve the security of monoalphabetic cipher, multiple ciphertext letters need to be mapped with each corresponding plaintext letter. This technique is called polyalphabetic cipher, and it will be described later in the chapter.

2.3 Playfair Cipher

As seen in the previous section, not even a large number of keys in a monoalphabetic cipher provides the desired security. To improve the security, one approach is to use the digraph substitution cipher, where multiple letters are encrypted at a time. The Playfair cipher was the earliest practical digraph substitution cipher. The technique was invented by Charles Wheatstone in 1854. However, it was named after his friend Lord Playfair, who promoted the use of this cipher. Playfair was massively used by British forces in the Second Boer War and World War I. It was also used by the Australians for tactical purposes during World War II.

Playfair actually encrypts digraphs or pairs of letters rather than single letters like the plain substitution cipher (e.g., Caesar cipher). It is equivalent to a monoalphabetic cipher with a set of 25 × 25 = 625 characters (i.e., for each possible pair) for the English language. Therefore, security is significantly improved over the simple monoalphabetic cipher.

2.3.1 Algorithm

Step 0: Select the character key. The maximum size of the key is 25, and it can only be letters.

Step 1: Identify double letters in the key and count them as one.

Table 2.3 Sample Playfair Matrix for Key Simple

S

I/J

M

P

L

E

A

B

C

D

F

G

H

K

N

O

Q

R

T

U

V

W

X

Y

Z

Step 2: Set the 5 × 5 matrix by filling the first positions with the key. Fill the rest of the matrix with other letters. I and J will be placed in the same cell as shown in Table 2.3.

Step 3: Identify double letters in the plaintext and replace the duplicate letter with x (e.g., killer will become kilxer).

Step 4: Plaintext is encrypted in pairs, two letters at a time. If the plaintext has an odd number of characters, append an x to the end to make it even.

Step 5: For encryption: (1) If both letters fall in the same row, substitute each with the letter to its right in a circular pattern. (2) If both letters fall in the same column, substitute each letter with the letter below it in a circular pattern. (3) Otherwise, each letter is substituted by the letter in the same row, but in the column of the other letter of the pair.

Step 6: For deciphering, reverse the procedure in step 5, step 4, and finally, step 3, respectively.

2.3.2 Implementation

#include <iostream>
#include <string>
#include <vector>
using namespace std;

classPlayFair
{
public:

PlayFair ();
  ~PlayFair () {}

voidsetKey (string k) {key = k;}
stringgetKey () {return key;}
stringkeyWithoutDuplicateAlphabet (string k);
string encrypt (string str);
string decrypt (string str);

voidsetMatrix ();
voidshowMatrix ();

intfindRow (char ch);
intfindCol (char ch);

charfindLetter (intx_val, inty_val);

private:

char matrix[5][5];
string key;
};

PlayFair::PlayFair ()
{
  // Initializing the playfair matrix
for (inti = 0; i< 5; i++) {
for (int j = 0; j < 5; j++) {
matrix[i][j] = 0;
     }
   }
}

stringPlayFair::keyWithoutDuplicateAlphabet (string k)
{
stringstr_wo_dup;//string without duplicate alphabets

for (string::iterator it = k.begin(); it ! = k.end();
it++) {
      boolalphabet_exist = false;
      for (string::iterator it1 = str_wo_dup.begin();
      it1 ! = str_wo_dup.end(); it1++) {
      if (*it1 = = *it) {
alphabet_exist = true;
          }
       }

if (!alphabet_exist) {
str_wo_dup.push_back(*it);
    }
  }
returnstr_wo_dup;
}

voidPlayFair::setMatrix ()
{
stringkwda = keyWithoutDuplicateAlphabet(getKey());
// Getting the key with unique characters

inti_val, j_val;

int count = 0;
  // Populating the Playfair matrix with the key and
other letters
for (inti = 0; i< 5; i++) {
for (int j = 0; j < 5; j++) {
          if (count = = kwda.length()) break;
          else {
          matrix[i][j] = toupper(kwda[(5 * i) + j]);
            ++count;
          }
   }
if (count = = kwda.length()) break;
   }
for (inti = 0; i< 26; i++) {
          charch = 65 + i;
          boolalphabet_exist = false;
          for (string::iterator it = kwda.begin();
          it ! = kwda.end(); it++) {
          if (ch = = toupper(*it)) {
                     alphabet_exist = true;
             }
          }

          if (ch = = `J') alphabet_exist = true;//since
          i and j both co-exist in the same cell, we'll
          only put i in the cell

      bool exit = false;
      if (!alphabet_exist) {
      for (inti = 0; i< 5; i++) {
                for (int j = 0; j < 5; j++) {
                if (!isalpha(matrix[i][j])) {
                          matrix[i][j] = toupper(ch);
                          exit = true;
                      }
                  if (exit = = true) break;
                  }
                  if (exit = = true) break;
        }
    }
}
}

voidPlayFair::showMatrix()
{
for (inti = 0; i< 5; i++) {
      for (int j = 0; j < 5; j++) {
      if (matrix[i][j] ! = `I') cout<< matrix[i][j] <<
      " ";
      elsecout<< "I/J" << " ";
      }
      cout<<endl;
  }
cout<<endl;
}

intPlayFair::findRow (char ch)
{
  //Finding the specific row for a character
if (ch = = `j') ch = `i';
for (inti = 0; i< 5; i++) {
      for (int j = 0; j < 5; j++) {
      if (matrix[i][j] = = toupper(ch)) {return i;}
      }
   }
return -1; //If not found
}

intPlayFair::findCol (char ch)
{
  //Finding the specific row for a character
if (ch = = `j') ch = `i';
for (inti = 0; i< 5; i++) {
      for (int j = 0; j < 5; j++) {
      if (matrix[i][j] = = toupper(ch)) {return j;}
      }
   }
return -1; //If not found
}
stringPlayFair::encrypt (string str)
{
string output;

  //replace (by x) the repeating plaintext letters
that are in the same pair for (inti = 1; i<str.
length(); i = i + 2) {
      if (str[i-1] = = str[i]) {
      string temp1, temp2;

      for (int j = 0; j <i; j++) {
               temp1.push_back(str[j]);
        }

      for (int j = i; j <str.length(); j++) {
            temp2.push_back(str[j]);
      }
      str.clear();
      str = temp1 + `x' + temp2;
      }
}

for (inti = 0; i<str.length(); i = i + 2) {

          //for the letter pair falls in the same row if
          (findRow(str[i]) = = findRow(str[i+1])) {
          output.push_back(matrix[findRow(str[i])]
          [(findCol(str[i]) + 1)% 5]);
          output.push_back(matrix[findRow(str[i + 1])]
          [(findCol(str[i + 1]) + 1)% 5]);
          }
          //for the letter pair falls in the same
          column
          else if (findCol(str[i]) = =
          findCol(str[i+1])) {
          output.push_back(matrix[(findRow(str[i])
          + 1)% 5][findCol(str[i])]);
          output.push_back(matrix[(findRow(str[i + 1])
          + 1)% 5][findCol(str[i + 1])]);
          }

           //for other cases
          else {
          output.push_back(matrix[findRow(str[i])]
          [findCol(str[i + 1])]);
          output.push_back(matrix[findRow(str[i + 1])]
          [findCol(str[i])]);
          }
}

if ((str.length()% 2) ! = 0) {
           output[output.length() - 1] =
toupper(str[str.length() - 1]);
     }

return output;
}

stringPlayFair::decrypt (string str)
{
string output;

for (inti = 0; i<str.length(); i = i + 2) {
          //for the letter pair falls in the same row if
          (findRow(str[i]) = = findRow(str[i+1])) {
          int y;
          if ((findCol(str[i]) - 1) > = 0)
          y = (findCol(str[i]) - 1);
          else y = 4;
          output.push_back(matrix[findRow(str[i])]
          [y]);
          if ((findCol(str[i + 1]) - 1) > = 0)
          y = (findCol(str[i + 1]) - 1);
          else y = 4;
          output.push_back(matrix[findRow(str[i + 1])]
          [y]);
          }
          //for the letter pair falls in the same
          coloumn
          else if (findCol(str[i]) = =
          findCol(str[i+1])) {
          int x;
          if ((findRow(str[i]) - 1) > = 0) x =
          (findRow(str[i]) - 1);
          else x = 4;
          output.push_back(matrix[x][findCol(str[i])]);

          if ((findRow(str[i + 1]) - 1) > = 0) x =
          (findRow(str[i + 1]) - 1);
          else x = 4;
          output.push_back(matrix[x][findCol(str[i
          + 1])]);
          }

          //for other cases
          else {
          output.push_back(matrix[findRow(str[i])]
          [findCol(str[i + 1])]);
          output.push_back(matrix[findRow(str[i + 1])]
          [findCol(str[i])]);
          }
  }

   //remove x from the string
for (inti = 0; i<output.length(); i++) {
          if (output[i] = = `X') {
          output.erase(output.begin() + i);
          }
  }

return output;
}
int main () {
PlayFair pf;
string key, input;
  // Input the key to generate Playfair matrix
cout<< "Put key value (put alphabets/words): " <<endl;
getline(cin,key);
cout<< key <<endl;
  // Generating the Playfair matrix
pf.setKey(key);
pf.setMatrix();
pf.showMatrix();
  // Input the data to encrypt or decrypt
cout<< "Put your text " <<endl;
getline(cin,input);

cout<< "Press 1: Encrypt | 2: Decrypt" <<endl;
int choice;
cin>> choice;

if (choice = = 1) cout<<pf.encrypt(input) <<endl;
elsecout<<pf.decrypt(input) <<endl;
return 0;
}

2.3.3 Limitations

Even though Playfair is considerably complicated to break, it is still vulnerable to frequency analysis because it leaves some formation of plaintext intact. However, in the case of Playfair, frequency analysis will be applied on the 25*25 = 625 possible digraphs rather than the 25 possible monographs (i.e., in the case of monoalphabetic). Frequency analysis thus needs a lot of ciphertext in order to work. Therefore, assuming some of the words from the plaintext using the knowledge of area, time, or context of the message can be helpful for retrieving the key, and so far this is the simplest way to crack this cipher.

2.4 Polyalphabetic Cipher

A polyalphabetic substitution cipher is a series of simple substitution ciphers. It is used to change each character of the plaintext with a variable length. The Vigenère cipher is a special example of the polyalphabetic cipher.

In 1467, the Alberti cipher introduced by Leon Battista Alberti was the first polyalphabetic cipher. Typically, Alberti used a mixed set of alphabet for encryption, but that set was not fixed. Based on the requirement, he occasionally switched to a different alphabet set, including uppercase letters or numbers.

To reduce the effectiveness of frequency analysis on the ciphertext, the polyalphabetic cipher uses a collection of standard Caesar ciphers. Usually, the polyalphabetic cipher defines a text string (i.e., a word) as a key. In the case of encryption/decryption, this key is repeated until it reaches the length of the plaintext/ciphertext. An example is depicted in Table 2.4.

As can be observed from the table, the key run is repeated until it reaches the length of the plaintext. Now, the Vigenère table is utilized to find out the ciphertext that is illustrated in Table 2.5.

Table 2.4 Sample Polyalphabetic Encryption for Key Run

Plaintext

t

o

b

e

o

r

n

o

t

t

o

b

e

t

h

a

t

i

s

t

h

e

Key

r

u

n

r

u

n

r

u

n

r

u

n

r

u

n

r

u

n

r

u

n

r

Cipher

K

I

O

V

I

E

E

I

G

K

I

O

V

N

U

R

N

V

J

N

U

V

Table 2.5 Vigenère Table (Also Known as Tabula Recta)

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

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

A

C

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

A

B

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

A

B

C

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

A

B

C

D

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

A

B

C

D

E

G

H

I

J

K

L

M

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

A

B

C

D

E

F

H

I

J

K

L

M

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

A

B

C

D

E

F

G

I

J

K

L

M

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

A

B

C

D

E

F

G

H

J

K

L

M

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

A

B

C

D

E

F

G

H

I

K

L

M

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

A

B

C

D

E

F

G

H

I

J

L

M

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

A

B

C

D

E

F

G

H

I

J

K

M

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

A

B

C

D

E

F

G

H

I

J

K

L

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

A

B

C

D

E

F

G

H

I

J

K

L

M

O

P

Q

R

S

T

U

V

W

X

Y

Z

A

B

C

D

E

F

G

H

I

J

K

L

M

N

P

Q

R

S

T

U

V

W

X

Y

Z

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

Q

R

S

T

U

V

W

X

Y

Z

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

P

R

S

T

U

V

W

X

Y

Z

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

S

T

U

V

W

X

Y

Z

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

T

U

V

W

X

Y

Z

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

U

V

W

X

Y

Z

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

T

V

W

X

Y

Z

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

T

U

W

X

Y

Z

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

T

U

V

X

Y

Z

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

T

U

V

W

Y

Z

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

T

U

V

W

X

Z

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

Every plaintext letter tells the position of the row, and every keyword letter tells the position of the column. For instance, t is 20th in the alphabet and r is 18th in the English alphabet table. Therefore, t is substituted by the alphabet that is in row 20 and column 18 in the Vigenère table, i.e., K. In this way, all the plaintext letters are substituted. As can be observed from the table, the letter t is sometimes enciphered as a K and sometimes as a G since the relative key letter is once r and another time n.

In case of decryption, a similar table is utilized, but in a different way. First, the keyword letter needs to be found in the first row. After that, we have to trace down until the ciphertext letter is found. Once discovered, the plaintext letter is then found at the first column of that row.

2.4.1 Algorithm

Step 0: Select a multiple-letter key.

Step 1: To encrypt, the first letter of the key encrypts the first letter of the plaintext, the second letter of the key encrypts the second letter of the plaintext, and so on.

Step 2: When all letters of the key are used, start over with the first letter of the key.

Step 3: The decryption process is the reverse of step 1. The number of letters in the key determines the period of the cipher.

2.4.2 Implementation

#include <iostream>
#include <string>
#include <cmath>
using namespace std;

charvigenere_table[26][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',
`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', `A',
`C', `D', `E', `F', `G', `H', `I', `J', `K', `L', `M',
`N', `O', `P', `Q', `R', `S', `T', `U', `V', `W', `X',
`Y', `Z', `A', `B',
`D', `E', `F', `G', `H', `I', `J', `K', `L', `M', `N',
`O', `P', `Q', `R', `S', `T', `U', `V', `W', `X', `Y',
`Z', `A', `B', `C',
`E', `F', `G', `H', `I', `J', `K', `L', `M', `N', `O',
`P', `Q', `R', `S', `T', `U', `V', `W', `X', `Y', `Z',
`A', `B', `C', `D',
`F', `G', `H', `I', `J', `K', `L', `M', `N', `O', `P',
`Q', `R', `S', `T', `U', `V', `W', `X', `Y', `Z', `A',
`B', `C', `D', `E',
`G', `H', `I', `J', `K', `L', `M', `N', `O', `P', `Q',
`R', `S', `T', `U', `V', `W', `X', `Y', `Z', `A', `B',
`C', `D', `E', `F',
`H', `I', `J', `K', `L', `M', `N', `O', `P', `Q', `R',
`S', `T', `U', `V', `W', `X', `Y', `Z', `A', `B', `C',
`D', `E', `F', `G',
`I', `J', `K', `L', `M', `N', `O', `P', `Q', `R', `S',
`T', `U', `V', `W', `X', `Y', `Z', `A', `B', `C', `D',
`E', `F', `G', `H',
`J', `K', `L', `M', `N', `O', `P', `Q', `R', `S', `T',
`U', `V', `W', `X', `Y', `Z', `A', `B', `C', `D', `E',
`F', `G', `H', `I',
`K', `L', `M', `N', `O', `P', `Q', `R', `S', `T', `U',
`V', `W', `X', `Y', `Z', `A', `B', `C', `D', `E', `F',
`G', `H', `I', `J',
`L', `M', `N', `O', `P', `Q', `R', `S', `T', `U', `V',
`W', `X', `Y', `Z', `A', `B', `C', `D', `E', `F', `G',
`H', `I', `J', `K',
`M', `N', `O', `P', `Q', `R', `S', `T', `U', `V', `W',
`X', `Y', `Z', `A', `B', `C', `D', `E', `F', `G', `H',
`I', `J', `K', `L',
`N', `O', `P', `Q', `R', `S', `T', `U', `V', `W', `X',
`Y', `Z', `A', `B', `C', `D', `E', `F', `G', `H', `I',
`J', `K', `L', `M',
`O', `P', `Q', `R', `S', `T', `U', `V', `W', `X', `Y',
`Z', `A', `B', `C', `D', `E', `F', `G', `H', `I', `J',
`K', `L', `M', `N',
`P', `Q', `R', `S', `T', `U', `V', `W', `X', `Y', `Z',
`A', `B', `C', `D', `E', `F', `G', `H', `I', `J', `K',
`L', `M', `N', `O',
`Q', `R', `S', `T', `U', `V', `W', `X', `Y', `Z', `A',
`B', `C', `D', `E', `F', `G', `H', `I', `J', `K', `L',
`M', `N', `O', `P',
`R', `S', `T', `U', `V', `W', `X', `Y', `Z', `A', `B',
`C', `D', `E', `F', `G', `H', `I', `J', `K', `L', `M',
`N', `O', `P', `Q',
`S', `T', `U', `V', `W', `X', `Y', `Z', `A', `B', `C',
`D', `E', `F', `G', `H', `I', `J', `K', `L', `M', `N',
`O', `P', `Q', `R',
`T', `U', `V', `W', `X', `Y', `Z', `A', `B', `C', `D',
`E', `F', `G', `H', `I', `J', `K', `L', `M', `N', `O',
`P', `Q', `R', `S',
`U', `V', `W', `X', `Y', `Z', `A', `B', `C', `D', `E',
`F', `G', `H', `I', `J', `K', `L', `M', `N', `O', `P',
`Q', `R', `S', `T',
`V', `W', `X', `Y', `Z', `A', `B', `C', `D', `E', `F',
`G', `H', `I', `J', `K', `L', `M', `N', `O', `P', `Q',
`R', `S', `T', `U',
`W', `X', `Y', `Z', `A', `B', `C', `D', `E', `F', `G',
`H', `I', `J', `K', `L', `M', `N', `O', `P', `Q', `R',
`S', `T', `U', `V',
`X', `Y', `Z', `A', `B', `C', `D', `E', `F', `G', `H',
`I', `J', `K', `L', `M', `N', `O', `P', `Q', `R', `S',
`T', `U', `V', `W',
`Y', `Z', `A', `B', `C', `D', `E', `F', `G', `H', `I',
`J', `K', `L', `M', `N', `O', `P', `Q', `R', `S', `T',
`U', `V', `W', `X',
`Z', `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'
};

void Encrypt (string in, string &out, string k) {
inti = 0;
for (string :: iterator it = in.begin(); it ! =
in.end(); it++) {
if (*it ! = ` `) {
int row = toupper(*it) - `A';
int column = toupper(k[i% k.length()]) - `A';
out + = vigenere_table[row][column];
     }
else {
out + = ` `;
     }

i++;
   }

}

void Decrypt (string in, string &out, string k) {
inti = 0;
for (string :: iterator it = in.begin(); it ! =
in.end(); it++) {
if (*it ! = ` `) {
int column = toupper(k[i% k.length()]) - `A';
int row;
for (row = 0; row < 26; row++) {
if (vigenere_table[row][column] = = *it) break;
        }
out + = `A' + row;
     }
else {
out + = ` `;
      }
i++;
 }
}

int main ()
{
string input, output, key;
         cout<< "Put key value (put alphabets/words): ";
getline(cin,key);
int choice = 0;

while (choice ! = 3) {
cout<<endl<< "Press 1: Encryption, 2: Decryption; 3:
quit: " ;

try {
cin>> choice;
cin.ignore();
if (choice ! = 1 && choice ! = 2 && choice ! = 3)
throw "Incorrect Choice";
      }
catch (const char* chc) {
cerr<< "INCORRECT CHOICE !!!!" <<endl;
return 1;
     }
if (choice = = 1 || choice = = 2) {
try {
cout<<endl<< "Enter cipertext (only alphabets) and
press enter to continue: ";
getline(cin, input);

for (inti = 0; i<input.size(); i++) {
if ((!(input[i] > = 'a' && input[i] < = 'z')) &&
(!(input[i] > = 'A' && input[i] < = 'Z')) &&
(!(input[i] = = ' ')))
throw "Incorrect string";
         }
      }
catch (const char* str) {
cerr<< "YOUR STRING MAY HAVE DIGITS OR SPECIAL SYMBOLS
!!!" <<endl;
cerr<< "PLEASE PUT ONLY ALPHABETS !!! " <<endl;
return 1;
       }
if (choice = = 1) {
Encrypt(input, output, key);
cout<<endl<< "Cipher text: " << output <<endl;
       }
else if (choice = = 2) {
input = output;
output.clear();
Decrypt(input, output, key);
cout<<endl<< "Plain text: " << output <<endl;
       }
   }

  }
return 0;
}

2.4.3 Limitations

Even though polyalphabetic is more secure than simple substitution cipher, it can still be broken by analyzing the period. In the above example, KOIV is repeated after nine letters, and NU is repeated after six letters. So the period being 3 is a good assumption here, as 3 is a common divisor of 6 and 9. Frequency analysis is applicable here again by knowing which letters were encoded with the same key.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.225.72.245