Implementation of DES in C

Below is an implementation I did of DES back in the early 90’s while I was still in college. It’s one of the first complex C programs I wrote. It served its purpose back in the day, but now more advanced algorithms and APIs have eliminated the need for such things. It’s been heavily optimized, more so than is practical in today’s world, so you probably couldn’t get it to compile even if you wanted to use it. I post it here to reminisce on my programming ability at the time, and to give an example of the complexity/simplicity of implementing an encryption algorithm.

    1 #include <stdio.h>
    2 
    3 static int keyout[17][48];
    4 
    5 void des_init(),lshift(),cypher(),des_encrypt(),des_descrypt();
    6 
    7 void des_init(unsigned char *key){
    8  unsigned char c[28],d[28];
    9  static int pc1[56] = {57,49,41,33,25,17,9,
   10               01,58,50,42,34,26,18,
   11               10,02,59,51,43,35,27,
   12               19,11,03,60,52,44,36,
   13               63,55,47,39,31,23,15,
   14               07,62,54,46,38,30,22,
   15               14,06,61,53,45,37,29,
   16               21,13,05,28,20,12,04};
   17  static int pc2[48] = {14,17,11,24,1,5,
   18               3,28,15,6,21,10,
   19               23,19,12,4,26,8,
   20               16,7,27,20,13,2,
   21               41,52,31,37,47,55,
   22               30,40,51,45,33,48,
   23               44,49,39,56,34,53,
   24               46,42,50,36,29,32};
   25  static int nls[17] = {
   26   0,1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};
   27 
   28  static int cd[56],keyb[64];
   29  static int cnt,n=0;
   30  register int i,j;
   31 
   32  for(i=0;i<8;i++) /*Read in key*/
   33   for(j=0;j<8;j++) keyb[n++]=(key[i]>>j&0x01);
   34 
   35  for(i=0;i<56;i++) /*Permuted choice 1*/
   36   cd[i]=keyb[pc1[1]-1];
   37  for(i=0;i<28;i++){
   38   c[i]=cd[i];
   39   d[i]=cd[i+28];
   40  }
   41  for(cnt=1;cnt<=16;cnt++){
   42   for(i=0;i<nls[cnt];i++){
   43    lshift(c); lshift(d);
   44   }
   45   for(i=0;i<28;i++){
   46    cd[i]=c[i];
   47    cd[i+28]=d[i];
   48   }
   49   for(i=0;i<48;i++) /*Permuted Choice 2*/
   50    keyout[cnt][i]=cd[pc2[i]-1];
   51  }
   52 }
   53 
   54 static void lshift(unsigned char shft[]){
   55  register int temp,i;
   56 
   57  temp=shft[0];
   58  for(i=0;i<27;i++) shft[i]=shft[i+1];
   59  shft[27]=temp;
   60 }
   61 
   62 static void cypher(int *r, int cnt, int *fout){
   63  static int expand[48],b[8][6],sout[8],pin[48];
   64  register int i,j;
   65  static int n,row,col,scnt;
   66  static int p[32]={
   67     16,7,20,21,29,12,28,17,1,15,23,26,
   68      5,18,31,10,2,8,24,14,32,27,3,9,
   69     19,13,30,6,22,11,4,25};
   70 
   71  static int   e[48] = {32,1,2,3,4,5,
   72               4,5,6,7,8,9,
   73               8,9,10,11,12,13,
   74               12,13,14,15,16,17,
   75               16,17,18,19,20,21,
   76               20,21,22,23,24,25,
   77               24,25,26,27,28,29,
   78               28,29,30,31,32,1};
   79 
   80  static char s[8][64] = {
   81     14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7, /*s1*/
   82      0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8,
   83      4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0,
   84     15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13,
   85     15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10, /*s2*/
   86      3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5,
   87      0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15,
   88     13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9,
   89     10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8, /*s3*/
   90     13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1,
   91     13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7,
   92      1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12,
   93      7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15,/*s4*/
   94     13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9,
   95     10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4,
   96      3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14,
   97      2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9,/*s5*/
   98     14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6,
   99      4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14,
  100     11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3,
  101     12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11, /*s6*/
  102     10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8,
  103      9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6,
  104      4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13,
  105      4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1,/*s7*/
  106     13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6,
  107      1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2,
  108      6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12,
  109     13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7, /*s8*/
  110      1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2,
  111      7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8,
  112      2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11
  113  };
  114 
  115  for(i=0;i<48;i++) expand[i]=r[e[i]-1]; /*Expansion Function*/
  116  for(i=n=0;i<8;i++) {
  117   for(j=0;j<6;j++,n++) b[i][j]=expand[n]^keyout[cnt][n];
  118  }
  119 
  120  /*Selection functions*/
  121 
  122   for(scnt=n=0;scnt<8;scnt++){
  123    row=(b[scnt][0]<<1)+b[scnt][5];
  124    col=(b[scnt][1]<<3)+(b[scnt][2]<<2)+(b[scnt][3]<<1)+b[scnt][4];
  125    sout[scnt]=s[scnt][(row<<4)+col];
  126    for(i=3;i>=0;i--){
  127     pin[n]=sout[scnt]>>i;
  128     sout[scnt]=sout[scnt]-(pin[n++]<<i);
  129    }
  130   }
  131   for(i=0;i<32;i++) fout[i]=pin[p[i]-1]; /*Permutation Function*/
  132 }
  133 
  134 static int p[64] = {58,50,42,34,26,18,10,2,
  135               60,52,44,36,28,20,12,4,
  136               62,54,46,38,30,22,14,6,
  137               64,56,48,40,32,24,16,8,
  138               5 = {58,50,42,34,26,18,10,2,
  139               60,52,44,36,28,20,12,4,
  140               62,54,46,38,30,22,14,6,
  141               64,56,48,40,32,24,16,8,
  142               57,49,41,33,25,17,9,1,
  143               59,51,43,35,27,19,11,3,
  144               61,53,45,37,29,21,13,5,
  145               63,55,47,39,31,23,15,7};
  146 
  147 static int invp[64]={
  148  40, 8,48,16,56,24,64,32,39, 7,47,15,55,23,63,31,
  149  38, 6,46,14,54,22,62,30,37, 5,45,13,53,21,61,29,
  150  36, 4,44,12,52,20,60,28,35, 3,43,11,51,19,59,27,
  151  34, 2,42,10,50,18,58,26,33, 1,41, 9,49,17,57,25};
  152 
  153 void des_encrypt(unsigned char *input){
  154  static unsigned char out[64];
  155  static int inputb[64],lr[64],l[32],r[32];
  156  static int fn[32];
  157  static int cnt,n;
  158  register int i,j;
  159 
  160  for(i=n=0;i<8;i++)
  161   for(j=0;j<8;j++) inputb[n++]=(input[i]>>j&0x01);
  162 
  163  for(i=0;i<64;i++){ /*Initial Permutation*/
  164   lr[i]=inputb[p[i]-1];
  165   if(i<32) l[i]=lr[i];
  166   else r[i-32]=lr[i];
  167  }
  168  for(cnt=1;cnt<=16;cnt++){ /*Main encryption loop*/
  169   cypher(r,cnt,fn);
  170   for(i=0;i<32;i++){
  171    j=r[i];
  172    r[i]=l[i]^fn[i];
  173    l[i]=j;
  174   }
  175  }
  176  for(i=0;i<32;i++){
  177   lr[i]=r[i];
  178   lr[i+32]=l[i];
  179  }
  180  for(i=0;i<64;i++) out[i]=lr[invp[i]-1]; /*Inverse IP*/
  181 
  182  for(i=1;i<=8;i++)
  183   for(j=1;j<=8;j++) input[i-1]=(input[i-1]<<1)|out[i*8-j];
  184 }
  185 
  186 void des_decrypt(unsigned char *input){
  187  static unsigned char out[64];
  188  static int inputb[64],lr[64],l[32],r[32];
  189  static int fn[32];
  190  static int cnt,rtemp,n;
  191  register int i,j;
  192 
  193  for(i=n=0;i<8;i++)
  194   for(j=0;j<8;j++) inputb[n++]=(input[i]>>j&0x01);
  195 
  196  for(i=0;i<64;i++){ /*Initial Permutation*/
  197   lr[i]=inputb[p[i]-1];
  198   if(i<32) l[i]=lr[i];
  199   else r[i-32]=lr[i];
  200  }
  201  for(cnt=16;cnt>0;cnt--){ /*Main decryption loop*/
  202   cypher(r,cnt,fn);
  203   for(i=0;i<32;i++){
  204    rtemp=r[i];
  205    if(l[i]==1 && fn[i]==1) r[i]=0;
  206    else r[i]=(l[i] || fn[i]);
  207    l[i]=rtemp;
  208   }
  209  }
  210  for(i=0;i<32;i++){
  211   lr[i]=r[i];
  212   lr[i+32]=l[i];
  213  }
  214  for(i=0;i<64;i++) out[i]=lr[invp[i]-1]; /*Inverse IP*/
  215 
  216  for(i=1;i<=8;i++)
  217   for(j=1;j<=8;j++) input[i-1]=(input[i-1]<<1) | out[i*8-j];
  218 }
  219 
  220 int main(int argc, char *argv[]){
  221  unsigned char *key;
  222  unsigned char data[8];
  223  int n;
  224  FILE *in;
  225  FILE *out;
  226 
  227  if (argc!=4) {
  228   printf("\r\nUsage:  des [e][d] <source file> <destination file>\r\n");
  229   return 1;
  230  }
  231 
  232  key=(unsigned char*)getpass("Enter Key:");
  233  des_init(key);
  234 
  235  if((in=fopen(argv[2],"rb"))==NULL){
  236   fprintf(stderr,"\r\nCould not open input file: %s",argv[2]);
  237   return 2;
  238  }
  239 
  240  if((out=fopen(argv[3],"wb"))==NULL){
  241   fprintf(stderr,"\r\nCould not open output file: %s",argv[3]);
  242   return 3;
  243  }
  244 
  245  if(argv[1][0]=='e'){
  246   while ((n=fread(data,1,8,in)) >0){
  247    des_encrypt(data);
  248    printf("data enctyted");
  249    if(fwrite(data,1,8,out) < 8){
  250     fprintf(stderr,"\r\nError writing to output file\r\n");
  251     return(3);
  252    }
  253   }
  254  }
  255 
  256  if(argv[1][0]=='d'){
  257   while ((n=fread(data,1,8,in)) >0){
  258    des_decrypt(data);
  259    if(fwrite(data,1,8,out) < 8){
  260     fprintf(stderr,"\r\nError writing to output file\r\n");
  261     return(3);
  262    }
  263   }
  264  }
  265 
  266  fclose(in); fclose(out);
  267  return 0;
  268 }ntf(stderr,"\r\nError writing to output file\r\n");
  269     return(3);
  270    }
  271   }
  272  }
  273 
  274  fclose(in); fclose(out);
  275  return 0;
  276 }