Ilovepdf Merged

Download as pdf or txt
Download as pdf or txt
You are on page 1of 73

BCSE309P – Cryptography and Network Security Laboratory

Name: Mohamed Rasheed Ahamed

Register No: 21BCE5570

Course Code: BCSE309P

Ex. No. 1: Implementation of Classical Cryptography 06-01-2024

TASK:
1. Write a socket program to demonstrate Caesar Cipher.
AIM:
Develop a socket program in C to showcase the implementation of Caesar Cipher, demonstrating
encryption and decryption functionalities between a client and server.
ALGORITHM:
1. Server Side:
a. Create a socket using socket().
b. Set socket options using setsockopt().
c. Bind the socket to a specific address and port using bind().
d. Listen for incoming connections using listen().
e. Accept the connection from the client using accept().
f. Receive the plain text and key from the client using recv().
g. Encrypt the plain text using the Caesar Cipher algorithm.
h. Send the encrypted text back to the client using send().
i. Close the connected socket and the listening socket.

2. Client Side:
a. Create a socket using socket().
b. Define the server address and port.
c. Connect to the server using connect().
d. Input the plain text and key from the user.
e. Send the plain text and key to the server using send().
f. Receive the encrypted text from the server using recv().
g. Display the encrypted text.
h. Close the connected socket.

CODE:
Server code:
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <ctype.h>
#define PORT 8080
int main(int argc, char const* argv[])
{
int server_fd, new_socket;
ssize_t valread;
struct sockaddr_in address;
int opt = 1;
socklen_t addrlen = sizeof(address);
char buffer[1024] = { 0 };

// Creating socket file descriptor


if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}

// Forcefully attaching socket to the port 8080


if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt,
sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);

// Forcefully attaching socket to the port 8080


if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket= accept(server_fd, (struct sockaddr*)&address,&addrlen))< 0) {
perror("accept");
exit(EXIT_FAILURE);
}

//Receiving plain text and key to server side


char plainText[20];
int key;

if (recv(new_socket, &plainText, sizeof(plainText), 0) < 0) {


perror("Failed to receive plain text\n");
exit(EXIT_FAILURE);
}
if (recv(new_socket, &key, sizeof(key), 0) < 0) {
perror("Failed to receive key\n");
exit(EXIT_FAILURE);
}
printf("Received Plain Text from the client\n");

// Converting plain text to Caeser cipher text

char* cipherText = malloc(strlen(plainText) + 1);

for (int i = 0; i < strlen(plainText); i++) {


if (isupper(plainText[i]))
cipherText[i] = (plainText[i] + key - 'A') % 26 + 'A';
else
cipherText[i] = (plainText[i] + key - 'a') % 26 + 'a';
}

cipherText[strlen(plainText)] = '\0';

send(new_socket, cipherText, strlen(cipherText), 0);


printf("Caeser Cipher text has been sent to client\n");

// closing the connected socket


close(new_socket);
// closing the listening socket
close(server_fd);
return 0;
}
Client code:

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#define PORT 8080

int main(int argc, char const* argv[])


{
int status, valread, client_fd;
struct sockaddr_in serv_addr;
char buffer[1024] = { 0 };
if ((client_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Socket creation error \n");
return -1;
}

serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);

// Convert IPv4 and IPv6 addresses from text to binary


// form
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<= 0) {
printf("\nInvalid address/ Address not supported \n");
return -1;
}

if ((status = connect(client_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)))< 0) {


printf("\nConnection Failed \n");
return -1;
}

// Receiving text and shift


char plainText[20];
int key;
printf("Enter the Plain text: ");
scanf("%s", plainText);
printf("Enter the key: ");
scanf("%d", &key);

//Sending plain text and key to server side


if (send(client_fd, &plainText, sizeof(plainText), 0) < 0) {
perror("Failed to send plain text\n");
exit(EXIT_FAILURE);
}
if (send(client_fd, &key, sizeof(key), 0) < 0) {
perror("Failed to send key\n");
exit(EXIT_FAILURE);
}
printf("The plain text and key has been sent\n");

valread = read(client_fd, buffer, 1024 - 1);


printf("The Caeser Cipher Text is: %s\n", buffer);
// closing the connected socket
close(client_fd);
return 0;
}
OUTPUT:
server side:

Client side:
2. Write a socket program to demonstrate Rail Fence Cipher.
AIM:
Create a C socket program to illustrate Rail Fence Cipher, showcasing encryption and decryption
processes through communication between a client and server.
ALGORITHM:
Server Side:
a. Create a socket using socket().
b. Set socket options using setsockopt().
c. Bind the socket to a specific address and port using bind().
d. Listen for incoming connections using listen().
e. Accept the connection from the client using accept().
f. Receive the plain text from the client using recv().
g. Remove spaces from the received plain text using removeSpaces().
h. Encrypt the plain text using the Rail Fence Cipher algorithm.
i. Send the encrypted text back to the client using send().
j. Close the connected socket and the listening socket.

Client Side:
a. Create a socket using socket().
b. Define the server address and port.
c. Connect to the server using connect().
d. Input the plain text from the user.
e. Send the plain text to the server using send().
f. Receive the encrypted text from the server using recv().
g. Display the encrypted text in uppercase.
h. Close the connected socket.

CODE:
Server code:
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <ctype.h>

#define MAX_BUFFER_SIZE 1024


#define PORT 8080

void removeSpaces(char* text) {


// Remove spaces
int l = strlen(text);
int j = 0;
for (int i = 0;i<l;i++) {
if (text[i] != ' ') {
text[j++] = text[i];
}
}
text[j] = '\0';
}
//void railFenceCipher
int main(int argc, char const* argv[])
{
int server_fd, new_socket;
ssize_t valread;
struct sockaddr_in address;
int opt = 1;
socklen_t addrlen = sizeof(address);
char buffer[1024] = { 0 };

// Creating socket file descriptor


if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}

// Forcefully attaching socket to the port 8080


if (setsockopt(server_fd, SOL_SOCKET,SO_REUSEADDR | SO_REUSEPORT, &opt,
sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);

// Forcefully attaching socket to the port 8080


if (bind(server_fd, (struct sockaddr*)&address,sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket= accept(server_fd, (struct sockaddr*)&address,&addrlen))< 0) {
perror("accept");
exit(EXIT_FAILURE);
}
//Receiving plain text and key to server side
char plainText[MAX_BUFFER_SIZE];
int key;

if (recv(new_socket, &plainText, sizeof(plainText), 0) < 0) {


perror("Failed to receive plain text\n");
exit(EXIT_FAILURE);
}
printf("Received Plain Text from the client\n");

removeSpaces(plainText);

// Converting plain text to Rail Fence cipher text

int size = sizeof(plainText);


char cipherText[size];
int j = 0;
for (int i=0;i<size;i=i+2) {
if (!(isalpha(plainText[i]))) {
break;
}
cipherText[j] = plainText[i];
j++;
}
j = j-2;
for (int i=1;i<size;i=i+2) {
if (!(isalpha(plainText[i]))) {
break;
}
cipherText[j] = plainText[i];
j++;
}

send(new_socket, cipherText, strlen(cipherText), 0);


printf("Rail Fence Cipher text has been sent to client\n");

// closing the connected socket


close(new_socket);
// closing the listening socket
close(server_fd);
return 0;
}
Client code:
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>

#define MAX_BUFFER_SIZE 1024


#define PORT 8080

int main(int argc, char const* argv[])


{
int status, valread, client_fd;
struct sockaddr_in serv_addr;

char buffer[1024] = { 0 };
if ((client_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Socket creation error \n");
return -1;
}

serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);

// Convert IPv4 and IPv6 addresses from text to binary


// form
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<= 0) {
printf("\nInvalid address/ Address not supported \n");
return -1;
}

if ((status = connect(client_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)))< 0) {


printf("\nConnection Failed \n");
return -1;
}

// Receiving text
char plainText[MAX_BUFFER_SIZE];
printf("Enter the Plain text: ");
fgets(plainText, sizeof(plainText), stdin);
plainText[strcspn(plainText, "\n")] = '\0';
//Sending plain texT to server side
if (send(client_fd, &plainText, sizeof(plainText), 0) < 0) {
perror("Failed to send plain text\n");
exit(EXIT_FAILURE);
}

char cipherText[sizeof(plainText)];
if (recv(client_fd, &cipherText, sizeof(cipherText), 0) < 0) {
perror("Failed to receive cipher text\n");
exit(EXIT_FAILURE);
}

printf("The Rail Fence Cipher Text is: ");

for (int i=0;cipherText[i] != '\0';i++) {


putchar(toupper((char)cipherText[i]));
}
printf("\n");
// closing the connected socket
close(client_fd);
return 0;
}

OUTPUT:
Server side:

Client side:
3. Write a socket program to demonstrate Playfair Cipher.
AIM:
Construct a C socket program to exhibit Playfair Cipher, highlighting encryption and decryption
functionalities during communication between a client and server.
ALGORITHM:
Server Side:
a. Create a socket using socket().
b. Set socket options using setsockopt().
c. Bind the socket to a specific address and port using bind().
d. Listen for incoming connections using listen().
e. Accept the connection from the client using accept().
f. Receive the cipher text from the client using recv().
g. Print the received cipher text.
h. Close the connected socket and the listening socket.

Client Side:
a. Create a socket using socket().
b. Define the server address and port.
c. Connect to the server using connect().
d. Input the plain text and key from the user.
e. Create the Playfair matrix using the key.
f. Encrypt the plain text using the Playfair cipher algorithm.
g. Send the cipher text to the server using send().
h. Print a success message.
i. Close the connected socket.

CODE:
Server code:
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <ctype.h>

#define PORT 8080


#define MAX_BUFFER_SIZE 1024

int main(int argc, char const* argv[])


{
int server_fd, new_socket;
ssize_t valread;
struct sockaddr_in address;
int opt = 1;
socklen_t addrlen = sizeof(address);
char buffer[1024] = { 0 };

// Creating socket file descriptor


if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}

// Forcefully attaching socket to the port 8080


if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt,
sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);

// Forcefully attaching socket to the port 8080


if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket= accept(server_fd, (struct sockaddr*)&address,&addrlen))< 0) {
perror("accept");
exit(EXIT_FAILURE);
}
//Receiving plain text and key to server side
char cipherText[MAX_BUFFER_SIZE];

if (recv(new_socket, &cipherText, sizeof(cipherText), 0) < 0) {


perror("Failed to receive plain text\n");
exit(EXIT_FAILURE);
}
printf("Received Cipher Text from the client\n");

printf("The Cipher text is: %s\n", cipherText);

// closing the connected socket


close(new_socket);
// closing the listening socket
close(server_fd);
return 0;
}
Client code:
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>

#define PORT 8080

#define SIZE 5
#define MAX_BUFFER_SIZE 1024

char keyMatrix[SIZE][SIZE];
char cipherText[MAX_BUFFER_SIZE];
int x = 0;

// Function to create and return a 5x5 matrix based on the keyword


void createMatrix(char keyword[]) {
char alphabet[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int k = 0;

// Add each letter of the keyword to the matrix


for (int i = 0; i < strlen(keyword); i++) {
char currentChar = keyword[i];
// Skip 'I' (considered the same as 'J' in Playfair cipher)
if (currentChar == 'I') {
continue;
}

// Check if the letter is not already in the matrix


int found = 0;
for (int row = 0; row < SIZE && !found; row++) {
for (int col = 0; col < SIZE; col++) {
if (keyMatrix[row][col] == currentChar) {
found = 1;
break;
}
}
}

if (!found) {
keyMatrix[k / SIZE][k % SIZE] = currentChar;
k++;
}
}

// Add the remaining letters of the alphabet to the matrix


for (int i = 0; i < 26; i++) {
char currentChar = alphabet[i];

// Skip 'I' (considered the same as 'J' in Playfair cipher)


if (currentChar == 'I') {
continue;
}

// Check if the letter is not already in the matrix


int found = 0;
for (int row = 0; row < SIZE && !found; row++) {
for (int col = 0; col < SIZE; col++) {
if (keyMatrix[row][col] == currentChar) {
found = 1;
break;
}
}
}

if (!found) {
keyMatrix[k / SIZE][k % SIZE] = currentChar;
k++;
}
}
}
void findPosition(char letter, int *row, int *col) {
if (letter == 'I') {
letter = 'J';
}
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (keyMatrix[i][j] == letter) {
*row = i;
*col = j;
return;
}
}
}
}

// Function to encrypt a pair of letters


void encryptPair(char letter1, char letter2) {
int row1, col1, row2, col2;
findPosition(letter1, &row1, &col1);
findPosition(letter2, &row2, &col2);

if (row1 == row2) {
col1 = (col1 + 1) % SIZE;
col2 = (col2 + 1) % SIZE;
}
else if (col1 == col2) {
row1 = (row1 + 1) % SIZE;
row2 = (row2 + 1) % SIZE;
}
else {
int temp = col1;
col1 = col2;
col2 = temp;
}
cipherText[x++] = keyMatrix[row1][col1];
cipherText[x++] = keyMatrix[row2][col2];
cipherText[x++] = ' ';
// printf("%c%c ", keyMatrix[row1][col1], keyMatrix[row2][col2]);
}
void removeSpaces(char* text) {
// Remove spaces
int l = strlen(text);
int j = 0;
for (int i = 0;i<l;i++) {
if (text[i] != ' ') {
text[j++] = text[i];
}
}
text[j] = '\0';
}

// Function to encrypt the plaintext using Playfair cipher


void playfairEncrypt(char plaintext[]) {
int len = strlen(plaintext);

removeSpaces(plaintext);

for (int i = 0; i < len; i += 2) {


char letter1 = plaintext[i];
char letter2;

if (i + 1 < len && (plaintext[i] == plaintext[i + 1])) {


// If a pair is a repeated letter, insert filler like ‘X’
letter2 = 'X';
i--;
}
else {
if (i+1 < len && (isalpha(plaintext[i+1]))) {
letter2 = plaintext[i+1];
}
else {
letter2 = 'X';
}
}
encryptPair(letter1, letter2);
}

printf("\n");
}

int main(int argc, char const* argv[])


{
int status, valread, client_fd;
struct sockaddr_in serv_addr;

char buffer[1024] = { 0 };
if ((client_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Socket creation error \n");
return -1;
}

serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);

// Convert IPv4 and IPv6 addresses from text to binary


// form
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<= 0) {
printf("\nInvalid address/ Address not supported \n");
return -1;
}

if ((status = connect(client_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)))< 0) {


printf("\nConnection Failed \n");
return -1;
}

// Receiving plain text and keyword

char key[25];
char plaintext[MAX_BUFFER_SIZE];
char ciphertext[100];

printf("Enter the Plain text: ");


fgets(plaintext, sizeof(plaintext), stdin);
plaintext[strcspn(plaintext, "\n")] = '\0';

printf("Enter the key: ");


scanf("%s", key);

createMatrix(key);

int j = 0;
for (int i=0;i<MAX_BUFFER_SIZE;i++) {
if (plaintext[i] == ' ' && plaintext[i++] == ' ') {
break;
}
j++;
}

char text[j];
for (int i=0;i<j;i++) {
text[i] = plaintext[i];
}
printf("Encrypting...\n");
playfairEncrypt(plaintext);

//Sending plain text and keyword to server side


if (send(client_fd, &cipherText, sizeof(cipherText), 0) < 0) {
perror("Failed to send plain text\n");
exit(EXIT_FAILURE);
}

printf("The Play Fair Cipher Text has been successfully sent to the server\n");

// closing the connected socket


close(client_fd);
return 0;
}
OUTPUT:
Server Side:

Client side:

4. Write a socket program to demonstrate Row Transposition Cipher.


AIM:
Design a C socket program to exemplify Row Transposition Cipher, demonstrating encryption
and decryption processes through communication between a client and server.
ALGORTIHM:
Server Side:
a. Create a socket using socket().
b. Set socket options using setsockopt().
c. Bind the socket to a specific address and port using bind().
d. Listen for incoming connections using listen().
e. Accept the connection from the client using accept().
f. Receive the size of the cipher text and cipher text itself from the client using recv().
g. Print the received cipher text.
h. Close the connected socket and the listening socket.

Client Side:
a. Create a socket using socket().
b. Define the server address and port.
c. Connect to the server using connect().
d. Input the plain text and key from the user.
e. Remove spaces from the plain text.
f. Encrypt the plain text using the Row Transposition Cipher algorithm.
g. Send the size of the cipher text and the cipher text to the server using send().
h. Print a success message.
i. Close the connected socket.
CODE:
Server code:
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <ctype.h>

#define PORT 8080


#define MAX_BUFFER_SIZE 1024

int main(int argc, char const *argv[])


{
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
socklen_t addrlen = sizeof(address);
char buffer[1024] = {0};
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}

// Forcefully attaching socket to the port 8080


if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt,
sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}

address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);

// Forcefully attaching socket to the port 8080


if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}

if (listen(server_fd, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}

if ((new_socket = accept(server_fd, (struct sockaddr *)&address, &addrlen)) < 0)


{
perror("accept");
exit(EXIT_FAILURE);
}

// Receiving plain text and key to server side


int size;
if (recv(new_socket, &size, sizeof(size), 0) < 0) {
perror("Failed to receive plain text\n");
exit(EXIT_FAILURE);
}

char cipherText[size];
if (recv(new_socket, &cipherText, sizeof(cipherText), 0) < 0) {
perror("Failed to receive plain text\n");
exit(EXIT_FAILURE);
}

printf("Received Cipher Text from the client\n");

printf("The Cipher text is: \n");


for (int i=0;i<size;i++) {
printf("%c", cipherText[i]);
}
printf("\n");

// closing the connected socket


close(new_socket);
// closing the listening socket
close(server_fd);

return 0;
}
Client code:
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>

#define PORT 8080


#define MAX_BUFFER_SIZE 1024
int SIZE = 100;

int findIndex(int array[], int target) {


int index = -1;

for (int i = 0; array[i] != '\0'; i++) {


if (array[i] == target) {
index = i;
break;
}
}

return index;
}
char* RowTranspositionCipher(int key, char text[], int size) {
int c = 0;
int n = key;

while (n != 0){
n /= 10;
c++;
}

int numberArray[c];
n = key;
int i = c;
/* extract each digit */
while (n != 0) {
i--;
numberArray[i] = n % 10;
n /= 10;
}

int r = size % c;
char textMatrix[r][c];

int k = 0, z;
if (size != r*c) {
z = (r * c) - size;
}

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


for (int j=0;j<c;j++){
if (k < size) {
textMatrix[i][j] = text[k];
k++;
}
else {
z--;
textMatrix[i][j] = (char)(90-z);
}
}
}

printf("Row Transposition Matrix: \n");


for (int i=0;i<r;i++) {
for (int j=0;j<c;j++){
printf("%c ", textMatrix[i][j]);
}
printf("\n");
}

// plain text to cipher text conversation


SIZE = r*c;
char* cipherText = malloc((SIZE+1) * sizeof(char));//[r*c];
int index;
k=0;

for (int i=1;i<=c;i++) {


index = findIndex(numberArray, i);
for (int j=0;j<r;j++) {
cipherText[k++] = textMatrix[j][index];
}
}
cipherText[SIZE] = '\0';

return cipherText;

int main(int argc, char const* argv[]) {


int status, valread, client_fd;
struct sockaddr_in serv_addr;

char buffer[1024] = { 0 };

if ((client_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {


printf("\n Socket creation error \n");
return -1;
}

serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);

// Convert IPv4 and IPv6 addresses from text to binary


// form
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<= 0) {
printf("\nInvalid address/ Address not supported \n");
return -1;
}

if ((status = connect(client_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)))< 0) {


printf("\nConnection Failed \n");
return -1;
}
// Receiving plain text and keyword
int key;
char plaintext[SIZE];
char ciphertext[SIZE];

printf("Enter the Plain text: ");


fgets(plaintext, sizeof(plaintext), stdin);
plaintext[strcspn(plaintext, "\n")] = '\0';

printf("Enter the key: ");


scanf("%d", &key);

int size = 0, b = 0;
for (int i=0;i<SIZE;i++) {
if (plaintext[i] == '\0') {
break;
}
if (plaintext[i] == ' ') {
b++;
}
size++;
}

//printf("%d %d %d\n", size, b, size - b);


char text[size-b];
int j =0;
for (int i=0;i<size;i++) {
if (plaintext[i] == ' ') {
continue;
}
else {
text[j++] = plaintext[i];
}
}

printf("Encrypting...\n");

char * cipherText = RowTranspositionCipher(key, text, size-b);

char cipher[SIZE];
for (int i=0;i<SIZE;i++){
cipher[i] = cipherText[i];
}
//Sending cipher text and size of cipher text to server side
if (send(client_fd, &SIZE, sizeof(SIZE), 0) < 0) {
perror("Failed to send size\n");
exit(EXIT_FAILURE);
}
if (send(client_fd, &cipher, sizeof(cipher), 0) < 0) {
perror("Failed to send cipher text\n");
exit(EXIT_FAILURE);
}

printf("\nThe Row Transposition Cipher Text has been successfully sent to the server\n");

// closing the connected socket


close(client_fd);
return 0;

OUTPUT:
Server Side:

Client side:
BCSE309P – Cryptography and Network Security Laboratory
Name: Mohamed Rasheed Ahamed
Register No: 21BCE5570
Course Code: BCSE309P
Ex. No. 2: Cryptography & Network Security 08-01-2024
TASK:

1) Demonstrate Euclidean Algorithm.


AIM: To illustrate the step-by-step execution of the Euclidean Algorithm for finding the greatest
common divisor (GCD) of two integers.
ALGORITHM:
1. Start with two non-negative integers, a and b.
2. If a is zero, the GCD is b.
3. Otherwise, compute the remainder of b divided by a.
4. Replace b with a and a with the remainder obtained in the previous step.
5. Repeat steps 2-4 until a becomes zero.
6. The GCD is the non-zero value of b after a becomes zero.

CODE:
#include <stdio.h>

// Euclidean Algorithm
int euclidean_GCD(int a, int b)
{
if (a == 0)
return b;
return euclidean_GCD(b % a, a);
}

int main() {
int a, b;
printf("Enter two numbers: ");
scanf("%d %d", &a, &b);
printf("The GCD of %d and %d is: %d\n", a, b, euclidean_GCD(a, b));
return 0;
}

OUTPUT:

2) Demonstrate Extended Euclidean Algorithm.


AIM: To showcase the stepwise implementation of the Extended Euclidean Algorithm,
emphasizing the calculation of Bézout's coefficients and the GCD for a pair of integers.
ALGORITHM:
1. If a is zero, set y to 1, x to 0, and return b.
2. Otherwise, recursively call the Extended Euclidean Algorithm with arguments (b % a, a,
&x1, &y1).
3. Compute the GCD and obtain coefficients x1 and y1.
4. Update x and y based on the formulas:
x = y1 - (b / a) * x1
y = x1
5. Return the GCD.
CODE:
#include <stdio.h>
// Extended Euclidean Function
int ExtendedEuclidean(int a, int b, int* x, int* y) {
if (a == 0) {
*y = 1;
*x = 0;
return b;
}
int x1, y1;
int gcd = ExtendedEuclidean(b % a, a, &x1, &y1);

*x = y1 - (b / a) * x1;
*y = x1;
return gcd;
}

int main() {
int a, b, x, y;
printf("Enter two numbers: ");
scanf("%d %d", &a, &b);

int GCD = ExtendedEuclidean(a, b, &x, &y);


printf("The GCD of %d and %d is: %d\n", a, b, GCD);
printf("The values of x and y are: (%d, %d)\n", x, y);

return 0;
}
OUTPUT:
3) Demonstrate Euler’s Theorem.
AIM: To elucidate Euler's Theorem by demonstrating its application in modular arithmetic,
emphasizing the relationship between modular exponentiation and the totient function.
ALGORITHM:
1. Input: Obtain values for a and n from the user.
2. Compute GCD: Calculate the greatest common divisor (gcd) of a and n.
3. Check Coprimality: If gcd(a, n) is not 1, print an error message and exit.
4. Calculate Totient (ϕ): Determine Euler's totient function (ϕ(n)) by counting coprime integers
less than n.
5. Compute Modular Exponentiation: Utilize modular exponentiation to find a^ϕ(n) mod n.
6. Output: Print the result of a^ϕ(n) mod n.
7. Main Algorithm: Execute the above steps in order, checking coprimality, calculating ϕ(n),
performing modular exponentiation, and printing the result.

CODE:
#include <stdio.h>
int gcd(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}

int phi(int n) {
int result = 1;
for (int i = 2; i < n; ++i) {
if (gcd(i, n) == 1) {
++result;
}
}
return result;
}
int power(int x, unsigned int y, int m) {
int result = 1;
x = x % m;
while (y > 0) {
if (y & 1) {
result = (result * x) % m;
}
y = y >> 1;
x = (x * x) % m;
}
return result;
}

// Function to demonstrate Euler's Theorem


void eulerTheorem(int a, int n) {
if (gcd(a, n) != 1) {
printf("Error: a and n must be coprime.\n");
return;
}

int value = phi(n);


int result = power(a, value, n);

printf("%d^%d mod %d is equal to %d\n", a, value, n, result % n);


}

int main() {
int a, n;

printf("Enter values for a and n: ");


scanf("%d %d", &a, &n);

eulerTheorem(a, n);

return 0;
}
OUTPUT:

4) Demonstrate the Miller Rabin Algorithm.


AIM: To present a detailed demonstration of the Miller-Rabin Algorithm, highlighting its
probabilistic nature and its effectiveness in determining whether a given number is likely to be a
prime or composite, based on a specified number of iterations.

ALGORITHM:
1. Find integers k, q, k > 0, q odd, so that (n–1)=(2^k).q
2. Select a random integer a, 1<a<n–1
3. if a^q mod n = 1 then return (“inconclusive");
4. for j = 0 to k – 1 do
5. if ((a^((2^j).q)) mod n = n-1), then return(“inconclusive")
6. return (“composite")

CODE:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

long long modular_pow(long long base, long long exponent, long long modulus) {
long long result = 1;
while (exponent > 0) {
if (exponent % 2 == 1) {
result = (result * base) % modulus;
}
base = (base * base) % modulus;
exponent /= 2;
}
return result;
}

int millerRabinTest(long long n, int iterations) {


if (n <= 1 || n == 4) {
return 0; // Not a prime
}
if (n <= 3) {
return 1; // Prime
}

long long k = 0;
long long q = n - 1;
while (q % 2 == 0) {
k++;
q /= 2;
}

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


long long a = 2 + rand() % (n - 3);

long long x = modular_pow(a, q, n);


if (x == 1 || x == n - 1) {
continue;
}

int inconclusive = 0;
for (long long j = 0; j < k - 1; j++) {
x = modular_pow(x, 2, n);
if (x == n - 1) {
inconclusive = 1;
break;
}
}

if (!inconclusive) {
return 0;
}
}
return 1;
}

int main() {
long long num;
int iterations;

printf("Enter a number to test: ");


scanf("%lld", &num);

printf("Enter the number of iterations: ");


scanf("%d", &iterations);

// Miller-Rabin primality test


if (millerRabinTest(num, iterations)) {
printf("%lld is likely a prime number.\n", num);
} else {
printf("%lld is composite.\n", num);
}

return 0;
}
OUTPUT:
BCSE309P – Cryptography and Network Security Laboratory
Name: Mohamed Rasheed Ahamed
Register No: 21BCE5570
Course Code: BCSE309P
Ex. No. 3: Implementation of DES 22-01-2024
TASK:

• Consider a sender and receiver who need to exchange data confidentially


using symmetric encryption. Write a program that implements DES
encryption and decryption using a 64-bit key size and 64-bit block size.
AIM: To showcase the practical implementation and step-by-step execution of the Data
Encryption Standard (DES) symmetric encryption algorithm with a 64-bit key size and a 64-bit
block size.
ALGORITHM:
Server Side (DES_server):
1. Initialize Server Socket:
a. Create a ServerSocket on a specified port (e.g., 12345).
b. Print a message indicating that the server is waiting for a client.

2. Accept Client Connection:


a. Use serverSocket.accept() to wait for and accept a client connection.
b. Print a message indicating that the client is connected.

3. Key Initialization:
a. Replace the keyString with your own 64-bit key (8 bytes).
b. Convert the keyString to bytes using UTF-8 encoding.
4. Initialize Input and Output Streams:
a. Create DataInputStream and DataOutputStream to communicate with the client.

5.Receive Ciphertext from Client:


a. Read the Base64-encoded ciphertext from the client using inputStream.readUTF().
b. Decode the Base64 string to obtain the ciphertext bytes.

6. Decrypt Ciphertext:
a. Call the decrypt method with the received ciphertext and key to obtain decrypted bytes.

7.Display Decrypted Message:


a. Convert the decrypted bytes to a String using UTF-8 encoding.
b. Print the decrypted message.

8. Close Connection:
a. Close the client socket and the server socket.

Client Side (DES_client):


1. Initialize Socket:
a. Create a socket to connect to the server at the specified address and port (e.g.,
localhost:12345).

2. Key Initialization:
a. Replace the keyString with your own 64-bit key (8 bytes).
b. Convert the keyString to bytes using UTF-8 encoding.

3. Initialize Input and Output Streams:


a. Create DataInputStream and DataOutputStream to communicate with the server.

4. Take Plaintext Input:


a. Use a Scanner to take plaintext input from the user.

5. Encrypt Plaintext:
a. Convert the plaintext to bytes using UTF-8 encoding.
b. Call the encrypt method with the plaintext bytes and key to obtain encrypted bytes.

6. Display Ciphertext:
a. Print the Base64-encoded ciphertext before sending it to the server.

7. Send Ciphertext to Server:


a. Encode the encrypted bytes to Base64 and send the resulting string to the server using
outputStream.writeUTF().

8. Close Connection:
a. Close the socket.

CODE:
Server Code:
// server code
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class DES_server {

public static void main(String[] args) {


try {
ServerSocket serverSocket = new ServerSocket(12345);
System.out.println("Server waiting for client...");

Socket socket = serverSocket.accept();


System.out.println("Client connected.");

String keyString = "76543210";


byte[] keyBytes = keyString.getBytes(StandardCharsets.UTF_8);

DataInputStream inputStream = new DataInputStream(socket.getInputStream());


DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());

String receivedCiphertextBase64 = inputStream.readUTF();


byte[] receivedCiphertext = Base64.getDecoder().decode(receivedCiphertextBase64);

byte[] decryptedBytes = decrypt(receivedCiphertext, keyBytes);

String decryptedMessage = new String(decryptedBytes, StandardCharsets.UTF_8);


System.out.println("Decrypted Message: " + decryptedMessage);

// Close the connection


socket.close();
serverSocket.close();
}
catch (Exception e) {
e.printStackTrace();
}
}

private static byte[] decrypt(byte[] ciphertext, byte[] key) throws Exception {


Cipher cipher = getCipher(key, Cipher.DECRYPT_MODE);
return cipher.doFinal(ciphertext);
}

private static Cipher getCipher(byte[] key, int mode) throws Exception {


DESKeySpec desKeySpec = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);

Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");


cipher.init(mode, secretKey);
return cipher;
}
}
Client Code:
// client code
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Scanner;

public class DES_client {

public static void main(String[] args) {


try {
Socket socket = new Socket("localhost", 12345);

String keyString = "76543210";


byte[] keyBytes = keyString.getBytes(StandardCharsets.UTF_8);

DataInputStream inputStream = new DataInputStream(socket.getInputStream());


DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
Scanner scanner = new Scanner(System.in);
System.out.print("Enter the message: ");
String plaintext = scanner.nextLine();
byte[] plaintextBytes = plaintext.getBytes(StandardCharsets.UTF_8);

// Encrypt the plaintext


byte[] encryptedBytes = encrypt(plaintextBytes, keyBytes);

System.out.println("Ciphertext: " +
Base64.getEncoder().encodeToString(encryptedBytes));

outputStream.writeUTF(Base64.getEncoder().encodeToString(encryptedBytes));

// Close the connection


socket.close();

} catch (Exception e) {
e.printStackTrace();
}
}

private static byte[] encrypt(byte[] plaintext, byte[] key) throws Exception {


Cipher cipher = getCipher(key, Cipher.ENCRYPT_MODE);
return cipher.doFinal(plaintext);
}

private static Cipher getCipher(byte[] key, int mode) throws Exception {


DESKeySpec desKeySpec = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);

Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");


cipher.init(mode, secretKey);
return cipher;
}
}

OUTPUT:
BCSE309P – Cryptography and Network Security Laboratory
Name: Mohamed Rasheed Ahamed
Register No: 21BCE5570
Course Code: BCSE309P
Ex. No. 4: Implementation of AES 29-01-2024
TASK:

• Consider a sender and receiver who need to exchange data confidentially


using symmetric encryption. Write a program that implements AES
encryption and decryption using a 128/256- bit key size and 128-bit block
size.
AIM: To demonstrate the practical implementation and step-by-step execution of
the Advanced Encryption Standard (AES) symmetric encryption algorithm with a
key size of 128 or 256 bits and a block size of 128 bits, enabling secure and
confidential data exchange between a sender and a receiver.
ALGORITHM:
Server Algorithm:
• Initialize Server Socket:
• Create a ServerSocket on a specified port (e.g., 12345).
• Print a message indicating that the server is waiting for a client.
• Accept Client Connection:
• Use serverSocket.accept() to wait for and accept a client connection.
• Print a message indicating that the client is connected.
• Receive AES Key from Client:
• Read the Base64-encoded AES key from the client using inputStream.readUTF().
• Decode the Base64 string to obtain the AES key bytes.
• Create a SecretKey from the decoded bytes using SecretKeySpec.
• Receive Ciphertext from Client:
• Read the Base64-encoded ciphertext from the client using inputStream.readUTF().
• Decode the Base64 string to obtain the ciphertext bytes.
• Decrypt Ciphertext:
• Call the decryptAES method with the received ciphertext and AES key to obtain
decrypted bytes.

• Display Key and Decrypted Message:

• Print the Base64-encoded AES key used for decryption.


• Convert the decrypted bytes to a String using UTF-8 encoding.
• Print the decrypted message.
• Close Connection:
• Close the client socket and the server socket.

Client Algorithm:
• Initialize Socket:
• Create a socket to connect to the server at the specified address and port (e.g.,
localhost:12345).
• nitialize Input and Output Streams:
• Create DataInputStream and DataOutputStream to communicate with the server.
• Generate AES Key:
• Call the generateAESKey method to generate a fixed AES key (for demonstration
purposes).
• Display Key for Encryption:
• Print the Base64-encoded AES key used for encryption.
• Encrypt Plaintext:
• Use the encryptAES method to encrypt the plaintext using the generated AES key.
• Print the Base64-encoded ciphertext.
• Send Key and Ciphertext to Server:
• Send the Base64-encoded AES key to the server using outputStream.writeUTF().
• Send the Base64-encoded ciphertext to the server using outputStream.writeUTF().
• Close Connection:
• Close the socket.
CODE:
Server Code:
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class AES_server {

public static void main(String[] args) {


try {
ServerSocket serverSocket = new ServerSocket(12345);
System.out.println("Server waiting for client...");

Socket socket = serverSocket.accept();


System.out.println("Client connected.");

DataInputStream inputStream = new DataInputStream(socket.getInputStream());


DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());

try {
String receivedKeyBase64 = inputStream.readUTF();
byte[] receivedKeyBytes = Base64.getDecoder().decode(receivedKeyBase64);
SecretKey secretKey = new SecretKeySpec(receivedKeyBytes, "AES");

String receivedCiphertextBase64 = inputStream.readUTF();


byte[] receivedCiphertext = Base64.getDecoder().decode(receivedCiphertextBase64);

String decryptedMessage = decryptAES(receivedCiphertext, secretKey);

System.out.println("Decrypted Message: " + decryptedMessage);


} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
} finally {
// Close the connection
socket.close();
serverSocket.close();
}

} catch (Exception e) {
e.printStackTrace();
}
}

private static String decryptAES(byte[] ciphertext, SecretKey key) throws Exception {


Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedBytes = cipher.doFinal(ciphertext);
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
}

Client Code:
//client
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Scanner;

public class AES_client {

public static void main(String[] args) {


try {
Socket socket = new Socket("localhost", 12345);

DataInputStream inputStream = new DataInputStream(socket.getInputStream());


DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());

SecretKey secretKey = generateAESKey();// Generate AES key

String plaintext = getInput("Enter the message to encrypt: ");


byte[] encryptedBytes = encryptAES(plaintext, secretKey);

System.out.println("Encrypted Text: " +


Base64.getEncoder().encodeToString(encryptedBytes));

outputStream.writeUTF(Base64.getEncoder().encodeToString(secretKey.getEncoded()));

outputStream.writeUTF(Base64.getEncoder().encodeToString(encryptedBytes));

// Close the connection


socket.close();

} catch (Exception e) {
e.printStackTrace();
}
}

private static SecretKey generateAESKey() throws Exception {


return new SecretKeySpec(new byte[16], "AES");
}
private static byte[] encryptAES(String plaintext, SecretKey key) throws Exception {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
}

private static String getInput(String prompt) {


Scanner scanner = new Scanner(System.in);
System.out.print(prompt);
return scanner.nextLine();
}
}
OUTPUT:
Server Side:

Client Side:
BCSE309P – Cryptography and Network Security Laboratory
Name: Mohamed Rasheed Ahamed
Register No: 21BCE5570
Course Code: BCSE309P
Ex. No. 5: Implementation of RSA Cryptosystem 05-02-2024
TASK:
1) Develop a cipher scheme using the RSA algorithm.
AIM: To illustrate the process of creating a secure communication channel through the
development of a cipher scheme using the RSA algorithm.
ALGORITHM:
Server Algorithm:
• Create a server socket using socket().
• Bind the server socket to a specific port using bind().
• Listen for incoming connections using listen().
• Accept the connection from the client using accept().
• Generate two random prime numbers (prime1 and prime2) using the prime filler function
(primefiller()).
• Calculate n as the product of prime1 and prime2.
• Calculate Euler's totient function (fi) as (prime1 - 1) * (prime2 - 1).
• Choose a public key (e) such that it is coprime with fi.
• Calculate a corresponding private key (d) using the extended Euclidean algorithm.
• Send the public key (e) to the client.
• Receive the encrypted message from the client.
• Decrypt the message using the private key (d) and n.
• Display the decrypted message.
• Close the client socket and the server socket.
Client Algorithm:
• Create a client socket using socket().
• Connect to the server using the server's IP address and port using connect().
• Input the message to be sent from the user.
• Encode the message into a vector of integers using the encoder() function.
• Send the encoded message to the server.
• Close the client socket.

CODE:
Server Code:
//Server code:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <bits/stdc++.h>

using namespace std;

set<int> prime;
int public_key;
int private_key;
int n;

void primefiller() {
vector<bool> sieve(250, true);
sieve[0] = false;
sieve[1] = false;

for (int i = 2; i < 250; i++) {


for (int j = i * 2; j < 250; j += i) {
sieve[j] = false;
}
}

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


if (sieve[i])
prime.insert(i);
}
}
int pickrandomprime() {
int k = rand() % prime.size();
auto it = prime.begin();
while (k--)
it++;
int ret = *it;
prime.erase(it);
return ret;
}

void setkeys() {
int prime1 = pickrandomprime();
int prime2 = pickrandomprime();
n = prime1 * prime2;
int fi = (prime1 - 1) * (prime2 - 1);
int e = 2;

while (1) {
if (__gcd(e, fi) == 1)
break;
e++;
}

public_key = e;
int d = 2;

while (1) {
if ((d * e) % fi == 1)
break;
d++;
}

private_key = d;
}

long long int encrypt(double message) {


int e = public_key;
long long int encrypted_text = 1;

while (e--) {
encrypted_text *= message;
encrypted_text %= n;
}

return encrypted_text;
}
long long int decrypt(int encrypted_text) {
int d = private_key;
long long int decrypted = 1;

while (d--) {
decrypted *= encrypted_text;
decrypted %= n;
}

return decrypted;
}

vector<int> encoder(string message) {


vector<int> form;

for (auto& letter : message)


form.push_back(encrypt((int)letter));

return form;
}

string decoder(vector<int> encoded) {


string s;

for (auto& num : encoded)


s += decrypt(num);

return s;
}

int main() {
primefiller();
setkeys();

int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);

if (server_socket == -1) {
cerr << "Error creating socket" << endl;
exit(EXIT_FAILURE);
}
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8080);
server_address.sin_addr.s_addr = INADDR_ANY;

if (bind(server_socket, (struct sockaddr*)&server_address, sizeof(server_address)) < 0) {


cerr << "Binding failed" << endl;
exit(EXIT_FAILURE);
}

if (listen(server_socket, 3) < 0) {
cerr << "Listening failed" << endl;
exit(EXIT_FAILURE);
}

int client_socket;
struct sockaddr_in client_address;
socklen_t client_addr_size = sizeof(client_address);

client_socket = accept(server_socket, (struct sockaddr*)&client_address, &client_addr_size);

if (client_socket < 0) {
cerr << "Acceptance failed" << endl;
exit(EXIT_FAILURE);
}

char buffer[1024] = {0};


read(client_socket, buffer, 1024);
cout << "Encrypted message received from client: " << buffer << endl;

string message(buffer);
istringstream iss(message);
vector<int> encoded_text;
int num;

while (iss >> num) {


encoded_text.push_back(num);
}

string decrypted_message = decoder(encoded_text);


cout << "Decrypted message: " << decrypted_message << endl;

close(server_socket);
return 0;
}
Client Code:
// Client side:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <bits/stdc++.h>

using namespace std;

set<int> prime;
int public_key;
int private_key;
int n;

void primefiller() {
vector<bool> sieve(250, true);
sieve[0] = false;
sieve[1] = false;

for (int i = 2; i < 250; i++) {


for (int j = i * 2; j < 250; j += i) {
sieve[j] = false;
}
}

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


if (sieve[i])
prime.insert(i);
}
}

int pickrandomprime() {
int k = rand() % prime.size();
auto it = prime.begin();
while (k--)
it++;
int ret = *it;
prime.erase(it);
return ret;
}
void setkeys() {
int prime1 = pickrandomprime();
int prime2 = pickrandomprime();
n = prime1 * prime2;
int fi = (prime1 - 1) * (prime2 - 1);
int e = 2;

while (1) {
if (__gcd(e, fi) == 1)
break;
e++;
}

public_key = e;
int d = 2;

while (1) {
if ((d * e) % fi == 1)
break;
d++;
}

private_key = d;
}

long long int encrypt(double message) {


int e = public_key;
long long int encrypted_text = 1;

while (e--) {
encrypted_text *= message;
encrypted_text %= n;
}

return encrypted_text;
}

long long int decrypt(int encrypted_text) {


int d = private_key;
long long int decrypted = 1;

while (d--) {
decrypted *= encrypted_text;
decrypted %= n;
}
return decrypted;
}

vector<int> encoder(string message) {


vector<int> form;

for (auto& letter : message)


form.push_back(encrypt((int)letter));

return form;
}

string decoder(vector<int> encoded) {


string s;

for (auto& num : encoded)


s += decrypt(num);

return s;
}

int main() {
primefiller();
setkeys();

int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);

if (server_socket == -1) {
cerr << "Error creating socket" << endl;
exit(EXIT_FAILURE);
}

struct sockaddr_in server_address;


server_address.sin_family = AF_INET;
server_address.sin_port = htons(8080);
server_address.sin_addr.s_addr = INADDR_ANY;

if (bind(server_socket, (struct sockaddr*)&server_address, sizeof(server_address)) < 0) {


cerr << "Binding failed" << endl;
exit(EXIT_FAILURE);
}
if (listen(server_socket, 3) < 0) {
cerr << "Listening failed" << endl;
exit(EXIT_FAILURE);
}

int client_socket;
struct sockaddr_in client_address;
socklen_t client_addr_size = sizeof(client_address);

client_socket = accept(server_socket, (struct sockaddr*)&client_address, &client_addr_size);

if (client_socket < 0) {
cerr << "Acceptance failed" << endl;
exit(EXIT_FAILURE);
}

char buffer[1024] = {0};


read(client_socket, buffer, 1024);
cout << "Encrypted message received from client: " << buffer << endl;

string message(buffer);
istringstream iss(message);
vector<int> encoded_text;
int num;

while (iss >> num) {


encoded_text.push_back(num);
}

string decrypted_message = decoder(encoded_text);


cout << "Decrypted message: " << decrypted_message << endl;

close(server_socket);
return 0;
}
OUTPUT:
Server Side:

Client side:
BCSE309P – Cryptography and Network Security Laboratory
Name: Mohamed Rasheed Ahamed
Register No: 21BCE5570
Course Code: BCSE309P

Ex. No. 6: Implementation of Elgamal Cryptosystem 19-02-2024


TASK:
1) Develop a cipher scheme using the Elgamal public key cryptographic
algorithm.
AIM: To establish a secure communication protocol by implementing a cipher scheme using the
ElGamal public key cryptographic algorithm, facilitating secure data exchange through the
generation of public and private keys for encryption and decryption operations.
ALGORITHM:
Server Algorithm:
a. Create a server socket using `ServerSocket`.
b. Bind the server socket to a specific port using `bind()`.
c. Listen for incoming connections using `listen()`.
d. Accept the connection from the client using `accept()`.
e. Generate a large prime number (`prime`), a base (`base`), a private key (`privateKey`), and
a public key (`publicKey`) using the Elgamal key generation algorithm.
f.Send the `prime`, `base`, and `publicKey` to the client using `ObjectOutputStream`.
g. Receive the encrypted message (`cipher`) from the client using `ObjectInputStream`.
h. Decrypt the `cipher` using the Elgamal decryption algorithm.
i. Display the decrypted message.
j. Close the client socket and the server socket.
Client Algorithm:
a. Create a socket to connect to the server using `Socket`.
b. Connect to the server using the server's IP address and port.
c. Input the message to be encrypted from the user.
d. Generate a large prime number (`prime`), a base (`base`), and a public key (`publicKey`)
received from the server.
e. Encrypt the message using the Elgamal encryption algorithm with the received `prime`,
`base`, and `publicKey`.
f.Send the encrypted message (`cipher`) to the server using `ObjectOutputStream`.
g. Close the socket connection.

CODE:
Server Code:
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.SecureRandom;

public class Elgamal_Server {


private BigInteger prime, base, publicKey, privateKey;

public Elgamal_Server() {
SecureRandom random = new SecureRandom();
prime = BigInteger.probablePrime(512, random);
base = new BigInteger("3");
privateKey = new BigInteger(512, random);
publicKey = base.modPow(privateKey, prime);
}

public BigInteger[] encrypt(BigInteger message) {


SecureRandom random = new SecureRandom();
BigInteger randomK = new BigInteger(512, random);
BigInteger a = base.modPow(randomK, prime);
BigInteger b = publicKey.modPow(randomK, prime).multiply(message).mod(prime);
return new BigInteger[]{a, b};
}
public BigInteger decrypt(BigInteger[] cipher) {
BigInteger a = cipher[0];
BigInteger b = cipher[1];
BigInteger s = a.modPow(privateKey, prime);
return b.multiply(s.modInverse(prime)).mod(prime);
}

public static void main(String[] args) throws Exception {


Elgamal_Server server = new Elgamal_Server();
ServerSocket serverSocket = new ServerSocket(8000);
System.out.println("Server started. Waiting for client...");
Socket socket = serverSocket.accept();
System.out.println("Client connected.");

ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());


out.writeObject(server.prime);
out.writeObject(server.base);
out.writeObject(server.publicKey);

ObjectInputStream in = new ObjectInputStream(socket.getInputStream());


BigInteger[] cipher = (BigInteger[]) in.readObject();
System.out.println("Received encrypted message from the client.");
BigInteger decryptedMessage = server.decrypt(cipher);
System.out.println("Decrypted message: " + decryptedMessage);

socket.close();
serverSocket.close();
}
}

Client Code:
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.net.Socket;
import java.util.Random;
import java.util.Scanner;

public class Elgamal_Client {


public BigInteger[] encrypt(BigInteger prime, BigInteger base, BigInteger publicKey,
BigInteger message) {
Random random = new Random();
BigInteger randomK = new BigInteger(512, random);
BigInteger a = base.modPow(randomK, prime);
BigInteger b = publicKey.modPow(randomK, prime).multiply(message).mod(prime);
return new BigInteger[]{a, b};
}

public static void main(String[] args) throws Exception {


Scanner scanner = new Scanner(System.in);

System.out.print("Enter your message: ");


String plaintext = scanner.nextLine();
BigInteger message = new BigInteger(plaintext.getBytes());

Socket socket = new Socket("localhost", 8000);


ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());

ObjectInputStream in = new ObjectInputStream(socket.getInputStream());


BigInteger prime = (BigInteger) in.readObject();
BigInteger base = (BigInteger) in.readObject();
BigInteger publicKey = (BigInteger) in.readObject();

Elgamal_Client client = new Elgamal_Client();


BigInteger[] cipher = client.encrypt(prime, base, publicKey, message);
out.writeObject(cipher);

System.out.println("Encrypted Message has been sent to server.");

socket.close();
}
}
OUTPUT:
Server Side:

Client side:
BCSE309P – Cryptography and Network Security Laboratory
Name: Mohamed Rasheed Ahamed
Register No: 21BCE5570
Course Code: BCSE309P
Ex. No. 7: Implementation of Elliptic Curve Cryptosystem 26-02-2024
TASK:
1) Develop a cipher scheme using the Elliptic Curve Cryptosystem algorithm
AIM: To enhance data security by designing a cipher scheme utilizing the Elliptic Curve
Cryptosystem algorithm.
ALGORITHM:
Server Algorithm:
1. Create a server socket using `ServerSocket`.
2. Bind the server socket to a specific port.
3. Listen for incoming connections.
4. Accept the connection from the client.
5. Receive the encrypted points `C1` and `C2` and the private key `privateKey` from the client.
6. Perform decryption:
a. Calculate `decryptedPoint` as `C2` + `C1` * (-`privateKey`).
7. Display the decrypted point `decryptedPoint`.
8. Close the client socket and the server socket.
Client Algorithm:
1. Create a socket to connect to the server using `Socket`.
2. Connect to the server using the server's IP address and port.
3. Input the parameters: prime modulus (`p`), parameters `a`, `b`, coordinates of base point `G`,
private key (`nB`), coordinates of the point to be encrypted (`Pm`), and a random integer (`k`).
4. Calculate the public key `PB` as `G` * `nB`.
5. Encrypt the point `Pm` using Elliptic Curve Cryptography:
a. Calculate `kG` as `G` * `k`.
b. Calculate `kPB` as `PB` * `k`.
c. Calculate `C1` as `kG`.
d. Calculate `C2` as `Pm` + `kPB`.
6. Send the encrypted points `C1` and `C2`, and the private key `nB` to the server.
7. Close the socket connection.
CODE:
Server Code:
import java.io.*;
import java.net.*;

public class ECC_Server {


public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(12345);
System.out.println("ECC Server is running. Waiting for connections...");
Socket socket = serverSocket.accept();
System.out.println("ECC Client connected.");
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());

// Receive the encrypted message from the client


ECC_Client.Point C1 = (ECC_Client.Point) in.readObject();
ECC_Client.Point C2 = (ECC_Client.Point) in.readObject();
int privateKey = in.readInt();
System.out.println("Received private key (nB): " + privateKey);

System.out.println("Received encrypted message:");


System.out.println("C1: " + C1);
System.out.println("C2: " + C2);

// Perform decryption
ECC_Client.Point decryptedPoint = C2.add1(C1.multiply1(-privateKey));

// Display the decrypted message


System.out.println("Decrypted message:");
System.out.println("Decrypted Point: " + decryptedPoint);

// Close streams and sockets


in.close();
out.close();
socket.close();
serverSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Client Code:
import java.io.*;
import java.net.*;
import java.util.Scanner;

public class ECC_Client {


public static void main(String[] args) {
try {
Scanner scanner = new Scanner(System.in);
Socket socket = new Socket("localhost", 12345);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
System.out.print("Enter the prime modulus (p): ");
int p = scanner.nextInt();
System.out.print("Enter the parameter a: ");
int a = scanner.nextInt();
System.out.print("Enter the parameter b: ");
int b = scanner.nextInt();
System.out.print("Enter the x-coordinate of the base point G: ");
int Gx = scanner.nextInt();
System.out.print("Enter the y-coordinate of the base point G: ");
int Gy = scanner.nextInt();
System.out.print("Enter the private key (nB): ");
int privateKey = scanner.nextInt();
System.out.print("Enter the x-coordinate of the point to be encrypted (Pm): ");
int Pmx = scanner.nextInt();
System.out.print("Enter the y-coordinate of the point to be encrypted (Pm): ");
int Pmy = scanner.nextInt();
System.out.print("Enter the random integer (k): ");
int k = scanner.nextInt();

// Create the point to be encrypted


Point Pm = new Point(Pmx, Pmy, a, p);

// Calculate the public key point PB


Point G = new Point(Gx, Gy, a, p);
Point PB = G.multiply1(privateKey);
System.out.println("Public Key (PB): " + PB);

// Encrypt the point Pm using Elliptic Curve Cryptography


Point[] encryptedPoints = encrypt(Pm, PB, G, k);
// Print the encrypted result
System.out.println("Encrypted Result:");
System.out.println("C1: " + encryptedPoints[0]);
System.out.println("C2: " + encryptedPoints[1]);

out.writeObject(encryptedPoints[0]);
out.writeObject(encryptedPoints[1]);
out.writeInt(privateKey);

out.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static Point[] encrypt(Point P, Point PB, Point G, int k) {
// Calculate kG
Point kG = G.multiply1(k);

// Calculate kPB
Point kPB = PB.multiply1(k);

// Calculate C1 = kG
Point C1 = kG;

// Calculate C2 = P + kPB
Point C2 = P.add1(kPB);

return new Point[]{C1, C2};


}

public static class Point implements Serializable {


private static final long serialVersionUID = 1L;
int x;
int y;
int a; // Coefficient a of the curve
int p; // Prime modulus of the curve
public Point(int x, int y, int a, int p) {
this.x = x;
this.y = y;
this.a = a;
this.p = p;
}

// Point addition
public Point add1(Point other) {
if (other == null) return this;
int lambda;
int xr, yr;
if (this.equals(other)) {
int numerator = (3 * x * x + a) % p;
int denominator = (2 * y) % p;
int inverseDenominator = modInverse(denominator, p);
lambda = (numerator * inverseDenominator) % p;
} else {
int l = (other.x - x + p);
int inverseL = modInverse(l, p);
int l1 = modInverse(-l, p);
if (l < 0) {
lambda = (((other.y - y) * -1) % p * l1) % p;
} else {
lambda = ((other.y - y) % p * inverseL) % p;
}
}
lambda = (lambda + p) % p;
System.out.println("Lambda: " + lambda);
xr = ((lambda * lambda) % p - x - other.x + 2 * p) % p;
if (xr < 0) {
xr += p;
}
yr = ((lambda * (x - xr)) % p - y + p) % p;
if (yr < 0) {
yr += p;
}
return new Point(xr, yr, a, p);
}
// Point multiplication
public Point multiply1(int n) {
Point result = null;
for (int i = 0; i < n; i++) {
result = result != null ? result.add1(result) : this;
}
return result;
}

// Modular inverse function


private 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;
}

@Override
public String toString() {
return "(" + x + ", " + y + ")";
}
}
}
OUTPUT:
Server Side:

Client side:
BCSE309P – Cryptography and Network Security Laboratory
Name: Mohamed Rasheed Ahamed
Register No: 21BCE5570
Course Code: BCSE309P
Ex. No. 8: Implementation of Diffie-Hellman Key Exchange Protocol 4-03-2024
TASK:
1) Design a Diffie Hellman multiparty key exchange protocol and perform a
Man-in-the-Middle Attack.
AIM: To Develop a multiparty key exchange protocol using Diffie-Hellman, ensuring secure
communication. This includes generating public/private keys for encryption. Additionally,
simulate a Man-in-the-Middle Attack to showcase vulnerabilities in the protocol's security.
ALGORITHM:
Server Algorithm:
1. Create a server socket using `ServerSocket`.
2. Bind the server socket to a specific port.
3. Listen for incoming connections.
4. Accept the connection from the client.
5. Generate a large prime number (`prime`), a base (`generator`), a private key
(`server_private_key`), and a public key (`server_public_key`) using the Diffie-Hellman key
exchange algorithm.
6. Send the `prime`, `generator`, and `server_public_key` to the client using `ObjectOutputStream`.
7. Receive the encrypted message (`encryptedMessage`) from the client using `ObjectInputStream`.
8. Calculate the shared secret key (`shared_secret_key`) using the received public key from the
client and the server's private key.
9. Decrypt the `encryptedMessage` using the shared secret key.
10. Display the decrypted message.
11. Close the client socket and the server socket.
Client Algorithm:
1. Create a socket to connect to the server using `Socket`.
2. Connect to the server using the server's IP address and port.
3. Input the message to be encrypted from the user.
4. Receive the prime number (`prime`), base (`generator`), and public key (`server_public_key`)
from the server.
5. Generate a private key (`client_private_key`).
6. Calculate the shared secret key (`shared_secret_key`) using the received public key from the
server and the client's private key.
7. Encrypt the message using the shared secret key.
8. Send the encrypted message (`encryptedMessage`) to the server using `ObjectOutputStream`.
9. Close the socket connection.

CODE:
Server Code:
import java.io.*;
import java.net.*;
import java.math.BigInteger;

public class DH_Server {


private static final int PORT_NUMBER = 12345;

public static void main(String[] args) {


try {
ServerSocket serverSocket = new ServerSocket(PORT_NUMBER);
System.out.println("Server is awaiting connections...");
Socket clientSocket = serverSocket.accept();
System.out.println("Client has connected.");

// Generate public parameters


BigInteger prime = new BigInteger("23"); // Prime number
BigInteger generator = new BigInteger("5"); // Generator

// Generate private key (server_private_key)


BigInteger server_private_key = new BigInteger("6");

// Calculate public key (server_public_key)


BigInteger server_public_key = generator.modPow(server_private_key, prime);

// Send public parameters and public key to the client


ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream());
out.writeObject(prime);
out.writeObject(generator);
out.writeObject(server_public_key);

// Receive public key from the client


ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
BigInteger client_public_key = (BigInteger) in.readObject();

// Calculate the shared secret key


BigInteger shared_secret_key = client_public_key.modPow(server_private_key, prime);
System.out.println("Shared Secret Key: " + shared_secret_key);

// Receive encrypted message from the client


byte[] encryptedMessage = (byte[]) in.readObject();
System.out.println("Received encrypted message from the client.");

// Print the encrypted message (byte array)


System.out.println("Encrypted message: " + new String(encryptedMessage));

serverSocket.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}

Client Code:
import java.io.*;
import java.net.*;
import java.math.BigInteger;
import java.util.Scanner;

public class DH_Client {


private static final String SERVER_IP = "localhost";
private static final int PORT_NUMBER = 12345;

public static void main(String[] args) {


try {
Socket socket = new Socket(SERVER_IP, PORT_NUMBER);
System.out.println("Connected to the server.");

// Receive public parameters and public key from the server


ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
BigInteger prime = (BigInteger) in.readObject();
BigInteger generator = (BigInteger) in.readObject();
BigInteger server_public_key = (BigInteger) in.readObject();

// Generate private key (client_private_key)


BigInteger client_private_key = new BigInteger("15");

// Calculate public key (client_public_key)


BigInteger client_public_key = generator.modPow(client_private_key, prime);

// Send public key to the server


ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(client_public_key);

// Calculate the shared secret key


BigInteger shared_secret_key = server_public_key.modPow(client_private_key, prime);
System.out.println("Shared Secret Key: " + shared_secret_key);

// Take input from the user


Scanner scanner = new Scanner(System.in);
System.out.print("Enter the message to encrypt and send: ");
String message = scanner.nextLine();

// Encrypt the message using the shared secret key


byte[] encryptedMessage = encryptMessage(message, shared_secret_key);

// Send encrypted message to the server


out.writeObject(encryptedMessage);

scanner.close();
socket.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}

private static byte[] encryptMessage(String message, BigInteger key) {


// Simple XOR encryption for demonstration purposes
byte[] encrypted = message.getBytes();
for (int i = 0; i < encrypted.length; i++) {
encrypted[i] ^= key.byteValue();
}
return encrypted;
}
}
OUTPUT:
Server Side:

Client side:

You might also like