Pages

Friday 3 March 2017

DATA ENCRYPTION STANDARD

DATA ENCRYPTION STANDARD PROGRAM in C++ for both Encryption and Decryption :-

/*=====================================================|
|    AUTHOR :- RAVI SHANKAR KUMAR                                                          |
|    FROM :- SITAMARHI(BIHAR),INDIA                                                          |
|    Email :- ravisk.cs.14@gmail.com                                                                |
|    NIT JALANDHAR, CSE PRE-FINAL YEAR                                                 |
|====================================================*/
/*PROGRAM CHECKER INPUT
  19 52 87 121 155 188 223 241
   1 35 69 103 137 171 205 239
*/
#include<bits/stdc++.h>
using namespace std;
//IP is Initial Permutation Block for Plain Text
//============================INPUT BLOCK============================
static const int IP[64]={58,50,42,34,26,18,10, 2,
                     60,52,44,36,28,20,12, 4,
                     62,54,46,38,30,22,14, 6,
                     64,56,48,40,32,24,16, 8,
                     57,49,41,33,25,17, 9, 1,
                     59,51,43,35,27,19,11, 3,
                     61,53,45,37,29,21,13, 5,
                     63,55,47,39,31,23,15, 7};
//IIP is inverse of initial permutation block.
//Note :- It can be generated by IP also.
static const int IIP[64]={40,8,48,16,56,24,64,32,
                       39,7,47,15,55,23,63,31,
                       38,6,46,14,54,22,62,30,
                       37,5,45,13,53,21,61,29,
                       36,4,44,12,52,20,60,28,
                       35,3,43,11,51,19,59,27,
                       34,2,42,10,50,18,58,26,
                         33,1,41, 9,49,17,57,25};
//C0 and D0 for 64bit key to 56bit key generation and rotation to get
//the permuted key of 48 bit using Compression Block of permutation.
static const int c0[28]={57,49,41,33,25,17, 9, 1,
             58,50,42,34,26,18,10, 2,
             59,51,43,35,27,19,11, 3,
             60,52,44,36};
static const int d0[28]={63,55,47,39,31,23,15, 7,
             62,54,46,38,30,22,14, 6,
             61,53,45,37,29,21,13, 5,
             28,20,12, 4};
static const int compression[48]={14,17,11,24, 1, 5, 3,28,15, 6,21,10,
                  23,19,12, 4,26, 8,16, 7,27,20,13, 2,
                  41,52,31,37,47,55,30,40,51,45,33,48,
                  44,49,39,56,34,53,46,42,50,36,29,32};
//EXPANSION BOX used to expand 32 bit Plain text to 48 bit for Xor operation
//with key for the current round
static const int expansion[48]={32, 1, 2, 3, 4, 5,
                 4, 5, 6, 7, 8, 9,
                 8, 9,10,11,12,13,
                                 12,13,14,15,16,17,
                                 16,17,18,19,20,21,
                           20,21,22,23,24,25,
                           24,25,26,27,28,29,
                           28,29,30,31,32, 1};
//8 S-box will be used in Each round of encryption and decryption.
static const int sbx[8][4][16]={//S1 BOX
                    14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
                    0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
                    4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
                   15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,
                   //S2 BOX
                   15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
                    3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
                    0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
                   13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,
                   //S3 BOX
                  10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
                   13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
                   13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
                       1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,
                   //S4 BOX
                    7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
                   13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
                   10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
                    3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,
                   //S5 BOX
                    2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
                   14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
                    4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
                   11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,
                   //S6 BOX
                   12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
                   10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
                    9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
                    4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,
                   //S7 BOX
                    4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
                   13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
                    1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
                    6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,
                   //S8 BOX
                      13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
                    1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
                    7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
                    2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11};
static const int straightPer[32]={16, 7,20,21,29,12,28,17,
                        1,15,23,26, 5,18,31,10,
                        2, 8,24,14,32,27, 3, 9,
                       19,13,30, 6,22,11, 4,25};
//================================HELPER FUNCTION=======================
/*
 Here Function char_to_binary takes input as integer
 equivalent of character and returns the number equivalent
 in base b; Generally we needed b=2 in DES.
*/
char *char_to_binary(int num,int b)
{
  char *bin=new char[9]; int k=7;
  while(k>=0)
  {
      bin[k--]=num%b+'0';
      num/=b;
  }
  bin[8]='\0';
  return bin;
}
/*
  Here Function binary_to_char takes character array as input,
  convert them into decimal ascii value and return corresponding character
*/
char binary_to_char(char a[])
{
  int num=0;
  for(int i=0;i<8;i++)
      num=(num*2)+(a[i]-'0');
  char ans=num;
  return ans;
}
/*
 Here function Initial_Permute will permute the 2d char array
 input according to Initial_Permutation block IP and will return
 Permuted 2d char array output.
*/
char **Initial_Permute(char **input)
{
   //Declaration of 2d char array.
   char **output=new char*[8];
   for(int i=0;i<8;i++) output[i]=new char[9];
   //Mapping of input to output using IP
   for(int i=0;i<8;i++)
      for(int j=0;j<8;j++)
         {
            int row=(IP[i*8+j]-1)/8,col=(IP[i*8+j]-1)%8;
            output[i][j]=input[row][col];
         }
   return output;
}
/*
 Here function Initial_Permute will permute the 2d char array
 input according to Initial_Permutation block IP and will return
 Permuted 2d char array output.
*/
char **Inv_Initial_Permute(char **input)
{
   //Declaration of 2d char array.
   char **output=new char*[8];
   for(int i=0;i<8;i++) output[i]=new char[9];
   //Mapping of input to output using IP
   for(int i=0;i<8;i++)
      for(int j=0;j<8;j++)
         {
            int row=(IIP[i*8+j]-1)/8,col=(IIP[i*8+j]-1)%8;
            output[i][j]=input[row][col];
         }
   return output;
}
//This function is very simple.
char xors(char a,char b)
{
  if(a==b) return '0';
  else return '1';
}
//================================KEY GENERATION=======================
/*
 Here function will convert 64 bit character of key to 56 bit char key
 using C0 and D0 block.
*/
void convert_64_to_56(char **input,char **output)
{
   //Maping using C0 and D0 block.
   for(int i=0;i<28;i++)
   {
      int row=(c0[i]-1)/8,col=(c0[i]-1)%8;
      output[0][i]=input[row][col];
      row=(d0[i]-1)/8,col=(d0[i]-1)%8;
      output[1][i]=input[row][col];
   }
   output[0][28]=output[1][28]='\0';
   return;
}
/*
  Here function left_shift will shift 56bit key by one bit.
  You need to call it twice if you want to shift left by 2 bit.
*/
void left_shift(char **input)
{
   char temp1=input[0][0],temp2=input[1][0];
   for(int i=0;i<27;i++)
      {
         input[0][i]=input[0][i+1];
         input[1][i]=input[1][i+1];
      }
   input[0][27]=temp1; input[1][27]=temp2;
   return;
}
void key_generation(char key[],char **keys)
{
   //Declare a 2d character array to store 64bit keys
   char **binary=new char*[8];
   for(int i=0;i<8;i++) binary[i]=new char[9];
   //Initialize 64bit key by calling char_to_binary converter.
   for(int i=0;i<8;i++)
        binary[i]=char_to_binary(key[i],2);
   //Call Initial Permutation of 64-bit Key.
   //binary=Initial_Permute(binary);
   //Call convert_64_to_56
   char **output=new char*[2];
   output[0]=new char[29];
   output[1]=new char[29];
   convert_64_to_56(binary,output);
   //16 round key generation.
   for(int i=0;i<16;i++)
   {
       //Call one time shift if round=1,2,9 or 16
       //Else call twice.
       if(i==0||i==1||i==8||i==15) left_shift(output);
       else left_shift(output),left_shift(output);
       //MAP shifted 2d array to round key using fin block
       for(int k=0;k<48;k++)
       {
          int row=(compression[k]-1)/28,col=(compression[k]-1)%28;
          keys[i][k]=output[row][col];
       }
       keys[i][48]='\0';
   }
   return;
}
//================================ENCRYPTION=======================
char *use_SBox(char inp[])
{
   char *ans=new char[33];
   char *temp=new char[9];
   int row,col,indx=0,pos;
   //USE all S-Box to compress each 6-bit into 4bit
   for(int i=0;i<8;i++)
   {
      pos=i*6;
      row=(inp[pos]-'0')*2+(inp[pos+5]-'0'); //First and last bit for row index
      //Second,Third,Fourth and fifth bits for column index
      col=(inp[pos+1]-'0')*8+(inp[pos+2]-'0')*4+(inp[pos+3]-'0')*2+(inp[pos+4]-'0');
      temp=char_to_binary(sbx[i][row][col],2);
      ans[indx++]=temp[4],ans[indx++]=temp[5],ans[indx++]=temp[6],ans[indx++]=temp[7];
   }
   return ans;
}
char *Encryption(char pt[],char **keys)
{
   //Declare a 2d character array to store 64bit PlainText
   char **binary=new char*[8];
   for(int i=0;i<8;i++) binary[i]=new char[9];
   //Initialize 64bit array by calling char_to_binary converter.
   for(int i=0;i<8;i++)
        binary[i]=char_to_binary(pt[i],2);
   //Call Initial Permutation of 64-bit Key.
   binary=Initial_Permute(binary);
   //Break 64bit block into left and right block of 32bit each
   char *left=new char[33];
   char *right=new char[33];
   char *temp=new char[33];
   for(int i=0;i<4;i++)
      for(int j=0;j<8;j++)
        {
           left[i*8+j]=binary[i][j];
           right[i*8+j]=binary[i+4][j];
        }
   left[32]=right[32]='\0';
   //Apply all 16 rounds to get final output.
   for(int k=0;k<16;k++)
   {
     //Take copy of right part.
     for(int i=0;i<32;i++) temp[i]=right[i];
     temp[32]='\0';
     //Expand 32bit right part to 48bit using expansion box
     char *expands=new char[49];
     for(int i=0;i<48;i++) expands[i]=temp[expansion[i]-1];
     expands[48]='\0';
     //XOR it with kth key block of 48 bit.
     for(int i=0;i<48;i++) expands[i]=xors(expands[i],keys[k][i]);
     //Apply all 8 S-box upon it to get 32bit output.
     temp=use_SBox(expands);
     //Apply stright permutation box
     for(int i=0;i<32;i++) expands[i]=temp[straightPer[i]-1];
     //XOR this output with left 32bit
     for(int i=0;i<32;i++) left[i]=xors(left[i],expands[i]);
     //SWAPS between left and right
     for(int i=0;i<32;i++)
       temp[i]=left[i],left[i]=right[i],right[i]=temp[i];
   }
   //SWAPS left and right because we don't have to swap in the last
   //round but we have got the swapped value.
   for(int i=0;i<32;i++)
       temp[i]=left[i],left[i]=right[i],right[i]=temp[i];
   //Make this 64 bit 1D to 2D array
   for(int i=0;i<32;i++)
    binary[i/8][i%8]=left[i],binary[(i+32)/8][(i+32)%8]=right[i];
    //Apply inverse permutation box by calling Inv_Initial_Permute function
    binary=Inv_Initial_Permute(binary);
    //Convert this binary 64bit to 8 charactes.
    for(int i=0;i<8;i++)
      pt[i]=binary_to_char(binary[i]);
    return pt;
}
//================================DECRYPTION=========================
char *Decryption(char pt[],char **keys)
{
   //Declare a 2d character array to store 64bit PlainText
   char **binary=new char*[8];
   for(int i=0;i<8;i++) binary[i]=new char[9];
   //Initialize 64bit array by calling char_to_binary converter.
   for(int i=0;i<8;i++)
        binary[i]=char_to_binary(pt[i],2);
   //Call Initial Permutation of 64-bit Key.
   binary=Initial_Permute(binary);
   //Break 64bit block into left and right block of 32bit each
   char *left=new char[33];
   char *right=new char[33];
   char *temp=new char[33];
   for(int i=0;i<4;i++)
      for(int j=0;j<8;j++)
        {
           left[i*8+j]=binary[i][j];
           right[i*8+j]=binary[i+4][j];
        }
   left[32]=right[32]='\0';
   //Apply all 16 rounds to get final output.
   for(int k=0;k<16;k++)
   {
     //Take copy of right part.
     for(int i=0;i<32;i++) temp[i]=right[i];
     temp[32]='\0';
     //Expand 32bit right part to 48bit using expansion box
     char *expands=new char[49];
     for(int i=0;i<48;i++) expands[i]=temp[expansion[i]-1];
     expands[48]='\0';
     //XOR it with kth key block of 48 bit.
     for(int i=0;i<48;i++) expands[i]=xors(expands[i],keys[15-k][i]);
     //Apply all 8 S-box upon it to get 32bit output.
     temp=use_SBox(expands);
     //Apply stright permutation box
     for(int i=0;i<32;i++) expands[i]=temp[straightPer[i]-1];
     //XOR this output with left 32bit
     for(int i=0;i<32;i++) left[i]=xors(left[i],expands[i]);
     //SWAPS between left and right
     for(int i=0;i<32;i++)
       temp[i]=left[i],left[i]=right[i],right[i]=temp[i];
   }
   //SWAPS left and right because we don't have to swap in the last
   //round but we have got the swapped value.
   for(int i=0;i<32;i++)
       temp[i]=left[i],left[i]=right[i],right[i]=temp[i];
   //Make this 64 bit 1D to 2D array
   for(int i=0;i<32;i++)
    binary[i/8][i%8]=left[i],binary[(i+32)/8][(i+32)%8]=right[i];
    //Apply inverse permutation box by calling Inv_Initial_Permute function
    binary=Inv_Initial_Permute(binary);
    //Convert this binary 64bit to 8 charactes.
    for(int i=0;i<8;i++)
      pt[i]=binary_to_char(binary[i]);
    return pt;
}
//================================MAIN FUNCTION=======================
int main()
{
  //Declare and take input key string of 8 characters
  char *key=new char[9];
  cout<<"Enter a key string : ";
  cin>>key;
  //Declare 2d keys array to store all 16 round keys
  char **keys=new char*[16];
  for(int i=0;i<16;i++) keys[i]=new char[49];
  //Call key Generation function
  key_generation(key,keys);
  for(int i=0;i<16;i++)
     printf("Key for round %2d : %s\n",i+1,keys[i]);
  //Declare and take input plain text string of 8 characters
  char *pt=new char[9];
  cout<<"Enter plain text of 8 character : ";
  cin>>pt;
  //Call Encryption function to encrypt the plain text
  pt=Encryption(pt,keys);
  cout<<"Encrypted text = "<<pt<<endl;
  //Call Decryption function to decrypt the encrypted text
  pt=Decryption(pt,keys);
  cout<<"Decrypted text = "<<pt<<endl;
  return 0;
}