Playfair File Encryption

 

 

            In this encryption a matrix manipulation is used. A public key is needed to generate a matrix. Then for any input character, generated matrix is used as a lookup table. Here there is a simple implementation of this encryption method. This program encrypts/decrypts a binary file by the help of a public key. This method is really fast. A 107 MB file is encrypted in 98 seconds. Again this implementation is basic. Really much work is needed for robust encryption.

 

 

Encrypted File Format

 

File format size is 22 bytes.

Order of first 22 bytes:

 0    1     2     3     4     5    6      7     8      9    10   11   12   13   14   15    16   17   18   19   20   21

P

L

A

Y

F

Encrypted file's name and extension (total 12 bytes)

 

File size

 

17'th byte = Input key's character size.

Encrypted file is placed starting from 22'nd byte.

 

Sample key: metal_money

 

Repeated characters are truncated from input key.

ASCII representation of sample key is 109,101, 116, 97, 108, 95, 111, 110 and 121. These numbers are written in the starting elements of matrix. The rest unused ASCII numbers are written in sorted ascending order.

 

Generated Playfair matrix using "metal_money" key

i/j

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

0

109 101 116  97 108  95 111 110 121 0   1    2    3    4    5    6

1

 7    8   9  10  11  12  13  14  15  16  17   18   19  20   21   22

2

 23  24  25  26  27  28  29  30  31  32  33   34   35  36   37   38

3

 39  40  41  42  43  44  45  46  47  48  49   50   51  52   53   54

4

 55  56  57  58  59  60  61  62  63  64  65   66   67  68   69   70

5

 71  72  73  74  75  76  77  78  79  80  81   82   83  84   85   86

6

 87  88  89  90  91  92  93  94  96  98  99  100  102 103  104  105

7

106 107 112 113 114 115 117 118 119 120 122  123  124 125  126  127

8

128 129 130 131 132 133 134 135 136 137 138  139  140 141  142  143

9

144 145 146 147 148 149 150 151 152 153 154  155  156 157  158  159

10

160 161 162 163 164 165 166 167 168 169 170  171  172 173  174  175

11

176 177 178 179 180 181 182 183 184 185 186  187  188 189  190  191

12

192 193 194 195 196 197 198 199 200 201 202  203  204 205  206  207

13

208 209 210 211 212 213 214 215 216 217 218  219  220 221  222  223

14

224 225 226 227 228 229 230 231 232 233 234  235  236 237  238  239

15

240 241 242 243 244 245 246 247 248 249 250  251  252 253  254  255

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 

C Source Code

 

#include<stdio.h>
#include<conio.h>
#include<dos.h>
#include<math.h>
#include<time.h>
 
#define info_size 5
 
struct plc {
  unsigned short i,j;
} pl[256];
int num=0;
 
long filesize(FILE *stream) {
  long curpos, length;
  curpos = ftell(stream);
  fseek(stream, 0L, SEEK_END);
  length = ftell(stream);
  fseek(stream, curpos, SEEK_SET);
  return length;
}
 
int make_matris(unsigned char len, unsigned char sifre[],unsigned char A[][16]) {
 unsigned char sif[50];
 int i, j, k, L, n, ascii[256];
 
// array sifre[] is truncating.
 for(i=0;i<50;i++) sif[i] = 0;
 i = 1;
 n = 1;
 sif[0] = sifre[0];
 while(i < len) {
   k = 0;
   for(j=0;j<i;j++)
     if (sifre[j] == sifre[i])  k = 1;
   if (k == 0) { // so character didn't used before
     sif[n] = sifre[i];
     n++;
    }
   i++;
  }
for(i=0;i<256;i++)
   ascii[i] = i;
 i = 0;
 j = 0;
 k = 0;
 while (k < n) {
   A[i][j] = sif[k];
   ascii[sif[k]] = -1;
   if (j  == 15) {
     i++;
     j = 0;
    }
 
   else
     j++;
   k++;
  }
 for(k=0;k<256;k++)
   if (ascii[k] != -1) {
     A[i][j] = ascii[k];
     if (j == 15) {
       i++;
       j = 0;
      }
      else
       j++;
     }
for(i=0;i<16;i++)
   for(j=0;j<16;j++) {
     pl[A[i][j]].i = i;
     pl[A[i][j]].j = j;
    }
 return 0;
}
 
int get_encrypted_data(unsigned char A[][16],
                               unsigned char ch1, unsigned char ch2,
                               unsigned char *ch3, unsigned char *ch4) {
 int i1, i2, j1, j2;
 
 i1 = pl[ch1].i;
 j1 = pl[ch1].j;
 i2 = pl[ch2].i;
 j2 = pl[ch2].j;
 if ((i1 != i2) && (j1 != j2)) {
   *ch3 = A[i1][j2];
   *ch4 = A[i2][j1];
  }
 else {
   if (i1 == i2) {
     j1++;
     j2++;
     if (j1 > 15) j1 = 0;
     if (j2 > 15) j2 = 0;
    }
   else if ( j1 == j2) {
     i1++;
     i2++;
     if (i1 > 15) i1 = 0;
     if (i2 > 15) i2 = 0;
    }
   *ch3 = A[i1][j1];
   *ch4 = A[i2][j2];
  }
 return 0;
}
 
int get_decrypted_data(unsigned char A[][16],
                               unsigned char ch1, unsigned char ch2,
                               unsigned char *ch3, unsigned char *ch4) {
 
 int i1, i2, j1, j2;
 
 i1 = pl[ch1].i;
 j1 = pl[ch1].j;
 i2 = pl[ch2].i;
 j2 = pl[ch2].j;
 if ((i1 != i2) && (j1 != j2)) {
   *ch3 = A[i1][j2];
   *ch4 = A[i2][j1];
  }
 else {
   if (i1 == i2) {
     j1--;
     j2--;
     if (j1 < 0) j1 = 15;
     if (j2 < 0) j2 = 15;
    }
   else if ( j1 == j2) {
     i1--;
     i2--;
     if (i1 < 0) i1 = 15;
     if (i2 < 0) i2 = 15;
    }
   *ch3 = A[i1][j1];
   *ch4 = A[i2][j2];
  }
 return 0;
}
 
void do_work() {
  unsigned char ch1, ch2, ch3, ch4;
  unsigned char sifre[50], src[13], dst[13], length, length_got,
                        type[]={0,0,0,0,0,0,0,0,0,0,0,0}; // 12 byte
  char info[]="PLAYF";   // 5 byte
  char read_info[info_size], ch;
  int i, j, k, mode=0;
  long dst_data_size, den;
  FILE *src_file, *dst_file;
  unsigned char A[16][16];
   time_t time_begin, time_end;
 
  for(i=0;i<49;i++) sifre[i] = 0;
  for(i=0;i<16;i++)
   for(j=0;j<16;j++)
     A[i][j] = 0;
  clrscr();
  printf("Password: ");scanf("%s", sifre);
  printf("Mode(1:Encrypt 2:Decrypt): ");scanf("%d", &mode);
  if (mode == 1) {
    printf("Source File: ");scanf("%s", src);
    printf("Destination File: ");scanf("%s", dst);
    }
  else if (mode == 2) {
    printf("Source File: ");scanf("%s", src);
   }
  if ((src_file = fopen(src,"rb")) == NULL ) {
    clrscr();
    printf("Couldn't open %s... ", src);
    sleep(1);
    return;
   }
  for(i=0;i<12;i++)
    type[i] = src[i];
  length = 0;
  i = 0;
  while (( (sifre[i] != 0) || (sifre[i] != NULL) ) && ( i < 50 )) {
    i++;
    length++;
   }
  
  time_begin = time(NULL);
 
  if (mode == 1) {  
    if ((dst_file = fopen(dst,"wb")) == NULL ) {
      clrscr();
      printf("Couldn't create %s file... ", dst);
      sleep(1);
      return;
     }
    make_matris(length, sifre, A);
    dst_data_size = filesize(src_file);
    fwrite(&info, info_size, 1, dst_file); 
    fwrite(&type, 121, dst_file); 
    fputc(length, dst_file);        
    fwrite(&dst_data_size, 41, dst_file);  
    if ( fmod(dst_data_size, 2) == 0 ) {  // file size is even number
      for(den=0;den<dst_data_size;den=den+2) {
            ch1 = fgetc(src_file);
            ch2 = fgetc(src_file);
            get_encrypted_data(A,ch1, ch2, &ch3, &ch4);
            fputc(ch3 ,dst_file);
            fputc(ch4 ,dst_file);
       }
     }
    else {   // fil size is odd number
      for(den=0;den<dst_data_size-1;den=den+2) {
            ch1 = fgetc(src_file);
            ch2 = fgetc(src_file);
            get_encrypted_data(A,ch1, ch2, &ch3, &ch4);
            fputc(ch3 ,dst_file);
            fputc(ch4 ,dst_file);
       }
      fputc(fgetc(src_file), dst_file);
     }
   }
  else if (mode == 2) {  // decrypt 
    i = 0;
    if (fgetc(src_file) !='P') i++;
    if (fgetc(src_file) !='L') i++;
    if (fgetc(src_file) !='A') i++;
    if (fgetc(src_file) !='Y') i++;
    if (fgetc(src_file) !='F') i++;
    if (i != 0) {
      printf("\nIncorrect File...");
      sleep(2);
      return;
     }
    fread(&type, 121, src_file);
    if ((dst_file = fopen(type,"wb")) == NULL ) {
      clrscr();
      printf("Couldn't create %s file... ", type);
      sleep(1);
      return;
     }
    length_got = fgetc(src_file);
    if (length == length_got)  
      make_matris(length,sifre, A);
    else {
      printf("\nWrong Password %s... ", sifre);
      sleep(2);
      return;
     }
    fread(&dst_data_size, 41, src_file);
 
    if ( fmod(dst_data_size, 2) == 0 ) {  
      for(den=0;den<dst_data_size;den=den+2) {
            ch1 = fgetc(src_file);
            ch2 = fgetc(src_file);
            get_decrypted_data(A,ch1, ch2, &ch3, &ch4);
            fputc(ch3 ,dst_file);
            fputc(ch4 ,dst_file);
       }
     }
    else {   // dosya boyutu tek rakamly
      for(den=0;den<dst_data_size-1;den=den+2) {
            ch1 = fgetc(src_file);
            ch2 = fgetc(src_file);
            get_decrypted_data(A,ch1, ch2, &ch3, &ch4);
            fputc(ch3 ,dst_file);
            fputc(ch4 ,dst_file);
       }
      fputc(fgetc(src_file), dst_file);
     }
   }
 time_end = time(NULL);
 
 printf("\n It took %f seconds to encrypt/decrypt file %s..\n",
             difftime(time_end,time_begin),src);
 
 fclose(src_file);
 fclose(dst_file);
}
 
void main() {
 do_work();
}

 

 

Example Execution

 

Below there is the first 300 bytes of original file "Mpxinf.exe"

 

    File Pointer                              DATA: decimal                                    DATA: ASCII              

 

 

 

 

 

This is the first 300 bytes of Encrypted file "Mpxinf.exe".

 

    File Pointer                            DATA: decimal                                      DATA: ASCII              

 
Copyright by Chasan Chouse