Quadcap Embeddable Database

com/quadcap/crypto/Rijndael.java

Go to the documentation of this file.
00001 /* Copyright 2003 Quadcap Software. All rights reserved. 00002 * 00003 * This software is distributed under the Quadcap Free Software License. 00004 * This software may be used or modified for any purpose, personal or 00005 * commercial. Open Source redistributions are permitted. Commercial 00006 * redistribution of larger works derived from, or works which bundle 00007 * this software requires a "Commercial Redistribution License"; see 00008 * http://www.quadcap.com/purchase. 00009 * 00010 * Redistributions qualify as "Open Source" under one of the following terms: 00011 * 00012 * Redistributions are made at no charge beyond the reasonable cost of 00013 * materials and delivery. 00014 * 00015 * Redistributions are accompanied by a copy of the Source Code or by an 00016 * irrevocable offer to provide a copy of the Source Code for up to three 00017 * years at the cost of materials and delivery. Such redistributions 00018 * must allow further use, modification, and redistribution of the Source 00019 * Code under substantially the same terms as this license. 00020 * 00021 * Redistributions of source code must retain the copyright notices as they 00022 * appear in each source code file, these license terms, and the 00023 * disclaimer/limitation of liability set forth as paragraph 6 below. 00024 * 00025 * Redistributions in binary form must reproduce this Copyright Notice, 00026 * these license terms, and the disclaimer/limitation of liability set 00027 * forth as paragraph 6 below, in the documentation and/or other materials 00028 * provided with the distribution. 00029 * 00030 * The Software is provided on an "AS IS" basis. No warranty is 00031 * provided that the Software is free of defects, or fit for a 00032 * particular purpose. 00033 * 00034 * Limitation of Liability. Quadcap Software shall not be liable 00035 * for any damages suffered by the Licensee or any third party resulting 00036 * from use of the Software. 00037 */ 00038 00039 package com.quadcap.crypto; 00040 00041 /* 00042 * Public domain SHA implementation. 00043 * 00044 **/ 00045 00046 import java.util.Random; 00047 00048 import java.nio.ByteBuffer; 00049 import java.nio.IntBuffer; 00050 00051 import com.quadcap.util.Debug; 00052 import com.quadcap.util.text.Text; 00053 00054 /* $Id: Rijndael.java,v 1.3 2004/05/16 15:05:10 stan Exp $ 00055 * 00056 * This file is in the public domain. 00057 */ 00058 // package cryptix.provider.cipher; 00059 00060 /** 00061 * Rijndael --pronounced Reindaal-- is a symmetric cipher with a 128-bit 00062 * block size and variable key-size (128-, 192- and 256-bit). 00063 * <p> 00064 * Rijndael was designed by <a href="mailto:rijmen@esat.kuleuven.ac.be">Vincent 00065 * Rijmen</a> and <a href="mailto:daemen.j@protonworld.com">Joan Daemen</a>. 00066 * <p> 00067 * @version $Revision: 1.3 $ 00068 * @author Raif S. Naffah 00069 * @author Paulo S. L. M. Barreto (pbarreto@cryptix.org) 00070 * @author Jeroen C. van Gelderen (gelderen@cryptix.org) 00071 * @author Edwin Woudt (edwin@cryptix.org) 00072 * @since Cryptix 3.1.3/3.2.0 00073 */ 00074 public class Rijndael extends AbstractSymmetricKey implements SymmetricKey { 00075 byte[] keyBytes = null; 00076 00077 /** 00078 * Default constructor 00079 */ 00080 public Rijndael() {} 00081 00082 /** 00083 * Initialize key from serialized representation 00084 */ 00085 public void init(String s) throws Exception { 00086 String[] v = Text.extractN(s, "*:*"); 00087 byte[] k = v[1].getBytes(); 00088 init(k); 00089 } 00090 00091 /** 00092 * Initialize from key bytes 00093 */ 00094 final void init(byte[] k) { 00095 try { 00096 this.coreInit(k, false); 00097 Rijndael decryptor = new Rijndael(); 00098 decryptor.coreInit(k, true); 00099 dkey = new DecryptionKey(decryptor); 00100 } catch (Exception e) { 00101 Debug.print(e); 00102 throw new RuntimeException(e.toString()); 00103 } 00104 } 00105 00106 /** 00107 * Initialize: Create a random key 00108 */ 00109 public void init(Random r) { 00110 byte[] b = new byte[KEYSIZE]; 00111 r.nextBytes(b); 00112 init(b); 00113 } 00114 00115 /** 00116 * Return the serialized form of the key 00117 */ 00118 public String toString() { 00119 return "Rijndael:" + new String(keyBytes); 00120 } 00121 00122 /** 00123 * Encrypt a buffer (must be multiple of 8 bytes) 00124 */ 00125 public void encrypt(ByteBuffer m, ByteBuffer c) { 00126 while (m.position() < m.limit()) { 00127 blockEncrypt(m, c); 00128 } 00129 } 00130 00131 /** 00132 * Decrypt a buffer (must be a multiple of 8 bytes) 00133 */ 00134 public void decrypt(ByteBuffer c, ByteBuffer m) { 00135 while (c.position() < c.limit()) { 00136 blockDecrypt(c, m); 00137 } 00138 } 00139 00140 static final int KEYSIZE = 16; // default, that is. 00141 00142 private boolean 00143 ROUNDS_12, 00144 ROUNDS_14; 00145 00146 /** True if in decrypt mode */ 00147 private boolean decrypt; 00148 00149 /** Subkeys */ 00150 private int[] K; 00151 00152 /** (ROUNDS-1) * 4 */ 00153 private int limit; 00154 00155 00156 protected void coreInit(byte[] userKey, boolean decrypt) 00157 throws Exception 00158 { 00159 this.keyBytes = userKey; 00160 00161 int len = userKey.length; 00162 if (len != 16 && len != 24 && len != 32) { 00163 throw new Exception("Invalid user key length"); 00164 } 00165 00166 this.decrypt = decrypt; 00167 this.K = makeKey(userKey, decrypt); 00168 if (decrypt) invertKey(this.K); 00169 00170 ROUNDS_12 = (len >= 24); 00171 ROUNDS_14 = (len == 32); 00172 00173 this.limit = getRounds(len) * 4; 00174 } 00175 00176 public int getBlockSize() { return BLOCK_SIZE; } 00177 00178 private static final int BLOCK_SIZE = 16; // block size in bytes 00179 00180 private static final String SS = 00181 "\u637C\u777B\uF26B\u6FC5\u3001\u672B\uFED7\uAB76" + 00182 "\uCA82\uC97D\uFA59\u47F0\uADD4\uA2AF\u9CA4\u72C0" + 00183 "\uB7FD\u9326\u363F\uF7CC\u34A5\uE5F1\u71D8\u3115" + 00184 "\u04C7\u23C3\u1896\u059A\u0712\u80E2\uEB27\uB275" + 00185 "\u0983\u2C1A\u1B6E\u5AA0\u523B\uD6B3\u29E3\u2F84" + 00186 "\u53D1\u00ED\u20FC\uB15B\u6ACB\uBE39\u4A4C\u58CF" + 00187 "\uD0EF\uAAFB\u434D\u3385\u45F9\u027F\u503C\u9FA8" + 00188 "\u51A3\u408F\u929D\u38F5\uBCB6\uDA21\u10FF\uF3D2" + 00189 "\uCD0C\u13EC\u5F97\u4417\uC4A7\u7E3D\u645D\u1973" + 00190 "\u6081\u4FDC\u222A\u9088\u46EE\uB814\uDE5E\u0BDB" + 00191 "\uE032\u3A0A\u4906\u245C\uC2D3\uAC62\u9195\uE479" + 00192 "\uE7C8\u376D\u8DD5\u4EA9\u6C56\uF4EA\u657A\uAE08" + 00193 "\uBA78\u252E\u1CA6\uB4C6\uE8DD\u741F\u4BBD\u8B8A" + 00194 "\u703E\uB566\u4803\uF60E\u6135\u57B9\u86C1\u1D9E" + 00195 "\uE1F8\u9811\u69D9\u8E94\u9B1E\u87E9\uCE55\u28DF" + 00196 "\u8CA1\u890D\uBFE6\u4268\u4199\u2D0F\uB054\uBB16"; 00197 00198 private static final byte[] 00199 S = new byte[256], 00200 Si = new byte[256]; 00201 00202 private static final int[] 00203 T1 = new int[256], 00204 T2 = new int[256], 00205 T3 = new int[256], 00206 T4 = new int[256], 00207 T5 = new int[256], 00208 T6 = new int[256], 00209 T7 = new int[256], 00210 T8 = new int[256]; 00211 00212 private static final int[] 00213 U1 = new int[256], 00214 U2 = new int[256], 00215 U3 = new int[256], 00216 U4 = new int[256]; 00217 00218 private static final byte[] rcon = new byte[30]; 00219 00220 00221 // Static code - to intialise S-boxes and T-boxes 00222 //....................................................................... 00223 00224 static { 00225 int ROOT = 0x11B; 00226 int i, j = 0; 00227 00228 for (i = 0; i < 256; i++) { 00229 int s, s2, s3, i2, i4, i8, i9, ib, id, ie, t; 00230 char c = SS.charAt(i >>> 1); 00231 S[i] = (byte)(((i & 1) == 0) ? c >>> 8 : c & 0xFF); 00232 s = S[i] & 0xFF; 00233 Si[s] = (byte)i; 00234 s2 = s << 1; 00235 if (s2 >= 0x100) { 00236 s2 ^= ROOT; 00237 } 00238 s3 = s2 ^ s; 00239 i2 = i << 1; 00240 if (i2 >= 0x100) { 00241 i2 ^= ROOT; 00242 } 00243 i4 = i2 << 1; 00244 if (i4 >= 0x100) { 00245 i4 ^= ROOT; 00246 } 00247 i8 = i4 << 1; 00248 if (i8 >= 0x100) { 00249 i8 ^= ROOT; 00250 } 00251 i9 = i8 ^ i; 00252 ib = i9 ^ i2; 00253 id = i9 ^ i4; 00254 ie = i8 ^ i4 ^ i2; 00255 00256 T1[i] = t = (s2 << 24) | (s << 16) | (s << 8) | s3; 00257 T2[i] = (t >>> 8) | (t << 24); 00258 T3[i] = (t >>> 16) | (t << 16); 00259 T4[i] = (t >>> 24) | (t << 8); 00260 00261 T5[s] = U1[i] = t = (ie << 24) | (i9 << 16) | (id << 8) | ib; 00262 T6[s] = U2[i] = (t >>> 8) | (t << 24); 00263 T7[s] = U3[i] = (t >>> 16) | (t << 16); 00264 T8[s] = U4[i] = (t >>> 24) | (t << 8); 00265 } 00266 // 00267 // round constants 00268 // 00269 int r = 1; 00270 rcon[0] = 1; 00271 for (i = 1; i < 30; i++) { 00272 r <<= 1; 00273 if (r >= 0x100) { 00274 r ^= ROOT; 00275 } 00276 rcon[i] = (byte)r; 00277 } 00278 00279 } 00280 00281 //........................................................................... 00282 00283 00284 /** 00285 * Encrypt exactly one block of plaintext. 00286 */ 00287 private void blockEncrypt(ByteBuffer in, ByteBuffer out) { 00288 // plaintext to ints + key 00289 int keyOffset = 0; 00290 int t0 = ((in.get() ) << 24 | 00291 (in.get() & 0xFF) << 16 | 00292 (in.get() & 0xFF) << 8 | 00293 (in.get() & 0xFF) ) ^ K[keyOffset++]; 00294 int t1 = ((in.get() ) << 24 | 00295 (in.get() & 0xFF) << 16 | 00296 (in.get() & 0xFF) << 8 | 00297 (in.get() & 0xFF) ) ^ K[keyOffset++]; 00298 int t2 = ((in.get() ) << 24 | 00299 (in.get() & 0xFF) << 16 | 00300 (in.get() & 0xFF) << 8 | 00301 (in.get() & 0xFF) ) ^ K[keyOffset++]; 00302 int t3 = ((in.get() ) << 24 | 00303 (in.get() & 0xFF) << 16 | 00304 (in.get() & 0xFF) << 8 | 00305 (in.get() & 0xFF) ) ^ K[keyOffset++]; 00306 00307 // apply round transforms 00308 while( keyOffset < limit ) { 00309 int a0, a1, a2; 00310 a0 = T1[(t0 >>> 24) ] ^ 00311 T2[(t1 >>> 16) & 0xFF] ^ 00312 T3[(t2 >>> 8) & 0xFF] ^ 00313 T4[(t3 ) & 0xFF] ^ K[keyOffset++]; 00314 a1 = T1[(t1 >>> 24) ] ^ 00315 T2[(t2 >>> 16) & 0xFF] ^ 00316 T3[(t3 >>> 8) & 0xFF] ^ 00317 T4[(t0 ) & 0xFF] ^ K[keyOffset++]; 00318 a2 = T1[(t2 >>> 24) ] ^ 00319 T2[(t3 >>> 16) & 0xFF] ^ 00320 T3[(t0 >>> 8) & 0xFF] ^ 00321 T4[(t1 ) & 0xFF] ^ K[keyOffset++]; 00322 t3 = T1[(t3 >>> 24) ] ^ 00323 T2[(t0 >>> 16) & 0xFF] ^ 00324 T3[(t1 >>> 8) & 0xFF] ^ 00325 T4[(t2 ) & 0xFF] ^ K[keyOffset++]; 00326 t0 = a0; t1 = a1; t2 = a2; 00327 } 00328 00329 // last round is special 00330 int tt = K[keyOffset++]; 00331 out.put((byte)(S[(t0 >>> 24) ] ^ (tt >>> 24))); 00332 out.put((byte)(S[(t1 >>> 16) & 0xFF] ^ (tt >>> 16))); 00333 out.put((byte)(S[(t2 >>> 8) & 0xFF] ^ (tt >>> 8))); 00334 out.put((byte)(S[(t3 ) & 0xFF] ^ (tt ))); 00335 tt = K[keyOffset++]; 00336 out.put((byte)(S[(t1 >>> 24) ] ^ (tt >>> 24))); 00337 out.put((byte)(S[(t2 >>> 16) & 0xFF] ^ (tt >>> 16))); 00338 out.put((byte)(S[(t3 >>> 8) & 0xFF] ^ (tt >>> 8))); 00339 out.put((byte)(S[(t0 ) & 0xFF] ^ (tt ))); 00340 tt = K[keyOffset++]; 00341 out.put((byte)(S[(t2 >>> 24) ] ^ (tt >>> 24))); 00342 out.put((byte)(S[(t3 >>> 16) & 0xFF] ^ (tt >>> 16))); 00343 out.put((byte)(S[(t0 >>> 8) & 0xFF] ^ (tt >>> 8))); 00344 out.put((byte)(S[(t1 ) & 0xFF] ^ (tt ))); 00345 tt = K[keyOffset++]; 00346 out.put((byte)(S[(t3 >>> 24) ] ^ (tt >>> 24))); 00347 out.put((byte)(S[(t0 >>> 16) & 0xFF] ^ (tt >>> 16))); 00348 out.put((byte)(S[(t1 >>> 8) & 0xFF] ^ (tt >>> 8))); 00349 out.put((byte)(S[(t2 ) & 0xFF] ^ (tt ))); 00350 } 00351 00352 00353 /** 00354 * Decrypt exactly one block of plaintext. 00355 */ 00356 private void blockDecrypt(ByteBuffer in, ByteBuffer out) { 00357 int keyOffset = 8; 00358 int t0, t1, t2, t3, a0, a1, a2; 00359 00360 t0 = ((in.get() ) << 24 | 00361 (in.get() & 0xFF) << 16 | 00362 (in.get() & 0xFF) << 8 | 00363 (in.get() & 0xFF) ) ^ K[4]; 00364 t1 = ((in.get() ) << 24 | 00365 (in.get() & 0xFF) << 16 | 00366 (in.get() & 0xFF) << 8 | 00367 (in.get() & 0xFF) ) ^ K[5]; 00368 t2 = ((in.get() ) << 24 | 00369 (in.get() & 0xFF) << 16 | 00370 (in.get() & 0xFF) << 8 | 00371 (in.get() & 0xFF) ) ^ K[6]; 00372 t3 = ((in.get() ) << 24 | 00373 (in.get() & 0xFF) << 16 | 00374 (in.get() & 0xFF) << 8 | 00375 (in.get() & 0xFF) ) ^ K[7]; 00376 00377 if(ROUNDS_12) { 00378 a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ 00379 T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++]; 00380 a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ 00381 T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++]; 00382 a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ 00383 T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; 00384 t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ 00385 T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++]; 00386 t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ 00387 T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++]; 00388 t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ 00389 T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++]; 00390 t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ 00391 T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; 00392 t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ 00393 T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++]; 00394 00395 if(ROUNDS_14) { 00396 a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ 00397 T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++]; 00398 a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ 00399 T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++]; 00400 a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ 00401 T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; 00402 t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ 00403 T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++]; 00404 t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ 00405 T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++]; 00406 t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ 00407 T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++]; 00408 t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ 00409 T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; 00410 t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ 00411 T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++]; 00412 } 00413 } 00414 a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ 00415 T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++]; 00416 a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ 00417 T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++]; 00418 a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ 00419 T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; 00420 t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ 00421 T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++]; 00422 t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ 00423 T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++]; 00424 t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ 00425 T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++]; 00426 t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ 00427 T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; 00428 t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ 00429 T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++]; 00430 a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ 00431 T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++]; 00432 a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ 00433 T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++]; 00434 a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ 00435 T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; 00436 t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ 00437 T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++]; 00438 t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ 00439 T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++]; 00440 t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ 00441 T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++]; 00442 t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ 00443 T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; 00444 t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ 00445 T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++]; 00446 a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ 00447 T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++]; 00448 a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ 00449 T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++]; 00450 a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ 00451 T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; 00452 t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ 00453 T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++]; 00454 t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ 00455 T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++]; 00456 t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ 00457 T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++]; 00458 t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ 00459 T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; 00460 t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ 00461 T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++]; 00462 a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ 00463 T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++]; 00464 a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ 00465 T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++]; 00466 a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ 00467 T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; 00468 t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ 00469 T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++]; 00470 t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ 00471 T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++]; 00472 t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ 00473 T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++]; 00474 t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ 00475 T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; 00476 t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ 00477 T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++]; 00478 a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ 00479 T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++]; 00480 a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ 00481 T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++]; 00482 a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ 00483 T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; 00484 t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ 00485 T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++]; 00486 00487 t1 = K[0]; 00488 out.put((byte)(Si[(a0 >>> 24) ] ^ (t1 >>> 24))); 00489 out.put((byte)(Si[(t3 >>> 16) & 0xFF] ^ (t1 >>> 16))); 00490 out.put((byte)(Si[(a2 >>> 8) & 0xFF] ^ (t1 >>> 8))); 00491 out.put((byte)(Si[(a1 ) & 0xFF] ^ (t1 ))); 00492 t1 = K[1]; 00493 out.put((byte)(Si[(a1 >>> 24) ] ^ (t1 >>> 24))); 00494 out.put((byte)(Si[(a0 >>> 16) & 0xFF] ^ (t1 >>> 16))); 00495 out.put((byte)(Si[(t3 >>> 8) & 0xFF] ^ (t1 >>> 8))); 00496 out.put((byte)(Si[(a2 ) & 0xFF] ^ (t1 ))); 00497 t1 = K[2]; 00498 out.put((byte)(Si[(a2 >>> 24) ] ^ (t1 >>> 24))); 00499 out.put((byte)(Si[(a1 >>> 16) & 0xFF] ^ (t1 >>> 16))); 00500 out.put((byte)(Si[(a0 >>> 8) & 0xFF] ^ (t1 >>> 8))); 00501 out.put((byte)(Si[(t3 ) & 0xFF] ^ (t1 ))); 00502 t1 = K[3]; 00503 out.put((byte)(Si[(t3 >>> 24) ] ^ (t1 >>> 24))); 00504 out.put((byte)(Si[(a2 >>> 16) & 0xFF] ^ (t1 >>> 16))); 00505 out.put((byte)(Si[(a1 >>> 8) & 0xFF] ^ (t1 >>> 8))); 00506 out.put((byte)(Si[(a0 ) & 0xFF] ^ (t1 ))); 00507 } 00508 00509 00510 /** 00511 * Expand a user-supplied key material into a session key. 00512 * 00513 * @param key The 128/192/256-bit user-key to use. 00514 * @exception InvalidKeyException If the key is invalid. 00515 */ 00516 private static int[] makeKey( byte[] keyBytes, boolean decrypt ) 00517 throws Exception 00518 { 00519 int ROUNDS = getRounds(keyBytes.length); 00520 int ROUND_KEY_COUNT = (ROUNDS + 1) * 4; 00521 00522 int[] Ki = new int[ROUND_KEY_COUNT]; 00523 00524 int KC = keyBytes.length / 4; // keylen in 32-bit elements 00525 int[] tk = new int[KC]; 00526 00527 int i, j; 00528 00529 // copy user material bytes into temporary ints 00530 for (i = 0, j = 0; i < KC; ) 00531 tk[i++] = (keyBytes[j++] ) << 24 | 00532 (keyBytes[j++] & 0xFF) << 16 | 00533 (keyBytes[j++] & 0xFF) << 8 | 00534 (keyBytes[j++] & 0xFF); 00535 00536 // copy values into round key arrays 00537 int t = 0; 00538 for ( ; t < KC; t++) Ki[t] = tk[t]; 00539 00540 int tt, rconpointer = 0; 00541 while (t < ROUND_KEY_COUNT) { 00542 // extrapolate using phi (the round key evolution function) 00543 tt = tk[KC - 1]; 00544 tk[0] ^= (S[(tt >>> 16) & 0xFF] ) << 24 ^ 00545 (S[(tt >>> 8) & 0xFF] & 0xFF) << 16 ^ 00546 (S[(tt ) & 0xFF] & 0xFF) << 8 ^ 00547 (S[(tt >>> 24) ] & 0xFF) ^ 00548 (rcon[rconpointer++] ) << 24; 00549 if (KC != 8) 00550 for (i = 1, j = 0; i < KC; ) tk[i++] ^= tk[j++]; 00551 else { 00552 for (i = 1, j = 0; i < KC / 2; ) tk[i++] ^= tk[j++]; 00553 tt = tk[KC / 2 - 1]; 00554 tk[KC / 2] ^= (S[(tt ) & 0xFF] & 0xFF) ^ 00555 (S[(tt >>> 8) & 0xFF] & 0xFF) << 8 ^ 00556 (S[(tt >>> 16) & 0xFF] & 0xFF) << 16 ^ 00557 (S[(tt >>> 24) ] ) << 24; 00558 for (j = KC / 2, i = j + 1; i < KC; ) tk[i++] ^= tk[j++]; 00559 } 00560 00561 // copy values into round key arrays 00562 for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++) 00563 Ki[t] = tk[j]; 00564 } 00565 00566 return Ki; 00567 } 00568 00569 00570 private static void invertKey(int[] K) { 00571 00572 for(int i=0; i<K.length/2-4;i+=4) { 00573 int jj0 = K[i+0]; 00574 int jj1 = K[i+1]; 00575 int jj2 = K[i+2]; 00576 int jj3 = K[i+3]; 00577 K[i+0] = K[K.length-i-4+0]; 00578 K[i+1] = K[K.length-i-4+1]; 00579 K[i+2] = K[K.length-i-4+2]; 00580 K[i+3] = K[K.length-i-4+3]; 00581 K[K.length-i-4+0] = jj0; 00582 K[K.length-i-4+1] = jj1; 00583 K[K.length-i-4+2] = jj2; 00584 K[K.length-i-4+3] = jj3; 00585 } 00586 00587 for (int r = 4; r < K.length-4; r++) { 00588 int tt = K[r]; 00589 K[r] = U1[(tt >>> 24) & 0xFF] ^ 00590 U2[(tt >>> 16) & 0xFF] ^ 00591 U3[(tt >>> 8) & 0xFF] ^ 00592 U4[ tt & 0xFF]; 00593 } 00594 00595 int j0 = K[K.length-4]; 00596 int j1 = K[K.length-3]; 00597 int j2 = K[K.length-2]; 00598 int j3 = K[K.length-1]; 00599 for( int i=K.length-1; i>3; i-- ) K[i] = K[i-4]; 00600 K[0] = j0; 00601 K[1] = j1; 00602 K[2] = j2; 00603 K[3] = j3; 00604 } 00605 00606 00607 /** 00608 * Return The number of rounds for a given Rijndael keysize. 00609 * 00610 * @param keySize The size of the user key material in bytes. 00611 * MUST be one of (16, 24, 32). 00612 * @return The number of rounds. 00613 */ 00614 private final static int getRounds( int keySize ) { 00615 return (keySize >> 2) + 6; 00616 } 00617 }