Dr.
KALAIGNAR GOVERNMENT ARTS COLLEGE
KULITHALAI - 639 120
DEPARTMENT OF COMPUTER SCIENCE
REGISTER NUMBER :
NAME :
SUBJECT : CRYPTOGRAPHY AND
NETWORK SECURITY
CLASS : II M.Sc. COMPUTER SCIENCE
Dr. KALAIGNAR GOVERNMENT ARTS COLLEGE
KULITHALAI - 639 120
DEPARTMENT OF COMPUTER SCIENCE
Register No.
This is to certify that the Bonafide record of the work done by
______________________ of II M.Sc.-CS in the Department of
Computer Science during the academic year 2023-2024 and submitted for
the University Practical Examination held on __________________ at
Dr. Kalaignar Government Arts College, Kulithalai-639120.
Head of the Department Faculty in charge
Examiners
1. 2.
CONTENTS
PAGE
Ex. No. DATE NAME OF THE EXPERIMENT FACULTY SIGN
No.
Implement Caesar cipher
1
encryption-decryption algorithm
Implement Playfair cipher
2
encryption-decryption algorithm
3 To implement a Simple DES or
AES algorithm
4 To implement a Simple AES
algorithm
5 Implement the Diffi-Hellmen
Key Exchange Method
6 Implement RSA encryption-
decryption algorithm
7 Write a program to generate a
SHA-1 hash
8 Implement a digital signature
algorithm
Implement Caesar cipher encryption-decryption
Aim:
To implement the Caesar cipher encryption and decryption.
Procedure:
1. Choose a shift value between 1 and 25.
2. Write down the alphabet in order from A to Z.
3. Create a new alphabet by shifting each letter of the original alphabet by the shift value.
For example, if the shift value is 3, the new alphabet would be:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
DEFGHIJKLMNOPQRSTUVWXYZABC
4. Replace each message letter with the corresponding letter from the new alphabet.
5. To decrypt the message, shift each letter back by the same amount.
6. Traverse the given text one character at a time.
7. For each character, transform the given character as per the rule, depending on whether
we’re encrypting or decrypting the text.
8. Return the new string generated.
Encryption:
#include<stdio.h>
#include<ctype.h>
int main() {
char text[500], ch;
int key;
// Taking user input.
printf("Enter a message to encrypt: ");
scanf("%s", text);
printf("Enter the key: ");
scanf("%d", & key);
// Visiting character by character.
for (int i = 0; text[i] != '\0'; ++i) {
ch = text[i];
// Check for valid characters.
if (isalnum(ch)) {
//Lowercase characters.
if (islower(ch)) {
ch = (ch - 'a' + key) % 26 + 'a';
}
// Uppercase characters.
if (isupper(ch)) {
ch = (ch - 'A' + key) % 26 + 'A';
}
// Numbers.
if (isdigit(ch)) {
ch = (ch - '0' + key) % 10 + '0';
}
}
// Invalid character.
else {
printf("Invalid Message");
}
// Adding encoded answer.
text[i] = ch;
}
printf("Encrypted message: %s", text);
return 0;
}
Output:
Enter a message to encrypt: axzd
Enter the key: 4
Encrypted message: ebdh
Decryption:
#include<stdio.h>
#include<ctype.h>
int main() {
char text[500], ch;
int key;
// Taking user input.
printf("Enter a message to decrypt: ");
scanf("%s", text);
printf("Enter the key: ");
scanf("%d", & key);
// Visiting each character.
for (int i = 0; text[i] != '\0'; ++i) {
ch = text[i];
// Check for valid characters.
if (isalnum(ch)) {
//Lowercase characters.
if (islower(ch)) {
ch = (ch - 'a' - key + 26) % 26 + 'a';
}
// Uppercase characters.
if (isupper(ch)) {
ch = (ch - 'A' - key + 26) % 26 + 'A';
}
// Numbers.
if (isdigit(ch)) {
ch = (ch - '0' - key + 10) % 10 + '0';
}
}
// Invalid characters.
else {
printf("Invalid Message");
}
// Adding decoded character back.
text[i] = ch;
}
printf("Decrypted message: %s", text);
return 0;
}
Output:
Enter a message to decrypt: ebdh
Enter the key: 4
Decrypted message: axzd
Implement Playfair cipher encryption-decryption
Aim:
To implement the Playfair cipher encryption and decryption algorithm.
Procedure:
1. Generate the key Square (5×5).
2. The key square is a 5×5 grid of alphabets that acts as the key for encrypting the
plaintext. Each of the 25 alphabets must be unique and one letter of the alphabet
(usually J) is omitted from the table (as the table can hold only 25 alphabets). If the
plaintext contains J, then it is replaced by I.
3. The initial alphabets in the key square are the unique alphabets of the key in the
order in which they appear followed by the remaining letters of the alphabet in order.
4. The plaintext is split into pairs of two letters (digraphs). If there is an odd number
of letters, a Z is added to the last letter.
5. Generate the key Square (5×5) at the receiver’s end.
6. The key square is a 5×5 grid of alphabets that acts as the key for encrypting the
plaintext. Each of the 25 alphabets must be unique and one letter of the alphabet
(usually J) is omitted from the table (as the table can hold only 25 alphabets). If the
plaintext contains J, then it is replaced by I.
7. The initial alphabets in the key square are the unique alphabets of the key in the
order in which they appear followed by the remaining letters of the alphabet in order.
8. The ciphertext is split into pairs of two letters (digraphs).
#include<stdio.h>
#include<conio.h>
void main() {
char v,w,ch,string[100],arr[5][5],key[10],a,b,enc[100];
int temp,i,j,k,l,r1,r2,c1,c2,t,var;
FILE * fp;
fp=fopen("sk.txt","r");
//keep message in sk.txt (e.g. jamia)
clrscr();
printf("Enter the key\n");
fflush(stdin);
scanf("%s",&key);
l=0;
while(1) {
ch=fgetc(fp);
if(ch!=EOF) {
string[l++]=ch;
}
if(ch==EOF)
break;
}
string[l]='\0';
puts(string);
for (i=0;key[i]!='\0';i++) {
for (j=i+1;key[j]!='\0';j++) {
if(key[i]==key[j]) {
temp=1;
break;
}
}
}
if(temp==1)
printf("invalid key"); else {
k=0;
a='a';
//printf("%c",b);
for (i=0;i<5;i++) {
for (j=0;j<5;j++) {
if(k<strlen(key))
arr[i][j]=key[k]; else if(k==strlen(key)) {
b:
for (l=0;l<strlen(key);l++) {
if(key[l]==a) {
a++;
goto b;
}
}
arr[i][j]=a;
if(a=='i')
a=a+2; else
a++;
}
if(k<strlen(key))
k++;
}
}
printf("\n");
printf("The matrix is\n");
for (i=0;i<5;i++) {
for (j=0;j<5;j++) {
printf("%c",arr[i][j]);
}
printf("\n");
}
t=0;
if(strlen(string)%2!=0)
var=strlen(string)-1;
for (i=0;i<var;) {
v=string[i++];
w=string[i++];
if(v==w) {
enc[t++]=v;
enc[t++]='$';
} else {
for (l=0;l<5;l++) {
for (k=0;k<5;k++) {
if(arr[l][k]==v||v=='j'&&arr[l][k]=='i') {
r1=l;
c1=k;
}
if(arr[l][k]==w||w=='j'&&arr[l][k]=='i') {
r2=l;
c2=k;
}
}
}
if(c1==c2) {
r1++;
r2++;
if(r1==5||r2==5) {
r1=0;
r2=0;
}
} else if(r1==r2) {
c1++;
c2++;
if(c1==5||c2==5) {
c1=0;
c2=0;
}
} else {
temp=r1;
r1=r2;
r2=temp;
}
enc[t++]=arr[r1][c1];
enc[t++]=arr[r2][c2];
}
}
if(strlen(string)%2!=0)
enc[t++]=string[var];
enc[t]='\0';
}
printf("The encrypted text is\n");
puts(enc);
getch();
}
Output:
Enter the key:
3421
moshin
The matrix is
3421a
bcdef
ghikl
mnopq
rstuv
The encrypted text is
np4$
To implement Simple DES or AES algorithm
Aim:
To implement the Simple DES or AES algorithm.
Procedure:
1. In the first step, the 64-bit plain text block is handed over to an initial Permutation
(IP) function.
2. The initial permutation is performed on plain text.
3. Next, the initial permutation (IP) produces two halves of the permuted block; saying
Left Plain Text (LPT) and Right Plain Text (RPT).
4. Now, each LPT and RPT goes through 16 rounds of the encryption process.
5. In the end, LPT and RPT are re-joined, and a Final Permutation (FP) is performed
on the combined block.
6. The result of this process produces 64-bit ciphertext.
#include<stdio.h>
int main()
{
int i, cnt=0, p8[8]={6,7,8,9,1,2,3,4};
int p10[10]={6,7,8,9,10,1,2,3,4,5};
char input[11], k1[10], k2[10], temp[11];
char LS1[5], LS2[5];
//k1, k2 are for storing interim keys
//p8 and p10 are for storing permutation key
//Read 10 bits from user...
printf("Enter 10 bits input:");
scanf("%s",input);
input[10]='\0';
//Applying p10...
for (i=0; i<10; i++)
{
cnt = p10[i];
temp[i] = input[cnt-1];
}
temp[i]='\0';
printf("\nYour p10 key is :");
for (i=0; i<10; i++)
{ printf("%d,",p10[i]); }
printf("\nBits after p10 :");
puts(temp);
//Performing LS-1 on first half of temp
for (i=0; i<5; i++)
{
if(i==4)
temp[i]=temp[0];
else
temp[i]=temp[i+1];
}
//Performing LS-1 on second half of temp
for (i=5; i<10; i++)
{
if(i==9)
temp[i]=temp[5];
else
temp[i]=temp[i+1];
}
printf("Output after LS-1 :");
puts(temp);
printf("\nYour p8 key is :");
for (i=0; i<8; i++)
{printf("%d,”, p8[i]); }
//Applying p8...
for (i=0; i<8; i++)
{
cnt = p8[i];
k1[i] = temp[cnt-1];
}
printf("\nYour key k1 is :");
puts(k1);
//This program can be extended to generate k2 as per DES Procedure.
}
Output:
Enter 10 bits input:1100011100
Your p10 key is :6,7,8,9,10,1,2,3,4,5,
Bits after p10 :1110011000
Output after LS-1 :1100110001
Your p8 key is :6,7,8,9,1,2,3,4,
Your key k1 is :10001100
To implement a Simple AES algorithm
Aim:
To implement the Simple AES algorithm.
Procedure:
1. AES performs operations on bytes of data rather than in bits. Since the block size is
128 bits, the cipher processes 128 bits (or 16 bytes) of the input data simultaneously.
2. The number of rounds depends on the key length as follows:
128 bit key – 10 rounds
192 bit key – 12 rounds
256 bit key – 14 rounds.
3. A Key Schedule Procedure is used to calculate all the round keys from the key. So the
initial key is used to create many different round keys used in the corresponding round
of the encryption.
4. AES considers each block as a 16 byte (4 byte x 4 byte = 128 ) grid in a column major
arrangement.
5. Now the resultant output of the previous stage is XOR-ed with the corresponding round
key. Here, the 16 bytes is not considered as a grid but just as 128 bits of data.
6. After all these rounds 128 bits of encrypted data is given back as output. This process
is repeated until all the data to be encrypted undergoes this process.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* MCrypt API available online:
* http://linux.die.net/man/3/mcrypt
*/
#include <mcrypt.h>
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
int encrypt(
void* buffer,
int buffer_len, /* Because the plaintext could include null bytes*/
char* IV,
char* key,
int key_len
){
MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
int blocksize = mcrypt_enc_get_block_size(td);
if( buffer_len % blocksize != 0 ){return 1;}
mcrypt_generic_init(td, key, key_len, IV);
mcrypt_generic(td, buffer, buffer_len);
mcrypt_generic_deinit (td);
mcrypt_module_close(td);
return 0;
}
int decrypt(
void* buffer,
int buffer_len,
char* IV,
char* key,
int key_len
){
MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
int blocksize = mcrypt_enc_get_block_size(td);
if( buffer_len % blocksize != 0 ){return 1;}
mcrypt_generic_init(td, key, key_len, IV);
mdecrypt_generic(td, buffer, buffer_len);
mcrypt_generic_deinit (td);
mcrypt_module_close(td);
return 0;
}
void display(char* ciphertext, int len){
int v;
for (v=0; v<len; v++){
printf("%d ", ciphertext[v]);
}
printf("\n");
}
int main()
{
MCRYPT td, td2;
char* plaintext = "test text 123";
char* IV = "AAAAAAAAAAAAAAAA";
char* key = "0123456789abcdef";
int keysize = 16; /* 128 bits */
char* buffer;
int buffer_len = 16;
buffer = calloc(1, buffer_len);
strncpy(buffer, plaintext, buffer_len);
printf("==C==\n");
printf("plain: %s\n", plaintext);
encrypt(buffer, buffer_len, IV, key, keysize);
printf("cipher: "); display(buffer , buffer_len);
decrypt(buffer, buffer_len, IV, key, keysize);
printf("decrypt: %s\n", buffer);
return 0;
}
Implement Diffi-Hellmen Key Exchange Method
Aim:
To implement the Diffi-Hellmen key exchange method
Procedure:
1. Get public numbers P = 23, G = 9
2. User-1 selected a private key a = 4 and User-2 selected a private key b = 3
3. Compute public values
User-1: x =(9^4 mod 23) = (6561 mod 23) = 6
User-2: y = (9^3 mod 23) = (729 mod 23) = 16
4. User-1 and User-2 exchange public numbers
5. User-1 receive public key y =16 and User-2 receive public key x = 6
6. Compute symmetric keys
User-1: ka = y^a mod p = 65536 mod 23 = 9
User-2: kb = x^b mod p = 216 mod 23 = 9
7. 9 is the shared secret.
/* This program calculates the Key for two persons
using the Diffie-Hellman Key exchange Procedure */
#include <math.h>
#include <stdio.h>
// Power function to return value of a ^ b mod P
long long int power(long long int a, long long int b,
long long int P)
{
if (b == 1)
return a;
else
return (((long long int)pow(a, b)) % P);
}
// Driver program
int main()
{
long long int P, G, x, a, y, b, ka, kb;
// Both the persons will be agreed upon the
// public keys G and P
P = 23; // A prime number P is taken
printf("The value of P : %lld\n", P);
G = 9; // A primitive root for P, G is taken
printf("The value of G : %lld\n\n", G);
// User-1 will choose the private key a
a = 4; // a is the chosen private key
printf("The private key a for User-1 : %lld\n", a);
x = power(G, a, P); // gets the generated key
// User-2 will choose the private key b
b = 3; // b is the chosen private key
printf("The private key b for User-2 : %lld\n\n", b);
y = power(G, b, P); // gets the generated key
// Generating the secret key after the exchange
// of keys
ka = power(y, a, P); // Secret key for User-1
kb = power(x, b, P); // Secret key for User-2
printf("Secret key for the User-1 is : %lld\n", ka);
printf("Secret Key for the User-2 is : %lld\n", kb);
return 0;
}
Output:
The value of P : 23
The value of G : 9
The private key a for User-1 : 4
The private key b for User-2 : 3
Secret key for the User-1 is : 9
Secret Key for the User-2 is : 9
Implement RSA encryption-decryption algorithm
Aim:
To implement the RSA encryption and decryption algorithm.
Procedure:
1. Two prime numbers are selected as p and q.
2. n = pq which is the modulus of both the keys.
3. Calculate totient = (p-1)(q-1).
4. Choose e such that e > 1 and coprime to totient which means gcd (e, totient) must be
equal to 1, e is the public key.
5. Choose d such that it satisfies the equation de = 1 + k (totient), d is the private key not
known to everyone.
6. Cipher text is calculated using the equation c = m^e mod n where m is the message.
7. With the help of c and d we decrypt message using equation m = c^d mod n where d
is the private key.
//Program for RSA asymmetric cryptographic algorithm
//for demonstration values are relatively small compared to practical application
#include<stdio.h>
#include<math.h>
//to find gcd
int gcd(int a, int h)
{
int temp;
while(1)
{
temp = a%h;
if(temp==0)
return h;
a = h;
h = temp;
}
}
int main()
{
//2 random prime numbers
double p = 3;
double q = 7;
double n=p*q;
double count;
double totient = (p-1)*(q-1);
//public key
//e stands for encrypt
double e=2;
//for checking co-prime which satisfies e>1
while(e<totient){
count = gcd(e,totient);
if(count==1)
break;
else
e++;
}
//private key
//d stands for decrypt
double d;
//k can be any arbitrary value
double k = 2;
//choosing d such that it satisfies d*e = 1 + k * totient
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);
printf("Message data = %lf",msg);
printf("\np = %lf",p);
printf("\nq = %lf",q);
printf("\nn = pq = %lf",n);
printf("\ntotient = %lf",totient);
printf("\ne = %lf",e);
printf("\nd = %lf",d);
printf("\nEncrypted data = %lf",c);
printf("\nOriginal Message Sent = %lf",m);
return 0;
}
Output:
Message data = 12
p=3
q=7
n = pq = 21
totient = 12
e=5
d=5
Encrypted data = 3
Original Message Sent = 12
Write a program to generate a SHA-1 hash
Aim:
To write a program to generate a SHA-1 hash.
Procedure:
1. Append padding bits − The original message is padded and its duration is congruent to
448 modulo 512. Padding is continually inserted although the message already has the
desired length. Padding includes a single 1 followed by the essential number of 0 bits.
2. Append length − A 64-bit block considered as an unsigned 64-bit integer (most essential
byte first), and defining the length of the original message (before padding in step 1),
is added to the message. The complete message's length is a multiple of 512.
3. Initialize the buffer − The buffer includes five (5) registers of 32 bits each indicated by
A, B, C, D, and E. This 160-bit buffer can be used to influence temporary and final
outcomes of the compression function. These five registers are initialized to the
following 32-bit integers (in hexadecimal notation).
A = 67 45 23 01
B = ef cd ab 89
C = 98 ba dc fe
D = 10 32 54 76
E = c3 d2 e1 f0
4. The registers A, B, C, and D are actually the same as the four registers used in MD5
algorithm. But in SHA-1, these values are saved in big-endian format, which define that
the most essential byte of the word is located in the low-address byte position. Therefore
the initialization values (in hexadecimal notation) occurs as follows −
word A = 67 45 23 01
word B = ef cd ab 89
word C = 98 ba dc fe
word D = 10 32 54 76
word E = c3 d2 e1 f0
5. Process message in 512-bit blocks − The compression function is divided into 20
sequential steps includes four rounds of processing where each round is made up of 20
steps.
6. The four rounds are structurally same as one another with the only difference that each
round need a different Boolean function, which it can define as f1, f2, f3, f4 and one of
four multiple additive constants Kt (0 ≤t ≤79) which is based on the step under
consideration.
7. Output − After processing the final 512-bit message block t (considering that the
message is divided into t 512-bit blocks), and it can obtain a 160-bit message digest.
// Java program to calculate SHA-1 hash value
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchProcedureException;
public class GFG {
public static String encryptThisString(String input)
{
try {
// getInstance() method is called with Procedure SHA-1
MessageDigest md = MessageDigest.getInstance("SHA-1");
// digest() method is called
// to calculate message digest of the input string
// returned as array of byte
byte[] messageDigest = md.digest(input.getBytes());
// Convert byte array into signum representation
BigInteger no = new BigInteger(1, messageDigest);
// Convert message digest into hex value
String hashtext = no.toString(16);
// Add preceding 0s to make it 32 bit
while (hashtext.length() < 32) {
hashtext = "0" + hashtext;
}
// return the HashText
return hashtext;
}
// For specifying wrong message digest Procedures
catch (NoSuchProcedureException e) {
throw new RuntimeException(e);
}
}
// Driver code
public static void main(String args[]) throws
NoSuchProcedureException
{
System.out.println("Hash Code Generated by SHA-1 for: ");
String s1 = "GeeksForGeeks";
System.out.println("\n" + s1 + " : " + encryptThisString(s1));
String s2 = "hello world";
System.out.println("\n" + s2 + " : " + encryptThisString(s2));
}
}
Output:
Hash Code Generated by SHA-1 for:
GeeksForGeeks: addf120b430021c36c232c99ef8d926aea2acd6b
hello world: 2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
Implement a digital signature algorithm
Aim:
To implement a digital signature algorithm.
Procedure:
1. Consider a simple text message.
2. Apply the hash function to this simple text message then our hash code is generated.
3. Hash code, along with the random variable k, is given input to the signature Procedure.
4. For this signature, we use the global public key PUA. Along with this, we will use the
private key of the sender PRA.
5. Now we get the signature appended to the simple text.
6. Along with the simple text, we will get two components named s and r.
7. These s and r are known as signature components.
8. Now reverse functions are applied.
9. The hash function is applied along with the s and r components to a verifying function.
10. The verifying function uses the global public key and the sender’s public key.
11. The resultant of verifying function is compared with signature component r.
// Java implementation for Generating
// and verifying the digital signature
package java_cryptography;
// Imports
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.util.Scanner;
import javax.xml.bind.DatatypeConverter;
public class Digital_Signature_GeeksforGeeks {
// Signing Procedure
private static final String
SIGNING_PROCEDURE
= “SHA256withRSA”;
private static final String RSA = “RSA”;
private static Scanner sc;
// Function to implement Digital signature
// using SHA256 and RSA Procedure
// by passing private key.
Public static byte[] Create_Digital_Signature(
byte[] input,
PrivateKey Key)
throws Exception
{
Signature signature
= Signature.getInstance(
SIGNING_PROCEDURE);
signature.initSign(Key);
signature.update(input);
return signature.sign();
}
// Generating the asymmetric key pair
// using SecureRandom class
// functions and RSA Procedure.
Public static KeyPair Generate_RSA_KeyPair()
throws Exception
{
SecureRandom secureRandom
= new SecureRandom();
KeyPairGenerator keyPairGenerator
= KeyPairGenerator
.getInstance(RSA);
keyPairGenerator
.initialize(
2048, secureRandom);
return keyPairGenerator
.generateKeyPair();
}
// Function for Verification of the
// digital signature by using the public key
public static eypair
Verify_Digital_Signature(
byte[] input,
byte[] signatureToVerify,
PublicKey key)
throws Exception
{
Signature signature
= Signature.getInstance(
SIGNING_PROCEDURE);
signature.initVerify(key);
signature.update(input);
return signature
.verify(signatureToVerify);
}
// Driver Code
public static void main(String args[])
throws Exception
{
String input
= “GEEKSFORGEEKS IS A”
+ “ COMPUTER SCIENCE PORTAL”;
KeyPair eypair
= Generate_RSA_KeyPair();
// Function Call
byte[] signature
= Create_Digital_Signature(
input.getBytes(),
eypair.getPrivate());
System.out.println(
“Signature Value:\n “
+ DatatypeConverter
.printHexBinary(signature));
System.out.println(
“Verification: “
+ Verify_Digital_Signature(
input.getBytes(),
signature, eypair.getPublic()));
}
}
Input:
msg = “GEEKSFORGEEEKS IS A COMPUTER SCIENCE PORTAL”
Output:
Signature Value:
80429D3FA203437B4098CAF774D96C827B6CC2489F437A82926DA2EFCE64EF68FB33
235B9F6BA8E3B033235B9F6BA8
Verification: true