## 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
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'){
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'){
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 }
```