View Javadoc
1   package org.bouncycastle.crypto.engines;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * SNMP Java Client
6    * ჻჻჻჻჻჻
7    * Copyright 2023 MetricsHub, Westhawk
8    * ჻჻჻჻჻჻
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
23   */
24  
25  import org.bouncycastle.crypto.BlockCipher;
26  import org.bouncycastle.crypto.CipherParameters;
27  import org.bouncycastle.crypto.DataLengthException;
28  import org.bouncycastle.crypto.params.KeyParameter;
29  
30  /**
31   * a class that provides a basic DES engine.
32   */
33  public class DESEngine
34          implements BlockCipher {
35      protected static final int BLOCK_SIZE = 8;
36  
37      private int[] workingKey = null;
38  
39      /**
40       * standard constructor.
41       */
42      public DESEngine() {
43      }
44  
45      /**
46       * initialise a DES cipher.
47       *
48       * @param encrypting whether or not we are for encryption.
49       * @param params     the parameters required to set up the cipher.
50       * @exception IllegalArgumentException if the params argument is
51       *                                     inappropriate.
52       */
53      public void init(
54              boolean encrypting,
55              CipherParameters params) {
56          if (params instanceof KeyParameter) {
57              workingKey = generateWorkingKey(encrypting,
58                      ((KeyParameter) params).getKey());
59  
60              return;
61          }
62  
63          throw new IllegalArgumentException("invalid parameter passed to DES init - " + params.getClass().getName());
64      }
65  
66      public String getAlgorithmName() {
67          return "DES";
68      }
69  
70      public int getBlockSize() {
71          return BLOCK_SIZE;
72      }
73  
74      public int processBlock(
75              byte[] in,
76              int inOff,
77              byte[] out,
78              int outOff) {
79          if (workingKey == null) {
80              throw new IllegalStateException("DES engine not initialised");
81          }
82  
83          if ((inOff + BLOCK_SIZE) > in.length) {
84              throw new DataLengthException("input buffer too short");
85          }
86  
87          if ((outOff + BLOCK_SIZE) > out.length) {
88              throw new DataLengthException("output buffer too short");
89          }
90  
91          desFunc(workingKey, in, inOff, out, outOff);
92  
93          return BLOCK_SIZE;
94      }
95  
96      public void reset() {
97      }
98  
99      /**
100      * what follows is mainly taken from "Applied Cryptography", by
101      * Bruce Schneier, however it also bears great resemblance to Richard
102      * Outerbridge's D3DES...
103      */
104 
105     static short[] Df_Key = {
106             0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
107             0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
108             0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67
109     };
110 
111     static short[] bytebit = {
112             0200, 0100, 040, 020, 010, 04, 02, 01
113     };
114 
115     static int[] bigbyte = {
116             0x800000, 0x400000, 0x200000, 0x100000,
117             0x80000, 0x40000, 0x20000, 0x10000,
118             0x8000, 0x4000, 0x2000, 0x1000,
119             0x800, 0x400, 0x200, 0x100,
120             0x80, 0x40, 0x20, 0x10,
121             0x8, 0x4, 0x2, 0x1
122     };
123 
124     /*
125      * Use the key schedule specified in the Standard (ANSI X3.92-1981).
126      */
127 
128     static byte[] pc1 = {
129             56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
130             9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
131             62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
132             13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
133     };
134 
135     static byte[] totrot = {
136             1, 2, 4, 6, 8, 10, 12, 14,
137             15, 17, 19, 21, 23, 25, 27, 28
138     };
139 
140     static byte[] pc2 = {
141             13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
142             22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
143             40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
144             43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
145     };
146 
147     static int[] SP1 = {
148             0x01010400, 0x00000000, 0x00010000, 0x01010404,
149             0x01010004, 0x00010404, 0x00000004, 0x00010000,
150             0x00000400, 0x01010400, 0x01010404, 0x00000400,
151             0x01000404, 0x01010004, 0x01000000, 0x00000004,
152             0x00000404, 0x01000400, 0x01000400, 0x00010400,
153             0x00010400, 0x01010000, 0x01010000, 0x01000404,
154             0x00010004, 0x01000004, 0x01000004, 0x00010004,
155             0x00000000, 0x00000404, 0x00010404, 0x01000000,
156             0x00010000, 0x01010404, 0x00000004, 0x01010000,
157             0x01010400, 0x01000000, 0x01000000, 0x00000400,
158             0x01010004, 0x00010000, 0x00010400, 0x01000004,
159             0x00000400, 0x00000004, 0x01000404, 0x00010404,
160             0x01010404, 0x00010004, 0x01010000, 0x01000404,
161             0x01000004, 0x00000404, 0x00010404, 0x01010400,
162             0x00000404, 0x01000400, 0x01000400, 0x00000000,
163             0x00010004, 0x00010400, 0x00000000, 0x01010004
164     };
165 
166     static int[] SP2 = {
167             0x80108020, 0x80008000, 0x00008000, 0x00108020,
168             0x00100000, 0x00000020, 0x80100020, 0x80008020,
169             0x80000020, 0x80108020, 0x80108000, 0x80000000,
170             0x80008000, 0x00100000, 0x00000020, 0x80100020,
171             0x00108000, 0x00100020, 0x80008020, 0x00000000,
172             0x80000000, 0x00008000, 0x00108020, 0x80100000,
173             0x00100020, 0x80000020, 0x00000000, 0x00108000,
174             0x00008020, 0x80108000, 0x80100000, 0x00008020,
175             0x00000000, 0x00108020, 0x80100020, 0x00100000,
176             0x80008020, 0x80100000, 0x80108000, 0x00008000,
177             0x80100000, 0x80008000, 0x00000020, 0x80108020,
178             0x00108020, 0x00000020, 0x00008000, 0x80000000,
179             0x00008020, 0x80108000, 0x00100000, 0x80000020,
180             0x00100020, 0x80008020, 0x80000020, 0x00100020,
181             0x00108000, 0x00000000, 0x80008000, 0x00008020,
182             0x80000000, 0x80100020, 0x80108020, 0x00108000
183     };
184 
185     static int[] SP3 = {
186             0x00000208, 0x08020200, 0x00000000, 0x08020008,
187             0x08000200, 0x00000000, 0x00020208, 0x08000200,
188             0x00020008, 0x08000008, 0x08000008, 0x00020000,
189             0x08020208, 0x00020008, 0x08020000, 0x00000208,
190             0x08000000, 0x00000008, 0x08020200, 0x00000200,
191             0x00020200, 0x08020000, 0x08020008, 0x00020208,
192             0x08000208, 0x00020200, 0x00020000, 0x08000208,
193             0x00000008, 0x08020208, 0x00000200, 0x08000000,
194             0x08020200, 0x08000000, 0x00020008, 0x00000208,
195             0x00020000, 0x08020200, 0x08000200, 0x00000000,
196             0x00000200, 0x00020008, 0x08020208, 0x08000200,
197             0x08000008, 0x00000200, 0x00000000, 0x08020008,
198             0x08000208, 0x00020000, 0x08000000, 0x08020208,
199             0x00000008, 0x00020208, 0x00020200, 0x08000008,
200             0x08020000, 0x08000208, 0x00000208, 0x08020000,
201             0x00020208, 0x00000008, 0x08020008, 0x00020200
202     };
203 
204     static int[] SP4 = {
205             0x00802001, 0x00002081, 0x00002081, 0x00000080,
206             0x00802080, 0x00800081, 0x00800001, 0x00002001,
207             0x00000000, 0x00802000, 0x00802000, 0x00802081,
208             0x00000081, 0x00000000, 0x00800080, 0x00800001,
209             0x00000001, 0x00002000, 0x00800000, 0x00802001,
210             0x00000080, 0x00800000, 0x00002001, 0x00002080,
211             0x00800081, 0x00000001, 0x00002080, 0x00800080,
212             0x00002000, 0x00802080, 0x00802081, 0x00000081,
213             0x00800080, 0x00800001, 0x00802000, 0x00802081,
214             0x00000081, 0x00000000, 0x00000000, 0x00802000,
215             0x00002080, 0x00800080, 0x00800081, 0x00000001,
216             0x00802001, 0x00002081, 0x00002081, 0x00000080,
217             0x00802081, 0x00000081, 0x00000001, 0x00002000,
218             0x00800001, 0x00002001, 0x00802080, 0x00800081,
219             0x00002001, 0x00002080, 0x00800000, 0x00802001,
220             0x00000080, 0x00800000, 0x00002000, 0x00802080
221     };
222 
223     static int[] SP5 = {
224             0x00000100, 0x02080100, 0x02080000, 0x42000100,
225             0x00080000, 0x00000100, 0x40000000, 0x02080000,
226             0x40080100, 0x00080000, 0x02000100, 0x40080100,
227             0x42000100, 0x42080000, 0x00080100, 0x40000000,
228             0x02000000, 0x40080000, 0x40080000, 0x00000000,
229             0x40000100, 0x42080100, 0x42080100, 0x02000100,
230             0x42080000, 0x40000100, 0x00000000, 0x42000000,
231             0x02080100, 0x02000000, 0x42000000, 0x00080100,
232             0x00080000, 0x42000100, 0x00000100, 0x02000000,
233             0x40000000, 0x02080000, 0x42000100, 0x40080100,
234             0x02000100, 0x40000000, 0x42080000, 0x02080100,
235             0x40080100, 0x00000100, 0x02000000, 0x42080000,
236             0x42080100, 0x00080100, 0x42000000, 0x42080100,
237             0x02080000, 0x00000000, 0x40080000, 0x42000000,
238             0x00080100, 0x02000100, 0x40000100, 0x00080000,
239             0x00000000, 0x40080000, 0x02080100, 0x40000100
240     };
241 
242     static int[] SP6 = {
243             0x20000010, 0x20400000, 0x00004000, 0x20404010,
244             0x20400000, 0x00000010, 0x20404010, 0x00400000,
245             0x20004000, 0x00404010, 0x00400000, 0x20000010,
246             0x00400010, 0x20004000, 0x20000000, 0x00004010,
247             0x00000000, 0x00400010, 0x20004010, 0x00004000,
248             0x00404000, 0x20004010, 0x00000010, 0x20400010,
249             0x20400010, 0x00000000, 0x00404010, 0x20404000,
250             0x00004010, 0x00404000, 0x20404000, 0x20000000,
251             0x20004000, 0x00000010, 0x20400010, 0x00404000,
252             0x20404010, 0x00400000, 0x00004010, 0x20000010,
253             0x00400000, 0x20004000, 0x20000000, 0x00004010,
254             0x20000010, 0x20404010, 0x00404000, 0x20400000,
255             0x00404010, 0x20404000, 0x00000000, 0x20400010,
256             0x00000010, 0x00004000, 0x20400000, 0x00404010,
257             0x00004000, 0x00400010, 0x20004010, 0x00000000,
258             0x20404000, 0x20000000, 0x00400010, 0x20004010
259     };
260 
261     static int[] SP7 = {
262             0x00200000, 0x04200002, 0x04000802, 0x00000000,
263             0x00000800, 0x04000802, 0x00200802, 0x04200800,
264             0x04200802, 0x00200000, 0x00000000, 0x04000002,
265             0x00000002, 0x04000000, 0x04200002, 0x00000802,
266             0x04000800, 0x00200802, 0x00200002, 0x04000800,
267             0x04000002, 0x04200000, 0x04200800, 0x00200002,
268             0x04200000, 0x00000800, 0x00000802, 0x04200802,
269             0x00200800, 0x00000002, 0x04000000, 0x00200800,
270             0x04000000, 0x00200800, 0x00200000, 0x04000802,
271             0x04000802, 0x04200002, 0x04200002, 0x00000002,
272             0x00200002, 0x04000000, 0x04000800, 0x00200000,
273             0x04200800, 0x00000802, 0x00200802, 0x04200800,
274             0x00000802, 0x04000002, 0x04200802, 0x04200000,
275             0x00200800, 0x00000000, 0x00000002, 0x04200802,
276             0x00000000, 0x00200802, 0x04200000, 0x00000800,
277             0x04000002, 0x04000800, 0x00000800, 0x00200002
278     };
279 
280     static int[] SP8 = {
281             0x10001040, 0x00001000, 0x00040000, 0x10041040,
282             0x10000000, 0x10001040, 0x00000040, 0x10000000,
283             0x00040040, 0x10040000, 0x10041040, 0x00041000,
284             0x10041000, 0x00041040, 0x00001000, 0x00000040,
285             0x10040000, 0x10000040, 0x10001000, 0x00001040,
286             0x00041000, 0x00040040, 0x10040040, 0x10041000,
287             0x00001040, 0x00000000, 0x00000000, 0x10040040,
288             0x10000040, 0x10001000, 0x00041040, 0x00040000,
289             0x00041040, 0x00040000, 0x10041000, 0x00001000,
290             0x00000040, 0x10040040, 0x00001000, 0x00041040,
291             0x10001000, 0x00000040, 0x10000040, 0x10040000,
292             0x10040040, 0x10000000, 0x00040000, 0x10001040,
293             0x00000000, 0x10041040, 0x00040040, 0x10000040,
294             0x10040000, 0x10001000, 0x10001040, 0x00000000,
295             0x10041040, 0x00041000, 0x00041000, 0x00001040,
296             0x00001040, 0x00040040, 0x10000000, 0x10041000
297     };
298 
299     /**
300      * generate an integer based working key based on our secret key
301      * and what we processing we are planning to do.
302      *
303      * Acknowledgements for this routine go to James Gillogly & Phil Karn.
304      * (whoever, and wherever they are!).
305      */
306     protected int[] generateWorkingKey(
307             boolean encrypting,
308             byte[] key) {
309         int[] newKey = new int[32];
310         boolean[] pc1m = new boolean[56],
311                 pcr = new boolean[56];
312 
313         for (int j = 0; j < 56; j++) {
314             int l = pc1[j];
315 
316             pc1m[j] = ((key[l >>> 3] & bytebit[l & 07]) != 0);
317         }
318 
319         for (int i = 0; i < 16; i++) {
320             int l, m, n;
321 
322             if (encrypting) {
323                 m = i << 1;
324             } else {
325                 m = (15 - i) << 1;
326             }
327 
328             n = m + 1;
329             newKey[m] = newKey[n] = 0;
330 
331             for (int j = 0; j < 28; j++) {
332                 l = j + totrot[i];
333                 if (l < 28) {
334                     pcr[j] = pc1m[l];
335                 } else {
336                     pcr[j] = pc1m[l - 28];
337                 }
338             }
339 
340             for (int j = 28; j < 56; j++) {
341                 l = j + totrot[i];
342                 if (l < 56) {
343                     pcr[j] = pc1m[l];
344                 } else {
345                     pcr[j] = pc1m[l - 28];
346                 }
347             }
348 
349             for (int j = 0; j < 24; j++) {
350                 if (pcr[pc2[j]]) {
351                     newKey[m] |= bigbyte[j];
352                 }
353 
354                 if (pcr[pc2[j + 24]]) {
355                     newKey[n] |= bigbyte[j];
356                 }
357             }
358         }
359 
360         //
361         // store the processed key
362         //
363         for (int i = 0; i != 32; i += 2) {
364             int i1, i2;
365 
366             i1 = newKey[i];
367             i2 = newKey[i + 1];
368 
369             newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10)
370                     | ((i2 & 0x00fc0000) >>> 10) | ((i2 & 0x00000fc0) >>> 6);
371 
372             newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16)
373                     | ((i2 & 0x0003f000) >>> 4) | (i2 & 0x0000003f);
374         }
375 
376         return newKey;
377     }
378 
379     /**
380      * the DES engine.
381      */
382     protected void desFunc(
383             int[] wKey,
384             byte[] in,
385             int inOff,
386             byte[] out,
387             int outOff) {
388         int work, right, left;
389 
390         left = (in[inOff + 0] & 0xff) << 24;
391         left |= (in[inOff + 1] & 0xff) << 16;
392         left |= (in[inOff + 2] & 0xff) << 8;
393         left |= (in[inOff + 3] & 0xff);
394 
395         right = (in[inOff + 4] & 0xff) << 24;
396         right |= (in[inOff + 5] & 0xff) << 16;
397         right |= (in[inOff + 6] & 0xff) << 8;
398         right |= (in[inOff + 7] & 0xff);
399 
400         work = ((left >>> 4) ^ right) & 0x0f0f0f0f;
401         right ^= work;
402         left ^= (work << 4);
403         work = ((left >>> 16) ^ right) & 0x0000ffff;
404         right ^= work;
405         left ^= (work << 16);
406         work = ((right >>> 2) ^ left) & 0x33333333;
407         left ^= work;
408         right ^= (work << 2);
409         work = ((right >>> 8) ^ left) & 0x00ff00ff;
410         left ^= work;
411         right ^= (work << 8);
412         right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff;
413         work = (left ^ right) & 0xaaaaaaaa;
414         left ^= work;
415         right ^= work;
416         left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff;
417 
418         for (int round = 0; round < 8; round++) {
419             int fval;
420 
421             work = (right << 28) | (right >>> 4);
422             work ^= wKey[round * 4 + 0];
423             fval = SP7[work & 0x3f];
424             fval |= SP5[(work >>> 8) & 0x3f];
425             fval |= SP3[(work >>> 16) & 0x3f];
426             fval |= SP1[(work >>> 24) & 0x3f];
427             work = right ^ wKey[round * 4 + 1];
428             fval |= SP8[work & 0x3f];
429             fval |= SP6[(work >>> 8) & 0x3f];
430             fval |= SP4[(work >>> 16) & 0x3f];
431             fval |= SP2[(work >>> 24) & 0x3f];
432             left ^= fval;
433             work = (left << 28) | (left >>> 4);
434             work ^= wKey[round * 4 + 2];
435             fval = SP7[work & 0x3f];
436             fval |= SP5[(work >>> 8) & 0x3f];
437             fval |= SP3[(work >>> 16) & 0x3f];
438             fval |= SP1[(work >>> 24) & 0x3f];
439             work = left ^ wKey[round * 4 + 3];
440             fval |= SP8[work & 0x3f];
441             fval |= SP6[(work >>> 8) & 0x3f];
442             fval |= SP4[(work >>> 16) & 0x3f];
443             fval |= SP2[(work >>> 24) & 0x3f];
444             right ^= fval;
445         }
446 
447         right = (right << 31) | (right >>> 1);
448         work = (left ^ right) & 0xaaaaaaaa;
449         left ^= work;
450         right ^= work;
451         left = (left << 31) | (left >>> 1);
452         work = ((left >>> 8) ^ right) & 0x00ff00ff;
453         right ^= work;
454         left ^= (work << 8);
455         work = ((left >>> 2) ^ right) & 0x33333333;
456         right ^= work;
457         left ^= (work << 2);
458         work = ((right >>> 16) ^ left) & 0x0000ffff;
459         left ^= work;
460         right ^= (work << 16);
461         work = ((right >>> 4) ^ left) & 0x0f0f0f0f;
462         left ^= work;
463         right ^= (work << 4);
464 
465         out[outOff + 0] = (byte) ((right >>> 24) & 0xff);
466         out[outOff + 1] = (byte) ((right >>> 16) & 0xff);
467         out[outOff + 2] = (byte) ((right >>> 8) & 0xff);
468         out[outOff + 3] = (byte) (right & 0xff);
469         out[outOff + 4] = (byte) ((left >>> 24) & 0xff);
470         out[outOff + 5] = (byte) ((left >>> 16) & 0xff);
471         out[outOff + 6] = (byte) ((left >>> 8) & 0xff);
472         out[outOff + 7] = (byte) (left & 0xff);
473     }
474 }