//============================================================================== // AESCipher.java //============================================================================== package tribble.crypto; // System imports import java.lang.Exception; import java.lang.String; import java.lang.System; import java.security.InvalidKeyException; import java.security.Key; // Local imports import tribble.crypto.SymmetricCipher; /******************************************************************************* * AES encryption standard algorithm (also known as Rijndael). * Rijndael (pronounced rain'doll) is a symmetric cipher * with a 128-bit block size and a variable key size (128-bit, 192-bit, and * 256-bit). * *
* Rijndael is the United States AES encryption standard algorithm, which * supersedes the previous DES encryption standard. * * *
* Acknowledgements * *
* Rijndael was designed by Vincent Rijmen * (rijmen@esat.kuleuven.ac.be) * and Joan Daemen * (daemen.j@protonworld.com). * *
* This implementation was derived from source originally written by Cryptix: *
* Rijndael.java 1.8 2000/10/02 * ** * * @version $Revision: 1.2 $ $Date: 2005/07/24 17:27:09 $ * @since 2005-05-07 * @author * Raif S. Naffah * @author * Paulo S. L. M. Barreto * (pbarreto@cryptix.org) * @author * Jeroen C. van Gelderen * (gelderen@cryptix.org) * @author * David R. Tribble * (david@tribble.com). * ** Copyright ©1995-2000 The Cryptix Foundation Limited. All rights reserved. * *
* Use, modification, copying and distribution of this software is subject * the terms and conditions of the Cryptix General Licence. You should have * received a copy of the Cryptix General Licence along with this library; * if not, you can download a copy from * <http://www.cryptix.org/>. *
* * THIS CODE MAY BE SUBJECT TO U.S. EXPORT RESTRICTIONS, AND SHOULD NOT BE * EXPORTED OUTSIDE THE BORDERS OF THE UNITED STATES OF AMERICA. * */ public final class AESCipher extends tribble.crypto.SymmetricCipher { // Identification /** Revision information. */ static final String REV = "@(#)tribble/crypto/AESCipher.java $Revision: 1.2 $ $Date: 2005/07/24 17:27:09 $\n"; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Private constants /** Algorithm name. */ private static final String ALGORITHM = "AES"; /** Block size, in bytes. */ private static final int BLOCK_SIZE = 128/8; private static final String SS = "\u637C\u777B\uF26B\u6FC5\u3001\u672B\uFED7\uAB76" + "\uCA82\uC97D\uFA59\u47F0\uADD4\uA2AF\u9CA4\u72C0" + "\uB7FD\u9326\u363F\uF7CC\u34A5\uE5F1\u71D8\u3115" + "\u04C7\u23C3\u1896\u059A\u0712\u80E2\uEB27\uB275" + "\u0983\u2C1A\u1B6E\u5AA0\u523B\uD6B3\u29E3\u2F84" + "\u53D1\u00ED\u20FC\uB15B\u6ACB\uBE39\u4A4C\u58CF" + "\uD0EF\uAAFB\u434D\u3385\u45F9\u027F\u503C\u9FA8" + "\u51A3\u408F\u929D\u38F5\uBCB6\uDA21\u10FF\uF3D2" + "\uCD0C\u13EC\u5F97\u4417\uC4A7\u7E3D\u645D\u1973" + "\u6081\u4FDC\u222A\u9088\u46EE\uB814\uDE5E\u0BDB" + "\uE032\u3A0A\u4906\u245C\uC2D3\uAC62\u9195\uE479" + "\uE7C8\u376D\u8DD5\u4EA9\u6C56\uF4EA\u657A\uAE08" + "\uBA78\u252E\u1CA6\uB4C6\uE8DD\u741F\u4BBD\u8B8A" + "\u703E\uB566\u4803\uF60E\u6135\u57B9\u86C1\u1D9E" + "\uE1F8\u9811\u69D9\u8E94\u9B1E\u87E9\uCE55\u28DF" + "\u8CA1\u890D\uBFE6\u4268\u4199\u2D0F\uB054\uBB16"; private static final byte[] S = new byte[256]; private static final byte[] Si = new byte[256]; private static final int[] T1 = new int[256]; private static final int[] T2 = new int[256]; private static final int[] T3 = new int[256]; private static final int[] T4 = new int[256]; private static final int[] T5 = new int[256]; private static final int[] T6 = new int[256]; private static final int[] T7 = new int[256]; private static final int[] T8 = new int[256]; private static final int[] U1 = new int[256]; private static final int[] U2 = new int[256]; private static final int[] U3 = new int[256]; private static final int[] U4 = new int[256]; private static final byte[] rcon = new byte[30]; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Static class initializers static { int ROOT = 0x11B; int r; // Intialize the S-boxes and T-boxes for (int i = 0; i < 256; i++) { int s, s2, s3, i2, i4, i8, i9, ib, id, ie, t; char c; c = SS.charAt(i >>> 1); S[i] = (byte) (((i & 1) == 0) ? c >>> 8 : c & 0xFF); s = S[i] & 0xFF; Si[s] = (byte) i; s2 = s << 1; if (s2 >= 0x100) s2 ^= ROOT; s3 = s2 ^ s; i2 = i << 1; if (i2 >= 0x100) i2 ^= ROOT; i4 = i2 << 1; if (i4 >= 0x100) i4 ^= ROOT; i8 = i4 << 1; if (i8 >= 0x100) i8 ^= ROOT; i9 = i8 ^ i; ib = i9 ^ i2; id = i9 ^ i4; ie = i8 ^ i4 ^ i2; T1[i] = t = (s2 << 24) | (s << 16) | (s << 8) | s3; T2[i] = (t >>> 8) | (t << 24); T3[i] = (t >>> 16) | (t << 16); T4[i] = (t >>> 24) | (t << 8); T5[s] = U1[i] = t = (ie << 24) | (i9 << 16) | (id << 8) | ib; T6[s] = U2[i] = (t >>> 8) | (t << 24); T7[s] = U3[i] = (t >>> 16) | (t << 16); T8[s] = U4[i] = (t >>> 24) | (t << 8); } // Round constants r = 1; rcon[0] = 1; for (int i = 1; i < 30; i++) { r <<= 1; if (r >= 0x100) r ^= ROOT; rcon[i] = (byte) r; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Public static methods /*************************************************************************** * Test driver. * *
* Usage * * java tribble.crypto.AESCipher [args...] * * * * @param args * Command line arguments. * * @throws Exception * Thrown if an error occurs in the encryption engine. * * @since 1.1, 2005-07-05 */ public static final void main(String[] args) throws Exception { // Test this cipher test(new AESCipher(), args); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Private static methods /*************************************************************************** * Expand a user-supplied key material into a session key. * * @param key * The encryption key, which must be 128, 192, or 256 bits long. * * @param decrypt * If true, this indicates that this cipher is to be initialized for * decrypting, otherwise it is to be initialized for encrypting. * * @return * The encryption key schedule computed from key. * * @throws InvalidKeyException * If the key is invalid. * * @since 1.1, 2002-04-26 */ private static int[] makeKey(byte[] key, boolean decrypt) throws InvalidKeyException { int ROUNDS; int ROUND_KEY_COUNT; int[] K; int KC; int[] tk; int t; int tt; int rconpointer; ROUNDS = getRounds(key.length); ROUND_KEY_COUNT = (ROUNDS + 1) * 4; K = new int[ROUND_KEY_COUNT]; KC = key.length/4; // Keylen in 32-bit elements tk = new int[KC]; // Copy user material bytes into temporary ints for (int i = 0, j = 0; i < KC; ) { tk[i++] = (key[j++] ) << 24 | (key[j++] & 0xFF) << 16 | (key[j++] & 0xFF) << 8 | (key[j++] & 0xFF); } // Copy values into round key arrays for (t = 0; t < KC; t++) K[t] = tk[t]; rconpointer = 0; while (t < ROUND_KEY_COUNT) { // Extrapolate using phi (the round key evolution function) tt = tk[KC - 1]; tk[0] ^= (S[(tt >>> 16) & 0xFF] ) << 24 ^ (S[(tt >>> 8) & 0xFF] & 0xFF) << 16 ^ (S[(tt ) & 0xFF] & 0xFF) << 8 ^ (S[(tt >>> 24) ] & 0xFF) ^ (rcon[rconpointer++] ) << 24; if (KC != 8) { for (int i = 1, j = 0; i < KC; ) tk[i++] ^= tk[j++]; } else { for (int i = 1, j = 0; i < KC/2; ) tk[i++] ^= tk[j++]; tt = tk[KC / 2 - 1]; tk[KC / 2] ^= (S[(tt ) & 0xFF] & 0xFF) ^ (S[(tt >>> 8) & 0xFF] & 0xFF) << 8 ^ (S[(tt >>> 16) & 0xFF] & 0xFF) << 16 ^ (S[(tt >>> 24) ] ) << 24; for (int j = KC/2, i = j + 1; i < KC; ) tk[i++] ^= tk[j++]; } // Copy values into round key arrays for (int j = 0; j < KC && t < ROUND_KEY_COUNT; j++, t++) K[t] = tk[j]; } // Wipe sensitive info for (int j = 0; j < KC; j++) tk[j] = 0; return (K); } /*************************************************************************** * Compute the inverse (decryption) key schedule. * * @param K * Encryption key to be inverted into a decryption key. * * @since 1.1, 2002-04-26 */ private static void invertKey(int[] K) { int j0; int j1; int j2; int j3; for (int i = 0; i < K.length/2-4; i += 4) { int jj0; int jj1; int jj2; int jj3; jj0 = K[i+0]; jj1 = K[i+1]; jj2 = K[i+2]; jj3 = K[i+3]; K[i+0] = K[K.length-i-4+0]; K[i+1] = K[K.length-i-4+1]; K[i+2] = K[K.length-i-4+2]; K[i+3] = K[K.length-i-4+3]; K[K.length-i-4+0] = jj0; K[K.length-i-4+1] = jj1; K[K.length-i-4+2] = jj2; K[K.length-i-4+3] = jj3; } for (int r = 4; r < K.length-4; r++) { int tt; tt = K[r]; K[r] = U1[(tt >>> 24) & 0xFF] ^ U2[(tt >>> 16) & 0xFF] ^ U3[(tt >>> 8) & 0xFF] ^ U4[ tt & 0xFF]; } j0 = K[K.length-4]; j1 = K[K.length-3]; j2 = K[K.length-2]; j3 = K[K.length-1]; for (int i = K.length-1; i > 3; i--) K[i] = K[i-4]; K[0] = j0; K[1] = j1; K[2] = j2; K[3] = j3; } /*************************************************************************** * Determine the number of rounds for a given keysize. * * @param keySize * The size of the user key material in bytes. * MUST be one of (16, 24, 32). * * @return * The number of rounds. * * @since 1.1, 2002-04-26 */ private static int getRounds(int keySize) { return (keySize >> 2) + 6; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Private variables /** Subkeys. */ private int[] m_K; /** (ROUNDS-1)*4. */ private int m_limit; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Public constructors /*************************************************************************** * Default constructor. * * @since 1.1, 2005-07-05 */ public AESCipher() { // Initialize super(ALGORITHM, BLOCK_SIZE); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Public methods /*************************************************************************** * Retrieve the key sizes supported by this cipher. * * @return * An array of key sizes (in bytes) used by this cipher algorithm. * * @since 1.2, 2005-07-24 */ public int[] getKeySizes() /*const*/ //overrides tribble.crypto.SymmetricCipher { int[] sizes; // AES supports three key sizes sizes = new int[3]; sizes[0] = 128/8; sizes[1] = 192/8; sizes[2] = 256/8; return (sizes); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Protected methods /*************************************************************************** * Initialize this cipher. * * @param key * The symmetric (secret) encryption key for this cipher. * * @param decrypt * If true, this indicates that this cipher is to be initialized for * decrypting, otherwise it is to be initialized for encrypting. * * @since 1.1, 2002-04-26 */ protected void initialize(byte[] key, boolean decrypt) throws InvalidKeyException //overrides tribble.crypto.SymmetricCipher { int len; if (key == null) throw new InvalidKeyException("Key missing"); // Initialize len = key.length; if (len != 128/8 && len != 192/8 && len != 256/8) throw new InvalidKeyException("Invalid key length"); this.m_keyLen = len; this.m_decrypt = decrypt; this.m_K = makeKey(key, decrypt); if (decrypt) invertKey(this.m_K); this.m_limit = getRounds(len)*4; this.m_init = true; } /*************************************************************************** * Reset this cipher, wiping all sensitive information. * *
* This method will be called after this cipher object is no longer needed. * It should overwrite any sensitive data contained within this object * (e.g., encryption key schedules). * This cipher object can no longer be used after this method has been * called. * * @see #initialize initialize() * * @since 1.1, 2005-07-05 */ protected void clear() //overrides tribble.crypto.SymmetricCipher { // Wipe the key info if (m_K != null) { for (int i = 0; i < m_K.length; i++) m_K[i] = 0; m_K = null; } } /*************************************************************************** * Encrypt a block of plaintext. * * @param in * Array containing a single block of plaintext bytes to encrypt. * The length of the block is exactly equal to the cipher block size. * * @param inOff * Index of the first byte of the plaintext block within array in to * encrypt. * * @param out * Array that will be filled with the encrypted ciphertext block. * The length of the block is exactly equal to the cipher block size. * * @param outOff * Index of the first byte of array out to fill with the encrypted * ciphertext block. * * @since 1.1, 2002-04-26 * * @see #blockDecrypt */ protected void blockEncrypt(/*const*/ byte[] in, int inOff, byte[] out, int outOff) //overrides tribble.crypto.SymmetricCipher { int keyOff; int t0, t1, t2, t3; int tt; // Plaintext to ints + key keyOff = 0; t0 = ((in[inOff++] ) << 24 | (in[inOff++] & 0xFF) << 16 | (in[inOff++] & 0xFF) << 8 | (in[inOff++] & 0xFF) ) ^ m_K[keyOff++]; t1 = ((in[inOff++] ) << 24 | (in[inOff++] & 0xFF) << 16 | (in[inOff++] & 0xFF) << 8 | (in[inOff++] & 0xFF) ) ^ m_K[keyOff++]; t2 = ((in[inOff++] ) << 24 | (in[inOff++] & 0xFF) << 16 | (in[inOff++] & 0xFF) << 8 | (in[inOff++] & 0xFF) ) ^ m_K[keyOff++]; t3 = ((in[inOff++] ) << 24 | (in[inOff++] & 0xFF) << 16 | (in[inOff++] & 0xFF) << 8 | (in[inOff++] & 0xFF) ) ^ m_K[keyOff++]; // Apply round transforms while (keyOff < m_limit) { int a0, a1, a2; a0 = T1[(t0 >>> 24) ] ^ T2[(t1 >>> 16) & 0xFF] ^ T3[(t2 >>> 8) & 0xFF] ^ T4[(t3 ) & 0xFF] ^ m_K[keyOff++]; a1 = T1[(t1 >>> 24) ] ^ T2[(t2 >>> 16) & 0xFF] ^ T3[(t3 >>> 8) & 0xFF] ^ T4[(t0 ) & 0xFF] ^ m_K[keyOff++]; a2 = T1[(t2 >>> 24) ] ^ T2[(t3 >>> 16) & 0xFF] ^ T3[(t0 >>> 8) & 0xFF] ^ T4[(t1 ) & 0xFF] ^ m_K[keyOff++]; t3 = T1[(t3 >>> 24) ] ^ T2[(t0 >>> 16) & 0xFF] ^ T3[(t1 >>> 8) & 0xFF] ^ T4[(t2 ) & 0xFF] ^ m_K[keyOff++]; t0 = a0; t1 = a1; t2 = a2; } // Last round is special tt = m_K[keyOff++]; out[outOff++] = (byte) (S[(t0 >>> 24) ] ^ (tt >>> 24)); out[outOff++] = (byte) (S[(t1 >>> 16) & 0xFF] ^ (tt >>> 16)); out[outOff++] = (byte) (S[(t2 >>> 8) & 0xFF] ^ (tt >>> 8)); out[outOff++] = (byte) (S[(t3 ) & 0xFF] ^ (tt )); tt = m_K[keyOff++]; out[outOff++] = (byte) (S[(t1 >>> 24) ] ^ (tt >>> 24)); out[outOff++] = (byte) (S[(t2 >>> 16) & 0xFF] ^ (tt >>> 16)); out[outOff++] = (byte) (S[(t3 >>> 8) & 0xFF] ^ (tt >>> 8)); out[outOff++] = (byte) (S[(t0 ) & 0xFF] ^ (tt )); tt = m_K[keyOff++]; out[outOff++] = (byte) (S[(t2 >>> 24) ] ^ (tt >>> 24)); out[outOff++] = (byte) (S[(t3 >>> 16) & 0xFF] ^ (tt >>> 16)); out[outOff++] = (byte) (S[(t0 >>> 8) & 0xFF] ^ (tt >>> 8)); out[outOff++] = (byte) (S[(t1 ) & 0xFF] ^ (tt )); tt = m_K[keyOff++]; out[outOff++] = (byte) (S[(t3 >>> 24) ] ^ (tt >>> 24)); out[outOff++] = (byte) (S[(t0 >>> 16) & 0xFF] ^ (tt >>> 16)); out[outOff++] = (byte) (S[(t1 >>> 8) & 0xFF] ^ (tt >>> 8)); out[outOff] = (byte) (S[(t2 ) & 0xFF] ^ (tt )); } /*************************************************************************** * Decrypt a block of ciphertext. * * @param in * Array containing a single block of ciphertext bytes to decrypt. * The length of the block is exactly equal to the cipher block size. * * @param inOff * Index of the first byte of the ciphertext block within array in * to decrypt. * * @param out * Array that will be filled with the decrypted plaintext block. * The length of the block is exactly equal to the cipher block size. * * @param outOff * Index of the first byte of array out to fill with the decrypted * plaintext block. * * @since 1.1, 2002-04-26 * * @see #blockEncrypt */ protected void blockDecrypt(/*const*/ byte[] in, int inOff, byte[] out, int outOff) //overrides tribble.crypto.SymmetricCipher { int keyOff; int t0, t1, t2, t3, a0, a1, a2; keyOff = 8; t0 = ((in[inOff++] ) << 24 | (in[inOff++] & 0xFF) << 16 | (in[inOff++] & 0xFF) << 8 | (in[inOff++] & 0xFF) ) ^ m_K[4]; t1 = ((in[inOff++] ) << 24 | (in[inOff++] & 0xFF) << 16 | (in[inOff++] & 0xFF) << 8 | (in[inOff++] & 0xFF) ) ^ m_K[5]; t2 = ((in[inOff++] ) << 24 | (in[inOff++] & 0xFF) << 16 | (in[inOff++] & 0xFF) << 8 | (in[inOff++] & 0xFF) ) ^ m_K[6]; t3 = ((in[inOff++] ) << 24 | (in[inOff++] & 0xFF) << 16 | (in[inOff++] & 0xFF) << 8 | (in[inOff] & 0xFF) ) ^ m_K[7]; if (m_keyLen >= 24) { a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ m_K[keyOff++]; a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ m_K[keyOff++]; a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ m_K[keyOff++]; t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ m_K[keyOff++]; t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ m_K[keyOff++]; t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ m_K[keyOff++]; t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ m_K[keyOff++]; t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ m_K[keyOff++]; if (m_keyLen == 32) { a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ m_K[keyOff++]; a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ m_K[keyOff++]; a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ m_K[keyOff++]; t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ m_K[keyOff++]; t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ m_K[keyOff++]; t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ m_K[keyOff++]; t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ m_K[keyOff++]; t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ m_K[keyOff++]; } } a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ m_K[keyOff++]; a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ m_K[keyOff++]; a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ m_K[keyOff++]; t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ m_K[keyOff++]; t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ m_K[keyOff++]; t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ m_K[keyOff++]; t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ m_K[keyOff++]; t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ m_K[keyOff++]; a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ m_K[keyOff++]; a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ m_K[keyOff++]; a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ m_K[keyOff++]; t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ m_K[keyOff++]; t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ m_K[keyOff++]; t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ m_K[keyOff++]; t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ m_K[keyOff++]; t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ m_K[keyOff++]; a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ m_K[keyOff++]; a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ m_K[keyOff++]; a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ m_K[keyOff++]; t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ m_K[keyOff++]; t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ m_K[keyOff++]; t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ m_K[keyOff++]; t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ m_K[keyOff++]; t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ m_K[keyOff++]; a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ m_K[keyOff++]; a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ m_K[keyOff++]; a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ m_K[keyOff++]; t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ m_K[keyOff++]; t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ m_K[keyOff++]; t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ m_K[keyOff++]; t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ m_K[keyOff++]; t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ m_K[keyOff++]; a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ m_K[keyOff++]; a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ m_K[keyOff++]; a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ m_K[keyOff++]; t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ m_K[keyOff++]; t1 = m_K[0]; out[outOff++] = (byte) (Si[(a0 >>> 24) ] ^ (t1 >>> 24)); out[outOff++] = (byte) (Si[(t3 >>> 16) & 0xFF] ^ (t1 >>> 16)); out[outOff++] = (byte) (Si[(a2 >>> 8) & 0xFF] ^ (t1 >>> 8)); out[outOff++] = (byte) (Si[(a1 ) & 0xFF] ^ (t1 )); t1 = m_K[1]; out[outOff++] = (byte) (Si[(a1 >>> 24) ] ^ (t1 >>> 24)); out[outOff++] = (byte) (Si[(a0 >>> 16) & 0xFF] ^ (t1 >>> 16)); out[outOff++] = (byte) (Si[(t3 >>> 8) & 0xFF] ^ (t1 >>> 8)); out[outOff++] = (byte) (Si[(a2 ) & 0xFF] ^ (t1 )); t1 = m_K[2]; out[outOff++] = (byte) (Si[(a2 >>> 24) ] ^ (t1 >>> 24)); out[outOff++] = (byte) (Si[(a1 >>> 16) & 0xFF] ^ (t1 >>> 16)); out[outOff++] = (byte) (Si[(a0 >>> 8) & 0xFF] ^ (t1 >>> 8)); out[outOff++] = (byte) (Si[(t3 ) & 0xFF] ^ (t1 )); t1 = m_K[3]; out[outOff++] = (byte) (Si[(t3 >>> 24) ] ^ (t1 >>> 24)); out[outOff++] = (byte) (Si[(a2 >>> 16) & 0xFF] ^ (t1 >>> 16)); out[outOff++] = (byte) (Si[(a1 >>> 8) & 0xFF] ^ (t1 >>> 8)); out[outOff] = (byte) (Si[(a0 ) & 0xFF] ^ (t1 )); } } // End AESCipher.java