Professional Documents
Culture Documents
Lab File
Submitted By
Kartikay Singh
(2K20/CO/228)
Submitted To
Prof. Shailender Kumar
Theory: The Caesar Cipher technique is one of the earliest and simplest methods of encryption
technique. It’s simply a type of substitution cipher, i.e., each letter of a given text is replaced by a
letter with a fixed number of positions down the alphabet. The method is apparently named after
Julius Caesar, who apparently used it to communicate with his officials.
Source Code:
class CaesarCipher
{ public:
char letters[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'};
char letters_2[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'};
int numberOfLetters = sizeof(letters);
string encrypt(string, int);
string decrypt(string, int);
};
int main()
{ CaesarCipher cc;
string encryptedTxt, decryptedTxt;
int key;
cout << "Enter the text to be encrypted: ";
getline(cin, encryptedTxt);
cin >> key;
if (key >= 0)
{key %= 26;
cout << endl<< "Encrypted: " << cc.encrypt(encryptedTxt, key) << endl;
decryptedTxt = cc.encrypt(encryptedTxt, key);
cout << endl<< "Decrypted: " << cc.decrypt(decryptedTxt, key) << endl;}
else
{key %= 26;
key += 26;
cout << endl<< "Encrypted: " << cc.encrypt(encryptedTxt, key) << endl;
decryptedTxt = cc.encrypt(encryptedTxt, key);
cout << endl<< "Decrypted: " << cc.decrypt(decryptedTxt, key) << endl; }
}
Output:
EXPERIMENT - 2
Theory: A monoalphabetic cipher is a type of substitution cipher where each character in the
alphabet is replaced by another character in a one-to-one ratio. For example, if "A" is encrypted
as "D", then "A" will always be encrypted to "D".
Source Code:
Import java.util.Scanner;
public class Mono
{
public static char p[] = { 'aS', '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' };
public static char ch[] = { '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' };
Output:
EXPERIMENT - 3
Theory:
Playfair cipher is a substitution cipher which encrypts a pair of alphabets called diagrams
instead of a single alphabet. Playfair cipher encrypts the text in two steps:
● It creates a 5x5 matrix in which the key is stored and remaining positions are filled with
remaining alphabets. Since there are 26 alphabets but only 25 positions in the matrix,
the letter i and j are considered the same.
● It encrypts the text by looking in the matrix and performing by following the rules:
○ Pair cannot be made with the same letter. Break the letter in single and add a
bogus letter to the previous letter. If the letter is standing alone in the process of
pairing, then add an extra bogus letter with the alone letter.
○ If both the letters are in the same column: Take the letter below each one (going
back to the top if at the bottom).
○ If both the letters are in the same row: Take the letter to the right of each one
(going back to the leftmost if at the rightmost position).
○ If neither of the above rules is true: Form a rectangle with the two letters and take
the letters on the horizontal opposite corner of the rectangle.
For decryption the above-mentioned rules are followed in reverse manner.
Source Code:
#include <bits/stdc++.h>
using namespace std;
string cmatrix(string keyword) {
char array[24];
int i = 0;
int k = 0;
int value = 0;
int count = 0;
bool unique = true;
int len = keyword.length();
int run = 1;
for (int tmp = 0; tmp < len; tmp++) {
if (keyword[tmp] == 'j') {
keyword[tmp] = 'i';
}
}
for (run = 0; run < len; run++) {
for (k = 0; k < run; k++){
if (keyword[run] == keyword[k]){
unique = false;
}
}
if (unique == true){
array[i] = keyword[run];
i++;
}
unique = true;
}
while (count < 26){
for (k = 0; k < len; k++){
if (value == keyword[k] - 97){
unique = false;
}
}
if (unique == true){
if (value != 9){
array[i] = 97 + value;
i++;
}
}
value++;
count++;
k = 0;
unique = true;
}
return array;
}
txt.open("textfile.txt", ios::in);
en.open("encrypted.txt", ios::out);
int main() {
string key = "monarchy";
string matrix = cmatrix(key);
encrypt(matrix);
decrypt(matrix);
return 0;
}
Output:
EXPERIMENT - 4
Theory:
A poly-alphabetic cipher is any cipher based on substitution, using several substitution
alphabets. In polyalphabetic substitution ciphers, the plaintext letters are enciphered differently
based upon their installation in the text. Rather than being a one-to-one correspondence, there
is a one-to-many relationship between each letter and its substitutes. To encrypt, a table of
alphabets can be used, termed a tabula recta, Vigenère square or Vigenère table. It has the
alphabet written out 26 times in different rows, each alphabet shifted cyclically to the left
compared to the previous alphabet, corresponding to the 26 possible Caesar ciphers. At
different points in the encryption process, the cipher uses a different alphabet from one of the
rows. The alphabet used at each point depends on a repeating keyword.
Source Code:
#include<bits/stdc++.h>
using namespace std;
void encrypt(string key){
fstream txt, en;
txt.open("textfile.txt", ios::in);
en.open("encrypted.txt", ios::out);
if(txt && en){
while(!txt.eof()){
string st, s = "";
getline(txt, st);
int c = 0;
for(int i = 0 ; i < st.size() ; i++){
if(st[i] == ' ')
s += ' ';
else{
s += (char)((st[i] + key[c] -2*'a') % 26 + 'a');
c++;
c = c%(key.length());
}
}
if(!txt.eof())
en << s << endl;
else
en << s;
}
}else{
cout << "Error";
}
txt.close();
en.close();
}
void decrypt(string key){
fstream dr, en;
dr.open("decrypted.txt", ios::out);
en.open("encrypted.txt", ios::in);
if(dr && en){
while(!en.eof()){
string st, s = "";
getline(en, st);
int c = 0;
for(int i = 0 ; i < st.size() ; i++){
if(st[i] == ' ')
s += ' ';
else{
s += (char)((st[i] - key[c] + 26) % 26 + 'a');
c++;
c %= key.length();
}
}
if(!en.eof())
dr << s << endl;
else
dr << s;
}
}else{
cout << "Error";
}
dr.close();
en.close();
}
int main(){
string key = "welcome";
encrypt(key);
decrypt(key);
return 0;
}
Output:
EXPERIMENT - 5
Theory:
Hill cipher is a polygraphic substitution cipher based on linear algebra.Each letter is represented
by a number modulo 26. Often the simple scheme A = 0, B = 1, …, Z = 25 is used, but this is not
an essential feature of the cipher. To encrypt a message, each block of n letters (considered as
an n-component vector) is multiplied by an invertible n × n matrix, against modulus 26. To
decrypt the message, each block is multiplied by the inverse of the matrix used for encryption.
Source Code:
#include <iostream>
#include <math.h>
using namespace std;
float encrypt[3][1], decrypt[3][1], a[3][3], b[3][3], mes[3][1], c[3][3];
void encryption();
void decryption();
void getKeyMessage();
void inverse();
int main()
{
getKeyMessage();
encryption();
decryption();
}
void encryption()
{
int i, j, k;
for (i = 0; i < 3; i++)
for (j = 0; j < 1; j++)
for (k = 0; k < 3; k++)
encrypt[i][j] = encrypt[i][j] + a[i][k] * mes[k][j];
cout << "\nEncrypted string is: ";
for (i = 0; i < 3; i++)
cout << (char)(fmod(encrypt[i][0], 26) + 97);
}
void decryption()
{
int i, j, k;
inverse();
for (i = 0; i < 3; i++)
for (j = 0; j < 1; j++)
for (k = 0; k < 3; k++)
decrypt[i][j] = decrypt[i][j] + b[i][k] * encrypt[k][j];
cout << "\nDecrypted string is: ";
for (i = 0; i < 3; i++)
cout << (char)(fmod(decrypt[i][0], 26) + 97);
cout << "\n";
}
void getKeyMessage()
{
int i, j;
char msg[3];
cout << "Enter 3x3 matrix for key (It should be inversible):\n";
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
{
cin >> a[i][j];
c[i][j] = a[i][j];
}
cout << "\nEnter a 3 letter string: ";
cin >> msg;
for (i = 0; i < 3; i++)
mes[i][0] = msg[i] - 97;
}
void inverse()
{
int i, j, k;
float p, q;
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
{
if (i == j)
b[i][j] = 1;
else
b[i][j] = 0;
}
for (k = 0; k < 3; k++)
{
for (i = 0; i < 3; i++)
{
p = c[i][k];
q = c[k][k];
for (j = 0; j < 3; j++)
{
if (i != k)
{
c[i][j] = c[i][j] * q - p * c[k][j];
b[i][j] = b[i][j] * q - p * b[k][j];
}
}
}
}
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
b[i][j] = b[i][j] / c[i][i];
}
Output:
EXPERIMENT - 6
Theory:
It is a block cipher that takes a block of plaintext and converts it into cipher text. It takes an 8 bit
block. It is a symmetric key cipher i.e. they use the same key for both encryption and decryption.
In the key generation algorithm, we accept the 10-bit key and convert it into two 8 bit keys. This
key is shared between both sender and receiver.
Source Code:
#include <iostream>
using namespace std;
void p10(int key[]){
int out[10]={3,5,2,7,4,10,1,9,8,6};
int temp[10];
for(int i=0;i<10;i++)
temp[i]=key[i];
for(int i=0;i<8;i++){
key[i]=temp[out[i]-1];
}
}
void left_shift(int left_half[], int right_half[], int shift_count)
{
int temp1=left_half[0];
int temp2=right_half[0];
for(int i=0;i<4;i++)
{
left_half[i]=left_half[i+1];
right_half[i]=right_half[i+1];
}
left_half[4]=temp1;
right_half[4]=temp2;
if(shift_count==2)
left_shift(left_half,right_half,1);
}
int* generate_key(int key[],int round)
{
int left_half[5],right_half[5];
int key1[10],key2[8];
p10(key);
for(int i= 0; i< 10; i++){
if(i<5){
left_half[i]= key[i];
}
else{
right_half[i-5]= key[i];
}
}
left_shift(left_half,right_half,1);
for(int i= 0; i< 5; i++) {
key1[i]= left_half[i];
key1[i+5]= right_half[i];
}
if(round==1){
p8(key1);
for(int i= 0; i< 8; ++i)
cout<<key1[i];
return key1;
}
else{
left_shift(left_half, right_half, 2);
for(int i= 0; i< 5; i++){
key2[i]= left_half[i];
key2[i+5]= right_half[i];
}
p8(key2);
for(int i= 0; i< 8; ++i)
cout<<key2[i];
return key2;
}
}
int main()
{
int pt[8],key[10],num;
cout<<"\nEnter the plain text (8-bits) :";
for(int i= 0; i< 8; i++)
cin>>pt[i];
cout<<"\nEnter the key (10-bits) :";
for(int i= 0; i< 10; i++)
cin>>key[i];
cout<<"\nEnter Round No. :";
cin>>num;
Theory:
Diffie-Hellman key exchange raises numbers to a selected power to produce decryption keys.
The two parties use symmetric cryptography to encrypt and decrypt their messages. The
components of the keys are never directly transmitted, making the task of a would-be code
breaker mathematically overwhelming. The method doesn't share information during the key
exchange. The two parties have no prior knowledge of each other, but the two parties create a
key together.
Source Code:
#include <cmath>
#include <iostream>
using namespace std;
long long int power(long long int a, long long int b, long long int P)
{
if (b == 1)
return a;
else
return (((long long int)pow(a, b)) % P);
}
int main()
{
long long int N, G, x, a, y, b, ka, kb;
N = 23;
cout << "The value of N : " << N << endl;
G = 9;
cout << "The value of G : " << G << endl;
a = 4;
cout << "The private key a for Alice : " << a << endl;
x = power(G, a, N);
b = 3;
cout << "The private key b for Bob : " << b << endl;
y = power(G, b, N);
ka = power(y, a, N);
kb = power(x, b, N);
cout << "Secret key for the Alice is : " << ka << endl;
cout << "Secret key for the Bob is : " << kb << endl;
return 0;
}
Output:
EXPERIMENT - 8
Theory:
RSA algorithm is an asymmetric cryptography algorithm. Asymmetric actually means that it
works on two different keys i.e. Public Key and Private Key. As the name describes, the Public
Key is given to everyone and the Private key is kept private.
The idea of RSA is based on the fact that it is difficult to factorize a large integer. The public key
consists of two numbers where one number is a multiplication of two large prime numbers. And
private keys are also derived from the same two prime numbers. So if somebody can factorize
the large number, the private key is compromised. Therefore encryption strength totally lies on
the key size and if we double or triple the key size, the strength of encryption increases
exponentially.
Source Code:
#include<bits/stdc++.h>
using namespace std;
long int p, q, n, t, flag, e[100], d[100], temp[100], j, m[100], en[100], i;
char msg[1000];
int prime(long int);
void ce();
long int cd(long int);
void encrypt();
void decrypt();
int prime(long int pr)
{
int i;
j = sqrt(pr);
for (i = 2; i <= j; i++)
{
if (pr % i == 0)
return 0;
}
return 1;
}
int main()
{
cout<< "ENTER FIRST PRIME NUMBER: "<<endl;
cin>> p;
flag = prime(p);
if (flag == 0)
{
cout<< "WRONG INPUT!"<<endl;
exit(1);
}
cout<< "ENTER ANOTHER PRIME NUMBER: "<<endl;
cin>> q;
flag = prime(q);
if (flag == 0 || p == q)
{
cout<< "WRONG INPUT!"<<endl;
exit(1);
}
cout<< "ENTER MESSAGE: "<<endl;
fflush(stdin);
cin>>msg;
for (i = 0; msg[i] != NULL; i++){
m[i] = msg[i];
n = p * q;
t = (p - 1) * (q - 1);
ce();
cout << "POSSIBLE VALUES OF en AND de ARE: " << endl;
for (i = 0; i < j - 1; i++)
cout << e[i] << "\t" << d[i] << "\n";
encrypt();
decrypt();
return 0;
}
void ce()
{
int k;
k = 0;
for (i = 2; i < t; i++)
{
if (t % i == 0)
continue;
flag = prime(i);
if (flag == 1 && i != p && i != q)
{
e[k] = i;
flag = cd(e[k]);
if (flag > 0)
{
d[k] = flag;
k++;
}
if (k == 99)
break;
}
}
}
long int cd(long int x)
{
long int k = 1;
while (1)
{
k = k + t;
if (k % x == 0)
return (k / x);
}
}
void encrypt()
{
long int pt, ct, key = e[0], k, len;
i = 0;
len = strlen(msg);
while (i != len)
{
pt = m[i];
pt = pt - 96;
k = 1;
for (j = 0; j < key; j++)
{
k = k * pt;
k = k % n;
}
temp[i] = k;
ct = k + 96;
en[i] = ct;
i++;
}
en[i] = -1;
cout<< "THE ENCRYPTED MESSAGE IS: "<<endl;
for (i = 0; en[i] != -1; i++)
printf("%c", en[i]);
}
void decrypt()
{
long int pt, ct, key = d[0], k;
i = 0;
while (en[i] != -1)
{
ct = temp[i];
k = 1;
for (j = 0; j < key; j++)
{
k = k * ct;
k = k % n;
}
pt = k + 96;
m[i] = pt;
i++;
}
m[i] = -1;
cout<< "\nTHE DECRYPTED MESSAGE IS: "<<endl;
for (i = 0; m[i] != -1; i++)
printf("%c", m[i]);
}
Output:
EXPERIMENT - 9
Theory:
SHA-1 or Secure Hash Algorithm 1 is a cryptographic algorithm which takes an input and
produces a 160-bit (20-byte) hash value. This hash value is known as a message digest. This
message digest is usually then rendered as a hexadecimal number which is 40 digits long. It is
a U.S. Federal Information Processing Standard and was designed by the United States
National Security Agency. SHA-1 is now considered insecure since 2005.
Source Code:
#include <stdio.h>
#include <openssl/sha.h>
SHA1_Init(&shactx);
SHA1_Update(&shactx, testdata, DataLen);
SHA1_Final(digest, &shactx);
return 0;
}
Output:
EXPERIMENT - 10
Theory:
A digital signature is a mathematical technique used to validate the authenticity and integrity of
a message, software, or digital document.
● Key Generation Algorithms: Digital signature is electronic signatures, which assure that
the message was sent by a particular sender. While performing digital transactions
authenticity and integrity should be assured, otherwise, the data can be altered or
someone can also act as if he was the sender and expect a reply.
● Signing Algorithms: To create a digital signature, signing algorithms like email programs
create a one-way hash of the electronic data which is to be signed. The signing
algorithm then encrypts the hash value using the private key (signature key). This
encrypted hash along with other information like the hashing algorithm is the digital
signature. This digital signature is appended with the data and sent to the verifier. The
reason for encrypting the hash instead of the entire message or document is that a hash
function converts any arbitrary input into a much shorter fixed-length value. This saves
time as now instead of signing a long message a shorter hash value has to be signed
and moreover hashing is much faster than signing.
● Signature Verification Algorithms: Verifier receives Digital Signature along with the data.
It then uses a Verification algorithm to process the digital signature and the public key
(verification key) and generates some value. It also applies the same hash function on
the received data and generates a hash value. Then the hash value and the output of
the verification algorithm are compared. If they both are equal, then the digital signature
is valid else it is invalid.
Source Code:
#include <iostream>
#include <vector>
int euclid(int m, int n) {
if (n == 0) {
return m;
} else {
int r = m % n;
return euclid(n, r);
}
}
std::pair<int, int> exteuclid(int a, int b) {
int r1 = a;
int r2 = b;
int s1 = 1;
int s2 = 0;
int t1 = 0;
int t2 = 1;
while (r2 > 0) {
int q = r1 / r2;
int r = r1 - q * r2;
r1 = r2;
r2 = r;
int s = s1 - q * s2;
s1 = s2;
s2 = s;
int t = t1 - q * t2;
t1 = t2;
t2 = t;
}
if (t1 < 0) {
t1 = t1 % a;
}
return std::make_pair(r1, t1);
}
int main() {
int p = 823;
int q = 953;
int n = p * q;
int Pn = (p - 1) * (q - 1);
std::vector<int> key;
for (int i = 2; i < Pn; ++i) {
int gcd = euclid(Pn, i);
if (gcd == 1) {
key.push_back(i);
}
}
int e = 313;
auto result = exteuclid(Pn, e);
int r = result.first;
int d = result.second;
if (r == 1) {
d = d;
std::cout << "Decryption key is: " << d << std::endl;
} else {
std::cout << "Multiplicative inverse for the given encryption key does not exist. Choose a different
encryption key" << std::endl;
}
int M = 19070;
int S = 1;
for (int i = 0; i < d; ++i) {
S = (S * M) % n;
}
int M1 = 1;
for (int i = 0; i < e; ++i) {
M1 = (M1 * S) % n;
}
if (M == M1) {
std::cout << "As M = M1, Accept the message sent by Alice" << std::endl;
} else {
std::cout << "As M not equal to M1, Do not accept the message sent by Alice" << std::endl;
}
return 0;
}
Output: