Q1.
Write a program for the encryption and decryption process of hill cipher using the
following example. Print the cipher text, decryption key, encryption and decryption.
Message: ATTACK IS TONIGHT
KEY = [[3, 10, 20], [20, 9, 17], [9, 4, 17]]
Program:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// Function to encrypt a message using Hill cipher
string encrypt(string message, vector<vector<int>> key) {
string encrypted_text = "";
int n = key.size();
int len = message.length();
// Padding the message if its length is not a multiple of n
while (len % n != 0) {
message += 'X';
len++;
}
for (int i = 0; i < len; i += n) {
vector<int> chunk(n);
for (int j = 0; j < n; j++) {
chunk[j] = message[i + j] - 'A';
}
for (int j = 0; j < n; j++) {
int sum = 0;
for (int k = 0; k < n; k++) {
sum += key[j][k] * chunk[k];
}
encrypted_text += (sum % 26) + 'A';
}
}
return encrypted_text;
}
// Function to calculate the modular inverse of a number
int modInverse(int a, int m) {
a = a % m;
for (int x = 1; x < m; x++)
if ((a * x) % m == 1)
return x;
return 1;
}
// Function to decrypt a message using Hill cipher
string decrypt(string message, vector<vector<int>> key) {
string decrypted_text = "";
int n = key.size();
int det = (key[0][0] * key[1][1] * key[2][2]) +
(key[0][1] * key[1][2] * key[2][0]) +
(key[0][2] * key[1][0] * key[2][1]) -
(key[0][2] * key[1][1] * key[2][0]) -
(key[0][0] * key[1][2] * key[2][1]) -
(key[0][1] * key[1][0] * key[2][2]);
det = (det % 26 + 26) % 26;
int det_inv = modInverse(det, 26);
// Calculating adjoint of the key matrix
vector<vector<int>> adj(n, vector<int>(n));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
adj[i][j] = ((key[(j + 1) % 3][(i + 1) % 3] * key[(j + 2) % 3][(i + 2) % 3]) -
(key[(j + 1) % 3][(i + 2) % 3] * key[(j + 2) % 3][(i + 1) % 3]));
adj[i][j] = (adj[i][j] % 26 + 26) % 26;
}
}
// Calculating the inverse of the key matrix
vector<vector<int>> inverse(n, vector<int>(n));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
inverse[i][j] = (adj[i][j] * det_inv) % 26;
}
}
// Decrypting the message
for (int i = 0; i < message.length(); i += n) {
vector<int> chunk(n);
for (int j = 0; j < n; j++) {
chunk[j] = message[i + j] - 'A';
}
for (int j = 0; j < n; j++) {
int sum = 0;
for (int k = 0; k < n; k++) {
sum += inverse[j][k] * chunk[k];
}
decrypted_text += (sum % 26) + 'A';
}
}
return decrypted_text;
}
int main() {
string message = "ATTACKISTONIGHT";
vector<vector<int>> key = {{3, 10, 20}, {20, 9, 17}, {9, 4, 17}};
cout << "Original Message: " << message << endl;
string encrypted_text = encrypt(message, key);
cout << "Encrypted Text: " << encrypted_text << endl;
cout << "Decryption Key: " << endl;
for (int i = 0; i < key.size(); i++) {
for (int j = 0; j < key[i].size(); j++) {
cout << key[i][j] << " ";
}
cout << endl;
}
string decrypted_text = decrypt(encrypted_text, key);
cout << "Decrypted Text: " << decrypted_text << endl;
return 0;
}
Q2. Write a program for the encryption and decryption process of Playfair Cipher text using the
key = "MidLab" Plaintext = "Cryptography lab exam".
#include <iostream>
#include <cstring>
#define SIZE 30
// Convert all the characters of a string to lowercase
void toLowerCase(char plain[], int ps) {
for (int i = 0; i < ps; i++) {
if (plain[i] > 64 && plain[i] < 91)
plain[i] += 32;
}
}
// Remove all spaces in a string, can be extended to remove punctuation
int removeSpaces(char* plain, int ps) {
int count = 0;
for (int i = 0; i < ps; i++) {
if (plain[i] != ' ')
plain[count++] = plain[i];
}
plain[count] = '\0';
return count;
}
// Generates the 5x5 key square
void generateKeyTable(char key[], int ks, char keyT[5][5]) {
int dicty[26] = {0};
for (int i = 0; i < ks; i++) {
if (key[i] != 'j')
dicty[key[i] - 97] = 2;
}
dicty['j' - 97] = 1;
int i = 0, j = 0;
for (int k = 0; k < ks; k++) {
if (dicty[key[k] - 97] == 2) {
dicty[key[k] - 97] -= 1;
keyT[i][j] = key[k];
j++;
if (j == 5) {
i++;
j = 0;
}
}
}
for (int k = 0; k < 26; k++) {
if (dicty[k] == 0) {
keyT[i][j] = (char)(k + 97);
j++;
if (j == 5) {
i++;
j = 0;
}
}
}
}
// Search for the characters of a digraph in the key square and return their position
void search(char keyT[5][5], char a, char b, int arr[]) {
if (a == 'j')
a = 'i';
else if (b == 'j')
b = 'i';
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (keyT[i][j] == a) {
arr[0] = i;
arr[1] = j;
} else if (keyT[i][j] == b) {
arr[2] = i;
arr[3] = j;
}
}
}
}
// Function to find the modulus with 5
int mod5(int a) {
if (a < 0)
a += 5;
return (a % 5);
}
// Function to decrypt
void decrypt(char str[], char keyT[5][5], int ps) {
int a[4];
for (int i = 0; i < ps; i += 2) {
search(keyT, str[i], str[i + 1], a);
if (a[0] == a[2]) {
str[i] = keyT[a[0]][mod5(a[1] - 1)];
str[i + 1] = keyT[a[0]][mod5(a[3] - 1)];
} else if (a[1] == a[3]) {
str[i] = keyT[mod5(a[0] - 1)][a[1]];
str[i + 1] = keyT[mod5(a[2] - 1)][a[1]];
} else {
str[i] = keyT[a[0]][a[3]];
str[i + 1] = keyT[a[2]][a[1]];
}
}
}
// Function to decrypt using Playfair Cipher
void decryptByPlayfairCipher(char str[], char key[]) {
char ps, ks, keyT[5][5];
// Key
ks = strlen(key);
ks = removeSpaces(key, ks);
toLowerCase(key, ks);
// Ciphertext
ps = strlen(str);
toLowerCase(str, ps);
ps = removeSpaces(str, ps);
generateKeyTable(key, ks, keyT);
decrypt(str, keyT, ps);
}
// Function to make the plain text length to be even
int prepare(char str[], int ptrs) {
if (ptrs % 2 != 0) {
str[ptrs++] = 'z';
str[ptrs] = '\0';
}
return ptrs;
}
// Function for performing the encryption
void encrypt(char str[], char keyT[5][5], int ps) {
int a[4];
for (int i = 0; i < ps; i += 2) {
search(keyT, str[i], str[i + 1], a);
if (a[0] == a[2]) {
str[i] = keyT[a[0]][mod5(a[1] + 1)];
str[i + 1] = keyT[a[0]][mod5(a[3] + 1)];
} else if (a[1] == a[3]) {
str[i] = keyT[mod5(a[0] + 1)][a[1]];
str[i + 1] = keyT[mod5(a[2] + 1)][a[1]];
} else {
str[i] = keyT[a[0]][a[3]];
str[i + 1] = keyT[a[2]][a[1]];
}
}
}
// Function to encrypt using Playfair Cipher
void encryptByPlayfairCipher(char str[], char key[]) {
char ps, ks, keyT[5][5];
// Key
ks = strlen(key);
ks = removeSpaces(key, ks);
toLowerCase(key, ks);
// Plaintext
ps = strlen(str);
toLowerCase(str, ps);
ps = removeSpaces(str, ps);
ps = prepare(str, ps);
generateKeyTable(key, ks, keyT);
encrypt(str, keyT, ps);
}
// Driver code
int main() {
char str[SIZE], key[SIZE];
// Key to be encrypted
strcpy(key, "midlab");
printf("Key text: %s\n", key);
// Plaintext to be encrypted
strcpy(str, "Cryptographylabexams");
printf("Plain text: %s\n", str);
// Encrypt using Playfair Cipher
encryptByPlayfairCipher(str, key);
printf("Cipher text: %s\n", str);
// Decrypt using Playfair Cipher
decryptByPlayfairCipher(str, key);
printf("Deciphered text: %s\n", str);
return 0;
}
Q3. Write a program for find the first & key Initial key: - 133457799BBCDFF1 in DES Algo, PC-
1, PC-2, bit rotation for round given.
Program:
#include <iostream>
#include <bitset>
#include <string>
using namespace std;
// Permutation Choice 1 (PC-1)
const int PC1[] = {
57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4
};
// Permutation Choice 2 (PC-2)
const int PC2[] = {
14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32
};
// Key rotation schedule
const int rotations[] = {
1, 1, 2, 2, 2, 2, 2, 2,
1, 2, 2, 2, 2, 2, 2, 1
};
// Function to perform permutation
string permute(const string& key, const int* table, int size) {
string result;
for (int i = 0; i < size; ++i) {
result += key[table[i] - 1];
}
return result;
}
// Function to rotate the key bits left
string leftRotate(const string& key, int bits) {
string rotatedKey = key.substr(bits) + key.substr(0, bits);
return rotatedKey;
}
// Function to generate round keys
void generateRoundKeys(const string& initialKey) {
// Apply PC-1 permutation
string permutedKey = permute(initialKey, PC1, 56);
cout << "Key after PC-1: " << permutedKey << endl;
// Split into left and right halves
string leftHalf = permutedKey.substr(0, 28);
string rightHalf = permutedKey.substr(28);
// Generate 16 subkeys
for (int round = 0; round < 16; ++round) {
// Rotate each half according to rotation schedule
leftHalf = leftRotate(leftHalf, rotations[round]);
rightHalf = leftRotate(rightHalf, rotations[round]);
// Combine and permute using PC-2
string combinedKey = leftHalf + rightHalf;
string roundKey = permute(combinedKey, PC2, 48);
// Output the round key
cout << "Round " << round + 1 << " Key: " << roundKey << endl;
}
}
int main() {
// Initial key in hexadecimal format
string initialKeyHex = "133457799BBCDFF1";
// Convert the hexadecimal key to binary
string initialKeyBinary;
for (char c : initialKeyHex) {
initialKeyBinary += bitset<4>(c >= 'A' ? c - 'A' + 10 : c - '0').to_string();
}
cout << "Initial Key (Hex): " << initialKeyHex << endl;
cout << "Initial Key (Binary): " << initialKeyBinary << endl;
generateRoundKeys(initialKeyBinary);
return 0;
}
Q4. Write a program to find the fourth- round key of AES-128 using the given third round key in
henadecimal, the S-Box, and the round constant 08.
Third round Rey
Co af df 39
89 2f 66 67
57 51 ad 06
b1 ae 7e co
Program:
#include <iostream>
#include <iomanip>
#include <cstring> // Include for memcpy
using namespace std;
// Round constant for key schedule
const unsigned char Rcon[10] = {
0x01, 0x02, 0x04, 0x08, 0x10,
0x20, 0x40, 0x80, 0x1B, 0x36
};
// RotWord transformation
void rotWord(unsigned char* word) {
unsigned char temp = word[0];
word[0] = word[1];
word[1] = word[2];
word[2] = word[3];
word[3] = temp;
}
// XOR operation between two words
void xorWords(unsigned char* word1, const unsigned char* word2) {
for (int i = 0; i < 4; ++i) {
word1[i] ^= word2[i];
}
}
// Key schedule function to generate next round key
void keySchedule(unsigned char* roundKey, int round) {
// Rotate word
rotWord(roundKey + 12);
// XOR with round constant
roundKey[12] ^= Rcon[round - 1];
// XOR with corresponding word from previous round
xorWords(roundKey + 12, roundKey + 8);
for (int i = 11; i >= 0; --i) {
xorWords(roundKey + i * 4, roundKey + (i + 1) * 4);
}
}
int main() {
// Given third-round key in hexadecimal
unsigned char thirdRoundKey[16] = {
0x3C, 0xD7, 0x2E, 0x69,
0x6A, 0x47, 0x98, 0xF3,
0xF5, 0x26, 0xA3, 0x0F,
0xC0, 0x2E, 0x3A, 0x33
};
cout << "Given Third Round Key:" << endl;
for (int i = 0; i < 16; ++i) {
cout << hex << setw(2) << setfill('0') << (int)thirdRoundKey[i] << " ";
if ((i + 1) % 4 == 0) {
cout << endl;
}
}
cout << endl;
// Generate fourth-round key
unsigned char fourthRoundKey[16];
memcpy(fourthRoundKey, thirdRoundKey, 16); // Copy third round key
keySchedule(fourthRoundKey, 4);
cout << "Fourth Round Key:" << endl;
for (int i = 0; i < 16; ++i) {
cout << hex << setw(2) << setfill('0') << (int)fourthRoundKey[i] << " ";
if ((i + 1) % 4 == 0) {
cout << endl;
}
}
cout << endl;
return 0;
}
Q5. RSA Encryption Decryption
Program:
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
// Function to calculate GCD (Greatest Common Divisor)
int gcd(int a, int b) {
if (b == 0)
return a;
return gcd(b, a % b);
}
// Function to generate keys
void generateKeys(int p, int q, int &e, int &d, int &n) {
n = p * q;
int phi = (p - 1) * (q - 1);
// Choose e such that 1 < e < phi and e is coprime with phi
for (e = 2; e < phi; e++) {
if (gcd(e, phi) == 1)
break;
}
// Calculate d such that (d * e) % phi = 1
for (d = 2; d < phi; d++) {
if ((d * e) % phi == 1)
break;
}
}
// Function to calculate power modulo m (base^exp % m)
int powerModulo(int base, int exp, int m) {
if (exp == 0)
return 1;
int result = powerModulo(base, exp / 2, m);
result = (result * result) % m;
if (exp % 2 == 1)
result = (result * base) % m;
return result;
}
// Function to encrypt a message
int encrypt(int message, int e, int n) {
return powerModulo(message, e, n);
}
// Function to decrypt a message
int decrypt(int encryptedMsg, int d, int n) {
return powerModulo(encryptedMsg, d, n);
}
int main() {
// Prime numbers p and q
int p = 17, q = 19;
int e = 7, d, n;
// Generate RSA keys
generateKeys(p, q, e, d, n);
// Display public and private keys
cout << "Public Key (e, n): (" << e << ", " << n << ")" << endl;
cout << "Private Key (d, n): (" << d << ", " << n << ")" << endl;
// Convert the message to numeric representation
string msg = "CRYPTO";
int message = 0;
for (char c : msg) {
message *= 26; // Shift by 26 for each character (assuming uppercase alphabet)
message += c - 'A'; // Convert character to numeric value (A=0, B=1, ..., Z=25)
}
cout << "Message: " << message << endl;
// Encrypt the message
int encryptedMsg = encrypt(message, e, n);
cout << "Encrypted message: " << encryptedMsg << endl;
// Decrypt the message
int decryptedMsg = decrypt(encryptedMsg, d, n);
// Convert numeric message back to string representation
string decryptedStr = "";
while (decryptedMsg > 0) {
char digit = 'A' + (decryptedMsg % 26); // Extract the last digit and convert it to character
decryptedStr = digit + decryptedStr; // Prepend the character to the result
decryptedMsg /= 26; // Divide by 26 to remove the last digit
}
cout << "Decrypted message: " << decryptedStr << endl;
return 0;
}
Q6: Write a program that implements padding in the MD5 algo for a given message and
displays the hexadecimals equivalents - from M0 - M15.
Program:
#include <iostream>
#include <iomanip> // Include <iomanip> for setw and setfill
#include <string>
#include <vector>
using namespace std;
int main() {
string message = "They are deterministic";
vector<int> array;
for (char ch : message) {
char temp = toupper(ch);
array.push_back(temp - 'A');
}
int len = array.size();
int t_len = len * 8;
int n = 0;
while ((512 * n - 64) < t_len) {
n++;
}
int padding_required = 512 * n - 64 - t_len;
// Calculate the number of bytes required for padding
int num_pad_bytes = (padding_required + 7) / 8;
// Create a vector to hold the padded message
vector<unsigned char> padded_message(array.begin(), array.end());
// Append the single '1' bit
padded_message.push_back(0x80);
// Append '0' bits until the length is congruent to 448 modulo 512
padded_message.resize(len + num_pad_bytes + 8, 0x00);
// Append the original message length as a 64-bit integer in little-endian format
uint64_t original_length_bits = t_len;
for (int i = 0; i < 8; i++) {
padded_message[len + num_pad_bytes + i] = (original_length_bits >> (8 * i)) & 0xFF;
}
// Output the padded message
cout << "Padded message:" << endl;
int i = 0;
for (unsigned char byte : padded_message) {
cout << "M"<<i<< ":"<< hex << setw(2) << setfill('0') << static_cast<int>(byte) << "
"<<endl;
i++;
}
cout << endl;
return 0;
}
Q7. Digital Signature Algorithm
Program
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
// Function to calculate the modular inverse of a modulo m using Extended Euclidean
Algorithm
int modInverse(int a, int m) {
int m0 = m, t, q;
int x0 = 0, x1 = 1;
if (m == 1)
return 0;
// Apply extended Euclid Algorithm
while (a > 1) {
q = a / m;
t = m;
m = a % m, a = t;
t = x0;
x0 = x1 - q * x0;
x1 = t;
}
// Make x1 positive
if (x1 < 0)
x1 += m0;
return x1;
}
// Function to calculate modular exponentiation (a^b mod m)
int modPow(int base, int exp, int m) {
int result = 1;
base = base % m; // Ensure base is in range [0, m)
while (exp > 0) {
// If exp is odd, multiply base with result
if (exp % 2 == 1)
result = (result * base) % m;
// exp must be even now
exp = exp / 2;
base = (base * base) % m;
}
return result;
}
bool verifySignature(int p, int q, int g, int y, int h, int hash, int r, int s) {
// Calculate w = (s')^(-1) mod q
int w = modInverse(s, q);
if (w == 0) {
cout << "Error: s' does not have a modular inverse modulo q." << endl;
return false; // Signature verification fails
}
// Calculate u1 = [H(M') * w] mod q
int u1 = (hash * w) % q;
// Calculate u2 = (r' * w) mod q
int u2 = (r * w) % q;
// Calculate v = [(g^u1 * y^u2) mod p] mod q
int temp1 = modPow(g, u1, p);
int temp2 = modPow(y, u2, p);
int v = ((temp1 * temp2) % p) % q;
// Check if v = r'
return v == r;
}
int main() {
int p, q, x, k, h, hash;
cout << "Enter the value of p: ";
cin >> p;
cout << "Enter the value of q: ";
cin >> q;
cout << "Enter the value of h: ";
cin >> h;
int g = static_cast<int>(pow(h, (p - 1) / q)) % p;
cout << "Enter the value of x: ";
cin >> x;
int y = static_cast<int>(pow(g, x)) % p;
cout << "Enter the value of k: ";
cin >> k;
cout << "Enter the value of hash: ";
cin >> hash;
// Calculate r
int r = static_cast<int>(pow(g, k)) % q;
// Calculate s
int kInv = modInverse(k, q);
if (kInv == 0) {
cout << "Error: k does not have a modular inverse modulo q." << endl;
return 1; // Exit with an error
}
int s = ((hash + x * r) % q) * kInv % q;
cout << "r: " << r << endl;
cout << "s: " << s << endl;
string ss = verifySignature(p, q, g, y, h, hash, r, s) ? "True" : "False";
cout << "Signature verification result: " << ss << endl;
return 0;
}
Q8. Diffie Hellman Man In The Middle
Program:
#include <iostream>
using namespace std;
// Function to calculate power modulo p
int powerMod(int base, int exponent, int p) {
int result = 1;
base = base % p;
while (exponent > 0) {
if (exponent & 1)
result = (result * base) % p;
exponent = exponent >> 1;
base = (base * base) % p;
}
return result;
}
int main() {
int p, g; // Publicly known prime number p and primitive root g
int a, b; // Secret keys for Alice and Bob respectively
int A, B; // Public keys for Alice and Bob respectively
int E; // Public key for the attacker (Eve)
// Step 1: Initialize p and g
cout << "Enter the value of prime number (p): ";
cin >> p;
cout << "Enter the value of primitive root (g): ";
cin >> g;
// Step 2: Eve captures Alice's public key (A) and Bob's public key (B)
cout << "Enter Alice's public key (A): ";
cin >> A;
cout << "Enter Bob's public key (B): ";
cin >> B;
// Step 3: Eve replaces A and B with her own public key (E)
cout << "Enter Eve's public key (E): ";
cin >> E;
// Step 4: Calculate shared secrets
int sharedSecretEA = powerMod(B, a, p); // Shared secret between Eve and Alice
int sharedSecretEB = powerMod(A, b, p); // Shared secret between Eve and Bob
// Step 5: Display shared secrets
cout << "Shared secret calculated by Eve and Alice: " << sharedSecretEA << endl;
cout << "Shared secret calculated by Eve and Bob: " << sharedSecretEB << endl;
return 0;
}