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 }