1   /* $RCSfile: DESCore1KeyBlockCipher.java,v $
2    * $Revision: 1.17 $
3    * $Date: 2002/11/23 11:09:57 $
4    * $Author: uwe_guenther $
5    * $State: Exp $
6    *
7    * Created on August 3, 2001 3:49 PM
8    *
9    * Copyright (C) 2001 Uwe Guenther <uwe@cscc.de>
10   *
11   * This file is part of the jhbci JCE-ServiceProvider. The jhbci JCE-
12   * ServiceProvider is a library, written in JavaTM, that should be 
13   * used in HBCI banking applications (clients and may be servers),
14   * to do cryptographic operations.
15   *
16   * The jhbci library is free software; you can redistribute it and/or
17   * modify it under the terms of the GNU Lesser General Public
18   * License as published by the Free Software Foundation; either
19   * version 2.1 of the License, or (at your option) any later version.
20   *
21   * The jhbci library is distributed in the hope that it will be useful,
22   * but WITHOUT ANY WARRANTY; without even the implied warranty of
23   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24   * Lesser General Public License for more details.
25   *
26   * You should have received a copy of the GNU Lesser General Public
27   * License along with this library; if not, write to the Free Software
28   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29   *
30   */
31  
32  package de.cscc.crypto.provider;
33  
34  import javax.crypto.IllegalBlockSizeException;
35  import javax.crypto.ShortBufferException;
36  
37  import de.cscc.crypto.util.IntegerUtil;
38  
39  /** DESCore1KeyBlockCipher Class.
40   *
41   * @author  <a href=mailto:uwe@cscc.de>Uwe G&uuml;nther</a>
42   * @version $Revision: 1.17 $
43   */
44  class DESCore1KeyBlockCipher extends DESCoreBlockCipher {
45      
46      /** 16 scheduled 48 bit keys in a order to encrypt. */    
47      private int[] encryptKey =null;
48      
49      /** 16 scheduled 48 bit keys in a order to decrypt. */    
50      private int[] decryptKey =null;
51      
52      /** Don't create a DESCore1KeyBlockCipher object with default constructor. */
53      private DESCore1KeyBlockCipher() {}
54      
55      /** 
56       * Creates a DESCore1KeyBlockCipher algorithm instance with 
57       * this byte[8] key, starting at offset. 
58       *
59       * @param key the key that is used for this algorithm object.
60       * @throws IllegalBlockSizeException will be thrown, if the
61       *          deliverd byte array is less than 8 byte.
62       */    
63      public DESCore1KeyBlockCipher(byte[] key) throws IllegalBlockSizeException {
64          
65          this.encryptKey = generateScheduledKeys(true, key, 0);
66          this.decryptKey = generateScheduledKeys(false, key, 0);
67      }    
68      
69      
70      /** 
71       * Creates a DESCore1KeyBlockCipher algorithm instance with 
72       * this byte[offset+8] key, starting at offset. 
73       *
74       * @param key the key that is used for this algorithm object.
75       * @param offset to start at.
76       * @throws IllegalBlockSizeException will be thrown, if the
77       *          deliverd byte array is less than offset+8 byte.
78       */    
79      public DESCore1KeyBlockCipher(byte[] key, int offset) 
80              throws IllegalBlockSizeException {
81          
82          this.encryptKey = generateScheduledKeys(true, key, offset);
83          this.decryptKey = generateScheduledKeys(false, key, offset);        
84      }
85      
86      /** 
87       * Returns a string representation of the object. 
88       *
89       * @return  a string representation of the object.
90       */
91      public String toString() {
92          return "encryptKey: [" + IntegerUtil.toHex(this.encryptKey) 
93                  + "] decryptKey: [" + IntegerUtil.toHex(this.decryptKey)  + "]";
94      }
95      
96      /**
97       * Return the algorithm specific key size in bits. If you subclass 
98       * these abstract class, you have to implement these method.
99       *
100      * @return the algorithm specific key size in bits.
101      */
102     public int getKeyBitSize() {
103         return 56;
104     }       
105     
106     /** 
107      * Return the algorithm specific key size in bytes. If you subclass 
108      * these abstract class, you have to implement these method.
109      *
110      * @return the algorithm specific key size in bytes.
111      */
112     public int getKeyByteSize() {
113         return 8;
114     }        
115      
116     /** 
117      * The DES encryption operation.
118      *
119      * If (input.length-inputOffset > 8) we use only the first 8 bytes 
120      * for the block.
121      *
122      * @param input the 64 bit data block that will be encrypted.
123      * @param inputOffset the offset in input where the input starts.
124      * @param output the buffer for the result.
125      * @param outputOffset the offset in output where the result is stored.
126      * @throws IllegalBlockSizeException will be thrown, if the
127      *          deliverd byte array has a length lesser than 8.
128      * @throws ShortBufferException will be thrown, if the
129      *          ouput buffer byte array has a length lesser than 8.
130      * @return the number of bytes stored in output.
131      */    
132     public int encrypt(byte[] input,  int inputOffset, 
133             byte[] output, int outputOffset) 
134             throws IllegalBlockSizeException, ShortBufferException {     
135 
136         if (input.length-inputOffset < 8) {
137             throw new IllegalBlockSizeException("Usable byte range is " 
138                     + (input.length-inputOffset) + " bytes large, but it "
139                     + "should be 8 bytes or larger.");
140         }
141         
142         if (output.length-outputOffset < 8) {
143             throw new ShortBufferException("Usable byte range is " 
144                     + (output.length-outputOffset) + " bytes large, but it "
145                     + "should be 8 bytes or larger.");            
146         }   
147         
148         desFunc(this.encryptKey, input, inputOffset, output, outputOffset);        
149         
150         return 8;
151     }    
152     
153      
154     /** 
155      * The DES decryption operation.
156      *
157      * If (input.length-inputOffset > 8) we use only the first 8 bytes 
158      * for the block.
159      *
160      * @param input the 64 bit data block that will be decrypted.
161      * @param inputOffset the offset in input where the input starts.
162      * @param output the buffer for the result.
163      * @param outputOffset the offset in output where the result is stored.
164      * @throws IllegalBlockSizeException will be thrown, if the
165      *          deliverd byte array has a length lesser than 8.
166      * @throws ShortBufferException will be thrown, if the
167      *          ouput buffer byte array has a length lesser than 8.
168      * @return the number of bytes stored in output.
169      */    
170     public int decrypt(byte[] input,  int inputOffset, 
171             byte[] output, int outputOffset) 
172             throws IllegalBlockSizeException, ShortBufferException {    
173         
174         if (input.length-inputOffset < 8){
175             throw new IllegalBlockSizeException(
176                 "Usable byte range is " + (input.length-inputOffset) + 
177                 " bytes large, but it should be 8 bytes or larger.");
178         }
179         
180         if (output.length-outputOffset < 8) {
181             throw new ShortBufferException(
182                       "Usable byte range is " + (output.length-outputOffset) + 
183                       " bytes large, but it should be 8 bytes or larger.");            
184         }        
185         
186         desFunc(this.decryptKey, input, inputOffset, output, outputOffset);  
187 
188         return 8;
189     }
190     
191     /* What follows is mainly taken from "Applied Cryptography", by
192      * Bruce Schneier, however it also bears great resemblance to Richard
193      * Outerbridge's D3DES...
194      */
195     
196     /** 
197      * Lookup table to get a specific bit mask.
198      * For BIT_MASK_FOR_BYTE[0] we get 0b10000000, 
199      * for BIT_MASK_FOR_BYTE[1] we get 0b01000000, and so on.
200      * So we can acces bit masks in a loop.
201      */
202     private static int[] BIT_MASK_FOR_BYTE = {
203         0x80, 0x40, 0x20, 0x10,
204         0x8,  0x4,  0x2,  0x1
205     };
206 
207     /** 
208      * Lookup table to get a specific bit mask.
209      * For BIT_MASK_FOR_24BIT[0] we get 0b1000000000000000000000000,
210      * for BIT_MASK_FOR_24BIT[1] we get 0b0100000000000000000000000, and so on.
211      * So we can acces bit masks in a loop.
212      */
213     private static int[] BIT_MASK_FOR_24BIT = {
214         0x800000, 0x400000, 0x200000, 0x100000,
215         0x80000,  0x40000,  0x20000,  0x10000,
216         0x8000,   0x4000,   0x2000,   0x1000,
217         0x800,    0x400,    0x200,    0x100,
218         0x80,     0x40,     0x20,     0x10,
219         0x8,      0x4,      0x2,      0x1
220     };
221 
222     /** 
223      * Permuted Choice 1. 
224      * See ANSI X3.92-1981 Page 16, Table 7
225      */
226     private static byte[] PC1 = {
227         56, 48, 40, 32, 24, 16,  8,   0, 57, 49, 41, 33, 25, 17,
228          9,  1, 58, 50, 42, 34, 26,  18, 10,  2, 59, 51, 43, 35,
229         62, 54, 46, 38, 30, 22, 14,   6, 61, 53, 45, 37, 29, 21,
230         13,  5, 60, 52, 44, 36, 28,  20, 12,  4, 27, 19, 11,  3
231     };
232 
233     /** 
234      * Permuted Choice 2. 
235      * See ANSI X3.92-1981 Page 16, Table 9
236      */    
237     private static byte[] PC2 = {
238         13, 16, 10, 23,  0,  4,  2, 27, 14,  5, 20,  9,
239         22, 18, 11,  3, 25,  7, 15,  6, 26, 19, 12,  1,
240         40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
241         43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
242     };    
243 
244     /** 
245      * Total rotation (total leftshifts) of key block C and D.
246      * See ANSI X3.92-1981 Page 16, Table 8
247      */
248     private static byte[] TOTAL_ROTATION = {
249          1,  2,  4,  6,  8, 10, 12, 14,
250         15, 17, 19, 21, 23, 25, 27, 28
251     };
252 
253 
254     
255     /** 
256      * Generate an integer based working key based on our secret key.
257      * Acknowledgements for this routine go to James Gillogly & Phil Karn.
258      * (whoever, and wherever they are!).
259      * @param encrypting true if a encryption key should be generated,
260      * false if a key for decryption should be generated.
261      * @param key the 8 byte (56 bit) DES secret key.
262      * @param offset the offset in key where the key material starts.
263      * @throws IllegalBlockSizeException if usable range in key lesser than 8 bytes.
264      * @return 16 scheduled 48 bit keys splited in 32 values (left and right side
265      * every scheduled key) a 24 bit.
266      */
267     private int[] generateScheduledKeys( boolean encrypting, byte[] key, int offset)
268             throws IllegalBlockSizeException {    
269                 
270         if (key.length-offset < 8) {
271             throw new IllegalBlockSizeException("Usable byte range is " 
272                     + (key.length-offset) 
273                     + " bytes large, but it should be 8 bytes or larger.");
274         }        
275         
276         int[]       newKey = new int[32];
277         boolean[]   pc1m   = new boolean[56];
278         boolean[]   pcr    = new boolean[56];
279 
280         for (int j = 0; j < 56; j++ ) {
281             
282             int    l = PC1[j];
283 
284             pc1m[j] = ((key[offset + (l >>> 3)] & BIT_MASK_FOR_BYTE[ l & 0x07 ]) != 0);
285         }
286 
287         
288         int l;
289         int m;
290         int n;
291         
292         for (int i = 0; i < 16; i++) {
293             
294             if (encrypting) {
295                 m = i << 1;
296             } else {
297                 m = (15 - i) << 1;
298             }
299 
300             n = m + 1;
301             newKey[m] = 0;
302             newKey[n] = 0;
303 
304             for (int j = 0; j < 28; j++) {
305                 
306                 l = j + TOTAL_ROTATION[i];
307                 
308                 if ( l < 28 ) {
309                     pcr[j] = pc1m[l];
310                 } else {
311                     pcr[j] = pc1m[l - 28];
312                 }
313             }
314 
315             for (int j = 28; j < 56; j++) {
316                 
317                 l = j + TOTAL_ROTATION[i];
318                 
319                 if (l < 56 ) {
320                     pcr[j] = pc1m[l];
321                 } else {
322                     pcr[j] = pc1m[l - 28];
323                 }
324             }
325 
326             for (int j = 0; j < 24; j++) {
327                 
328                 if (pcr[PC2[j]]) {
329                     newKey[m] |= BIT_MASK_FOR_24BIT[j];
330                 }
331 
332                 if (pcr[PC2[j + 24]]) {
333                     newKey[n] |= BIT_MASK_FOR_24BIT[j];
334                 }
335             }
336         }
337 
338         
339         // store the processed key
340         int i1;
341         int i2;
342         
343         for (int i = 0; i < 32; i += 2) {
344 
345             i1 = newKey[i];
346             i2 = newKey[i + 1];
347 
348             newKey[i]     = ((i1 & 0x00fc0000) <<   6) |
349                             ((i1 & 0x00000fc0) <<  10) | 
350                             ((i2 & 0x00fc0000) >>> 10) | 
351                             ((i2 & 0x00000fc0) >>>  6) ;
352 
353             newKey[i + 1] = ((i1 & 0x0003f000) <<  12) | 
354                             ((i1 & 0x0000003f) <<  16) | 
355                             ((i2 & 0x0003f000) >>>  4) | 
356                              (i2 & 0x0000003f)         ;
357         }
358 
359         return newKey;
360     }    
361 
362     /** SP1 is combination of SBox 1 and the attached permutation. */
363     private static int[] SP1 = {
364         0x01010400, 0x00000000, 0x00010000, 0x01010404,
365         0x01010004, 0x00010404, 0x00000004, 0x00010000,
366         0x00000400, 0x01010400, 0x01010404, 0x00000400,
367         0x01000404, 0x01010004, 0x01000000, 0x00000004,
368         0x00000404, 0x01000400, 0x01000400, 0x00010400,
369         0x00010400, 0x01010000, 0x01010000, 0x01000404,
370         0x00010004, 0x01000004, 0x01000004, 0x00010004,
371         0x00000000, 0x00000404, 0x00010404, 0x01000000,
372         0x00010000, 0x01010404, 0x00000004, 0x01010000,
373         0x01010400, 0x01000000, 0x01000000, 0x00000400,
374         0x01010004, 0x00010000, 0x00010400, 0x01000004,
375         0x00000400, 0x00000004, 0x01000404, 0x00010404,
376         0x01010404, 0x00010004, 0x01010000, 0x01000404,
377         0x01000004, 0x00000404, 0x00010404, 0x01010400,
378         0x00000404, 0x01000400, 0x01000400, 0x00000000,
379         0x00010004, 0x00010400, 0x00000000, 0x01010004
380     };
381 
382     /** SP2 is combination of SBox 2 and the attached permutation. */    
383     private static int[] SP2 = {
384         0x80108020, 0x80008000, 0x00008000, 0x00108020,
385         0x00100000, 0x00000020, 0x80100020, 0x80008020,
386         0x80000020, 0x80108020, 0x80108000, 0x80000000,
387         0x80008000, 0x00100000, 0x00000020, 0x80100020,
388         0x00108000, 0x00100020, 0x80008020, 0x00000000,
389         0x80000000, 0x00008000, 0x00108020, 0x80100000,
390         0x00100020, 0x80000020, 0x00000000, 0x00108000,
391         0x00008020, 0x80108000, 0x80100000, 0x00008020,
392         0x00000000, 0x00108020, 0x80100020, 0x00100000,
393         0x80008020, 0x80100000, 0x80108000, 0x00008000,
394         0x80100000, 0x80008000, 0x00000020, 0x80108020,
395         0x00108020, 0x00000020, 0x00008000, 0x80000000,
396         0x00008020, 0x80108000, 0x00100000, 0x80000020,
397         0x00100020, 0x80008020, 0x80000020, 0x00100020,
398         0x00108000, 0x00000000, 0x80008000, 0x00008020,
399         0x80000000, 0x80100020, 0x80108020, 0x00108000
400     };
401 
402     /** SP3 is combination of SBox 3 and the attached permutation. */    
403     private static int[] SP3 = {
404         0x00000208, 0x08020200, 0x00000000, 0x08020008,
405         0x08000200, 0x00000000, 0x00020208, 0x08000200,
406         0x00020008, 0x08000008, 0x08000008, 0x00020000,
407         0x08020208, 0x00020008, 0x08020000, 0x00000208,
408         0x08000000, 0x00000008, 0x08020200, 0x00000200,
409         0x00020200, 0x08020000, 0x08020008, 0x00020208,
410         0x08000208, 0x00020200, 0x00020000, 0x08000208,
411         0x00000008, 0x08020208, 0x00000200, 0x08000000,
412         0x08020200, 0x08000000, 0x00020008, 0x00000208,
413         0x00020000, 0x08020200, 0x08000200, 0x00000000,
414         0x00000200, 0x00020008, 0x08020208, 0x08000200,
415         0x08000008, 0x00000200, 0x00000000, 0x08020008,
416         0x08000208, 0x00020000, 0x08000000, 0x08020208,
417         0x00000008, 0x00020208, 0x00020200, 0x08000008,
418         0x08020000, 0x08000208, 0x00000208, 0x08020000,
419         0x00020208, 0x00000008, 0x08020008, 0x00020200
420     };
421 
422     /** SP4 is combination of SBox 4 and the attached permutation. */    
423     private static int[] SP4 = {
424         0x00802001, 0x00002081, 0x00002081, 0x00000080,
425         0x00802080, 0x00800081, 0x00800001, 0x00002001,
426         0x00000000, 0x00802000, 0x00802000, 0x00802081,
427         0x00000081, 0x00000000, 0x00800080, 0x00800001,
428         0x00000001, 0x00002000, 0x00800000, 0x00802001,
429         0x00000080, 0x00800000, 0x00002001, 0x00002080,
430         0x00800081, 0x00000001, 0x00002080, 0x00800080,
431         0x00002000, 0x00802080, 0x00802081, 0x00000081,
432         0x00800080, 0x00800001, 0x00802000, 0x00802081,
433         0x00000081, 0x00000000, 0x00000000, 0x00802000,
434         0x00002080, 0x00800080, 0x00800081, 0x00000001,
435         0x00802001, 0x00002081, 0x00002081, 0x00000080,
436         0x00802081, 0x00000081, 0x00000001, 0x00002000,
437         0x00800001, 0x00002001, 0x00802080, 0x00800081,
438         0x00002001, 0x00002080, 0x00800000, 0x00802001,
439         0x00000080, 0x00800000, 0x00002000, 0x00802080
440     };
441 
442     /** SP5 is combination of SBox 5 and the attached permutation. */    
443     private static int[] SP5 = {
444         0x00000100, 0x02080100, 0x02080000, 0x42000100,
445         0x00080000, 0x00000100, 0x40000000, 0x02080000,
446         0x40080100, 0x00080000, 0x02000100, 0x40080100,
447         0x42000100, 0x42080000, 0x00080100, 0x40000000,
448         0x02000000, 0x40080000, 0x40080000, 0x00000000,
449         0x40000100, 0x42080100, 0x42080100, 0x02000100,
450         0x42080000, 0x40000100, 0x00000000, 0x42000000,
451         0x02080100, 0x02000000, 0x42000000, 0x00080100,
452         0x00080000, 0x42000100, 0x00000100, 0x02000000,
453         0x40000000, 0x02080000, 0x42000100, 0x40080100,
454         0x02000100, 0x40000000, 0x42080000, 0x02080100,
455         0x40080100, 0x00000100, 0x02000000, 0x42080000,
456         0x42080100, 0x00080100, 0x42000000, 0x42080100,
457         0x02080000, 0x00000000, 0x40080000, 0x42000000,
458         0x00080100, 0x02000100, 0x40000100, 0x00080000,
459         0x00000000, 0x40080000, 0x02080100, 0x40000100
460     };
461 
462     /** SP6 is combination of SBox 6 and the attached permutation. */    
463     private static int[] SP6 = {
464         0x20000010, 0x20400000, 0x00004000, 0x20404010,
465         0x20400000, 0x00000010, 0x20404010, 0x00400000,
466         0x20004000, 0x00404010, 0x00400000, 0x20000010,
467         0x00400010, 0x20004000, 0x20000000, 0x00004010,
468         0x00000000, 0x00400010, 0x20004010, 0x00004000,
469         0x00404000, 0x20004010, 0x00000010, 0x20400010,
470         0x20400010, 0x00000000, 0x00404010, 0x20404000,
471         0x00004010, 0x00404000, 0x20404000, 0x20000000,
472         0x20004000, 0x00000010, 0x20400010, 0x00404000,
473         0x20404010, 0x00400000, 0x00004010, 0x20000010,
474         0x00400000, 0x20004000, 0x20000000, 0x00004010,
475         0x20000010, 0x20404010, 0x00404000, 0x20400000,
476         0x00404010, 0x20404000, 0x00000000, 0x20400010,
477         0x00000010, 0x00004000, 0x20400000, 0x00404010,
478         0x00004000, 0x00400010, 0x20004010, 0x00000000,
479         0x20404000, 0x20000000, 0x00400010, 0x20004010
480     };
481 
482     /** SP7 is combination of SBox 7 and the attached permutation. */    
483     private static int[] SP7 = {
484         0x00200000, 0x04200002, 0x04000802, 0x00000000,
485         0x00000800, 0x04000802, 0x00200802, 0x04200800,
486         0x04200802, 0x00200000, 0x00000000, 0x04000002,
487         0x00000002, 0x04000000, 0x04200002, 0x00000802,
488         0x04000800, 0x00200802, 0x00200002, 0x04000800,
489         0x04000002, 0x04200000, 0x04200800, 0x00200002,
490         0x04200000, 0x00000800, 0x00000802, 0x04200802,
491         0x00200800, 0x00000002, 0x04000000, 0x00200800,
492         0x04000000, 0x00200800, 0x00200000, 0x04000802,
493         0x04000802, 0x04200002, 0x04200002, 0x00000002,
494         0x00200002, 0x04000000, 0x04000800, 0x00200000,
495         0x04200800, 0x00000802, 0x00200802, 0x04200800,
496         0x00000802, 0x04000002, 0x04200802, 0x04200000,
497         0x00200800, 0x00000000, 0x00000002, 0x04200802,
498         0x00000000, 0x00200802, 0x04200000, 0x00000800,
499         0x04000002, 0x04000800, 0x00000800, 0x00200002
500     };
501 
502     /** SP8 is combination of SBox 8 and the attached permutation. */    
503     private static int[] SP8 = {
504         0x10001040, 0x00001000, 0x00040000, 0x10041040,
505         0x10000000, 0x10001040, 0x00000040, 0x10000000,
506         0x00040040, 0x10040000, 0x10041040, 0x00041000,
507         0x10041000, 0x00041040, 0x00001000, 0x00000040,
508         0x10040000, 0x10000040, 0x10001000, 0x00001040,
509         0x00041000, 0x00040040, 0x10040040, 0x10041000,
510         0x00001040, 0x00000000, 0x00000000, 0x10040040,
511         0x10000040, 0x10001000, 0x00041040, 0x00040000,
512         0x00041040, 0x00040000, 0x10041000, 0x00001000,
513         0x00000040, 0x10040040, 0x00001000, 0x00041040,
514         0x10001000, 0x00000040, 0x10000040, 0x10040000,
515         0x10040040, 0x10000000, 0x00040000, 0x10001040,
516         0x00000000, 0x10041040, 0x00040040, 0x10000040,
517         0x10040000, 0x10001000, 0x10001040, 0x00000000,
518         0x10041040, 0x00041000, 0x00041000, 0x00001040,
519         0x00001040, 0x00040040, 0x10000000, 0x10041000
520     };
521     
522 
523     /** 
524      * The DES engine.
525      * @param wKey int[32] int array with 16 scheduled keys a 2x24bit (48bit)
526      * in encryption or decryption order.
527      * @param input that should be processed.
528      * @param inputOffset offset in input where input starts.
529      * @param output output that would be produced.
530      * @param outputOffset offset in output where output starts.
531      */
532     private void desFunc(int[] wKey, byte[] input, int inputOffset,
533                                      byte[]  output, int outputOffset) {
534 
535         int     work, right, left;
536 
537         left      = (input[inputOffset + 0] & 0x000000ff) << 24;
538         left     |= (input[inputOffset + 1] & 0x000000ff) << 16;
539         left     |= (input[inputOffset + 2] & 0x000000ff) << 8;
540         left     |= (input[inputOffset + 3] & 0x000000ff);
541 
542         right     = (input[inputOffset + 4] & 0x000000ff) << 24;
543         right    |= (input[inputOffset + 5] & 0x000000ff) << 16;
544         right    |= (input[inputOffset + 6] & 0x000000ff) << 8;
545         right    |= (input[inputOffset + 7] & 0x000000ff);
546 
547         work = ((left >>> 4) ^ right) & 0x0f0f0f0f;
548         right ^= work;
549         left ^= (work << 4);
550         
551         work = ((left >>> 16) ^ right) & 0x0000ffff;
552         right ^= work;
553         left ^= (work << 16);
554         
555         work = ((right >>> 2) ^ left) & 0x33333333;
556         left ^= work;
557         right ^= (work << 2);
558         
559         work = ((right >>> 8) ^ left) & 0x00ff00ff;
560         left ^= work;
561         right ^= (work << 8);
562         right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff;
563         
564         work = (left ^ right) & 0xaaaaaaaa;
565         left ^= work;
566         right ^= work;
567         left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff;
568 
569         for (int round = 0; round < 8; round++) {
570             
571             int     fval;
572 
573             work  = (right << 28) | (right >>> 4);
574             work ^= wKey[round * 4 + 0];
575             fval  = SP7[ work      & 0x3f];
576             fval |= SP5[(work >>>  8) & 0x3f];
577             fval |= SP3[(work >>> 16) & 0x3f];
578             fval |= SP1[(work >>> 24) & 0x3f];
579             work  = right ^ wKey[round * 4 + 1];
580             fval |= SP8[ work      & 0x3f];
581             fval |= SP6[(work >>>  8) & 0x3f];
582             fval |= SP4[(work >>> 16) & 0x3f];
583             fval |= SP2[(work >>> 24) & 0x3f];
584             left ^= fval;
585             work  = (left << 28) | (left >>> 4);
586             work ^= wKey[round * 4 + 2];
587             fval  = SP7[ work      & 0x3f];
588             fval |= SP5[(work >>>  8) & 0x3f];
589             fval |= SP3[(work >>> 16) & 0x3f];
590             fval |= SP1[(work >>> 24) & 0x3f];
591             work  = left ^ wKey[round * 4 + 3];
592             fval |= SP8[ work      & 0x3f];
593             fval |= SP6[(work >>>  8) & 0x3f];
594             fval |= SP4[(work >>> 16) & 0x3f];
595             fval |= SP2[(work >>> 24) & 0x3f];
596             right ^= fval;
597         }
598 
599         right = (right << 31) | (right >>> 1);
600         
601         work = (left ^ right) & 0xaaaaaaaa;
602         left ^= work;
603         right ^= work;
604         left = (left << 31) | (left >>> 1);
605         
606         work = ((left >>> 8) ^ right) & 0x00ff00ff;
607         right ^= work;
608         left ^= (work << 8);
609         
610         work = ((left >>> 2) ^ right) & 0x33333333;
611         right ^= work;
612         left ^= (work << 2);
613         
614         work = ((right >>> 16) ^ left) & 0x0000ffff;
615         left ^= work;
616         right ^= (work << 16);
617         
618         work = ((right >>> 4) ^ left) & 0x0f0f0f0f;
619         left ^= work;
620         right ^= (work << 4);
621 
622         output[outputOffset + 0] = (byte)((right >>> 24) & 0x000000ff);
623         output[outputOffset + 1] = (byte)((right >>> 16) & 0x000000ff);
624         output[outputOffset + 2] = (byte)((right >>>  8) & 0x000000ff);
625         output[outputOffset + 3] = (byte)( right         & 0x000000ff);
626         output[outputOffset + 4] = (byte)((left  >>> 24) & 0x000000ff);
627         output[outputOffset + 5] = (byte)((left  >>> 16) & 0x000000ff);
628         output[outputOffset + 6] = (byte)((left  >>>  8) & 0x000000ff);
629         output[outputOffset + 7] = (byte)( left          & 0x000000ff);
630     }    
631 }
632