0% found this document useful (0 votes)
93 views10 pages

Parallel Programming Project Report

The document discusses the history and types of secret writing techniques. It begins by explaining the basic components of encryption - the plaintext, ciphertext, encryption, and decryption. It then discusses different approaches like steganography (hiding messages), codes (replacing words with other words), and ciphers (replacing letters). The document proceeds to provide examples of specific ciphers like the Caesar cipher (shifting the alphabet) and Vigenère cipher (using a keyword to shift letters). It concludes by outlining how the Vigenère cipher can be broken by looking for common trigrams if the keyword length is known.

Uploaded by

Waleed Amir
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
93 views10 pages

Parallel Programming Project Report

The document discusses the history and types of secret writing techniques. It begins by explaining the basic components of encryption - the plaintext, ciphertext, encryption, and decryption. It then discusses different approaches like steganography (hiding messages), codes (replacing words with other words), and ciphers (replacing letters). The document proceeds to provide examples of specific ciphers like the Caesar cipher (shifting the alphabet) and Vigenère cipher (using a keyword to shift letters). It concludes by outlining how the Vigenère cipher can be broken by looking for common trigrams if the keyword length is known.

Uploaded by

Waleed Amir
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 10

Introduction

Secret writing has been used for thousands of years; probably for as long as we have had secrets to
keep. These may be messages in war, messages between corporations, or just personal secret messages.
Even languages may be thought of as a kind of code. When we send secret messages there are three
types of participants. The sender, the intended recipient or receiver, and possibly the interceptor or ‘bad
guy’. The act of disguising your message is known as encryption, and the original message is called the
plaintext. The encrypted plaintext is known as the ciphertext (or cryptogram), and the act of turning the
ciphertext back into the original plaintext is decryption. Steganography is the act of physically hiding
your message; in ancient times you might write your message on the shell of a boiled egg using special
ink that would soak through the porous outer shell. When the egg was cracked and peeled, your secret
message would be found written on the egg white. In the 20th century, agents involved in espionage
would use the microdot, shrinking their entire message smaller than could be seen by the naked eye.
Codes on the other hand involve turning words or phrases into other words. For example, a command
such as ‘attack at midnight’ might simply become ‘eagle’. The problem with codes is that they involve
carrying a codebook, essentially a dictionary, to translate what you want to say into code. If this book
falls into enemy hands then your code is revealed and is now useless, and replacing each code book is
not something that can be done frequently. Also, a code may not have the flexibility to deal with all
messages you might conceivably wish to send. In comparison, ciphers work on the level of the individual
letters of your message. Ciphers may replace letters in a message with other letters, or numbers, or
symbols. For example, if ‘a’ becomes 0, ‘b’ becomes 1, ‘c’ becomes 2 and so on, then a word like ‘secret’
becomes ‘18 4 2 17 4 19’. (Note, counting from ‘a’ as zero is a necessary convention that we will
continue to use later on). This provides a much greater flexibility in our messages. Ciphers comes in two
parts: The first part is the algorithm; this is simply the method of encryption. The second part is the key.
The idea is these work together like a lock-and-key and, for the code breaker, having one without the
other is just half the problem. The key may change frequently meaning the greater the number of keys
the more difficult the cipher becomes break by brute force (an exhaustive check of all possible keys).
Secret writing has always been a constant struggle between the code maker and the code breaker.
Cryptography is the study of making secret messages, whereas cryptanalysis is the study of breaking
those secret messages. Cryptology is the collective name for both cryptography and cryptanalysis; the
word cryptology coming from the Greek words kryptos meaning hidden and logos meaning word.

1 Monoalphabetic Ciphers 1.1 The Caesar Shift We begin with a simple cipher as described by Julius
Caesar in the Gallic Wars. In it he describes taking two alphabets, from a to z, one above the other.
However, the second alphabet is shifted three places to the left. The top alphabet represents letters in
the plaintext, while the the alphabet underneath shows what these letters become in the ciphertext.
Note, throughout this course I will represent the plaintext in lowercase letters, and the ciphertext in
uppercase letters. plaintext 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 ciphertext 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 So, a plaintext message like veni, vidi, vici becomes YHQL, YLGL, YLFL in the
ciphertext. Clearly, the shift does not have to be 3, (it can be 4, 5, etc). The idea of shifting the alphabet
is the algorithm, and the size of the shift is the key. This is not a very secure cipher since there are only
26 keys (including plain English when you shift by 26). This cipher can be quickly broken by a simple
exhaustive check of all 26 possible keys. (The original strength of this cipher may have come from
Caesar’s enemies not realising he was using a cipher at all). A set is a collection of objects (numbers,
letters, symbols, or other objects). Let A denote the set of letters alphabet a, b, c, ..., z. Let P denote the
alphabet of the plaintext, usually P = A. Let C denote the ciphertext alphabet, this set may or may not be
the same as A. A monoalphabetic cipher is a rule which associates each letter of P with a unique letter in
C. Furthermore, different letters in P are sent to different objects in C. This means the size of C is equal
to or greater than the size of P, and each letter in P is paired with an image in C. This will allow us to
define an inverse rule from C to P that will decrypt our messages from the ciphertext back to the original
plaintext

Vigen`ere Cipher
The following cipher is named after the 16th century French diplomat Blaise de Vigen`ere. Imagine we
want to encrypt the message: ‘shaken not stirred’. We start by constructing a Vigen`ere Square: Notice,
each line of the Vigen`ere Square is a Caesar Shift, starting with a shift of zero, and ending with a shift of
25.

Next we need a keyword. Let’s use the word BOND. We write that repeatedly above our message:
Keyword: B O N D B O N D B O N D B O N D

Plaintext: s h a k e n n o t s t i r r e d To encrypt the first letter: go to row ‘B’ in the square - the first
letter of the keyword; next find column ‘s’ - the first letter of the plaintext; and where they meet in the
middle is the first letter of the ciphertext ‘T’. For the next letter do the same again: go to row ‘O’ and
column ‘h’, and where they meet is the second letter of the ciphertext ‘V’. Continuing in this way we get:
19 Keyword: B O N D B O N D B O N D B O N D Plaintext: s h a k e n n o t s t i r r e d Ciphertext: T V N N F
B A R U G G L S F R G Notice, the same letter in the plaintext may now be enciphered as different letters
in the ciphertext depending on its position.

Also notice, two letters that are the same in the ciphertext may come from two different letters in the
plaintext. If the keyword has length l, let k1, k2, . . . , kl be the letters of the keyword. If pi is the plaintext
letter in the ith position, then the ciphertext letter in the same position, ci , is given by ci = pi + k(i mod l)
mod 26. Given the keyword, we may decrypt our ciphertext by simply reversing this algorithm. The
effect of the Vigen`ere cipher is to disguise the frequencies. The longer the keyword the more effect it
has on frequency.

Breaking the Vigen`ere Cipher


If the keyword used in the Vigen`ere cipher has length l, then every lth letter will a result of the same
monoalphabetic cipher. If we can determine the length of the keyword then, given a long enough
message, we will be able to use standard cryptanalysis tools for monoalphabetic ciphers on every lth
letter to decrypt the whole message. If monoalphabetic ciphers are broken by looking for common
letters, polyalphabetic ciphers are broken by looking for common words. Example. Below is ciphertext,
188 letters long, believed to have been enciphered using a Vigen`ere cipher:
FHVDWSEEMFQCZXVQRZAOBOCGOXPYIPQTZKQUPYMFZADMRMFKMFFHVAWJTVMBFHT
MBFUIGTDEEKVPIGTCYAKJZMIJMRQVZOSZEIMOZDZBKMSVDSZTLIZXYSZCWEEBVD
EVPIZDIMRKERZGXAKMFGSZVUFHVUSFHFLGPEMMZAPVLPKKRAWEKZIBPBRJPMGV We begin our
cryptanalysis by looking for any string of letters that appears more than once in the ciphertext. If we
look closely, we can see the string ‘FHV’ appearing three times in the ciphertext. Since the keyword is
repeated, we proceed by assuming this is a common trigram that just happens to appear under the
same three letters of the keyword.
Code:
=============================Serial Code============================

#include <iostream>
#include <istream>
#include <ostream>
#include <fstream>
#include <cstdlib>
#include <string>
the rot13 function
std::string rot13(std::string s
static std::string const lcalph = "abcdefghijklmnopqrstuvwxyz", ucalph =

"ABCDEFGHIJKLMNOPQRSTUVWXYZ";

std::string result;
std::string::size_type pos;
result.reserve(s.length());
for (std::string::iterator it = s.begin(); it != s.end(); ++it)
{ if ((pos = lcalph.find(*it)) != std::string::npos result.push_back(lcalph[(pos + 13)
% 26]);

else if ((pos = ucalph.find(*it)) != std::string::npos)

result.push_back(ucalph[(pos + 13) % 26]);

else

result.push_back(*it);

return result;

// function to output the rot13 of a file on std::cout

// returns false if an error occurred processing the file, true otherwise

// on entry, the argument is must be open for reading

int rot13_stream(std::istream& is)

std::string line;
while (std::getline(is, line))

if (!(std::cout << rot13(line) << "\n"))

return false;

return is.eof();

// the main program

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

if (argc == 1) // no arguments given

return rot13_stream(std::cin) ? EXIT_SUCCESS : EXIT_FAILURE;

std::ifstream file;

for (int i = 1; i < argc; ++i)

file.open(argv[i], std::ios::in);

if (!file)

std::cerr << argv[0] << ": could not open for reading: " << argv[i]

<< "\n";

return EXIT_FAILURE;

if (!rot13_stream(file))

{
if (file.eof())

// no error occurred for file, so the error must have been in output

std::cerr << argv[0] << ": error writing to stdout\n";

else

std::cerr << argv[0] << ": error reading from " << argv[i]

<< "\n";

return EXIT_FAILURE;

file.clear();

file.close();

if (!file)

std::cerr << argv[0] << ": warning: closing failed for " << argv[i]

<< "\n";

return EXIT_SUCCESS;

=======================Parallel Encryption Code==========================


// Encryption using Vigenere Cipher
// Input: Message in UPPER CASE, Key in lowercase

#include "mpi.h"
#include <iostream>
#include <string.h>
#include <string>
#include <stdlib.h>
#include <ctype.h>
#define id rank
#define TAG 0

using namespace std;

char vigenere(char msg, char k)


{
if (!isalpha(msg))
return msg;
if (msg + k - 96 > 90)
return char((msg + k - 96) - 26);
else
return char(msg + k - 96);
}

int main(int a, char *b[])


{
MPI_Init(&a, &b);
int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Status status;
string str;
// char str[200];
char key[50];
string encrypted;
int len, keylen;
char key_character, encrypted_character, character_to_encrypt;

if (rank == 0)
{
cout << "\n----------------------------------------------------\n";
cout << "ENCRYPTION USING VIGENERE CIPHER";
cout << "\n----------------------------------------------------\n";

cout << "\nEnter the message to be encrypted: ";


//fgets(str, 200, stdin);// >> str;
getline(cin, str);
fflush(stdin);
len = str.length();
//len = strlen(str);
// str[len] = '\0';
cout << "\nEnter the cipher key: ";
cin >> key;
keylen = strlen(key);
key[keylen] = '\0';
}

MPI_Bcast(&keylen, 1, MPI_INT, 0, MPI_COMM_WORLD);


MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD);

if (rank == 0)
{
// Sending key - one character to one process
// cout << "Inside root process\n";
for (int i = 1; i <= keylen; i++)
{
// cout << "Sending " << key[i - 1] << " to " << i << endl;
MPI_Ssend(&key[i - 1], 1, MPI_CHAR, i, TAG, MPI_COMM_WORLD);
}

// Sending message, minimum len/keylen characters to a process


for (int i = 0; i < len; i++)
{
// cout << "Sending " << str[i] << " to " << (i % keylen) + 1 <<
endl;
MPI_Ssend(&str[i], 1, MPI_CHAR, (i % keylen) + 1, TAG,
MPI_COMM_WORLD);
// cout << "Receiving encrypted character: ";
MPI_Recv(&encrypted_character, 1, MPI_CHAR, (i % keylen) + 1, TAG,
MPI_COMM_WORLD, &status);
// cout << "Received encrypted: " << encrypted_character << " in
root\n";
encrypted.push_back(encrypted_character);
// append to encrypted message
}
// cout << "Exiting root process\n";
}
else
{
// cout << "Inside process-" << id << endl;
// Receive key character
MPI_Recv(&key_character, 1, MPI_CHAR, 0, TAG, MPI_COMM_WORLD, &status);
// cout << "Process-" << id << " received " << key_character << endl;

if (id <= len%keylen)


{
for (int i = 0; i < len / keylen + 1; i++)
{
// Receive character, encrypt and send to root
// cout << "Process-" << id << " is trying to receive " <<
endl;
MPI_Recv(&character_to_encrypt, 1, MPI_CHAR, 0, TAG,
MPI_COMM_WORLD, &status);
encrypted_character = vigenere(character_to_encrypt,
key_character);
MPI_Ssend(&encrypted_character, 1, MPI_CHAR, 0, TAG,
MPI_COMM_WORLD);
}
}
else
{
for (int i = 0; i < len / keylen; i++)
{
// Receive character, encrypt and send to root
// cout << "Process-" << id << " is trying to receive " <<
endl;
MPI_Recv(&character_to_encrypt, 1, MPI_CHAR, 0, TAG,
MPI_COMM_WORLD, &status);
encrypted_character = vigenere(character_to_encrypt,
key_character);
MPI_Ssend(&encrypted_character, 1, MPI_CHAR, 0, TAG,
MPI_COMM_WORLD);
}
}
// cout << "Exiting process-" << id << endl;
}
if (rank == 0)
{
cout << "\nThe encrypted string is: " << encrypted;
cout << endl;
}

MPI_Finalize();
return 0;
}

=======================Parallel Decryption Code==========================


// Decryption using Vigenere Cipher
// Input: Message in UPPER CASE, Key in lowercase

#include "mpi.h"
#include <iostream>
#include <string.h>
#include <string>
#include <stdlib.h>
#include <ctype.h>
#define id rank
#define TAG 0

using namespace std;

char vigenere_decrypt(char msg, char k)


{
if (!isalpha(msg))
return msg;
if (msg - k + 96 < 65)
return char((msg - k + 96) + 26);
else
return char(msg - k + 96);
}

int main(int a, char *b[])


{
MPI_Init(&a, &b);
int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Status status;

string str;
char key[50];
string decrypted;
int len, keylen;
char key_character, decrypted_character, character_to_decrypt;

if (rank == 0)
{
cout << "\n----------------------------------------------------\n";
cout << "DECRYPTION USING VIGENERE CIPHER";
cout << "\n----------------------------------------------------\n";

cout << "\nEnter the message to be decrypted: ";


getline(cin, str);
fflush(stdin);
len = str.length();
cout << "\nEnter the cipher key: ";
cin >> key;
keylen = strlen(key);
key[keylen] = '\0';
}

MPI_Bcast(&keylen, 1, MPI_INT, 0, MPI_COMM_WORLD);


MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD);

if (rank == 0)
{
for (int i = 1; i <= keylen; i++)
{
MPI_Ssend(&key[i - 1], 1, MPI_CHAR, i, TAG, MPI_COMM_WORLD);
}

for (int i = 0; i < len; i++)


{
MPI_Ssend(&str[i], 1, MPI_CHAR, (i % keylen) + 1, TAG,
MPI_COMM_WORLD);
MPI_Recv(&decrypted_character, 1, MPI_CHAR, (i % keylen) + 1, TAG,
MPI_COMM_WORLD, &status);
decrypted.push_back(decrypted_character);
}
}
else
{
MPI_Recv(&key_character, 1, MPI_CHAR, 0, TAG, MPI_COMM_WORLD, &status);

if (id <= len%keylen)


{
for (int i = 0; i < len / keylen + 1; i++)
{
MPI_Recv(&character_to_decrypt, 1, MPI_CHAR, 0, TAG,
MPI_COMM_WORLD, &status);
decrypted_character =
vigenere_decrypt(character_to_decrypt, key_character);
MPI_Ssend(&decrypted_character, 1, MPI_CHAR, 0, TAG,
MPI_COMM_WORLD);
}
}
else
{
for (int i = 0; i < len / keylen; i++)
{
MPI_Recv(&character_to_decrypt, 1, MPI_CHAR, 0, TAG,
MPI_COMM_WORLD, &status);
decrypted_character =
vigenere_decrypt(character_to_decrypt, key_character);
MPI_Ssend(&decrypted_character, 1, MPI_CHAR, 0, TAG,
MPI_COMM_WORLD);
}
}
}

if (rank == 0)
{
cout << "\nThe decrypted string is: " << decrypted;
cout << endl;
}

MPI_Finalize();

return 0;
}

You might also like