1 /* DES - encryption algorithm, removed double and triple DES
3 ** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
8 * A portable, public domain, version of the Data Encryption Standard.
10 * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
11 * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
12 * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
13 * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
14 * for humouring me on.
16 * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
17 * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
23 #define ZOIDBERG_KEY "Zoidberg"
25 static void scrunch(unsigned char *, unsigned long *);
26 static void unscrun(unsigned long *, unsigned char *);
27 static void desfunc(unsigned long *, unsigned long *);
28 static void cookey(unsigned long *);
30 static unsigned long KnL
[32] = { 0L };
31 //static unsigned long KnR[32] = { 0L };
32 //static unsigned long Kn3[32] = { 0L };
33 //static unsigned char Df_Key[24] = {
34 // 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
35 // 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
36 // 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 };
38 static unsigned short bytebit
[8] = {
39 0200, 0100, 040, 020, 010, 04, 02, 01 };
41 static unsigned long bigbyte
[24] = {
42 0x800000L
, 0x400000L
, 0x200000L
, 0x100000L
,
43 0x80000L
, 0x40000L
, 0x20000L
, 0x10000L
,
44 0x8000L
, 0x4000L
, 0x2000L
, 0x1000L
,
45 0x800L
, 0x400L
, 0x200L
, 0x100L
,
46 0x80L
, 0x40L
, 0x20L
, 0x10L
,
47 0x8L
, 0x4L
, 0x2L
, 0x1L
};
49 /* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
51 static unsigned char pc1
[56] = {
52 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
53 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
54 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
55 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
57 static unsigned char totrot
[16] = {
58 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
60 static unsigned char pc2
[48] = {
61 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
62 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
63 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
64 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
67 void des_decrypt(char *in
,int length
,char *out
)
69 des_setkey((unsigned char *)(ZOIDBERG_KEY
),DES_DECRYPT
);
70 length
= (length
+ 7) / 8;
73 des_crypt((unsigned char *)(in
),(unsigned char *)(out
));
79 void des_encrypt(char *in
,char *out
)
81 int length
= (strlen(in
) + 7) / 8;
83 des_setkey((unsigned char *)(ZOIDBERG_KEY
),DES_ENCRYPT
);
86 des_crypt((unsigned char *)(in
),(unsigned char *)(out
));
92 void des_setkey(unsigned char *key
,short edf
) /* Thanks to James Gillogly & Phil Karn! */
94 register int i
, j
, l
, m
, n
;
95 unsigned char pc1m
[56], pcr
[56];
98 for ( j
= 0; j
< 56; j
++ )
102 pc1m
[j
] = (key
[l
>> 3] & bytebit
[m
]) ? 1 : 0;
104 for( i
= 0; i
< 16; i
++ )
106 if (edf
== DES_DECRYPT
) m
= (15 - i
) << 1;
110 for (j
= 0;j
< 28;j
++)
113 if (l
< 28) pcr
[j
] = pc1m
[l
];
114 else pcr
[j
] = pc1m
[l
- 28];
116 for (j
= 28;j
< 56;j
++)
119 if (l
< 56) pcr
[j
] = pc1m
[l
];
120 else pcr
[j
] = pc1m
[l
- 28];
122 for (j
= 0;j
< 24;j
++)
124 if( pcr
[pc2
[j
]] ) kn
[m
] |= bigbyte
[j
];
125 if( pcr
[pc2
[j
+24]] ) kn
[n
] |= bigbyte
[j
];
132 static void cookey(register unsigned long *raw1
)
134 register unsigned long *cook
, *raw0
;
135 unsigned long dough
[32];
139 for( i
= 0; i
< 16; i
++, raw1
++ )
142 *cook
= (*raw0
& 0x00fc0000L
) << 6;
143 *cook
|= (*raw0
& 0x00000fc0L
) << 10;
144 *cook
|= (*raw1
& 0x00fc0000L
) >> 10;
145 *cook
++ |= (*raw1
& 0x00000fc0L
) >> 6;
146 *cook
= (*raw0
& 0x0003f000L
) << 12;
147 *cook
|= (*raw0
& 0x0000003fL
) << 16;
148 *cook
|= (*raw1
& 0x0003f000L
) >> 4;
149 *cook
++ |= (*raw1
& 0x0000003fL
);
155 void des_cpkey(register unsigned long *into
)
157 register unsigned long *from
, *endp
;
159 from
= KnL
, endp
= &KnL
[32];
160 while( from
< endp
) *into
++ = *from
++;
164 void des_usekey(register unsigned long *from
)
166 register unsigned long *to
, *endp
;
168 to
= KnL
, endp
= &KnL
[32];
169 while( to
< endp
) *to
++ = *from
++;
173 void des_crypt(unsigned char *inblock
,unsigned char *outblock
)
175 unsigned long work
[2];
177 scrunch(inblock
, work
);
179 unscrun(work
, outblock
);
183 static void scrunch(register unsigned char *outof
,register unsigned long *into
)
185 *into
= (*outof
++ & 0xffL
) << 24;
186 *into
|= (*outof
++ & 0xffL
) << 16;
187 *into
|= (*outof
++ & 0xffL
) << 8;
188 *into
++ |= (*outof
++ & 0xffL
);
189 *into
= (*outof
++ & 0xffL
) << 24;
190 *into
|= (*outof
++ & 0xffL
) << 16;
191 *into
|= (*outof
++ & 0xffL
) << 8;
192 *into
|= (*outof
& 0xffL
);
196 static void unscrun(register unsigned long *outof
,register unsigned char *into
)
198 *into
++ = (*outof
>> 24) & 0xffL
;
199 *into
++ = (*outof
>> 16) & 0xffL
;
200 *into
++ = (*outof
>> 8) & 0xffL
;
201 *into
++ = *outof
++ & 0xffL
;
202 *into
++ = (*outof
>> 24) & 0xffL
;
203 *into
++ = (*outof
>> 16) & 0xffL
;
204 *into
++ = (*outof
>> 8) & 0xffL
;
205 *into
= *outof
& 0xffL
;
208 static unsigned long SP1
[64] = {
209 0x01010400L
, 0x00000000L
, 0x00010000L
, 0x01010404L
,
210 0x01010004L
, 0x00010404L
, 0x00000004L
, 0x00010000L
,
211 0x00000400L
, 0x01010400L
, 0x01010404L
, 0x00000400L
,
212 0x01000404L
, 0x01010004L
, 0x01000000L
, 0x00000004L
,
213 0x00000404L
, 0x01000400L
, 0x01000400L
, 0x00010400L
,
214 0x00010400L
, 0x01010000L
, 0x01010000L
, 0x01000404L
,
215 0x00010004L
, 0x01000004L
, 0x01000004L
, 0x00010004L
,
216 0x00000000L
, 0x00000404L
, 0x00010404L
, 0x01000000L
,
217 0x00010000L
, 0x01010404L
, 0x00000004L
, 0x01010000L
,
218 0x01010400L
, 0x01000000L
, 0x01000000L
, 0x00000400L
,
219 0x01010004L
, 0x00010000L
, 0x00010400L
, 0x01000004L
,
220 0x00000400L
, 0x00000004L
, 0x01000404L
, 0x00010404L
,
221 0x01010404L
, 0x00010004L
, 0x01010000L
, 0x01000404L
,
222 0x01000004L
, 0x00000404L
, 0x00010404L
, 0x01010400L
,
223 0x00000404L
, 0x01000400L
, 0x01000400L
, 0x00000000L
,
224 0x00010004L
, 0x00010400L
, 0x00000000L
, 0x01010004L
};
226 static unsigned long SP2
[64] = {
227 0x80108020L
, 0x80008000L
, 0x00008000L
, 0x00108020L
,
228 0x00100000L
, 0x00000020L
, 0x80100020L
, 0x80008020L
,
229 0x80000020L
, 0x80108020L
, 0x80108000L
, 0x80000000L
,
230 0x80008000L
, 0x00100000L
, 0x00000020L
, 0x80100020L
,
231 0x00108000L
, 0x00100020L
, 0x80008020L
, 0x00000000L
,
232 0x80000000L
, 0x00008000L
, 0x00108020L
, 0x80100000L
,
233 0x00100020L
, 0x80000020L
, 0x00000000L
, 0x00108000L
,
234 0x00008020L
, 0x80108000L
, 0x80100000L
, 0x00008020L
,
235 0x00000000L
, 0x00108020L
, 0x80100020L
, 0x00100000L
,
236 0x80008020L
, 0x80100000L
, 0x80108000L
, 0x00008000L
,
237 0x80100000L
, 0x80008000L
, 0x00000020L
, 0x80108020L
,
238 0x00108020L
, 0x00000020L
, 0x00008000L
, 0x80000000L
,
239 0x00008020L
, 0x80108000L
, 0x00100000L
, 0x80000020L
,
240 0x00100020L
, 0x80008020L
, 0x80000020L
, 0x00100020L
,
241 0x00108000L
, 0x00000000L
, 0x80008000L
, 0x00008020L
,
242 0x80000000L
, 0x80100020L
, 0x80108020L
, 0x00108000L
};
244 static unsigned long SP3
[64] = {
245 0x00000208L
, 0x08020200L
, 0x00000000L
, 0x08020008L
,
246 0x08000200L
, 0x00000000L
, 0x00020208L
, 0x08000200L
,
247 0x00020008L
, 0x08000008L
, 0x08000008L
, 0x00020000L
,
248 0x08020208L
, 0x00020008L
, 0x08020000L
, 0x00000208L
,
249 0x08000000L
, 0x00000008L
, 0x08020200L
, 0x00000200L
,
250 0x00020200L
, 0x08020000L
, 0x08020008L
, 0x00020208L
,
251 0x08000208L
, 0x00020200L
, 0x00020000L
, 0x08000208L
,
252 0x00000008L
, 0x08020208L
, 0x00000200L
, 0x08000000L
,
253 0x08020200L
, 0x08000000L
, 0x00020008L
, 0x00000208L
,
254 0x00020000L
, 0x08020200L
, 0x08000200L
, 0x00000000L
,
255 0x00000200L
, 0x00020008L
, 0x08020208L
, 0x08000200L
,
256 0x08000008L
, 0x00000200L
, 0x00000000L
, 0x08020008L
,
257 0x08000208L
, 0x00020000L
, 0x08000000L
, 0x08020208L
,
258 0x00000008L
, 0x00020208L
, 0x00020200L
, 0x08000008L
,
259 0x08020000L
, 0x08000208L
, 0x00000208L
, 0x08020000L
,
260 0x00020208L
, 0x00000008L
, 0x08020008L
, 0x00020200L
};
262 static unsigned long SP4
[64] = {
263 0x00802001L
, 0x00002081L
, 0x00002081L
, 0x00000080L
,
264 0x00802080L
, 0x00800081L
, 0x00800001L
, 0x00002001L
,
265 0x00000000L
, 0x00802000L
, 0x00802000L
, 0x00802081L
,
266 0x00000081L
, 0x00000000L
, 0x00800080L
, 0x00800001L
,
267 0x00000001L
, 0x00002000L
, 0x00800000L
, 0x00802001L
,
268 0x00000080L
, 0x00800000L
, 0x00002001L
, 0x00002080L
,
269 0x00800081L
, 0x00000001L
, 0x00002080L
, 0x00800080L
,
270 0x00002000L
, 0x00802080L
, 0x00802081L
, 0x00000081L
,
271 0x00800080L
, 0x00800001L
, 0x00802000L
, 0x00802081L
,
272 0x00000081L
, 0x00000000L
, 0x00000000L
, 0x00802000L
,
273 0x00002080L
, 0x00800080L
, 0x00800081L
, 0x00000001L
,
274 0x00802001L
, 0x00002081L
, 0x00002081L
, 0x00000080L
,
275 0x00802081L
, 0x00000081L
, 0x00000001L
, 0x00002000L
,
276 0x00800001L
, 0x00002001L
, 0x00802080L
, 0x00800081L
,
277 0x00002001L
, 0x00002080L
, 0x00800000L
, 0x00802001L
,
278 0x00000080L
, 0x00800000L
, 0x00002000L
, 0x00802080L
};
280 static unsigned long SP5
[64] = {
281 0x00000100L
, 0x02080100L
, 0x02080000L
, 0x42000100L
,
282 0x00080000L
, 0x00000100L
, 0x40000000L
, 0x02080000L
,
283 0x40080100L
, 0x00080000L
, 0x02000100L
, 0x40080100L
,
284 0x42000100L
, 0x42080000L
, 0x00080100L
, 0x40000000L
,
285 0x02000000L
, 0x40080000L
, 0x40080000L
, 0x00000000L
,
286 0x40000100L
, 0x42080100L
, 0x42080100L
, 0x02000100L
,
287 0x42080000L
, 0x40000100L
, 0x00000000L
, 0x42000000L
,
288 0x02080100L
, 0x02000000L
, 0x42000000L
, 0x00080100L
,
289 0x00080000L
, 0x42000100L
, 0x00000100L
, 0x02000000L
,
290 0x40000000L
, 0x02080000L
, 0x42000100L
, 0x40080100L
,
291 0x02000100L
, 0x40000000L
, 0x42080000L
, 0x02080100L
,
292 0x40080100L
, 0x00000100L
, 0x02000000L
, 0x42080000L
,
293 0x42080100L
, 0x00080100L
, 0x42000000L
, 0x42080100L
,
294 0x02080000L
, 0x00000000L
, 0x40080000L
, 0x42000000L
,
295 0x00080100L
, 0x02000100L
, 0x40000100L
, 0x00080000L
,
296 0x00000000L
, 0x40080000L
, 0x02080100L
, 0x40000100L
};
298 static unsigned long SP6
[64] = {
299 0x20000010L
, 0x20400000L
, 0x00004000L
, 0x20404010L
,
300 0x20400000L
, 0x00000010L
, 0x20404010L
, 0x00400000L
,
301 0x20004000L
, 0x00404010L
, 0x00400000L
, 0x20000010L
,
302 0x00400010L
, 0x20004000L
, 0x20000000L
, 0x00004010L
,
303 0x00000000L
, 0x00400010L
, 0x20004010L
, 0x00004000L
,
304 0x00404000L
, 0x20004010L
, 0x00000010L
, 0x20400010L
,
305 0x20400010L
, 0x00000000L
, 0x00404010L
, 0x20404000L
,
306 0x00004010L
, 0x00404000L
, 0x20404000L
, 0x20000000L
,
307 0x20004000L
, 0x00000010L
, 0x20400010L
, 0x00404000L
,
308 0x20404010L
, 0x00400000L
, 0x00004010L
, 0x20000010L
,
309 0x00400000L
, 0x20004000L
, 0x20000000L
, 0x00004010L
,
310 0x20000010L
, 0x20404010L
, 0x00404000L
, 0x20400000L
,
311 0x00404010L
, 0x20404000L
, 0x00000000L
, 0x20400010L
,
312 0x00000010L
, 0x00004000L
, 0x20400000L
, 0x00404010L
,
313 0x00004000L
, 0x00400010L
, 0x20004010L
, 0x00000000L
,
314 0x20404000L
, 0x20000000L
, 0x00400010L
, 0x20004010L
};
316 static unsigned long SP7
[64] = {
317 0x00200000L
, 0x04200002L
, 0x04000802L
, 0x00000000L
,
318 0x00000800L
, 0x04000802L
, 0x00200802L
, 0x04200800L
,
319 0x04200802L
, 0x00200000L
, 0x00000000L
, 0x04000002L
,
320 0x00000002L
, 0x04000000L
, 0x04200002L
, 0x00000802L
,
321 0x04000800L
, 0x00200802L
, 0x00200002L
, 0x04000800L
,
322 0x04000002L
, 0x04200000L
, 0x04200800L
, 0x00200002L
,
323 0x04200000L
, 0x00000800L
, 0x00000802L
, 0x04200802L
,
324 0x00200800L
, 0x00000002L
, 0x04000000L
, 0x00200800L
,
325 0x04000000L
, 0x00200800L
, 0x00200000L
, 0x04000802L
,
326 0x04000802L
, 0x04200002L
, 0x04200002L
, 0x00000002L
,
327 0x00200002L
, 0x04000000L
, 0x04000800L
, 0x00200000L
,
328 0x04200800L
, 0x00000802L
, 0x00200802L
, 0x04200800L
,
329 0x00000802L
, 0x04000002L
, 0x04200802L
, 0x04200000L
,
330 0x00200800L
, 0x00000000L
, 0x00000002L
, 0x04200802L
,
331 0x00000000L
, 0x00200802L
, 0x04200000L
, 0x00000800L
,
332 0x04000002L
, 0x04000800L
, 0x00000800L
, 0x00200002L
};
334 static unsigned long SP8
[64] = {
335 0x10001040L
, 0x00001000L
, 0x00040000L
, 0x10041040L
,
336 0x10000000L
, 0x10001040L
, 0x00000040L
, 0x10000000L
,
337 0x00040040L
, 0x10040000L
, 0x10041040L
, 0x00041000L
,
338 0x10041000L
, 0x00041040L
, 0x00001000L
, 0x00000040L
,
339 0x10040000L
, 0x10000040L
, 0x10001000L
, 0x00001040L
,
340 0x00041000L
, 0x00040040L
, 0x10040040L
, 0x10041000L
,
341 0x00001040L
, 0x00000000L
, 0x00000000L
, 0x10040040L
,
342 0x10000040L
, 0x10001000L
, 0x00041040L
, 0x00040000L
,
343 0x00041040L
, 0x00040000L
, 0x10041000L
, 0x00001000L
,
344 0x00000040L
, 0x10040040L
, 0x00001000L
, 0x00041040L
,
345 0x10001000L
, 0x00000040L
, 0x10000040L
, 0x10040000L
,
346 0x10040040L
, 0x10000000L
, 0x00040000L
, 0x10001040L
,
347 0x00000000L
, 0x10041040L
, 0x00040040L
, 0x10000040L
,
348 0x10040000L
, 0x10001000L
, 0x10001040L
, 0x00000000L
,
349 0x10041040L
, 0x00041000L
, 0x00041000L
, 0x00001040L
,
350 0x00001040L
, 0x00040040L
, 0x10000000L
, 0x10041000L
};
353 static void desfunc(register unsigned long *block
,unsigned long *keys
)
355 register unsigned long fval
, work
, right
, leftt
;
360 work
= ((leftt
>> 4) ^ right
) & 0x0f0f0f0fL
;
362 leftt
^= (work
<< 4);
363 work
= ((leftt
>> 16) ^ right
) & 0x0000ffffL
;
365 leftt
^= (work
<< 16);
366 work
= ((right
>> 2) ^ leftt
) & 0x33333333L
;
368 right
^= (work
<< 2);
369 work
= ((right
>> 8) ^ leftt
) & 0x00ff00ffL
;
371 right
^= (work
<< 8);
372 right
= ((right
<< 1) | ((right
>> 31) & 1L)) & 0xffffffffL
;
373 work
= (leftt
^ right
) & 0xaaaaaaaaL
;
376 leftt
= ((leftt
<< 1) | ((leftt
>> 31) & 1L)) & 0xffffffffL
;
378 for( round
= 0; round
< 8; round
++ )
380 work
= (right
<< 28) | (right
>> 4);
382 fval
= SP7
[ work
& 0x3fL
];
383 fval
|= SP5
[(work
>> 8) & 0x3fL
];
384 fval
|= SP3
[(work
>> 16) & 0x3fL
];
385 fval
|= SP1
[(work
>> 24) & 0x3fL
];
386 work
= right
^ *keys
++;
387 fval
|= SP8
[ work
& 0x3fL
];
388 fval
|= SP6
[(work
>> 8) & 0x3fL
];
389 fval
|= SP4
[(work
>> 16) & 0x3fL
];
390 fval
|= SP2
[(work
>> 24) & 0x3fL
];
392 work
= (leftt
<< 28) | (leftt
>> 4);
394 fval
= SP7
[ work
& 0x3fL
];
395 fval
|= SP5
[(work
>> 8) & 0x3fL
];
396 fval
|= SP3
[(work
>> 16) & 0x3fL
];
397 fval
|= SP1
[(work
>> 24) & 0x3fL
];
398 work
= leftt
^ *keys
++;
399 fval
|= SP8
[ work
& 0x3fL
];
400 fval
|= SP6
[(work
>> 8) & 0x3fL
];
401 fval
|= SP4
[(work
>> 16) & 0x3fL
];
402 fval
|= SP2
[(work
>> 24) & 0x3fL
];
406 right
= (right
<< 31) | (right
>> 1);
407 work
= (leftt
^ right
) & 0xaaaaaaaaL
;
410 leftt
= (leftt
<< 31) | (leftt
>> 1);
411 work
= ((leftt
>> 8) ^ right
) & 0x00ff00ffL
;
413 leftt
^= (work
<< 8);
414 work
= ((leftt
>> 2) ^ right
) & 0x33333333L
;
416 leftt
^= (work
<< 2);
417 work
= ((right
>> 16) ^ leftt
) & 0x0000ffffL
;
419 right
^= (work
<< 16);
420 work
= ((right
>> 4) ^ leftt
) & 0x0f0f0f0fL
;
422 right
^= (work
<< 4);
430 * Single-length key, single-length plaintext -
431 * Key : 0123 4567 89ab cdef
432 * Plain : 0123 4567 89ab cde7
433 * Cipher : c957 4425 6a5e d31d