In cryptography, we use encryption ciphers to encode (“encrypt”) a plaintext into a ciphertext. In
theory the ciphertext is only readable by someone who knows how the plaintext was encrypted.
If they have this information they can “decrypt” and recover the plaintext.
There are some very simple ciphers, known as “substitution ciphers”. They’re so simple that
they’re not used any more because they are easy to break... but they are great for us because
they are easy to program!
First is the “rot13” cipher. Rot13 rotates each letter 13 positions in the alphabet. So an a
becomes an n, and an o becomes a b. (the rotation wraps). If the rot13 cipher is applied a
second time, the original plantext is restored: n becomes a, b becomes o.
Obviously the rot13 cipher provides no security! It’s really used in various places on the internet
to hide joke punch-lines or spoilers.
Another cipher, the “caesar cipher”, is a substitution cipher with a little more security. The cipher
uses a dictionary where each plaintext letter has a corresponding ciphertext letter paired with it.
For example we might say a is substituted with m, b is substituted with x, etc. to encrypt, each
letter is replaced with its ciphertext letter. To decrypt, the reverse process takes place: each
ciphertext letter is replaced with the plaintext letter.
This cipher is not particularly strong. It is quite easy to guess the plaintext-ciphertext mappings
by exploiting knowledge of letter frequency and word length. It is, however, harder to break than
rot13.
For this assignment, we will write a C++ program capable of doing 4 things:
1.
Perform a rot13 substitution
2.
Perform a caesar encryption given a dictionary
3.
Perform a caesar decryption given a dictionary
4.
Create a random caesar cipher dictionary
The format for the caesar cipher dictionary is a file with 26 pairs of letters, one per letter of the
alphabet, in alphabetical order. Each pair has two letters: the plaintext letter and the ciphertext
letter. The pairs are separated by whitespace. While the dictionary contains only lowercase
letters, the mappings also apply for uppercase letters. Note that the ciphertext letters must be
unique; you cannot have two different plaintext letters that map to the same ciphertext letter.
For all of the substitution operations, all upper and lower case letters on input should be
substituted (or rotated as the case may be) before being output. All other characters are simply
copied unchanged from input to output.
The program takes several command line arguments. The first, which is required, tells the
program what operation to perform:
-r
perform rot13 substitution.
-g
generate a random caesar cipher dictionary
-e
encrypt using the caesar cipher
-d
decrypt using the caesar cipher
If the first argument is missing, the program should print MISSING COMMAND, then stop.
If the first argument is not one of the four listed above, print the first argument followed by a
space and NOT A VALID COMMAND, then stop.
For -r, there is an optional second argument. If provided, it is the name of the file to read from. If
it is not provided, the program should read from standard input. The output should be generated
to the standard output. If a filename is provided but the file cannot open for any reason, the
program should print the filename followed by a space and FILE COULD NOT BE OPENED,
then stop.
For -g, the dictionary should be printed to the standard output. You must ensure that each
plaintext letter maps to a unique ciphertext letter.
For both -e and -d there is a required second argument, which is the filename of the dictionary.
If the second argument is missing, print the message NO DICTIONARY GIVEN, and stop. If the
dictionary cannot open for any reason, the program should print the filename followed by a
space and DICTIONARY COULD NOT BE OPENED, then stop.When reading the dictionary,
you must ensure that each plaintext letter maps to a unique ciphertext letter. If you find a case
where the dictionary is not in alphabetical order, you must print MISSING LETTER L, where L is
the missing letter, and stop.
Both -e and -d support an optional third argument, which is the file to read from. If it is not
provided, the program should read from standard input. The output should be generated to the
standard output. If a filename is provided but the file cannot open for any reason, the program
should print the filename followed by a space and FILE COULD NOT BE OPENED, then stop.
In all cases if there are too many command line arguments, your program should print TOO
MANY ARGUMENTS, then stop.
The test cases for part 1 will cover -r and -g. Cases for -e and -d will be added for part 2.
//please ignore syntax error, if any, and focus on the logic of the code
#include <bits/stdc++.h>
using namespace std;
int main(int argc, char** argv)
{
string line = "";
//when no command line argument given
if(argc == 1)
cout<<"MISSING COMMAND";
//when rot13 is to be done
else if(strcmp(argv[1], "-r") == 0)
{
string inp = "";
//if input file given
if(argc == 3)
{
ifstream f;
//open input file
f.open(argv[2]);
if (!f)
{
cerr<<argv[2]<<" FILE COULD NOT BE OPENED";
exit(1); // call system to stop
}
//read from input file and add to inp string
while(f)
{
getline(f, line);
inp += line;
}
}
//if input file not given read from stdin
else
getline(cin, inp);
for(int i = 0; i < inp.length(); i++)
{
if(inp[i] > 'z' || inp[i] < 'a')
{
cout<<inp[i];
continue;
}
//move every character by 13 places and round about to
a if 122(i.e. z) is passed
inp[i] = 'a' + (inp[i] + 13)%122;
cout<<inp[i];
}
}
//if deictionary is to be generated
else if(strcmp(argv[1], "-g") == 0)
{
srand(time(0));
//to hold pairwise letters
string dict = "";
//to check uniqueness of mapping
int a[26] = {};
for(int i = 0; i < 26; i++)
{
to generate a random number between 0 and 26
int randNum = rand()%(26);
dict += ('a' + i);
//if generated random number is already mapped then
move by +1
while(a[randNum] != 0)
randNum = (randNum+1)%26;
dict += ('a' + i + randNum);
a[randNum] == 1;
dict += ' ';
//hence plaintextciphertext is written to dict
}
cout<<dict;
}
else if(strcmp(argv[1], "-e") == 0)
{
if(argc < 3)
cout<<"NO DICTIONARY GIVEN";
else if (argc == 5)
cout<<"TOO MANY ARGUMENTS";
else
{
string inp = "";
line = "";
ifstream f;
//open dictionary
f.open(argv[2]);
if (!f)
{
cerr<<argv[2]<<" DICTIONARY COULD NOT BE OPENED";
exit(1); // call system to stop
}
//read dictionary to inp string
while(f)
{
getline(f, line);
inp += line;
}
//A will hold ciphertext with each index corresponding
to a letter (a=0, b=1,...)
char A[26];
bool a[26]={};
int k = 0;
//for every letter
for(int i = 0; i < 26; i++)
{
//inp[k] represents the plaintext, inp[k+1] represents
ciphertext
//if not in alphabetical order
if(k+1 >= inp.length() !! inp[k] !=
(char)('a'+i))
{
cout<<"MISSING LETTER
"<<(char)('a'+i);
}
else
{
//if ciphertext was already assigned to a previous
plaintext
if(a[ (int)inp[k+1] ] == true)
{
cout<<"NON UNIQUE ASSIGNMENT";
}
else
{
//update ciphertext in A
A[ (int)(inp[k] - i) ] = inp[k+1];
a[ (int)inp[k+1] ] = true;
k+=3;
}
}
}
//if file given
if(argc == 4)
{
inp = "";
line = "";
ifstream fin;
fin.open(argv[3]);
if (!fin)
{
cerr<<argv[3]<<" FILE COULD NOT BE OPENED";
exit(1); // call system to stop
}
//read file to inp
while(fin)
{
getline(fin, line);
inp += line;
}
}
//if file not given read from input
else
getline(cin, inp);
for(int i = 0; i < inp.length(); i++)
{
if(inp[i] < 'a' || inp[i] > 'z')
cout<<inp[i];
else
{
if(isupper(inp[i]))
{
cout<<toupper( A[ (tolower(inp[i])-'a') ])
}
else
cout<<A[ (inp[i]-'a') ];
}
}
}
}
//to decrypt
else if(strcmp(argv[1], "-d") == 0)
{
if(argc < 3)
cout<<"NO DICTIONARY GIVEN";
else if (argc == 5)
cout<<"TOO MANY ARGUMENTS";
else
{
string inp = "", line = "";
ifstream f;
//read dictionary to inp
f.open(argv[2]);
if (!f)
{
cerr<<argv[2]<<" DICTIONARY COULD NOT BE OPENED";
exit(1); // call system to stop
}
while(f)
{
getline(f, line);
inp += line;
}
char A[26];
bool a[26]={};
int k = 0;
for(int i = 0; i < 26; i++)
{
if(k+1 >= inp.length() !! inp[k] !=
(char)('a'+i))
{
cout<<"MISSING LETTER
"<<(char)('a'+i);
}
else
{
if(a[ (int)inp[k] ] == true)
{
cout<<"NON UNIQUE ASSIGNMENT";
}
else
{
A[ (int)(inp[k+1] - i) ] = inp[k];
a[ (int)inp[k] ] = true;
k+=3;
}
}
}
if(argc == 4)
{
inp = "";
line = "";
ifstream fin;
fin.open(argv[3]);
if (!fin)
{
cerr<<argv[3]<<" FILE COULD NOT BE OPENED";
exit(1); // call system to stop
}
while(fin)
{
getline(fin, line);
inp += line;
}
}
else
getline(cin, inp);
for(int i = 0; i < inp.length(); i++)
{
if(inp[i] < 'a' || inp[i] > 'z')
cout<<inp[i];
else
{
if(isupper(inp[i]))
{
cout<<toupper( A[ ( tolower(inp[i])-'a' )
];
}
else
cout<<A[ (inp[i]-'a') ];
}
}
}
}
else
{
cout<<argv[1]<<" NOT A VALID COMMAND";
}
return 0;
}
Get Answers For Free
Most questions answered within 1 hours.