Top Banner
Encryption & Error Checking Encryption Encryption, what the...? Yeah that's right, encryption, A Great Way to secure your privacy. Ok, you just got a new job and you are now quite comfortable with it? You download a couple of tools but there is one that catches your eye. It asks you to enter the Filename of the file you want to encrypt so you do as it says, and pick your co-worker‟s business file, work.dat it loads for a while and then says, encryption complete, you feel as though you could take on an army. Two days later, your co-worker is unable to complete his job for work and loses his job, you innocently deny the events that ruined up his data file. But deep down you feel guilty, you hate encryption and never want to see it again. Wrong! 'MOST' encryption programs are released with a 'decryptor'. You ARE able to turn your co-worker‟s work back into readable format! Ok, encryption turns your files into useless code that's unreadable, ready to continue on? The Basic Algorithm Ask for file1 to be encrypted. Ask for file2 to output encrypted data too. Encrypt file1 and save as file2, leave file1 untouched. Example Code (general encryption) FILE *stream1, *stream2; if((stream1 = fopen(argv[1], "rb")) == NULL) { /*ERROR*/ } if((stream2 = fopen(argv[2], "wb")) == NULL) { /* ERROR*/} encrypt(file1,file2); END C!
25

3 Encryption Error Checking

Apr 08, 2015

Download

Documents

Anubha Yadav
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 3 Encryption Error Checking

Encryption & Error Checking

Encryption

Encryption, what the...?

Yeah that's right, encryption, A Great Way to secure your privacy. Ok, you just got a new job

and you are now quite comfortable with it? You download a couple of tools but there is one that

catches your eye. It asks you to enter the Filename of the file you want to encrypt so you do as it

says, and pick your co-worker‟s business file, work.dat it loads for a while and then says,

encryption complete, you feel as though you could take on an army.

Two days later, your co-worker is unable to complete his job for work and loses his job, you

innocently deny the events that ruined up his data file. But deep down you feel guilty, you hate

encryption and never want to see it again.

Wrong! 'MOST' encryption programs are released with a 'decryptor'. You ARE able to turn your

co-worker‟s work back into readable format! Ok, encryption turns your files into useless code

that's unreadable, ready to continue on?

The Basic Algorithm

Ask for file1 to be encrypted.

Ask for file2 to output encrypted data too.

Encrypt file1 and save as file2, leave file1 untouched.

Example Code (general encryption)

FILE *stream1, *stream2;

if((stream1 = fopen(argv[1], "rb")) == NULL) { /*ERROR*/ }

if((stream2 = fopen(argv[2], "wb")) == NULL) { /* ERROR*/}

encrypt(file1,file2);

END C!

Page 2: 3 Encryption Error Checking

What was that above???

stream1 and 2 are simply pointers to of type FILE

argv[1] is the commandline parameter passed to programs in MS-Dos.

example:

program file1 file2 key

file1 is argv[1]

program is argv[0]

file2 is argv[2] and key is argv[3]

Ok so we know how to accept parameters! Or do we? Here's an example help you understand:

#include <cstdio>

int main(int argc, char *argv[])

{

printf("Parameter 1 is %s, 2 is %s.\n", argv[1], argv[2]);

printf("Program name is %s.\n", argv[0];

printf("Number of parameters: %d\n", argc);

return 0;

}

Enter the Binary

As you already know binary is the only language the computer really understands. Although you

may type some programs up and compile them, wether it be C++, asm, delphi, vb, fortran or

your neighbour‟s carrot tree, your computer does not read what you tell it to, I know it sucks, but

its the truth. All your pretty little code is converted into a jumble of 1's and 0's.

DO you remember the binary number system?

Page 3: 3 Encryption Error Checking

BINARY NUMBER SYSTEM:

Decimal - Binary

1 0001

2 0010

3 0011

4 0100

5 0101

6 0110

7 0111

8 1000

16 10000

32 100000

64 1000000

128 10000000

256 100000000

How about Logical AND

The 'And' operator in C is '&'. & will only return 1 when both bits are 1.

Logical XOR

Input Output

0 0 0

0 1 0

1 0 0

1 1 1

Input Output

0 0 0

0 1 1

1 0 1

1 1 0

Page 4: 3 Encryption Error Checking

One’s Complement

By applying ones compliment to the decimal number 21845 each bit in this number will be

inversed.

21845 = 10101010 1010101

Hence applying One‟s Complement we get

10101010 10101010 = 42945450

In C, we apply the ~ operator to decimal 21845

XOR is good for encryption because applying it with the old value it was XORED with turns the

bits back into their previous value:

Example-

We have two characters:

'a' and 'b'

We want to encrypt 'a' by XORing the bits of 'b' into it.

Do this:

int encrypted;

char a,b;

a = 'a';

b = 'b';

encrypted = a ^ b;

Which will yield this result:

'a' = 97 which is 01100001 in binary

'b' = 98 which is 01100010

encrypted now equals: 00000011

Page 5: 3 Encryption Error Checking

But were learning how to decrypt as well right? Sure are, to restore the value 'a' to its original

unencrypted state we simple XOR the encrypted value with 'b' again:

int new;

new = encrypted ^ b;

which gives us this binary number: 01100001 which is, you guesses it, 'a'!... WOW

So now we know the basic component behind the XOR encryption of characters. Continue on to

learn various other methods of encryption.

Ancient Cryptography

Back in the days of World War II and even before that, ancient methods of cryptography have

been passed down from generation to generation. The following is just a few of them:

I. ROT13 - A popular method of hiding text so that only people who actually take

the time to decode it can actually read it. You swap letters; A becomes N, and N

becomes A. It was quite popular on bulletin board systems and Usenet

newsgroups. You can do it with the cryptogram solver also, if you make A=N,

B=O, C=P, etc.

II. Caesarian Shift - Where ROT13 was based on you adding 13 to the letters, a

Caesar cipher lets you add an arbitrary value. Again, you can do it with the

cryptogram solver, but you can scroll through values of N pretty easily with this

tool.

III. Atabash - A very simplistic cipher where you change A into Z, B into Y, and so

on.

Page 6: 3 Encryption Error Checking

Ancient Methods in recent programming

Rot 13

What is Rot13 encryption?

Rot13 simple means rotating alphabet by 13 characters. It is a very primitive encryption method

which can be easily decrypted on knowledge. But for a non-technical user it still remains an

unsolved mystery. Rot13 encryption is very easy to understand and use. It is very similar to the

Caesar-Encryption method. Here what we do is rotate the character backwards or front by 13

characters in the ASCII table. The means "a" becomes "n" and "p" becomes "}". This method has

been used in many news delivery systems as to prevent third parties from gaining easy access to

it in the past. But now there are many better encryption systems being used which remain hard to

be decrypted. Rot13 uses very simple algorithms and the encryption/decryption functions can be

easily made.

Just below is the code that performs this operation by taking only the characters and shifts it 13

places alphabetically, while integers and any other input are left as they were. Ensure that you go

through each line carefully to understand the basic functionality of the program.

#include<stdio.h>

int ROT = 13;

int main(void)

{

int c,e;

while((c=getchar())!=EOF)

{

if(c >='A' && c <='Z')

{

if((e = c + ROT) <= 'Z')

putchar(e);

else

{

e = c - ROT;

putchar(e);

}

}

else if(c >='a' && c <='z')

{

if((e= c + ROT) <= 'z')

putchar(e);

else

{

e = c - ROT;

putchar(e);

Page 7: 3 Encryption Error Checking

}

}

else

putchar(c);

}

return 0;

}

putchar is a function in the C programming language that writes a single character to the

standard output stream, stdout. Now you can add the provided rot13.cpp file to a new project on

Microsoft Visual Studio and Run. You will see the command window appear (blank of course)

awaiting your message to be coded. Enter any message you like, e.g. your name, and see what

happens (WOW!)

Of course with an encoded message, the receiver would like to be able to decode it without

having to sift through each letter and rotate them by 13 places. How many letters does the

alphabet have? ___ 13 x 2 = ___ so if you rotate the encoded message characters by 13

places you should get.....(drum roll) The original message . So the decoding program is the

same as the encoding, you can see this for yourself by re-running the code and retyping the

encoded characters.

Given the code above, if you were to “copy and paste” it into Microsoft Visual Studio, it would

compile and run without errors.

So your mission is to now ask the user for an input and give the encrypted output. When this is

finished you now realize that the encryptor is a decryptor and can be used as any.

Caesarian Shift

In cryptography, a Caesar cipher, also known as a Caesarian shift, is one of the simplest and

most widely known encryption techniques. It is a type of substitution cipher in which each letter

in the plaintext is replaced by a letter some fixed number of positions down the alphabet. For

example, with a shift of 3, A would be replaced by D, B would become E, and so on. The

method is named after Julius Caesar, who used it to communicate with his generals.

The encryption step performed by a Caesar cipher is often incorporated as part of more complex

schemes, such as the Vigenère cipher, and still has modern application in the ROT13 system. As

with all single alphabet substitution ciphers, the Caesar cipher is easily broken and in practice

offers essentially no communication security.

Page 8: 3 Encryption Error Checking

This method is as simple as ROT 13 in that the algorithm that it takes to encode a message is the

simplest as can be. The code below is a clear example of this.

#include <iostream>

#include <string.h>

using namespace std;

int main()

{

char str1[80];

int i = 0;

int offset;

cout << "What do you want your password to be?\n";

cin >> str1;

cout << "What do you want your offset number to be?\n";

cin >> offset;

while(i<strlen(str1)){

str1[i] = int(str1[i]) + offset;

i++;

}

cout << str1<<endl;

return 0;

}

Since [Message + Offset = Encrypted Text]

Come up with your Caesarian Shift Decryptor. Write the program below.

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

Page 9: 3 Encryption Error Checking

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

Vigenère cipher

The Vigenère cipher is named for Blaise de Vigenère, although Giovan Battista Bellaso had

invented the cipher earlier. Vigenère did invent a stronger autokey cipher.The Vigenère cipher is

a method of encrypting alphabetic text by using a series of different Caesar ciphers based on the

letters of a keyword. It is a simple form of polyalphabetic substitution.

The Vigenère cipher has been reinvented many times. The method was originally described by

Giovan Battista Bellaso in his 1553 book La cifra del. Sig. Giovan Battista Bellaso; however, the

scheme was later misattributed to Blaise de Vigenère in the 19th century, and is now widely

known as the "Vigenère cipher".

This cipher is well known because while it is easy to understand and implement, it often appears

to beginners to be unbreakable; this earned it the description le chiffre indéchiffrable (French for

'the unbreakable cipher'). Consequently, many people have tried to implement encryption

schemes that are essentially Vigenère ciphers, only to have them broken.

This type of encryption is a little more difficult to „break‟ for any average whiz-kid but still the

algorithm is simple for you to have invented it yourself if you were living in Blaise de Vigenère

days.

The code below shows a program that can encrypt a message using the Vigenère cipher method

and decrypt as well. Ensure that you go through each line and understand carefully the

functionality.

#include <iostream>

#include <string>

using namespace std;

int main(int argc, char *argv[])

{

int mode,crypt,i = 0,z = 0;

char text[256],key[256],key2[256];

cout << "* Vigenere Cipher *" << endl;

cout << "Encrypt(1) or Decrypt(0)?: ";

Page 10: 3 Encryption Error Checking

cin >> mode;

if (argc)

{

cout << "Enter text: ";

cin >> text;

cout << "Enter key: ";

cin >> key;

}

while(string(key).length() < string(text).length())

{

strcpy(key2, key);

strcat(key, key2);

}

switch(mode)

{

case 1: // Encryption

while(text[i] != '\0')

{

crypt = int(text[i]) + int(key[z]) - 150;

cout << char(crypt);

if (z > string(key).length())

{

z = 0;

}

z++;

i++;

}

cout << "\n";

break;

case 0: // Decryption

while(text[i] != '\0')

{

crypt = int(text[i]) - (int(key[z]) - 150);

cout << char(crypt);

if (z > string(key).length())

{

z = 0;

}

z++;

i++;

}

cout << "\n";

break;

default: // Error

cout << "Incorrect value.";

break;

cout << "\n";

}

system("PAUSE");

return 0;

}

See the provided Vigenere.cpp file provided and run it with Visual C++ 2008. If run into any

problems the TA will be pleased to assist you in any way they can. Write your algorithm for the

code provided above.

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

Page 11: 3 Encryption Error Checking

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

Page 12: 3 Encryption Error Checking

Error Checking

Recursion Technique

This piece was extracted from

http://www.codeproject.com/KB/cpp/Recursion_Prmr_CPP_01.aspx

Introduction

In general, recursion means self repeating patterns. In Mathematics, it can be a function that is

defined in terms of itself, such as factorial, Fibonacci etc. In computer programming, recursion

means a function that is defined in terms of itself. In other words, a function that calls itself.

Every recursive function has a termination condition; otherwise, it will call itself forever, and

this condition can be called the base condition.

In C++, the types of recursion can be defined in more than one dimension. In one dimension, it

can be categorized as runtime recursion and compile time recursion using template meta-

programming.

Runtime recursion is the most common recursion technique used in C++. This can be

implemented when a C++ function (or member function) calls itself. In C++, we can also do

compile time recursion with the help of template meta-programming. When you instantiate a

template class (or structure) in C++, the compiler will create the code of that class at compile

time. Just like runtime recursion, we can instantiate the template class itself to perform the

recursion. Similarly, we also need the termination condition; otherwise, instantiation will go

forever, at least theoretically, but, of course, limited to the resources of the computer and the

compiler. In template meta-programming, we can specify the termination condition (or base

condition) with the help of template specialization or partial template specialization, depending

on the termination condition.

The other way to look at recursion is how a recursive algorithm is implemented. Recursive

algorithms can be implemented in more than one way, such as linear, tail, mutual, binary, or

nested recursion. We can implement them either at compile time using template meta-

programming, or at runtime using functions or member functions. For ECNG 2007 we will be

focusing on the runtime recursion technique.

Page 13: 3 Encryption Error Checking

We can represent the different types of recursion using the following diagram. This diagram

shows the different types of recursion based on their implementation (i.e., linear, tail, mutual

etc.) and when it will be performed.

Linear Recursion

Linear recursion is the simplest form of recursion, and perhaps the most commonly used. In this

recursion, a function simply calls itself until it reaches the termination condition (also known as

the base condition); this process is known as winding. After calling the termination condition, the

execution of the program returns to the caller; this is known as unwinding.

Functions may perform some additional tasks during winding or unwinding, such as in the case

of the factorial function, it will multiply the input number with the return value of the function

during the unwinding phase. This process can be demonstrated with the following diagram that

shows both the winding and unwinding phase of the factorial function using linear recursion.

Page 14: 3 Encryption Error Checking

Mathematically, we can write the factorial function recursively this way, i.e., when the value of

“n” is zero, then return one, and when the value of “n” is greater than zero, then call the function

recursively with “n-1” and multiply the result with the return value of the recursive function.

1 0

( )* ( 1) 0

nf n

n f n n

int Factorial(int no)

{

// error condition

if (no < 0)

return -1;

// termination condition

if (0 == no)

return 1;

// linear recursive call

return no * Factorial(no - 1);

}

Winding Process:

Function called Function return

Page 15: 3 Encryption Error Checking

Fact(6) 6*Fact(5)

Fact(5) 5*Fact(4)

Fact(4) 4*Fact(3)

Fact(3) 3* Fact(2)

Fact(2) 2* Fact(1)

Fact(1) 1* Fact(0)

Terminating Point

Fact(0) 1

Unwinding Process

Fact(1) 1*1

Fact(2) 2*1

Fact(3) 3*2*1

Fact(4) 4*3*2*1

Fact(5) 5*4*3*2*1

Fact(6) 6*5*4*3*2*1

The above program is a runtime version of linear recursion. Here, we have a termination

condition of 0, and this program starts unwinding when it reaches the termination condition.

There is one more error condition in this program to prevent infinite function calls if someone

passes a negative number to this function. This function will simply return -1 as an error if the

value of the parameter is negative.

Page 16: 3 Encryption Error Checking

Tail Recursion

Tail recursion is a specialized form of linear recursion where the recursive function call is

usually the last call of the function. This type of recursion is usually more efficient because a

smart compiler will automatically convert this recursion into a loop to avoid nested function

calls. Because a recursive function call is usually the last statement of a function, there isn‟t any

work done during the unwinding phase; instead, they simply return the value of the recursive

function call. Here is an example of the same program converted to tail recursion.

We can define the tail recursion mathematically using this equation, i.e., when the value of “n” is

zero, then simply return the value of “a”; if the value of “n” is greater than zero, then call the

recursive function by passing “n-a” and “n*a”. Here, you can also notice that during the

unwinding phase, every recursive function simply returns the value of “a”.

0

( , )( 1, * ) 0

a nf n a

f n n a n

int Factorial(int no, int a)

{

// error condition

if (no < 0)

return -1;

// termination condition

if (0 == no || 1 == no)

Page 17: 3 Encryption Error Checking

return a;

// Tail recursive call

return Factorial(no - 1, no * a);

}

This is a modified version of the linear recursion program. Here, we perform all the calculations

before calling the recursive function, and simply return whatever value we got from the recursive

function. Here, the calculation order is the reverse of the linear recursion. In linear recursion, we

first multiply 1 with 2, then its result with 3, and so on; on the other hand, here we multiply n

with n-1, then with n-2, until we reach 0.

Tail recursion is very useful and sometimes unavoidable in functional languages, because they

might not have a looping construct. They usually perform the looping with the help of tail

recursion. You can do almost everything with tail recursion that can be done with looping, but

this is usually not true in reverse. Here is a very simple example to demonstrate looping via tail

recursion:

// implement looping via tail recursion

// simple version

void RecursiveLoop(int n)

{

// termination condition

if (0 == n)

return;

// action to be performed

cout << n << endl;

// tail recursive call

return RecursiveLoop(--n);

}

Page 18: 3 Encryption Error Checking

Binary Recursion

In binary recursion, the recursive function calls itself twice, not once. This type of recursion is

very useful in some data structures like traversing a tree in prefix, postfix, or infix order,

generating Fibonacci numbers etc.

Binary recursion is a specific form of exponential recursion where one function calls the

recursive function more than once (in case of binary, two). In other words, recursive functions

call exponentially in this type of recursion.

Mathematically, we can define the Fibonacci sequence as:

0 0

( ) 1 1

( 1) ( 2) 1

n

F n n

F n F n n

int Fib(int no)

{

// error condition

if (no < 1)

return -1;

// termination condition

if (1 == no || 2 == no)

return 1;

// binary recursive call

return Fib(no - 1) + Fib(no - 2);

}

Here is a simple implementation of Fibonacci numbers calling the recursive function twice. Here

we have two base cases, when the value of input parameter is 1 and 2. This is, of course, not the

Page 19: 3 Encryption Error Checking

best implementation of Fibonacci numbers, and we can convert it into tail recursion by changing

it a little bit.

int Fib(int n, int a, int b)

{

// termination condition

if (1 == n)

return b;

else

// tail recursive call

return Fib(n-1, b, a+b);

}

Here, we convert binary recursion into tail recursion. We simply perform the calculation before

calling any recursive function, therefore we do not need to call the recursive function twice. In

Fibonacci numbers, we always need the last two numbers, so after performing the calculation on

the last two numbers, we just discard the first one, i.e., “a”, and replace the second one in place

of the first, i.e., place the value of “b” in “a”, and calculate the next number.

Mathematically, we can define this as:

1

( , , )( 1, , ) 1

b nF n a b

F n b a b n

Page 20: 3 Encryption Error Checking

Error checking using Recursion

Here is a decent program that accepts the user input based on the type and within certain range

and acknowledges the type only to return the exact same input. Could you decipher what type of

recursion is used here?

/*

Purpose: To get an integer input from the user

Accepts: msg - display message

Min - smallest acceptable value

Max - largest acceptable value

quit - vaue to force quit on return

*/

#include <cstdlib>

#include <iostream>

using namespace std;

int getUserInput ( const char* msg , const int min , const int max , const int quit );

char getUserInput ( const char* msg , const char min , const char max , const char quit );

int main(int argc, char *argv[])

{

int t = getUserInput ( "Enter an integer" , 0 , 10 , -1 );

if ( t != -1 )

cout << " Integer entered is: " << t << endl;

char c = getUserInput ( "Enter a letter" , 'A' , 'z' , '0' );

if ( c != '0' )

cout << "Letter entered is: " << c << endl;

system("PAUSE");

return EXIT_SUCCESS;

}

int getUserInput ( const char* msg , const int min , const int max , const int quit )

{

int input;

do {

cout << msg << " (Range: " << min << " to " << max << " , quit= " << quit << "): ";

cin >> input;

} while ( input != quit && ( input < min || input > max ) );

return input;

}

/*

Purpose: To get a char input from the user

Accepts: msg - display message

Min - smallest acceptable value

Max - largest acceptable value

quit - vaue to force quit on return

*/

char getUserInput ( const char* msg , const char min , const char max , const char quit )

{

char input;

do {

cout << msg << " (Range: " << min << " to " << max << " , quit= " << quit << "): ";

cin >> input;

} while ( input != quit && ( input < min || input > max ) );

return input;

}

Page 21: 3 Encryption Error Checking

Could you decipher what type of recursion is used here? Explain your findings.

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

______________________________________________________________________________

Page 22: 3 Encryption Error Checking

Reviewing and Moving On

So let‟s see what we‟ve done so far.

The first type of encryption technique that we‟ve been introduced to is that of substitution

techniques. For example, the Caesar cipher which allow that we replace each letter of the

alphabet with the letter standing three places further down in the alphabet. This was the simplest

substitution cipher, and was made famous by its use by Julius Caesar. For example:

Plain: meet me after the toga party

Cipher: PHHW PH DIWHU WKH WRJD SDUWB

Note that the alphabet is wrapped around, so when we reach Z, we wrap back around to A.

Can you write a function which takes a string as its parameter and utilizes a loop to produce and

return an encrypted string. Write that function of the form:

string encrypt_caesar_loop(string toEncrypt);

Can you write an equivalent function which does the same by way of recursion?

string encrypt_caesar_recursion(string toEncrypt);

Moving right along now, another form of substitution cipher is that of the monoalphabetic

ciphers. With only 25 possible keys, the Caesar cipher discussed so far is far from secure. A

dramatic increase in the key space can be achieved by allowing an arbitrary substitution. So

instead the cipher line may be any permutation of the 26 alphabetic characters, which means that

there are 26! different possibilities, or greater than 4x1026

possible keys. This approach is known

as a monoalphabetic substitution cipher, because a single cipher alphabet (mapping from plain

alphabet to cipher alphabet) is used per message.

However, there is a line of attack. If the cryptanalyst knows the nature of the plaintext, then the

analyst can exploit the regularities of the language. For example, with English, the most used

letter is the letter „E‟ and when a single letter is used, it is usually the letter A or the letter I.

There are dedicated techniques to exploiting this in order to overcome such encryption

techniques.

How would you go about writing a function which would arbitrarily encrypt along this

technique?

Page 23: 3 Encryption Error Checking

Hint: You can utilize an array lookup. If we treat with the letter „a‟ being the first indexing

position, we can compute an index location within a 26 character array by subtracting „a‟ from

our letter (to get 0 offset). Think carefully what I mean by this and see if you can write functions

of the form:

char lookup_encrypted_char(char someChar);

which would lookup within an array the encrypted character and another function:

string encrypt_mono_loop(string toEncrypt)

which utilizes a loop and the array lookup function to return an encrypted string.

Another early encryption technique is known as the playfair cipher. This technique is perhaps the

best known multiple letter encryption cipher. This treats diagrams in the plaintext as single units

and translates them into ciphertext diagrams. The playfair algorithm is based on the use of 5x5

matrix of letters constructed using a keyword. Here is an example, solved by Lord Peter Wimsey

in Dorothy Sayer‟s Have His Carcase:

M O N A R

C H Y B D

E F G I/J K

L P Q S T

U V W X Z

In this case, the keyword is monarchy. The matrix is constructed by filling in the letters of the

keyword (minus duplicates) from left to right and from top to bottom, and then filling in the

remainder of the matrix with the remaining letters in alphabetic order. The letters I and J count as

one letter. Plaintext is encrypted two letters at a time according to the following rules:

1. Repeating plaintext letters that would fall in the same pair are separated with a filler

letter, such as x, so that the word balloon would be treated as: ba lx lo on

Page 24: 3 Encryption Error Checking

2. Plaintext letters that fall in the same row of the matrix are each replaced by the letter to

the right, with the first element of the row circularly following the last. For example, ar is

encrypted as RM.

3. Plaintext letters that fall in the same column are each replaced by the letter beneath with

the top element of the row circularly following the last. For example, mu is encrypted as

CM.

4. Otherwise, each plaintext letter is replaced by the letter that lies in its own row and the

column occupied by the other plaintext letter. Thus hs becomes BP and ea becomes IM

(or JM as the encipherer wishes).

This is a pretty simple algorithm that was thought of as being near unbreakable during WW2. It

was thus used as the standard field system by the British army during the war and still enjoyed

considerable use by the US and other Allied forces during the war.

Despite this level of confidence in its security, the Playfair cipher is relatively easy to break

because it still leaves much of the structure of the plaintext language intact. A few hundred

letters of ciphertext are generally sufficient to crack the cipher.

Can you write a function that is of the form:

string encrypt_playfair (string toEncrypt)

that would implement the above algorithm for Lord Peter Wimsey‟s solution?

What we have considered above are some simple substitution encryption techniques.

Another type of encryption technique is that of transposition. While substitution techniques

involve the substitution of a ciphertext symbol for a plaintext symbol, a very different type of

mapping is achieved by performing some sort of permutation on the plaintext letters. This

technique is known as a transposition cipher.

The simplest form of such a cipher is the rail fence technique. The plaintext is written down as a

sequence of diagonals and then read off as a sequence of rows. For example, to encipher the

message: meet me after the toga party with a rail fence of depth 2:

Page 25: 3 Encryption Error Checking

m e m a t r h t g p r y

e t e f e t e o a a t

And thus the encrypted message becomes:

MEMATRHTGPRYETEFETEOAAT

This sort of thing would be trivial to cryptanalyze, and thus a more complex scheme may be to

write the message in a rectangle, row by row, and read the message off, column by column, and

read the message off, column by column, but permute the order of the columns. The order of the

columns then becomes the key to the algorithm. For example:

Key: 4 3 1 2 5 6 7

A T T A C K P

O S T P O N E

D U N T I L T

W O A M X Y Z

Thus the ciphertext becomes:

TTNAAPTMTSUOAODWCOIXKNLYPETZ

Can you write a function of the following prototype that would take as a string as input and

utilize this technique as it is presented here?

string encrypt_transposition(string toEncrypt)

To conclude, the above information that is presented here considered some rather simple

encryption techniques. There are many more encryption techniques which have far superior

levels of security, and also far greater levels of difficulty to implement. However, the basic idea

here is to apply your programming techniques in order to implement the above given algorithms.

All techniques given here can be written as functions utilizing loops and recursive techniques.