Secure Client-Server Communication with Encryption Techniques

int connectToServer(const char* ip, int port) { CLIENT 13
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr = {AF_INET, htons(port), inet_addr(ip)};
if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
cout << “\nRun server program first.” << endl;
exit(0); }
else
cout << “\nClient is connected to Server.” << endl;
return sock; }
int randInRange(int low, int high) {
return (rand() % (high – (low + 1))) + (low + 1); }
long powermod(long a, long b, long q) {
long res = 1;
for (long i = 0; i < b; i++)
res = (res * a) % q;
return res; }
int main() {
char ip[50];
cout << “\nEnter server’s IP address: “; cin >> ip;
int port; cout << “Enter port: “;
cin >> port;
int sock = connectToServer(ip, port);
long q, alpha;
cout << “\nEnter a prime number, q: “;
cin >> q;
cout << “Enter primitive root of q, alpha: “;
cin >> alpha;
srand(time(NULL));
long Xc = randInRange(1, q);
cout << “\nClient’s private key, Xc = ” << Xc << endl;
long Yc = powermod(alpha, Xc, q);
send(sock, &Yc, sizeof(Yc), 0);
cout << “Client’s public key, Yc = ” << Yc << endl;


string GenKey() { 3rd
string alpha = “abcdefghijklmnopqrstuvwxyz”;
string key = “abcdefghijklmnopqrstuvwxyz”;
random_device rd;
shuffle(key.begin(), key.end(), rd);
cout << “\nAlphabets: ” << alpha;
cout << “\nKey generated: ” << key;
return key; }
void MapKey(unordered_map &enKeyMap, unordered_map &deKeyMap, string key) {
string alpha = “abcdefghijklmnopqrstuvwxyz”;
for (int i = 0; i < 26; i++) {
enKeyMap[alpha[i]] = key[i];
deKeyMap[key[i]] = alpha[i]; } }
string Encrypt(string pText, unordered_map enKeyMap) {
string cText = “”;
for (int i = 0; i < pText.length(); i++) {
cText += enKeyMap[pText[i]]; }
return cText; }
void Decrypt(string &cText, unordered_map deKeyMap) {
cout << “After decryption: “;
for (int i = 0; i < cText.length(); i++) {
cout << deKeyMap[cText[i]]; }
cout << endl; }
void ShowFrequency(string pText, unordered_map enKeyMap) {
float fTable[26] = {0.000};
for (int i = 0; i < pText.length(); i++) {
fTable[pText[i] – ‘a’]++; }
cout << endl << “Frequency \t Plain Char \t Cipher Char” << endl;
for (int i = 0; i < pText.length(); i++) {
cout << fixed << setprecision(3) << (fTable[pText[i] – ‘a’] / pText.length()) << “\t\t ” << pText[i] << “\t\t ” << enKeyMap[pText[i]] << endl; } }


4th continuation

for (int i = 0; i < key.length(); i++) {
newkey += to_string(sortkey.find(key[i]) + 1); }
return newkey;
}
int main() {
int n;
cout << “Enter the value of n: “;
cin >> n;
string plaintext, key, k, ciphertext, decryptext;
cout << “Enter text: “;
cin >> plaintext;
cout << “Enter key: “;
cin >> k;
key = format(k);
int i = 1;
while (n > 0) {
cout << “LEVEL ” << i << endl;
ciphertext = encrypt(plaintext, key);
plaintext = ciphertext;
n–;
i++; }
n = i – 1, i = 1;
while (n > 0) {
cout << “LEVEL ” << i << endl;
decryptext = decrypt(ciphertext, key);
ciphertext = decryptext;
n–;
i++; }
return 0; }


string encrypt(string pt, string key) { 4th
string ct = “”;
int cols = key.length();
while (pt.length() % cols != 0) pt += ‘x’;
int rows = pt.length() / cols;
char mat[rows][cols];
int k = 0;
cout << “\nEncryption Matrix:” << endl;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
cout << (mat[i][j] = pt[k++]) << ” “; }
cout << endl; }
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++)
ct += mat[j][key.find(i + ‘1’)]; }
cout << “\nEncrypted text: ” << ct << endl;
return ct; }


string decrypt(string ct, string key) {
string pt = “”;
int cols = key.length();
int rows = ct.length() / cols;
char mat[rows][cols];
int k = 0;
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
mat[j][key.find(i + ‘1’)] = ct[k++]; } }
cout << “\nDecryption Matrix:” << endl;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
cout << mat[i][j] << ” “;
pt += mat[i][j]; }
cout << endl; }
cout << “\nDecrypted text: ” << pt << endl;
return pt; }


string format(string key) {

string sortkey = key, newkey = “”;
sort(sortkey.begin(), sortkey.end());


string leftshift(string text, int n) {
return text.substr(n, text.length() – n) + text.substr(0, n); }
string firstPermute(string key) {
string res = “”;
for (int i = 0; i < 56; i++)
res += key[permute_one[i] – 1];
return res;
}
string secondPermute(string key) {
string res = “”;
for (int i = 0; i < 48; i++)
res += key[permute_two[i] – 1];
return res; }
void gen_keys(string left, string right) {
string key;
for (int i = 0; i < 16; i++) {
left = leftshift(left, leftshiftTable[i]);
right = leftshift(right, leftshiftTable[i]);
key = secondPermute(left + right);
cout << “key ” << i + 1 << ” : ” << key << endl;
} }


int main() {
unsigned long long key;
cout << endl << “Enter 64 bit key in hexadecimal 16 digits: “;
cin >> hex >> key;
string binarykey = bitset<64>(key).to_string();
cout << endl << “Binary key: ” << binarykey << endl;
binarykey = firstPermute(binarykey);
cout << endl << “PC-1 key (k+): ” << binarykey << endl << endl;
gen_keys(binarykey.substr(0, 28), binarykey.substr(28, 28));
return 0;
}


int main() {
unsigned long long hexa, key_hex;
string binary;
cout << “Enter the 16 bit hexadecimal input:” << endl;
cin >> hex >> hexa;
binary = bitset<64>(hexa).to_string();
string key;
cout << “Enter the 12 bit hexadecimal key:” << endl;
cin >> hex >> key_hex;
key = bitset<48>(key_hex).to_string();
cout << “\nRound Function\n” << endl;
string left = binary.substr(0, 32);
string right = binary.substr(32, 32);
string expRight = expansion(right, ETable);
cout << “After expansion, right half will be: ” << expRight << endl;
cout << “Key is: ” << (key) << endl;
string sb_ip = xor_operation(expRight, key);
cout << “S-box operation\n”;
cout << “The 48 bit input for S-box will be: ” << sb_ip << endl;
string sBoxOutput = substitution(sb_ip);
cout << “\nS-Box output = ” << sBoxOutput << endl;
string P = permute(sBoxOutput);
cout << “Permuted output = ” << P << endl;
string Ri = xor_operation(P, left);
cout << “\nOutput of ith round (Ri) = ” << Ri << endl << endl;
return 0; }

string expansion(string ip, int *Etable) {
string res = “”;
for (int i = 0; i < 48; i++)
res += ip[Etable[i] – 1];
return res;
}


string w[44];
string rotLeft(string word) {
return word.substr(8) + word.substr(0, 8); }
string SBoxFun(string word) {
string res = “”;
for (int i = 0; i < 4; i++) {
string byte = word.substr(i * 8, 8);
int row = bitset<4>(byte.substr(0, 4)).to_ulong();
int col = bitset<4>(byte.substr(4, 4)).to_ulong();
res += bitset<8>(sbox[row][col]).to_string(); }
return res; }
string XOR(string x, string y) {
string res = “”;
for (int i = 0; i < x.length(); i++)
res += (x[i] == y[i]) ? “0” : “1”;
return res; }


int main() {
unsigned long long hexkey1, hexkey2;
cout << endl << “\nEnter first 64-bit key in hexadecimal (16-digits): “;
cin >> hex >> hexkey1;
cout << endl << “\nEnter next 64-bit key in hexadecimal (16-digits): “;
cin >> hex >> hexkey2;
string key = bitset<64>(hexkey1).to_string() + bitset<64>(hexkey2).to_string();
cout << endl << “Binary key (k): ” << key << endl;
cout << endl << “keyLen: ” << key.length() << endl << endl;
for (int i = 0; i < 4; i++) {
w[i] = key.substr(i * 32, 32); }
for (int i = 4; i < 44; i++) {
string first = w[i – 4];
string second = w[i – 1];
if (i % 4 == 0) {
second = rotLeft(second);
second = SBoxFun(second);
string tmp = bitset<32>(Rcon[i / 4 – 1]).to_string();
second = XOR(second, tmp); } }



int Sbox_subst(int input) {
return sbox[input / 16][input % 16]; }
int main() {
string msg;
cout << “Enter message (16 digits) 128-bit message: “;
cin >> msg;
int mat[4][4];
for (int i = 0; i < 16; i++) {
int ascii = msg[i];
mat[i % 4][i / 4] = ascii; }
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
cout << hex << mat[i][j] << ” “; }
cout << endl; }
int init[4][4];
cout << “\nInitial Transposition Matrix:\n”;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
init[i][j] = mat[i][j] ^ key[i][j];
cout << hex << init[i][j] << ” “; }
cout << endl; }
cout << “\nSubstituted Matrix:\n\n”;
int subst[4][4];
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
subst[i][j] = Sbox_subst(init[i][j]);
cout << hex << subst[i][j] << ” “; }
cout << endl; }
cout << “\nShift rows Matrix:\n\n”;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
cout << hex << subst[i][(j + i) % 4] << ” “; }
cout << endl; }
return 0;
}


int main() {
string plaintext;
cout << “Enter message: “;
cin >> plaintext;
string key;
cout << “\nEnter key: “;
cin >> key;
int n = plaintext.length();
int pt[256];
cout << “Plain text: “;
for (int i = 0; i < n; i++) {
pt[i] = (int)plaintext[i];
cout << pt[i] << ” “; }
int S[256], T[256];
for (int i = 0; i < 256; i++) {
S[i] = i;
T[i] = (int)key[i % key.length()]; }
int j = 0;
for (int i = 0; i < 256; i++) {
j = (j + S[i] + T[i]) % 256;
swap(S[i], S[j]); }
int keyStream[256];
cout << “\nKey Stream: “;
j = 0;
for (int i = 0; i < n; i++) {
j = (j + S[i]) % 256;
swap(S[i], S[j]);
int t = (S[i] + S[j]) % 256;
keyStream[i] = S[t];
cout << keyStream[i] << ” “; }
int ct[256];
cout << “\n\nENCRYPTION” << endl;
cout << “Cipher Text: “;
for (int i = 0; i < n; i++) {
ct[i] = pt[i] ^ keyStream[i]; // xor
cout << ct[i] << ” “; }


int randInRange(int low, int high) {
return rand() % (high – (low + 1)) + (low + 1); }
int genPrime3mod4() {
while (true) {
int num = randInRange(10000, 100000);
if (num % 4 != 3)
continue;
bool prime = true;
for (int i = 2; i <= sqrt(num); i++) {
if (num % i == 0) {
prime = false;
break; } }
if (prime)
return num; } }

int bbs(int p, int q) {
long long n = (long long)p * q;
long long s;
do {
s = rand();
} while (s % p == 0 || s % q == 0 || s == 0);
long long x = (s * s) % n;
int B = 0;
for (int i = 0; i < 10; i++) {
x = (x * x) % n;
B = B << 1 | (x & 1); // x % 2 = x & 1 }
cout << “Blum Blum Shub” << endl << “————–” << endl;
cout << “p = ” << p << “\nq = ” << q << “\nn = ” << n << “\ns = ” << s << endl;
return B; }


unsigned long long powModN(int a, int b, int n) {
unsigned long long res = 1;
for (int i = 0; i < b; i++) {
res = ((unsigned long long)(res * a)) % n; }
return res; }


string rabinMiller(int n) {
int k = 0;
int q = n – 1;
while (q % 2 == 0) {
q = q / 2;
k++; }
int a = randInRange(1, n – 1);
cout << “\nRabin Miller(” << n << “)\n—————–” << endl;
cout << n – 1 << ” = 2^” << k << ” * ” << q << endl;
cout << “k = ” << k << “\nq = ” << q << “\na = ” << a << endl;
if (powModN(a, q, n) == 1)
return “inconclusive”;
for (int j = 0; j < k; j++) {
if (powModN(a, pow(2, j) * q, n) == n – 1)
return “inconclusive”; }
return “composite”; }


int main() {
srand(time(NULL));
int p = genPrime3mod4();
int q = genPrime3mod4();
int randNum = bbs(p, q);
cout << “Random number generated by BBS = ” << randNum << endl;
cout << rabinMiller(randNum) << endl;


int createServer(int port) { SERVER 13
int sersock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr = {AF_INET, htons(port), INADDR_ANY};
bind(sersock, (struct sockaddr *) &addr, sizeof(addr));
cout << “\nServer Online. Waiting for client….” << endl;
listen(sersock, 5);
int sock = accept(sersock, NULL, NULL);
cout << “Connection Established.” << endl;
return sock; }


int randInRange(int low, int high) {
return (rand() % (high – (low + 1))) + (low + 1); }


long powermod(long a, long b, long q) {
long res = 1;
for (long i = 0; i < b; i++)
res = (res * a) % q;
return res; }


int main() {
int port; cout << “\nEnter port: “;
cin >> port;
int sock = createServer(port);
long q, alpha;
cout << “\nEnter a prime number, q: “; cin >> q;
cout << “Enter primitive root of q, alpha: “; cin >> alpha;
long Yc; recv(sock, &Yc, sizeof(Yc), 0);
cout << “\nClient’s public key, Yc = ” << Yc << endl;
srand(time(NULL));
long Xs = randInRange(1, q);
cout << “\nServer’s private key, Xs = ” << Xs << endl;
long Ys = powermod(alpha, Xs, q);
send(sock, &Ys, sizeof(Ys), 0);
cout << “Server’s public key, Ys = ” << Ys << endl;


int powermod(int a, int b, int n) { 11th server
int res = 1;
for (int i = 0; i < b; i++)
res = (res * a) % n;
return res; }


int encrypt(int M, int PU[2]) {
return powermod(M, PU[0], PU[1]); }


int toInt(char c) {
return (c < ‘a’) ? (c – ‘A’ + 26) : (c – ‘a’); }


int main() {
int port;
cout << “Enter port: “; cin >> port;
int sock = createServer(port);
int PU[2];
recv(sock, &PU, sizeof(PU), 0);
cout << “\nPublic key received from client: {” << PU[0] << “, ” << PU[1] << “}” << endl;
string msg;
cout << “\nEnter message to encrypt: “;
cin >> msg;
if (msg.length() % 2 != 0)
msg += “x”;
for (int i = 0; i < msg.length(); i += 2) {
int M = toInt(msg[i]) * 100 + toInt(msg[i + 1]);
cout << “\nPlaintext block: ” << M << endl;
int C = encrypt(M, PU);
cout << “Encrypted text: ” << C << endl;
send(sock, &C, sizeof(C), 0); }


int stop = -1;
send(sock, &stop, sizeof(stop), 0);
cout << “\nSent ciphertext to client.” << endl << endl;
}


int randInRange(int low, int high) {
return rand() % (high – (low + 1)) + (low + 1); } 11th client
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b); }


int powermod(int a, int b, int n) {
int res = 1; for (int i = 0; i < b; i++)
res = (res * a) % n;
return res; }


int decrypt(int C, int PR[2]) {
return powermod(C, PR[0], PR[1]); }


char toChar(int n) {
return (n >= 26) ? (n + ‘A’ – 26) : (n + ‘a’); }


int main() {
char ip[50]; int port;
cout << “Enter Server’s IP address: “; cin >> ip;
cout << “Enter port: “; cin >> port;
int sock = connectToServer(ip, port);
int p, q;
cout << “\nEnter two large prime numbers (>100): “; cin >> p >> q;
int n = p * q;
int phi = (p – 1) * (q – 1);
srand(time(NULL));
int e, d; do {
e = randInRange(1, phi); } while (gcd(e, phi) != 1);
for (d = 1; d < phi; d++)
if ((d * e) % phi == 1)
break;
int PU[2] = {e, n};
int PR[2] = {d, n};
cout << “\nPublic key, PU = {” << e << “, ” << n << “}” << endl;
cout << “Private key, PR = {” << d << “, ” << n << “}” << endl;
send(sock, &PU, sizeof(PU), 0);
cout << “\nSent Public key to server.” << endl;