0% found this document useful (0 votes)
52 views

NTC File

The document provides code for implementing various cryptographic algorithms and ciphers in C++. It includes code to: 1) Find the multiplicative inverse of a number using the extended Euclidean algorithm. 2) Find the inverse of a matrix in modulus n. 3) Find the multiplicative inverse of a polynomial using the extended Euclidean algorithm. 4) Implement traditional ciphers like the Shift Cipher, Multiplicative Cipher, and Affine Cipher. 5) Implement cryptographic algorithms like DES, AES, RSA, ElGamal, Rabin, and SHA-512. 6) Implement digital signature schemes like RSA and ElGamal.

Uploaded by

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

NTC File

The document provides code for implementing various cryptographic algorithms and ciphers in C++. It includes code to: 1) Find the multiplicative inverse of a number using the extended Euclidean algorithm. 2) Find the inverse of a matrix in modulus n. 3) Find the multiplicative inverse of a polynomial using the extended Euclidean algorithm. 4) Implement traditional ciphers like the Shift Cipher, Multiplicative Cipher, and Affine Cipher. 5) Implement cryptographic algorithms like DES, AES, RSA, ElGamal, Rabin, and SHA-512. 6) Implement digital signature schemes like RSA and ElGamal.

Uploaded by

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

Number Theory & Cryptography

Practical File

Dipesh Kumar : 2021UIT3113


Branch: IT-2
Submitted to: Mr. Mohit Sajwan
INDEX

SNO EXPERIMENT DATE SIGN

1 Find the multiplicative inverse of a number using extended Euclidean


algorithm in modus n

2 Find the inverse of a matrix in modulus n.

3 Find the multiplicative inverse of a polynomial using extended


Euclidean algorithm in modus irreducible polynomial.

4 Implement the following traditional ciphers:


a) Shift Cipher
b) Multiplicative Cipher
c) Affine Cipher
d) Playfair Cipher
e) Hill Cipher
f) Vignere Ciphere
g) Rail fence—Row & column transformation

5 Implement the following algorithms:


a) DES
b) AES
c) RSA
d) ElGlgamal
e) Rabin
f) SHA-512

6 Implement the digital signature schemes: RSA and ElGlgamal.


Practical 1
Find the multiplicative inverse of a number using extended Euclidean
algorithm in modus n.
CODE
#include <bits/stdc++.h>
using namespace std;
int main(){
int n, b, r1, r2, t1, t2;
cout << "\n Enter n and b: \t";
cin >> n >> b;
r1 = n;
r2 = b;
t1 = 0;
t2 = 1;
int q, r, t;
cout << "\nq\tr1\t r2\t r\tt1\tt2\tt\t\n";
cout << "______________________________________________________\n";
while (r2 > 0){
q = float(r1) / r2;
int R1 = r1, R2 = r2, T1 = t1, T2 = t2;
r = r1 - q * r2;
r1 = r2;
r2 = r;
t = t1 - q * t2;
t1 = t2;
t2 = t;
cout << q << "\t" << R1 << "\t" << R2 << "\t" << r << "\t" << T1 << "\t" << T2 <<
"\t" << t << endl;
}
cout << q << "\t" << r1 << "\t" << r2 << "\t" << r << "\t" << t1 << "\t"<< t2 << "\t"
<< t << endl;
if (t1 < 0)
t1 += n;
if (r1 == 1)
cout << "\n Multiplicative Inverse Exist, it is " << t1 << endl;
else
cout << "\n Since GCD not equal to 1 hence Multiplicative Inverse does not exist."
<< endl;
}

OUTPUT:
Practical 2
Find the inverse of a matrix in modulo n.
CODE:
#include <bits/stdc++.h>
using namespace std;
#define N 4
int findInverseModulo(int b, int n)
{
int t1 = 0;
int t2 = 1;
int r1 = n;
int r2 = b;
while (r2 > 0)
{
int q = r1 / r2;
int r = r1 - q * r2;
int t = t1 - q * t2;
r1 = r2;
r2 = r;
t1 = t2;
t2 = t;
}
if (r1 == 1)
{
t1 = t1 < 0 ? t1 + n : t1;
return t1;
}
return -1;
}
void getCofactor(int A[N][N], int temp[N][N], int p, int q, int n)
{
int i = 0, j = 0;
for (int row = 0; row < n; row++)
{
for (int col = 0; col < n; col++)
{
if (row != p && col != q)
{
temp[i][j++] = A[row][col];
if (j == n - 1)
{
j = 0;
i++;
}
}
}
}
}
int determinant(int A[N][N], int n)
{
int D = 0;
if (n == 1)
return A[0][0];
int temp[N][N];
int sign = 1;
for (int f = 0; f < n; f++)
{
getCofactor(A, temp, 0, f, n);
D += sign * A[0][f] * determinant(temp, n - 1);
sign = -sign;
}
return D;
}
void adjoint(int A[N][N], int adj[N][N])
{
if (N == 1)
{
adj[0][0] = 1;
return;
}
int sign = 1, temp[N][N];
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
getCofactor(A, temp, i, j, N);
sign = ((i + j) % 2 == 0) ? 1 : -1;
adj[j][i] = (sign) * (determinant(temp, N - 1));
}
}
}
bool inverseMatrix(int A[N][N], int inverse[N][N], int r)
{
int det = determinant(A, N);
if (det == 0)
return false;
if (__gcd(det, r) != 1)
return false;
int detInverse = findInverseModulo(det, r);
int adj[N][N];
adjoint(A, adj);
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
{
inverse[i][j] = adj[i][j] * detInverse;
if (inverse[i][j] < 0)
{
int q = abs(inverse[i][j]) / r;
inverse[i][j] = inverse[i][j] + (q + 1) * r;
}
inverse[i][j] %= r;
}
return true;
}
void display(int A[N][N])
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
cout << A[i][j] << " ";
cout << endl;
}
}
int main()
{
int A[N][N] = {{3, 5, 7, 2},
{1, 4, 7, 2},
{6, 3, 9, 17},
{13, 5, 4, 16}};
int adj[N][N];
int inv[N][N];
cout << "Enter modulus n: ";
int r;
cin >> r;
cout << "Input matrix is :\n";
display(A);
cout << "\nThe Inverse is :\n";
if (inverseMatrix(A, inv, r))
display(inv);
return 0;
}

OUTPUT:
Practical 3
Find the multiplicative inverse of a polynomial using
extended Euclidean algorithm in modus irreducible
polynomial.
CODE:
#include <iostream>
#include <vector>
#include <sstream>
#include <string>
using namespace std;

vector<int> polydiv(vector<int> &a, vector<int> &b){


int m = a.size();
int n = b.size();
if (m < n)
return {0};
vector<int> q(m - n + 1, 0);
for (int i = m - n; i >= 0; --i){
int factor = a[i + n - 1] / b[n - 1];
q[i] = factor;
for (int j = 0; j < n; ++j)
{
a[i + j] -= b[j] * factor;
}
}
while (a.size() > 0 && a.back() == 0)
a.pop_back();
return a;
}

vector<int> polyadd(vector<int> &a, vector<int> &b)


{
int m = a.size();
int n = b.size();
int len = max(m, n);
vector<int> result(len, 0);
for (int i = 0; i < m; ++i)
result[i + (len - m)] = a[i];
for (int i = 0; i < n; ++i)
result[i + (len - n)] += b[i];
return result;
}

vector<int> polymul(vector<int> &a, vector<int> &b)


{
int m = a.size();
int n = b.size();
vector<int> result(m + n - 1, 0);
for (int i = 0; i < m; ++i)
{
for (int j = 0; j < n; ++j)
{
result[i + j] += a[i] * b[j];
}
}
return result;
}

pair<vector<int>, vector<int>> extended_gcd_poly(vector<int> &a, vector<int> &b,


vector<int> &irreducible_poly){
if (b == vector<int>{0}){
vector<int> one = {1};
return {vector<int>(a.begin(), a.end()), one};
}
auto qr = polydiv(a, b);
vector<int> q = qr;
vector<int> r = a;
for (int i = 0; i < qr.size(); ++i){
r[i] = qr[i];
}
auto gcd_x = extended_gcd_poly(b, r, irreducible_poly);
vector<int> gcd = gcd_x.first;
vector<int> x = gcd_x.second;

vector<int> x_poly = {0};


x_poly = polyadd(x_poly, x);
vector<int> q_x_poly = polymul(q, x_poly);
vector<int> result = polyadd(x, q_x_poly);

return {gcd, result};


}

vector<int> mod_inverse_poly(vector<int> &a, vector<int> &irreducible_poly)


{
auto aa_inverse = extended_gcd_poly(a, irreducible_poly, irreducible_poly);
vector<int> aa = aa_inverse.first;
vector<int> inverse = aa_inverse.second;
if (aa != vector<int>{1})
{
throw invalid_argument("The polynomial has no inverse modulo the irreducible
polynomial");
}
for (auto &coefficient : inverse)
{
coefficient = coefficient % irreducible_poly.back();
}
return inverse;
}

vector<int> parseInput(string input)


{
vector<int> result;
istringstream iss(input);
string token;
while (getline(iss, token, ' '))
{
result.push_back(stoi(token));
}
return result;
}

int main()
{
string irreducible_poly_str, a_str;
cout << "Enter the irreducible polynomial coefficients as a space-separated list
(e.g., 1 0 1 1): ";
getline(cin, irreducible_poly_str);
vector<int> irreducible_poly = parseInput(irreducible_poly_str);
cout << "Enter the polynomial coefficients for 'a' as a space-separated list (e.g., 1
0 1 0): ";
getline(cin, a_str);
vector<int> a = parseInput(a_str);
try
{
vector<int> inverse = mod_inverse_poly(a, irreducible_poly);
cout << "The multiplicative inverse is: ";
for (int i = 0; i < inverse.size(); i++)
{
cout << inverse[i] << " ";
}
cout << endl;
}
catch (const invalid_argument &e)
{
cout << e.what() << endl;
}
return 0;
}

OUTPUT:
Practical 4
Implement the following traditional ciphers:
● Shift Cipher
CODE:
#include <bits/stdc++.h>
using namespace std;
map<char, int> m;
int main()
{
for (char c = 'A'; c <= 'Z'; ++c)
{
m[c] = c - 'A';
}
string input;
cout << "Enter Msg:" cin >> input;
transform(input.begin(), input.end(), input.begin(), ::toupper);
int key;
cin >> key;
string crypt;
for (auto i : input)
{
cout << m[i] << " " << i << " , ";
crypt.push_back((m[i] + key) % 26 + 'A');
}
cout << endl<< crypt << endl;
string decrypt;
for (auto i : crypt)
{
decrypt.push_back(((m[i] - key) + 26) % 26 + 'A');
}
cout << decrypt << endl;
}
OUTPUT:
Multiplicative Cipher
CODE:
#include <bits/stdc++.h>
using namespace std;
int multi_inverse(int n, int a, int t1, int t2)
{
if (a == 0)
return (t1 + 26) % 26;
int q = n / a;
int r = n % a;
int t = t1 - q * t2;
return multi_inverse(a, r, t2, t);
}
map<char, int> m;
int main()
{
for (char c = 'A'; c <= 'Z'; ++c)
{
m[c] = c - 'A';
}
string input;
cin >> input;
int a, b;
cin >> a >> b;
string crypt;
for (auto i : input)
{
crypt.push_back((a * m[i] + b) % 26 + 'A');
}
int inverse = multi_inverse(26, a, 0, 1);
cout << inverse << endl;
cout << crypt << endl;
string decrypt;
for (auto i : crypt)
{
decrypt.push_back((((i - 'A' - b + 26)) * inverse + 26) % 26 + 'A');
}
cout << decrypt << endl;
}

OUTPUT:
Affine Cipher
CODE:
#include<bits/stdc++.h>
using namespace std;
static int a = 7;
static int b = 6;
string encryption(string m) {
//Cipher Text initially empty
string c = "";
for (int i = 0; i < m.length(); i++) {
// Avoid space to be encrypted
if(m[i]!=' ')
// added 'A' to bring it in range of ASCII alphabet [ 65-90 | A-Z ]
c = c + (char) ((((a * (m[i]-'A') ) + b) % 26) + 'A');
else
//else append space character
c += m[i];
}
return c;
}
string decryption(string c) {
string m = "";
int a_inverse = 0;
int flag = 0;
//Find a^-1 (the multiplicative inverse of a
//in the group of integers modulo m.)
for (int i = 0; i < 26; i++) {
flag = (a * i) % 26;
//Check if (a * i) % 26 == 1,
//then i will be the multiplicative inverse of a
if (flag == 1) {
a_inverse = i;
}
}
for (int i = 0; i < c.length(); i++) {
if(c[i] != ' ')
// added 'A' to bring it in range of ASCII alphabet [ 65-90 | A-Z ]
m = m + (char) (((a_inverse * ((c[i]+'A' - b)) % 26)) + 'A');
else
//else append space character
m += c[i];
}
return m;
}
int main(void) {
string msg = "TUTORIALSPOINT";
string c = encryption(msg);
cout << "Encrypted Message is : " << c<<endl;
cout << "Decrypted Message is: " << decryption(c);
return 0;
}

OUTPUT:

Playfair Cipher
CODE:
#include <bits/stdc++.h>
#define SIZE 30
using namespace std;
void toLowerCase(char plain[], int ps){
int i;
for (i = 0; i < ps; i++)
{
if (plain[i] > 64 && plain[i] < 91)
plain[i] += 32;
}
}
int removeSpaces(char *plain, int ps)
{
int i, count = 0;
for (i = 0; i < ps; i++)
if (plain[i] != ' ')
plain[count++] = plain[i];
plain[count] = '\0';
return count;
}
void generateKeyTable(char key[], int ks, char keyT[5][5])
{
int i, j, k, flag = 0, *dicty;
dicty = (int *)calloc(26, sizeof(int));
for (i = 0; i < ks; i++)
{
if (key[i] != 'j')
dicty[key[i] - 97] = 2;
}
dicty['j' - 97] = 1;
i = 0;
j = 0;
for (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 (k = 0; k < 26; k++)
{
if (dicty[k] == 0)
{
keyT[i][j] = (char)(k + 97);
j++;
if (j == 5)
{
i++;
j = 0;
}
}
}
cout << "\n Key :\n";
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
cout << keyT[i][j] << " ";
cout << endl;
}
}
void search(char keyT[5][5], char a, char b, int arr[])
{
int i, j;
if (a == 'j')
a = 'i';
else if (b == 'j')
b = 'i';
for (i = 0; i < 5; i++)
{
for (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;
}
}
}
}
int mod5(int a)
{
return (a % 5);
}
int prepare(char str[], int ptrs)
{
if (ptrs % 2 != 0)
{
str[ptrs++] = 'z';
str[ptrs] = '\0';
}
return ptrs;
}
void encrypt(char str[], char keyT[5][5], int ps)
{
int i, a[4];
for (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]];
}
}
}
void encryptByPlayfairCipher(char str[], char key[])
{
char ps, ks, keyT[5][5];
ks = strlen(key);
ks = removeSpaces(key, ks);
toLowerCase(key, ks);
ps = strlen(str);
toLowerCase(str, ps);
ps = removeSpaces(str, ps);
ps = prepare(str, ps);
generateKeyTable(key, ks, keyT);
encrypt(str, keyT, ps);
}
int main()
{
char str[SIZE], key[SIZE];
strcpy(key, "fruits");
printf("Key text: %s\n", key);
strcpy(str, "watermelon");
printf("Plain text: %s\n", str);
encryptByPlayfairCipher(str, key);
printf("Cipher text: %s\n", str);
return 0;
}

OUTPUT:
Hill Cipher
CODE:
#include <iostream>
using namespace std;
void getKeyMatrix(string key, int keyMatrix[][3])
{
int k = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
keyMatrix[i][j] = (key[k]) % 65;
k++;
}
}
}
void encrypt(int cipherMatrix[][1],
int keyMatrix[][3],
int messageVector[][1])
{
int x, i, j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 1; j++)
{
cipherMatrix[i][j] = 0;

for (x = 0; x < 3; x++)


{
cipherMatrix[i][j] +=
keyMatrix[i][x] * messageVector[x][j];
}
cipherMatrix[i][j] = cipherMatrix[i][j] % 26;
}
}
}
void HillCipher(string message, string key){
int keyMatrix[3][3];
getKeyMatrix(key, keyMatrix);
int messageVector[3][1];
for (int i = 0; i < 3; i++)
messageVector[i][0] = (message[i]) % 65;
int cipherMatrix[3][1];
encrypt(cipherMatrix, keyMatrix, messageVector);
string CipherText;
for (int i = 0; i < 3; i++)
CipherText += cipherMatrix[i][0] + 65;
cout << " Ciphertext:" << CipherText;
}
int main(){
string message;
cout<<"Enter message:";
cin>>message;
string key;
cout<<"Enter key:";
cin>>key;

HillCipher(message, key);

return 0;
}

OUTPUT:

Vignere Cipher
CODE:
#include <bits/stdc++.h>
using namespace std;
string generateKey(string str, string key)
{
int x = str.size();
for (int i = 0;; i++)
{
if (x == i)
i = 0;
if (key.size() == str.size())
break;
key.push_back(key[i]);
}
return key;
}
string cipherText(string str, string key)
{
string cipher_text;
for (int i = 0; i < str.size(); i++)
{
char x = (str[i] + key[i]) % 26;
x += 'A';
cipher_text.push_back(x);
}
return cipher_text;
}
string originalText(string cipher_text, string key)
{
string orig_text;
for (int i = 0; i < cipher_text.size(); i++)
{
char x = (cipher_text[i] - key[i] + 26) % 26;
x += 'A';
orig_text.push_back(x);
}
return orig_text;
}
int main()
{
string str = "NUMBERTHEORY";
string keyword = "APPLE";
string key = generateKey(str, keyword);
string cipher_text = cipherText(str, key);
cout << "Plaintext : "<< str << "\n";
cout << "key : "<< keyword << "\n";
cout << "Ciphertext : "<< cipher_text << "\n";
cout << "Decrypted Text : "<< originalText(cipher_text, key);
return 0;
}
OUTPUT:

Rail fence—Row & column transformation Cipher


CODE:
#include <bits/stdc++.h>
using namespace std;
string encryptRailFence(string text, int key)
{
char rail[key][(text.length())];
for (int i = 0; i < key; i++)
for (int j = 0; j < text.length(); j++)
rail[i][j] = '\n';
bool dir_down = false;
int row = 0, col = 0;
for (int i = 0; i < text.length(); i++)
{
if (row == 0 || row == key - 1)
dir_down = !dir_down;
rail[row][col++] = text[i];
dir_down ? row++ : row--;
}
string result;
for (int i = 0; i < key; i++)
for (int j = 0; j < text.length(); j++)
if (rail[i][j] != '\n')
result.push_back(rail[i][j]);
return result;
}
string decryptRailFence(string cipher, int key)
{
char rail[key][cipher.length()];
for (int i = 0; i < key; i++)
for (int j = 0; j < cipher.length(); j++)
rail[i][j] = '\n';
bool dir_down;
int row = 0, col = 0;
for (int i = 0; i < cipher.length(); i++)
{
if (row == 0)
dir_down = true;
if (row == key - 1)
dir_down = false;
rail[row][col++] = '*';
dir_down ? row++ : row--;
}
int index = 0;
for (int i = 0; i < key; i++)
for (int j = 0; j < cipher.length(); j++)
if (rail[i][j] == '*' && index < cipher.length())
rail[i][j] = cipher[index++];
string result;
row = 0, col = 0;
for (int i = 0; i < cipher.length(); i++)
{
if (row == 0)
dir_down = true;
if (row == key - 1)
dir_down = false;
if (rail[row][col] != '*')
result.push_back(rail[row][col++]);
dir_down ? row++ : row--;
}
return result;
}
int main()
{
string text = "meet me at the park", cipher;
int key = 2;
cout << "\nPlain text: " << text;
cipher = encryptRailFence(text, key);
cout << "\nCipher text: " << cipher << endl;
cout << "\nDeciphered text: " << decryptRailFence(cipher, key) << endl;
return 0;
}

OUTPUT:

Practical 5
Implement the following algorithms:
DES
CODE:
#include <bits/stdc++.h>
using namespace std;
string hex2bin(string s)
{
// hexadecimal to binary conversion
unordered_map<char, string> mp;
mp['0'] = "0000";
mp['1'] = "0001";
mp['2'] = "0010";
mp['3'] = "0011";
mp['4'] = "0100";
mp['5'] = "0101";
mp['6'] = "0110";
mp['7'] = "0111";
mp['8'] = "1000";
mp['9'] = "1001";
mp['A'] = "1010";
mp['B'] = "1011";
mp['C'] = "1100";
mp['D'] = "1101";
mp['E'] = "1110";
mp['F'] = "1111";
string bin = "";
for (int i = 0; i < s.size(); i++)
{
bin += mp[s[i]];
}
return bin;
}
string bin2hex(string s)
{
// binary to hexadecimal conversion
unordered_map<string, string> mp;
mp["0000"] = "0";
mp["0001"] = "1";
mp["0010"] = "2";
mp["0011"] = "3";
mp["0100"] = "4";
mp["0101"] = "5";
mp["0110"] = "6";
mp["0111"] = "7";
mp["1000"] = "8";
mp["1001"] = "9";
mp["1010"] = "A";
mp["1011"] = "B";
mp["1100"] = "C";
mp["1101"] = "D";
mp["1110"] = "E";
mp["1111"] = "F";
string hex = "";
for (int i = 0; i < s.length(); i += 4)
{
string ch = "";
ch += s[i];
ch += s[i + 1];
ch += s[i + 2];
ch += s[i + 3];
hex += mp[ch];
}
return hex;
}
string permute(string k, int *arr, int n)
{
string per = "";
for (int i = 0; i < n; i++)
{
per += k[arr[i] - 1];
}
return per;
}
string shift_left(string k, int shifts)
{
string s = "";
for (int i = 0; i < shifts; i++)
{
for (int j = 1; j < 28; j++)
{
s += k[j];
}
s += k[0];
k = s;
s = "";
}
return k;
}
string xor_(string a, string b)
{
string ans = "";
for (int i = 0; i < a.size(); i++)
{
if (a[i] == b[i])
{
ans += "0";
}
else
{
ans += "1";
}
}
return ans;
}
string encrypt(string pt, vector<string> rkb, vector<string> rk)
{
// Hexadecimal to binary
pt = hex2bin(pt);
// Initial Permutation Table
int initial_perm[64] = {58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7};
// Initial Permutation
pt = permute(pt, initial_perm, 64);
cout << "After initial permutation: " << bin2hex(pt) << endl;
// Splitting
string left = pt.substr(0, 32);
string right = pt.substr(32, 32);
cout << "After splitting: L0=" << bin2hex(left)
<< " R0=" << bin2hex(right) << endl;
// Expansion D-box Table
int exp_d[48] = {32, 1, 2, 3, 4, 5, 4, 5,
6, 7, 8, 9, 8, 9, 10, 11,
12, 13, 12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21, 20, 21,
22, 23, 24, 25, 24, 25, 26, 27,
28, 29, 28, 29, 30, 31, 32, 1};
int s[8][4][16] = {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0,
7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3,
8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5,
0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6,
13},
{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5,
10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11,
5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2,
15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14,
9},
{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2,
8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15,
1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14,
7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2,
12},
{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4,
15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14,
9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8,
4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2,
14},
{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14,
9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8,
6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0,
14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5,
3},
{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5,
11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3,
8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11,
6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8,
13},
{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6,
1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8,
6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9,
2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3,
12},
{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12,
7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9,
2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5,
8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6,
11}};
// Straight Permutation Table
int per[32] = {16, 7, 20, 21,
29, 12, 28, 17,
1, 15, 23, 26,
5, 18, 31, 10,
2, 8, 24, 14,
32, 27, 3, 9,
19, 13, 30, 6,
22, 11, 4, 25};
cout << endl;
for (int i = 0; i < 16; i++)
{
// Expansion D-box
string right_expanded = permute(right, exp_d, 48);
// XOR RoundKey[i] and right_expanded
string x = xor_(rkb[i], right_expanded);
// S-boxes
string op = "";
for (int i = 0; i < 8; i++)
{
int row = 2 * int(x[i * 6] - '0') + int(x[i * 6 + 5] - '0');
int col = 8 * int(x[i * 6 + 1] - '0') + 4 * int(x[i * 6 + 2] -
'0') + 2 * int(x[i * 6 + 3] - '0') + int(x[i * 6 + 4] - '0');
int val = s[i][row][col];
op += char(val / 8 + '0');
val = val % 8;
op += char(val / 4 + '0');
val = val % 4;
op += char(val / 2 + '0');
val = val % 2;
op += char(val + '0');
}
// Straight D-box
op = permute(op, per, 32);
// XOR left and op
x = xor_(op, left);
left = x;
// Swapper
if (i != 15)
{
swap(left, right);
}
cout << "Round " << i + 1 << " " << bin2hex(left) << " "
<< bin2hex(right) << " " << rk[i] << endl;
}
// Combination
string combine = left + right;
// Final Permutation Table
int final_perm[64] = {40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25};
// Final Permutation
string cipher = bin2hex(permute(combine, final_perm, 64));
return cipher;
}
int main()
{
// pt is plain text
string pt, key;
/*cout<<"Enter plain text(in hexadecimal): ";
cin>>pt;
cout<<"Enter key(in hexadecimal): ";
cin>>key;*/
pt = "123456ABCD132536";
key = "AABB09182736CCDD";
// Key Generation
// Hex to binary
key = hex2bin(key);
// Parity bit drop table
int keyp[56] = {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};
// getting 56 bit key from 64 bit using the parity bits
key = permute(key, keyp, 56); // key without parity
// Number of bit shifts
int shift_table[16] = {1, 1, 2, 2,
2, 2, 2, 2,
1, 2, 2, 2,
2, 2, 2, 1};
// Key- Compression Table
int key_comp[48] = {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};
// Splitting
string left = key.substr(0, 28);
string right = key.substr(28, 28);
vector<string> rkb; // rkb for RoundKeys in binary
vector<string> rk; // rk for RoundKeys in hexadecimal
for (int i = 0; i < 16; i++)
{
// Shifting
left = shift_left(left, shift_table[i]);
right = shift_left(right, shift_table[i]);
// Combining
string combine = left + right;
// Key Compression
string RoundKey = permute(combine, key_comp, 48);
rkb.push_back(RoundKey);
rk.push_back(bin2hex(RoundKey));
}
cout << "\nEncryption:\n\n";
string cipher = encrypt(pt, rkb, rk);
cout << "\nCipher Text: " << cipher << endl;
cout << "\nDecryption\n\n";
reverse(rkb.begin(), rkb.end());
reverse(rk.begin(), rk.end());
string text = encrypt(cipher, rkb, rk);
cout << "\nPlain Text: " << text << endl;
}

OUTPUT:
AES
CODE:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
#define Nb 4
int Nr = 0;
int Nk = 0;
// in - the array that holds the plain text to be encrypted.
// out - the array that holds the cipher text.
// state - the array that holds the intermediate results during encryption.
unsigned char in[1024], out[1024], state[4][Nb];
// The array that stores the round keys.
unsigned char RoundKey[240];
// The Key input to the AES Program
unsigned char Key[32];
int getSBoxValue(int num)
{
int sbox[256] = {
// 0 1 2 3 4 5 6 7
// 8 9 A B C D E F
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, // 0
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, // 1
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, // 2
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, // 3
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, // 4
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, // 5
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, // 6
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, // 7
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, // 8
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, // 9
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, // A
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, // B
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, // C
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, // D
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, // E
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}; // F
return sbox[num];
}
// The round constant word array, Rcon[i], contains the values given by
// x to the power (i-1) being powers of x (x is denoted as {02}) in the
// field GF(28). Note that i starts at 1, not 0).
int Rcon[255] = {
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d,
0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91,
0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d,
0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa,
0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66,
0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d,
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f,
0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4,
0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72,
0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a,
0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74,
0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10,
0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab,
0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97,
0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5,
0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2,
0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83,
0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02,
0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc,
0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d,
0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3,
0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33,
0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb};
// This function produces Nb(Nr+1) round keys. The round keys are used in
// each round to encrypt the states.
void KeyExpansion()
{
int i, j;
unsigned char temp[4], k;
// The first round key is the key itself.
for (i = 0; i < Nk; i++)
{
RoundKey[i * 4] = Key[i * 4];
RoundKey[i * 4 + 1] = Key[i * 4 + 1];
RoundKey[i * 4 + 2] = Key[i * 4 + 2];
RoundKey[i * 4 + 3] = Key[i * 4 + 3];
}
// All other round keys are found from the previous round keys.
while (i < (Nb * (Nr + 1)))
{
for (j = 0; j < 4; j++)
{
temp[j] = RoundKey[(i - 1) * 4 + j];
}
if (i % Nk == 0)
{
// This function rotates the 4 bytes in a word to the left once.
// [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
// Function RotWord()
k = temp[0];
temp[0] = temp[1];
temp[1] = temp[2];
temp[2] = temp[3];
temp[3] = k;
// SubWord() is a function that takes a four-byte input word and
// applies the S-box to each of the four bytes to produce an
output
// word.
// Function Subword()
temp[0] = getSBoxValue(temp[0]);
temp[1] = getSBoxValue(temp[1]);
temp[2] = getSBoxValue(temp[2]);
temp[3] = getSBoxValue(temp[3]);
temp[0] = temp[0] ^ Rcon[i / Nk];
}
else if (Nk > 6 && i % Nk == 4)
{
// Function Subword()
temp[0] = getSBoxValue(temp[0]);
temp[1] = getSBoxValue(temp[1]);
temp[2] = getSBoxValue(temp[2]);
temp[3] = getSBoxValue(temp[3]);
}
RoundKey[i * 4 + 0] = RoundKey[(i - Nk) * 4 + 0] ^ temp[0];
RoundKey[i * 4 + 1] = RoundKey[(i - Nk) * 4 + 1] ^ temp[1];
RoundKey[i * 4 + 2] = RoundKey[(i - Nk) * 4 + 2] ^ temp[2];
RoundKey[i * 4 + 3] = RoundKey[(i - Nk) * 4 + 3] ^ temp[3];
i++;
}
}
// This function adds the round key to state.
// The round key is added to the state by an XOR function.
void AddRoundKey(int round)
{
int i, j;
for (i = 0; i < Nb; i++)
{
for (j = 0; j < 4; j++)
{
state[j][i] ^= RoundKey[round * Nb * 4 + i * Nb + j];
}
}
}
// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
void SubBytes()
{
int i, j;
for (i = 0; i < 4; i++)
{
for (j = 0; j < Nb; j++)
{
state[i][j] = getSBoxValue(state[i][j]);
}
}
}
// The ShiftRows() function shifts the rows in the state to the left.
// Each row is shifted with different offset.
// Offset = Row number. So the first row is not shifted.
void ShiftRows()
{
unsigned char temp;
// Rotate first row 1 columns to left
temp = state[1][0];
state[1][0] = state[1][1];
state[1][1] = state[1][2];
state[1][2] = state[1][3];
state[1][3] = temp;
// Rotate second row 2 columns to left
temp = state[2][0];
state[2][0] = state[2][2];
state[2][2] = temp;
temp = state[2][1];
state[2][1] = state[2][3];
state[2][3] = temp;
// Rotate third row 3 columns to left
temp = state[3][0];
state[3][0] = state[3][3];
state[3][3] = state[3][2];
state[3][2] = state[3][1];
state[3][1] = temp;
}
// xtime is a macro that finds the product of {02} and the argument to
// xtime modulo {1b}
#define xtime(x) ((x << 1) ^ (((x >> 7) & 1) * 0x1b))
// MixColumns function mixes the columns of the state matrix
void MixColumns()
{
int i;
unsigned char Tmp, Tm, t;
for (i = 0; i < Nb; i++)
{
t = state[0][i];
Tmp = state[0][i] ^ state[1][i] ^ state[2][i] ^ state[3][i];
Tm = state[0][i] ^ state[1][i];
Tm = xtime(Tm);
state[0][i] ^= Tm ^ Tmp;
Tm = state[1][i] ^ state[2][i];
Tm = xtime(Tm);
state[1][i] ^= Tm ^ Tmp;
Tm = state[2][i] ^ state[3][i];
Tm = xtime(Tm);
state[2][i] ^= Tm ^ Tmp;
Tm = state[3][i] ^ t;
Tm = xtime(Tm);
state[3][i] ^= Tm ^ Tmp;
}
}
// Cipher is the main function that encrypts the PlainText.
void Cipher()
{
int i, j, round = 0;
// Copy the input PlainText to state array.
for (i = 0; i < Nb; i++)
{
for (j = 0; j < 4; j++)
{
state[j][i] = in[i * 4 + j];
}
}
// Add the First round key to the state before starting the rounds.
AddRoundKey(0);
// There will be Nr rounds.
// The first Nr-1 rounds are identical.
// These Nr-1 rounds are executed in the loop below.
for (round = 1; round < Nr; round++)
{
SubBytes();
ShiftRows();
MixColumns();
AddRoundKey(round);
}
// The last round is given below.
// The MixColumns function is not here in the last round.
SubBytes();
ShiftRows();
AddRoundKey(Nr);
// The encryption process is over.
// Copy the state array to output array.
for (i = 0; i < Nb; i++)
{
for (j = 0; j < 4; j++)
{
out[i * 4 + j] = state[j][i];
}
}
}
int fillBlock(int sz, char *str, unsigned char *in)
{
int j = 0;
while (sz < strlen(str))
{
if (j >= Nb * 4)
break;
in[j++] = (unsigned char)str[sz];
sz++;
}
// Pad the block with 0s, if necessary
if (sz >= strlen(str))
for (; j < Nb * 4; j++)
in[j] = 0;
return sz;
}
int main(int argc, char **argv)
{
int i;
int argc;
if (argc != 2)
{
cerr << "Usage: " << argv[0] << " <keysize: 1=128, 2=192, 3=256>\n";
exit(0);
}
switch (atoi(argv[1]))
{
case 1:
Nk = 4;
break;
case 2:
Nk = 6;
break;
case 3:
Nk = 8;
break;
default:
Nk = 4;
break;
}
// Calculate Nr from Nk and, implicitly, from Nb
Nr = Nk + 6;
// The key values are placed here
Key[0] = 0x2b;
Key[1] = 0x7e;
Key[2] = 0x15;
Key[3] = 0x16;
Key[4] = 0x28;
Key[5] = 0xae;
Key[6] = 0xd2;
Key[7] = 0xa6;
Key[8] = 0xab;
Key[9] = 0xf7;
Key[10] = 0x15;
Key[11] = 0x88;
Key[12] = 0x09;
Key[13] = 0xcf;
Key[14] = 0x4f;
Key[15] = 0x3c;
// Get the input string
char str[1024];
fgets(str, 1024, stdin);
// The KeyExpansion routine is called before encryption.
KeyExpansion();
// sz is the cursor into the input string
int sz = 0;
// Each iteration encrypts one block = Nb*4 bytes = 128 bits in this case
while (sz < strlen(str))
{
// Fill the array 'in' with the next plaintext block
sz = fillBlock(sz, str, in);
// The block is encrypted here - the result is in the array 'out'
Cipher();
// Output the encrypted block.
for (i = 0; i < Nb * 4; i++)
cout << (int)out[i] << " ";
}
printf("\n\n");
}

OUTPUT:
RSA
CODE:
#include <iostream>
#include <math.h>
using namespace std;
int gcd(int a, int h)
{
int temp;
while (1)
{
temp = a % h;
if (temp == 0)
return h;
a = h;
h = temp;
}
}
int main()
{
double p = 3;
double q = 7;
double n = p * q;
double count;
double totient = (p - 1) * (q - 1);
double e = 2;
while (e < totient)
{
count = gcd(e, totient);
if (count == 1)
break;
else
e++;
}
double d;
double k = 2;
d = (1 + (k * totient)) / e;
double msg = 12;
double c = pow(msg, e);
double m = pow(c, d);
c = fmod(c, n);
m = fmod(m, n);
cout << "Message data = " << msg;
cout << "\n"
<< "p = " << p;
cout << "\n"
<< "q = " << q;
cout << "\n"
<< "n = pq = " << n;
cout << "\n"
<< "totient = " << totient;
cout << "\n"
<< "e = " << e;
cout << "\n"
<< "d = " << d;
cout << "\n"
<< "Encrypted data = " << c;
cout << "\n"
<< "Original Message sent = " << m;
return 0;
}
OUTPUT:

ElGamel
CODE:
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <cmath>

using namespace std;

// Function to calculate the greatest common divisor


int gcd(int a, int b) {
if (a < b) {
return gcd(b, a);
} else if (a % b == 0) {
return b;
} else {
return gcd(b, a % b);
}
}

// Function to generate a random key


long long int gen_key(long long int q) {
long long int key = rand() % q + pow(10, 20);
while (gcd(q, key) != 1) {
key = rand() % q + pow(10, 20);
}
return key;
}
// Function for modular exponentiation
long long int power(long long int a, long long int b, long long int c) {
long long int x = 1;
long long int y = a;

while (b > 0) {
if (b % 2 != 0) {
x = (x * y) % c;
}
y = (y * y) % c;
b = b / 2;
}

return x % c;
}

// Function for asymmetric encryption


pair<vector<long long int>, long long int> encrypt(string msg, long long int q, long long
int h, long long int g) {
vector<long long int> en_msg;
long long int k = gen_key(q); // Private key for sender
long long int s = power(h, k, q);
long long int p = power(g, k, q);

for (int i = 0; i < msg.length(); i++) {


en_msg.push_back(msg[i]);
}

cout << "g^k used: " << p << endl;


cout << "g^ak used: " << s << endl;

for (int i = 0; i < en_msg.size(); i++) {


en_msg[i] = s * int(en_msg[i]);
}

return make_pair(en_msg, p);


}

// Function to decrypt the message


string decrypt(vector<long long int> en_msg, long long int p, long long int key, long long
int q) {
vector<char> dr_msg;
long long int h = power(p, key, q);

for (int i = 0; i < en_msg.size(); i++) {


dr_msg.push_back(char(en_msg[i] / h));
}

string decrypted_msg(dr_msg.begin(), dr_msg.end());


return decrypted_msg;
}

// Driver code
int main() {
srand(time(0));

string msg = "encryption";


cout << "Original Message: " << msg << endl;

long long int q = rand() % int(pow(10, 50)) + pow(10, 20);


long long int g = int(rand()) % q + 2;

long long int key = gen_key(q); // Private key for receiver


long long int h = power(g, key, q);
cout << "g used: " << g << endl;
cout << "g^a used: " << h << endl;

pair<vector<long long int>, long long int> encrypted = encrypt(msg, q, h, g);


vector<long long int> en_msg = encrypted.first;
long long int p = encrypted.second;
string dmsg = decrypt(en_msg, p, key, q);

cout << "Decrypted Message: " << dmsg << endl;

return 0;
}

OUTPUT:

Rabin
CODE:
#include <iostream>
#include <vector>
#include <random>
#include <string>
#include <cstring>
#include <sstream>
#include <iomanip>

using namespace std;

class Cryptography {
private:
static random_device r;
static mt19937_64 gen;
static uniform_int_distribution<long long> dis;
static const long long TWO = 2;
static const long long THREE = 3;
static const long long FOUR = 4;

static vector<long long> Gcd(long long a, long long b) {


long long s = 0;
long long old_s = 1;
long long t = 1;
long long old_t = 0;
long long r = b;
long long old_r = a;

while (r != 0) {
long long q = old_r / r;
long long tr = r;
r = old_r - q * r;
old_r = tr;

long long ts = s;
s = old_s - q * s;
old_s = ts;

long long tt = t;
t = old_t - q * t;
old_t = tt;
}

vector<long long> result{old_r, old_s, old_t};


return result;
}

public:
static vector<long long> generateKey(int bitLength) {
long long p = blumPrime(bitLength / 2);
long long q = blumPrime(bitLength / 2);
long long N = p * q;
return vector<long long>{N, p, q};
}

static long long encrypt(long long m, long long N) {


return (m * m) % N;
}
static vector<long long> decrypt(long long c, long long p, long long q) {
long long N = p * q;
long long p1 = pow(c, (p + 1) / FOUR);
long long p2 = p - p1;
long long q1 = pow(c, (q + 1) / FOUR);
long long q2 = q - q1;

vector<long long> ext = Gcd(p, q);


long long y_p = ext[1];
long long y_q = ext[2];

long long d1 = (y_p * p * q1 + y_q * q * p1) % N;


long long d2 = (y_p * p * q2 + y_q * q * p1) % N;
long long d3 = (y_p * p * q1 + y_q * q * p2) % N;
long long d4 = (y_p * p * q2 + y_q * q * p2) % N;

return vector<long long>{d1, d2, d3, d4};


}

static long long blumPrime(int bitLength) {


long long p;
do {
p = dis(gen);
} while (p % FOUR != THREE);
return p;
}
};

random_device Cryptography::r;
mt19937_64 Cryptography::gen(Cryptography::r());
uniform_int_distribution<long long> Cryptography::dis(0, 1LL << 62);

int main() {
vector<long long> key = Cryptography::generateKey(512);
long long n = key[0];
long long p = key[1];
long long q = key[2];
string finalMessage;
int i = 1;
string s = "Hello";

cout << "Message sent by sender: " << s << endl;

long long m = 0;
stringstream ss;
ss << hex << s;
ss >> m;

long long c = Cryptography::encrypt(m, n);

cout << "Encrypted Message: " << c << endl;

vector<long long> m2 = Cryptography::decrypt(c, p, q);


for (long long b : m2) {
ostringstream os;
os << hex << b;
string dec(os.str());
string message;
for (size_t i = 0; i < dec.length(); i += 2) {
string byte = dec.substr(i, 2);
char chr = (char)(int)strtol(byte.c_str(), nullptr, 16);
message.push_back(chr);
}
if (message == s) {
finalMessage = message;
}
i++;
}

cout << "Message received by Receiver: " << finalMessage << endl;

return 0;
}

OUTPUT:
SHA-512
CODE:
// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long int int64;

int64 Message[80];

// Stores the hexadecimal values for


// calculating hash values
const int64 Constants[80]
= { 0x428a2f98d728ae22, 0x7137449123ef65cd,
0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
0x3956c25bf348b538, 0x59f111f1b605d019,
0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
0xd807aa98a3030242, 0x12835b0145706fbe,
0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
0x72be5d74f27b896f, 0x80deb1fe3b1696b1,
0x9bdc06a725c71235, 0xc19bf174cf692694,
0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483,
0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
0x983e5152ee66dfab, 0xa831c66d2db43210,
0xb00327c898fb213f, 0xbf597fc7beef0ee4,
0xc6e00bf33da88fc2, 0xd5a79147930aa725,
0x06ca6351e003826f, 0x142929670a0e6e70,
0x27b70a8546d22ffc, 0x2e1b21385c26c926,
0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
0x650a73548baf63de, 0x766a0abb3c77b2a8,
0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001,
0xc24b8b70d0f89791, 0xc76c51a30654be30,
0xd192e819d6ef5218, 0xd69906245565a910,
0xf40e35855771202a, 0x106aa07032bbd1b8,
0x19a4c116b8d2d0c8, 0x1e376c085141ab53,
0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
0x748f82ee5defb2fc, 0x78a5636f43172f60,
0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9,
0xbef9a3f7b2c67915, 0xc67178f2e372532b,
0xca273eceea26619c, 0xd186b8c721c0c207,
0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
0x06f067aa72176fba, 0x0a637dc5a2c898a6,
0x113f9804bef90dae, 0x1b710b35131c471b,
0x28db77f523047d84, 0x32caab7b40c72493,
0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
0x5fcb6fab3ad6faec, 0x6c44198c4a475817 };

// Function to convert a binary string


// to hexa-decimal value
string gethex(string bin)
{
if (bin == "0000")
return "0";
if (bin == "0001")
return "1";
if (bin == "0010")
return "2";
if (bin == "0011")
return "3";
if (bin == "0100")
return "4";
if (bin == "0101")
return "5";
if (bin == "0110")
return "6";
if (bin == "0111")
return "7";
if (bin == "1000")
return "8";
if (bin == "1001")
return "9";
if (bin == "1010")
return "a";
if (bin == "1011")
return "b";
if (bin == "1100")
return "c";
if (bin == "1101")
return "d";
if (bin == "1110")
return "e";
if (bin == "1111")
return "f";
}

// Function to convert a decimal value


// to hexa decimal value
string decimaltohex(int64 deci)
{
// Stores the value as string
string EQBIN = bitset<64>(deci).to_string();

// Stores the equivalent hexa decimal


string hexstring = "";
string temp;

// Traverse the string EQBIN


for (unsigned int i = 0;
i < EQBIN.length(); i += 4) {
temp = EQBIN.substr(i, 4);
hexstring += gethex(temp);
}

// Return the hexstring


return hexstring;
}

// Function to convert a binary


// string to decimal value
int64 BintoDec(string bin)
{

int64 value = bitset<64>(bin)


.to_ullong();
return value;
}

// Function to right rotate x by n bits


int64 rotate_right(int64 x, int n)
{
return (x >> n) | (x << (64 - n));
}

// Function to right shift x by n bits


int64 shift_right(int64 x, int n)
{
return (x >> n);
}

// Function to divide the string


// into chunks
void separator(string getBlock)
{
// Stores the size of chunks
int chunknum = 0;

// Traverse the string S


for (unsigned int i = 0;
i < getBlock.length();
i += 64, ++chunknum) {

// Update the Message[chunknum]


Message[chunknum]
= BintoDec(getBlock.substr(i, 64));
}

// Iterate over the range [16, 80]


for (int g = 16; g < 80; ++g) {

// Find the WordA


int64 WordA = rotate_right(Message[g - 2], 19)
^ rotate_right(Message[g - 2], 61)
^ shift_right(Message[g - 2], 6);

// Find the WordB


int64 WordB = Message[g - 7];

// Find the WordC


int64 WordC = rotate_right(Message[g - 15], 1)
^ rotate_right(Message[g - 15], 8)
^ shift_right(Message[g - 15], 7);

// Find the WordD


int64 WordD = Message[g - 16];

// Find the resultant code


int64 T = WordA + WordB + WordC + WordD;

// Return the resultant Hash Code


Message[g] = T;
}
}

// Function to find the major of a, b, c


int64 maj(int64 a, int64 b, int64 c)
{
return (a & b) ^ (b & c) ^ (c & a);
}

// Function to find the ch value of a,


// b, and c
int64 Ch(int64 e, int64 f, int64 g)
{
return (e & f) ^ (~e & g);
}

// Function to find the Bitwise XOR with


// the right rotate over 14, 18, and 41
int64 sigmaE(int64 e)
{
// Return the resultant value
return rotate_right(e, 14)
^ rotate_right(e, 18)
^ rotate_right(e, 41);
}

// Function to find the Bitwise XOR with


// the right rotate over 28, 34, and 39
int64 sigmaA(int64 a)
{

// Return the resultant value


return rotate_right(a, 28)
^ rotate_right(a, 34)
^ rotate_right(a, 39);
}

// Function to generate the hash code


void Func(int64 a, int64 b, int64 c,
int64& d, int64 e, int64 f,
int64 g, int64& h, int K)
{
// Find the Hash Code
int64 T1 = h + Ch(e, f, g) + sigmaE(e) + Message[K]
+ Constants[K];
int64 T2 = sigmaA(a) + maj(a, b, c);

d = d + T1;
h = T1 + T2;
}

// Function to convert the hash value


// of a given string
string SHA512(string myString)
{
// Stores the 8 blocks of size 64
int64 A = 0x6a09e667f3bcc908;
int64 B = 0xbb67ae8584caa73b;
int64 C = 0x3c6ef372fe94f82b;
int64 D = 0xa54ff53a5f1d36f1;
int64 E = 0x510e527fade682d1;
int64 F = 0x9b05688c2b3e6c1f;
int64 G = 0x1f83d9abfb41bd6b;
int64 H = 0x5be0cd19137e2179;

int64 AA, BB, CC, DD, EE, FF, GG, HH;

stringstream fixedstream;
// Traverse the string S
for (int i = 0;
i < myString.size(); ++i) {

// Add the character to stream


fixedstream << bitset<8>(myString[i]);
}

// Stores string of size 1024


string s1024;

// Stores the string in the


// fixedstream
s1024 = fixedstream.str();

// Stores the length of string


int orilen = s1024.length();
int tobeadded;

// Find modded string length


int modded = s1024.length() % 1024;

// If 1024-128 is greater than modded


if (1024 - modded >= 128) {
tobeadded = 1024 - modded;
}

// Else if 1024-128 is less than modded


else if (1024 - modded < 128) {
tobeadded = 2048 - modded;
}

// Append 1 to string
s1024 += "1";

// Append tobeadded-129 zeros


// in the string
for (int y = 0; y < tobeadded - 129; y++) {
s1024 += "0";
}

// Stores the binary representation


// of string length
string lengthbits
= std::bitset<128>(orilen).to_string();

// Append the lengthbits to string


s1024 += lengthbits;

// Find the count of chunks of


// size 1024 each
int blocksnumber = s1024.length() / 1024;
// Stores the numbering of chunks
int chunknum = 0;

// Stores hash value of each blocks


string Blocks[blocksnumber];

// Traverse the string s1024


for (int i = 0; i < s1024.length();
i += 1024, ++chunknum) {
Blocks[chunknum] = s1024.substr(i, 1024);
}

// Traverse the array Blocks[]


for (int letsgo = 0;
letsgo < blocksnumber;
++letsgo) {

// Divide the current string


// into 80 blocks size 16 each
separator(Blocks[letsgo]);

AA = A;
BB = B;
CC = C;
DD = D;
EE = E;
FF = F;
GG = G;
HH = H;

int count = 0;

// Find hash values


for (int i = 0; i < 10; i++) {

// Find the Hash Values

Func(A, B, C, D, E, F, G, H, count);
count++;
Func(H, A, B, C, D, E, F, G, count);
count++;
Func(G, H, A, B, C, D, E, F, count);
count++;
Func(F, G, H, A, B, C, D, E, count);
count++;
Func(E, F, G, H, A, B, C, D, count);
count++;
Func(D, E, F, G, H, A, B, C, count);
count++;
Func(C, D, E, F, G, H, A, B, count);
count++;
Func(B, C, D, E, F, G, H, A, count);
count++;
}
// Update the value of A, B, C,
// D, E, F, G, H

A += AA;
B += BB;
C += CC;
D += DD;
E += EE;
F += FF;
G += GG;
H += HH;
}

stringstream output;

// Print the hexadecimal value of


// strings as the resultant SHA-512
output << decimaltohex(A);
output << decimaltohex(B);
output << decimaltohex(C);
output << decimaltohex(D);
output << decimaltohex(E);
output << decimaltohex(F);
output << decimaltohex(G);
output << decimaltohex(H);

// Return the string


return output.str();
}

// Driver Code
int main()
{
// Input
string S = "GeeksForGeeks";

// Function Call
cout << S << ": " << SHA512(S);

return 0;
}

OUTPUT:
Practical 6: Implement the digital signature schemes: RSA
and ElGamal:
RSA
CODE:
#include <iostream>
#include <vector>

using namespace std;

int euclid(int m, int n) {


if (n == 0) {
return m;
} else {
int r = m % n;
return euclid(n, r);
}
}

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 make_pair(r1, t1);


}

int main() {
int p = 823;
int q = 953;
int n = p * q;
int Pn = (p - 1) * (q - 1);

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;
pair<int, int> result = exteuclid(Pn, e);
int r = result.first;
int d = result.second;

if (r == 1) {
d = d < 0 ? d + Pn : d;
cout << "decryption key is: " << d << endl;
} else {
cout << "Multiplicative inverse for the given encryption key does not exist.
Choose a different encryption key" << 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) {
cout << "As M = M1, Accept the message sent by Alice" << endl;
} else {
cout << "As M not equal to M1, Do not accept the message sent by Alice" << endl;
}

return 0;
}

OUTPUT:

ElGamal
CODE:
#include <iostream>
#include <random>
#include <cmath>

using namespace std;

int inverse(int k, int m) {


k = k % m;
for (int x = 1; x < m; x++) {
if ((k * x) % m == 1) {
return x;
}
}
return 1;
}

pair<int, int> pair(int s) {


int safe_prime = 0;
while (true) {
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<int> dis(2, pow(2, s));

int p = dis(gen);
safe_prime = 2 * p + 1;
if (pow(2, safe_prime - 1) % safe_prime == 1) {
break;
}
}

while (true) {
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<int> dis(2, safe_prime - 1);

int a = dis(gen);
if ((safe_prime - 1) % a != 1) {
break;
}
}
return make_pair(safe_prime, a);
}

tuple<int, int, int, int> egKey(int s) {


auto p_a = pair(s);
int p = p_a.first;
int a = p_a.second;

random_device rd;
mt19937 gen(rd());
uniform_int_distribution<int> dis(1, p - 2);
int x = dis(gen);

int y = pow(a, x) % p;
return make_tuple(p, a, x, y);
}

tuple<int, int> egGen(int p, int a, int x, int m) {


while (true) {
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<int> dis(1, p - 2);
int k = dis(gen);

if (__gcd(k, p - 1) == 1) {
int r = pow(a, k) % p;
int l = inverse(k, p - 1);
int s = (l * (m - x * r)) % (p - 1);
return make_tuple(r, s);
}
}
}

bool egVer(int p, int a, int y, int r, int s, int m) {


if (r < 1 || r > p - 1) {
return false;
}

int v1 = (int)(pow(y, r) % p * pow(r, s) % p);


int v2 = (int)pow(a, m) % p;

return v1 == v2;
}

int main() {
int message = 36;
cout << "Message: " << message << endl;

tuple<int, int, int, int> key = egKey(10);


int prime = get<0>(key);
int alpha = get<1>(key);
int private_key = get<2>(key);
int public_key = get<3>(key);
cout << "prime,alpha,private,public: " << prime << "," << alpha << "," <<
private_key << "," << public_key << endl;

tuple<int, int> generated = egGen(prime, alpha, private_key, message);


int rr = get<0>(generated);
int ss = get<1>(generated);
cout << "rr,ss: " << rr << "," << ss << endl;

bool is_valid = egVer(prime, alpha, public_key, rr, ss, message);


cout << "Valid Signature: " << (is_valid ? "true" : "false") << endl;

return 0;
}

OUTPUT:

You might also like