KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > quadcap > crypto > Rijndael


1 /* Copyright 2003 Quadcap Software. All rights reserved.
2  *
3  * This software is distributed under the Quadcap Free Software License.
4  * This software may be used or modified for any purpose, personal or
5  * commercial. Open Source redistributions are permitted. Commercial
6  * redistribution of larger works derived from, or works which bundle
7  * this software requires a "Commercial Redistribution License"; see
8  * http://www.quadcap.com/purchase.
9  *
10  * Redistributions qualify as "Open Source" under one of the following terms:
11  *
12  * Redistributions are made at no charge beyond the reasonable cost of
13  * materials and delivery.
14  *
15  * Redistributions are accompanied by a copy of the Source Code or by an
16  * irrevocable offer to provide a copy of the Source Code for up to three
17  * years at the cost of materials and delivery. Such redistributions
18  * must allow further use, modification, and redistribution of the Source
19  * Code under substantially the same terms as this license.
20  *
21  * Redistributions of source code must retain the copyright notices as they
22  * appear in each source code file, these license terms, and the
23  * disclaimer/limitation of liability set forth as paragraph 6 below.
24  *
25  * Redistributions in binary form must reproduce this Copyright Notice,
26  * these license terms, and the disclaimer/limitation of liability set
27  * forth as paragraph 6 below, in the documentation and/or other materials
28  * provided with the distribution.
29  *
30  * The Software is provided on an "AS IS" basis. No warranty is
31  * provided that the Software is free of defects, or fit for a
32  * particular purpose.
33  *
34  * Limitation of Liability. Quadcap Software shall not be liable
35  * for any damages suffered by the Licensee or any third party resulting
36  * from use of the Software.
37  */

38
39 package com.quadcap.crypto;
40
41 /*
42  * Public domain SHA implementation.
43  *
44  **/

45
46 import java.util.Random JavaDoc;
47
48 import java.nio.ByteBuffer JavaDoc;
49 import java.nio.IntBuffer JavaDoc;
50
51 import com.quadcap.util.Debug;
52 import com.quadcap.util.text.Text;
53
54 /* $Id: Rijndael.java,v 1.3 2004/05/16 15:05:10 stan Exp $
55  *
56  * This file is in the public domain.
57  */

58 // package cryptix.provider.cipher;
59

60 /**
61  * Rijndael --pronounced Reindaal-- is a symmetric cipher with a 128-bit
62  * block size and variable key-size (128-, 192- and 256-bit).
63  * <p>
64  * Rijndael was designed by <a HREF="mailto:rijmen@esat.kuleuven.ac.be">Vincent
65  * Rijmen</a> and <a HREF="mailto:daemen.j@protonworld.com">Joan Daemen</a>.
66  * <p>
67  * @version $Revision: 1.3 $
68  * @author Raif S. Naffah
69  * @author Paulo S. L. M. Barreto (pbarreto@cryptix.org)
70  * @author Jeroen C. van Gelderen (gelderen@cryptix.org)
71  * @author Edwin Woudt (edwin@cryptix.org)
72  * @since Cryptix 3.1.3/3.2.0
73  */

74 public class Rijndael extends AbstractSymmetricKey implements SymmetricKey {
75     byte[] keyBytes = null;
76     
77     /**
78      * Default constructor
79      */

80     public Rijndael() {}
81
82     /**
83      * Initialize key from serialized representation
84      */

85     public void init(String JavaDoc s) throws Exception JavaDoc {
86         String JavaDoc[] v = Text.extractN(s, "*:*");
87         byte[] k = v[1].getBytes();
88         init(k);
89     }
90
91     /**
92      * Initialize from key bytes
93      */

94     final void init(byte[] k) {
95         try {
96             this.coreInit(k, false);
97             Rijndael decryptor = new Rijndael();
98             decryptor.coreInit(k, true);
99             dkey = new DecryptionKey(decryptor);
100         } catch (Exception JavaDoc e) {
101             Debug.print(e);
102             throw new RuntimeException JavaDoc(e.toString());
103         }
104     }
105
106     /**
107      * Initialize: Create a random key
108      */

109     public void init(Random JavaDoc r) {
110         byte[] b = new byte[KEYSIZE];
111         r.nextBytes(b);
112         init(b);
113     }
114
115     /**
116      * Return the serialized form of the key
117      */

118     public String JavaDoc toString() {
119         return "Rijndael:" + new String JavaDoc(keyBytes);
120     }
121
122     /**
123      * Encrypt a buffer (must be multiple of 8 bytes)
124      */

125     public void encrypt(ByteBuffer JavaDoc m, ByteBuffer JavaDoc c) {
126         while (m.position() < m.limit()) {
127             blockEncrypt(m, c);
128         }
129     }
130
131     /**
132      * Decrypt a buffer (must be a multiple of 8 bytes)
133      */

134     public void decrypt(ByteBuffer JavaDoc c, ByteBuffer JavaDoc m) {
135         while (c.position() < c.limit()) {
136             blockDecrypt(c, m);
137         }
138     }
139
140     static final int KEYSIZE = 16; // default, that is.
141

142     private boolean
143         ROUNDS_12,
144         ROUNDS_14;
145
146     /** True if in decrypt mode */
147     private boolean decrypt;
148
149     /** Subkeys */
150     private int[] K;
151
152     /** (ROUNDS-1) * 4 */
153     private int limit;
154
155
156     protected void coreInit(byte[] userKey, boolean decrypt)
157         throws Exception JavaDoc
158     {
159         this.keyBytes = userKey;
160         
161         int len = userKey.length;
162         if (len != 16 && len != 24 && len != 32) {
163             throw new Exception JavaDoc("Invalid user key length");
164         }
165         
166         this.decrypt = decrypt;
167         this.K = makeKey(userKey, decrypt);
168         if (decrypt) invertKey(this.K);
169
170         ROUNDS_12 = (len >= 24);
171         ROUNDS_14 = (len == 32);
172
173         this.limit = getRounds(len) * 4;
174     }
175
176     public int getBlockSize() { return BLOCK_SIZE; }
177
178     private static final int BLOCK_SIZE = 16; // block size in bytes
179

180     private static final String JavaDoc SS =
181         "\u637C\u777B\uF26B\u6FC5\u3001\u672B\uFED7\uAB76" +
182         "\uCA82\uC97D\uFA59\u47F0\uADD4\uA2AF\u9CA4\u72C0" +
183         "\uB7FD\u9326\u363F\uF7CC\u34A5\uE5F1\u71D8\u3115" +
184         "\u04C7\u23C3\u1896\u059A\u0712\u80E2\uEB27\uB275" +
185         "\u0983\u2C1A\u1B6E\u5AA0\u523B\uD6B3\u29E3\u2F84" +
186         "\u53D1\u00ED\u20FC\uB15B\u6ACB\uBE39\u4A4C\u58CF" +
187         "\uD0EF\uAAFB\u434D\u3385\u45F9\u027F\u503C\u9FA8" +
188         "\u51A3\u408F\u929D\u38F5\uBCB6\uDA21\u10FF\uF3D2" +
189         "\uCD0C\u13EC\u5F97\u4417\uC4A7\u7E3D\u645D\u1973" +
190         "\u6081\u4FDC\u222A\u9088\u46EE\uB814\uDE5E\u0BDB" +
191         "\uE032\u3A0A\u4906\u245C\uC2D3\uAC62\u9195\uE479" +
192         "\uE7C8\u376D\u8DD5\u4EA9\u6C56\uF4EA\u657A\uAE08" +
193         "\uBA78\u252E\u1CA6\uB4C6\uE8DD\u741F\u4BBD\u8B8A" +
194         "\u703E\uB566\u4803\uF60E\u6135\u57B9\u86C1\u1D9E" +
195         "\uE1F8\u9811\u69D9\u8E94\u9B1E\u87E9\uCE55\u28DF" +
196         "\u8CA1\u890D\uBFE6\u4268\u4199\u2D0F\uB054\uBB16";
197
198     private static final byte[]
199         S = new byte[256],
200         Si = new byte[256];
201
202     private static final int[]
203         T1 = new int[256],
204         T2 = new int[256],
205         T3 = new int[256],
206         T4 = new int[256],
207         T5 = new int[256],
208         T6 = new int[256],
209         T7 = new int[256],
210         T8 = new int[256];
211
212     private static final int[]
213         U1 = new int[256],
214         U2 = new int[256],
215         U3 = new int[256],
216         U4 = new int[256];
217
218     private static final byte[] rcon = new byte[30];
219
220
221     // Static code - to intialise S-boxes and T-boxes
222
//.......................................................................
223

224     static {
225         int ROOT = 0x11B;
226         int i, j = 0;
227
228         for (i = 0; i < 256; i++) {
229             int s, s2, s3, i2, i4, i8, i9, ib, id, ie, t;
230             char c = SS.charAt(i >>> 1);
231             S[i] = (byte)(((i & 1) == 0) ? c >>> 8 : c & 0xFF);
232             s = S[i] & 0xFF;
233             Si[s] = (byte)i;
234             s2 = s << 1;
235             if (s2 >= 0x100) {
236                 s2 ^= ROOT;
237             }
238             s3 = s2 ^ s;
239             i2 = i << 1;
240             if (i2 >= 0x100) {
241                 i2 ^= ROOT;
242             }
243             i4 = i2 << 1;
244             if (i4 >= 0x100) {
245                 i4 ^= ROOT;
246             }
247             i8 = i4 << 1;
248             if (i8 >= 0x100) {
249                 i8 ^= ROOT;
250             }
251             i9 = i8 ^ i;
252             ib = i9 ^ i2;
253             id = i9 ^ i4;
254             ie = i8 ^ i4 ^ i2;
255
256             T1[i] = t = (s2 << 24) | (s << 16) | (s << 8) | s3;
257             T2[i] = (t >>> 8) | (t << 24);
258             T3[i] = (t >>> 16) | (t << 16);
259             T4[i] = (t >>> 24) | (t << 8);
260
261             T5[s] = U1[i] = t = (ie << 24) | (i9 << 16) | (id << 8) | ib;
262             T6[s] = U2[i] = (t >>> 8) | (t << 24);
263             T7[s] = U3[i] = (t >>> 16) | (t << 16);
264             T8[s] = U4[i] = (t >>> 24) | (t << 8);
265         }
266         //
267
// round constants
268
//
269
int r = 1;
270         rcon[0] = 1;
271         for (i = 1; i < 30; i++) {
272             r <<= 1;
273             if (r >= 0x100) {
274                 r ^= ROOT;
275             }
276             rcon[i] = (byte)r;
277         }
278
279     }
280
281 //...........................................................................
282

283
284     /**
285      * Encrypt exactly one block of plaintext.
286      */

287     private void blockEncrypt(ByteBuffer JavaDoc in, ByteBuffer JavaDoc out) {
288         // plaintext to ints + key
289
int keyOffset = 0;
290         int t0 = ((in.get() ) << 24 |
291                     (in.get() & 0xFF) << 16 |
292                     (in.get() & 0xFF) << 8 |
293                     (in.get() & 0xFF) ) ^ K[keyOffset++];
294         int t1 = ((in.get() ) << 24 |
295                     (in.get() & 0xFF) << 16 |
296                     (in.get() & 0xFF) << 8 |
297                     (in.get() & 0xFF) ) ^ K[keyOffset++];
298         int t2 = ((in.get() ) << 24 |
299                     (in.get() & 0xFF) << 16 |
300                     (in.get() & 0xFF) << 8 |
301                     (in.get() & 0xFF) ) ^ K[keyOffset++];
302         int t3 = ((in.get() ) << 24 |
303                     (in.get() & 0xFF) << 16 |
304                     (in.get() & 0xFF) << 8 |
305                     (in.get() & 0xFF) ) ^ K[keyOffset++];
306
307         // apply round transforms
308
while( keyOffset < limit ) {
309             int a0, a1, a2;
310             a0 = T1[(t0 >>> 24) ] ^
311                  T2[(t1 >>> 16) & 0xFF] ^
312                  T3[(t2 >>> 8) & 0xFF] ^
313                  T4[(t3 ) & 0xFF] ^ K[keyOffset++];
314             a1 = T1[(t1 >>> 24) ] ^
315                  T2[(t2 >>> 16) & 0xFF] ^
316                  T3[(t3 >>> 8) & 0xFF] ^
317                  T4[(t0 ) & 0xFF] ^ K[keyOffset++];
318             a2 = T1[(t2 >>> 24) ] ^
319                  T2[(t3 >>> 16) & 0xFF] ^
320                  T3[(t0 >>> 8) & 0xFF] ^
321                  T4[(t1 ) & 0xFF] ^ K[keyOffset++];
322             t3 = T1[(t3 >>> 24) ] ^
323                  T2[(t0 >>> 16) & 0xFF] ^
324                  T3[(t1 >>> 8) & 0xFF] ^
325                  T4[(t2 ) & 0xFF] ^ K[keyOffset++];
326             t0 = a0; t1 = a1; t2 = a2;
327         }
328
329         // last round is special
330
int tt = K[keyOffset++];
331         out.put((byte)(S[(t0 >>> 24) ] ^ (tt >>> 24)));
332         out.put((byte)(S[(t1 >>> 16) & 0xFF] ^ (tt >>> 16)));
333         out.put((byte)(S[(t2 >>> 8) & 0xFF] ^ (tt >>> 8)));
334         out.put((byte)(S[(t3 ) & 0xFF] ^ (tt )));
335         tt = K[keyOffset++];
336         out.put((byte)(S[(t1 >>> 24) ] ^ (tt >>> 24)));
337         out.put((byte)(S[(t2 >>> 16) & 0xFF] ^ (tt >>> 16)));
338         out.put((byte)(S[(t3 >>> 8) & 0xFF] ^ (tt >>> 8)));
339         out.put((byte)(S[(t0 ) & 0xFF] ^ (tt )));
340         tt = K[keyOffset++];
341         out.put((byte)(S[(t2 >>> 24) ] ^ (tt >>> 24)));
342         out.put((byte)(S[(t3 >>> 16) & 0xFF] ^ (tt >>> 16)));
343         out.put((byte)(S[(t0 >>> 8) & 0xFF] ^ (tt >>> 8)));
344         out.put((byte)(S[(t1 ) & 0xFF] ^ (tt )));
345         tt = K[keyOffset++];
346         out.put((byte)(S[(t3 >>> 24) ] ^ (tt >>> 24)));
347         out.put((byte)(S[(t0 >>> 16) & 0xFF] ^ (tt >>> 16)));
348         out.put((byte)(S[(t1 >>> 8) & 0xFF] ^ (tt >>> 8)));
349         out.put((byte)(S[(t2 ) & 0xFF] ^ (tt )));
350     }
351
352
353     /**
354      * Decrypt exactly one block of plaintext.
355      */

356     private void blockDecrypt(ByteBuffer JavaDoc in, ByteBuffer JavaDoc out) {
357         int keyOffset = 8;
358         int t0, t1, t2, t3, a0, a1, a2;
359
360         t0 = ((in.get() ) << 24 |
361               (in.get() & 0xFF) << 16 |
362               (in.get() & 0xFF) << 8 |
363               (in.get() & 0xFF) ) ^ K[4];
364         t1 = ((in.get() ) << 24 |
365               (in.get() & 0xFF) << 16 |
366               (in.get() & 0xFF) << 8 |
367               (in.get() & 0xFF) ) ^ K[5];
368         t2 = ((in.get() ) << 24 |
369               (in.get() & 0xFF) << 16 |
370               (in.get() & 0xFF) << 8 |
371               (in.get() & 0xFF) ) ^ K[6];
372         t3 = ((in.get() ) << 24 |
373               (in.get() & 0xFF) << 16 |
374               (in.get() & 0xFF) << 8 |
375               (in.get() & 0xFF) ) ^ K[7];
376
377         if(ROUNDS_12) {
378             a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^
379                  T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++];
380             a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^
381                  T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++];
382             a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^
383                  T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++];
384             t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^
385                  T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++];
386             t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^
387                  T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++];
388             t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^
389                  T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++];
390             t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^
391                  T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++];
392             t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^
393                  T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++];
394
395             if(ROUNDS_14) {
396                 a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^
397                      T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++];
398                 a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^
399                      T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++];
400                 a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^
401                      T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++];
402                 t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^
403                      T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++];
404                 t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^
405                      T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++];
406                 t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^
407                      T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++];
408                 t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^
409                      T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++];
410                 t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^
411                      T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++];
412             }
413         }
414         a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^
415              T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++];
416         a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^
417              T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++];
418         a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^
419              T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++];
420         t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^
421              T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++];
422         t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^
423              T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++];
424         t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^
425              T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++];
426         t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^
427              T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++];
428         t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^
429              T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++];
430         a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^
431              T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++];
432         a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^
433              T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++];
434         a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^
435              T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++];
436         t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^
437              T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++];
438         t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^
439              T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++];
440         t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^
441              T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++];
442         t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^
443              T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++];
444         t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^
445              T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++];
446         a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^
447              T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++];
448         a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^
449              T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++];
450         a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^
451              T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++];
452         t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^
453              T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++];
454         t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^
455              T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++];
456         t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^
457              T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++];
458         t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^
459              T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++];
460         t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^
461              T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++];
462         a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^
463              T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++];
464         a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^
465              T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++];
466         a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^
467              T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++];
468         t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^
469              T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++];
470         t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^
471              T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++];
472         t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^
473              T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++];
474         t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^
475              T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++];
476         t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^
477              T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++];
478         a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^
479              T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++];
480         a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^
481              T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++];
482         a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^
483              T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++];
484         t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^
485              T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++];
486
487         t1 = K[0];
488         out.put((byte)(Si[(a0 >>> 24) ] ^ (t1 >>> 24)));
489         out.put((byte)(Si[(t3 >>> 16) & 0xFF] ^ (t1 >>> 16)));
490         out.put((byte)(Si[(a2 >>> 8) & 0xFF] ^ (t1 >>> 8)));
491         out.put((byte)(Si[(a1 ) & 0xFF] ^ (t1 )));
492         t1 = K[1];
493         out.put((byte)(Si[(a1 >>> 24) ] ^ (t1 >>> 24)));
494         out.put((byte)(Si[(a0 >>> 16) & 0xFF] ^ (t1 >>> 16)));
495         out.put((byte)(Si[(t3 >>> 8) & 0xFF] ^ (t1 >>> 8)));
496         out.put((byte)(Si[(a2 ) & 0xFF] ^ (t1 )));
497         t1 = K[2];
498         out.put((byte)(Si[(a2 >>> 24) ] ^ (t1 >>> 24)));
499         out.put((byte)(Si[(a1 >>> 16) & 0xFF] ^ (t1 >>> 16)));
500         out.put((byte)(Si[(a0 >>> 8) & 0xFF] ^ (t1 >>> 8)));
501         out.put((byte)(Si[(t3 ) & 0xFF] ^ (t1 )));
502         t1 = K[3];
503         out.put((byte)(Si[(t3 >>> 24) ] ^ (t1 >>> 24)));
504         out.put((byte)(Si[(a2 >>> 16) & 0xFF] ^ (t1 >>> 16)));
505         out.put((byte)(Si[(a1 >>> 8) & 0xFF] ^ (t1 >>> 8)));
506         out.put((byte)(Si[(a0 ) & 0xFF] ^ (t1 )));
507     }
508
509
510     /**
511      * Expand a user-supplied key material into a session key.
512      *
513      * @param key The 128/192/256-bit user-key to use.
514      * @exception InvalidKeyException If the key is invalid.
515      */

516     private static int[] makeKey( byte[] keyBytes, boolean decrypt )
517         throws Exception JavaDoc
518     {
519         int ROUNDS = getRounds(keyBytes.length);
520         int ROUND_KEY_COUNT = (ROUNDS + 1) * 4;
521
522         int[] Ki = new int[ROUND_KEY_COUNT];
523
524         int KC = keyBytes.length / 4; // keylen in 32-bit elements
525
int[] tk = new int[KC];
526
527         int i, j;
528
529         // copy user material bytes into temporary ints
530
for (i = 0, j = 0; i < KC; )
531             tk[i++] = (keyBytes[j++] ) << 24 |
532                       (keyBytes[j++] & 0xFF) << 16 |
533                       (keyBytes[j++] & 0xFF) << 8 |
534                       (keyBytes[j++] & 0xFF);
535
536         // copy values into round key arrays
537
int t = 0;
538         for ( ; t < KC; t++) Ki[t] = tk[t];
539
540         int tt, rconpointer = 0;
541         while (t < ROUND_KEY_COUNT) {
542             // extrapolate using phi (the round key evolution function)
543
tt = tk[KC - 1];
544             tk[0] ^= (S[(tt >>> 16) & 0xFF] ) << 24 ^
545                      (S[(tt >>> 8) & 0xFF] & 0xFF) << 16 ^
546                      (S[(tt ) & 0xFF] & 0xFF) << 8 ^
547                      (S[(tt >>> 24) ] & 0xFF) ^
548                      (rcon[rconpointer++] ) << 24;
549             if (KC != 8)
550                 for (i = 1, j = 0; i < KC; ) tk[i++] ^= tk[j++];
551             else {
552                 for (i = 1, j = 0; i < KC / 2; ) tk[i++] ^= tk[j++];
553                 tt = tk[KC / 2 - 1];
554                 tk[KC / 2] ^= (S[(tt ) & 0xFF] & 0xFF) ^
555                               (S[(tt >>> 8) & 0xFF] & 0xFF) << 8 ^
556                               (S[(tt >>> 16) & 0xFF] & 0xFF) << 16 ^
557                               (S[(tt >>> 24) ] ) << 24;
558                 for (j = KC / 2, i = j + 1; i < KC; ) tk[i++] ^= tk[j++];
559             }
560
561             // copy values into round key arrays
562
for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++)
563                 Ki[t] = tk[j];
564         }
565
566         return Ki;
567     }
568
569
570     private static void invertKey(int[] K) {
571
572         for(int i=0; i<K.length/2-4;i+=4) {
573             int jj0 = K[i+0];
574             int jj1 = K[i+1];
575             int jj2 = K[i+2];
576             int jj3 = K[i+3];
577             K[i+0] = K[K.length-i-4+0];
578             K[i+1] = K[K.length-i-4+1];
579             K[i+2] = K[K.length-i-4+2];
580             K[i+3] = K[K.length-i-4+3];
581             K[K.length-i-4+0] = jj0;
582             K[K.length-i-4+1] = jj1;
583             K[K.length-i-4+2] = jj2;
584             K[K.length-i-4+3] = jj3;
585         }
586         
587         for (int r = 4; r < K.length-4; r++) {
588             int tt = K[r];
589             K[r] = U1[(tt >>> 24) & 0xFF] ^
590                    U2[(tt >>> 16) & 0xFF] ^
591                    U3[(tt >>> 8) & 0xFF] ^
592                    U4[ tt & 0xFF];
593         }
594
595         int j0 = K[K.length-4];
596         int j1 = K[K.length-3];
597         int j2 = K[K.length-2];
598         int j3 = K[K.length-1];
599         for( int i=K.length-1; i>3; i-- ) K[i] = K[i-4];
600         K[0] = j0;
601         K[1] = j1;
602         K[2] = j2;
603         K[3] = j3;
604     }
605
606
607     /**
608      * Return The number of rounds for a given Rijndael keysize.
609      *
610      * @param keySize The size of the user key material in bytes.
611      * MUST be one of (16, 24, 32).
612      * @return The number of rounds.
613      */

614     private final static int getRounds( int keySize ) {
615         return (keySize >> 2) + 6;
616     }
617 }
618
Popular Tags