private static void rijndaelDecrypt( byte[] in, int inOffset, byte[] out, int outOffset, Object sessionKey, int bs) { Object[] sKey = (Object[]) sessionKey; // extract decryption round keys int[][] Kd = (int[][]) sKey[1]; int BC = bs / 4; int ROUNDS = Kd.length - 1; int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2); int s1 = shifts[SC][1][1]; int s2 = shifts[SC][2][1]; int s3 = shifts[SC][3][1]; int[] a = new int[BC]; int[] t = new int[BC]; // temporary work array int i, tt; for (i = 0; i < BC; i++) // ciphertext to ints + key t[i] = (in[inOffset++] << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF)) ^ Kd[0][i]; for (int r = 1; r < ROUNDS; r++) // apply round transforms { for (i = 0; i < BC; i++) a[i] = (T5[(t[i] >>> 24)] ^ T6[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ T7[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ T8[t[(i + s3) % BC] & 0xFF]) ^ Kd[r][i]; System.arraycopy(a, 0, t, 0, BC); if (Configuration.DEBUG) log.fine("PT" + r + "=" + Util.toString(t)); } for (i = 0; i < BC; i++) // last round is special { tt = Kd[ROUNDS][i]; out[outOffset++] = (byte) (Si[(t[i] >>> 24)] ^ (tt >>> 24)); out[outOffset++] = (byte) (Si[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ (tt >>> 16)); out[outOffset++] = (byte) (Si[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ (tt >>> 8)); out[outOffset++] = (byte) (Si[t[(i + s3) % BC] & 0xFF] ^ tt); } if (Configuration.DEBUG) log.fine("PT=" + Util.toString(out, outOffset - bs, bs)); }
private static void aesDecrypt(byte[] in, int i, byte[] out, int j, Object key) { int[][] Kd = (int[][]) ((Object[]) key)[1]; // extract decryption round keys int ROUNDS = Kd.length - 1; int[] Kdr = Kd[0]; // ciphertext to ints + key int t0 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF)) ^ Kdr[0]; int t1 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF)) ^ Kdr[1]; int t2 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF)) ^ Kdr[2]; int t3 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF)) ^ Kdr[3]; int a0, a1, a2, a3; for (int r = 1; r < ROUNDS; r++) // apply round transforms { Kdr = Kd[r]; a0 = (T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(t2 >>> 8) & 0xFF] ^ T8[t1 & 0xFF]) ^ Kdr[0]; a1 = (T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[t2 & 0xFF]) ^ Kdr[1]; a2 = (T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF] ^ T7[(t0 >>> 8) & 0xFF] ^ T8[t3 & 0xFF]) ^ Kdr[2]; a3 = (T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF] ^ T7[(t1 >>> 8) & 0xFF] ^ T8[t0 & 0xFF]) ^ Kdr[3]; t0 = a0; t1 = a1; t2 = a2; t3 = a3; if (Configuration.DEBUG) log.fine( "PT" + r + "=" + Util.toString(t0) + Util.toString(t1) + Util.toString(t2) + Util.toString(t3)); } // last round is special Kdr = Kd[ROUNDS]; int tt = Kdr[0]; out[j++] = (byte) (Si[(t0 >>> 24)] ^ (tt >>> 24)); out[j++] = (byte) (Si[(t3 >>> 16) & 0xFF] ^ (tt >>> 16)); out[j++] = (byte) (Si[(t2 >>> 8) & 0xFF] ^ (tt >>> 8)); out[j++] = (byte) (Si[t1 & 0xFF] ^ tt); tt = Kdr[1]; out[j++] = (byte) (Si[(t1 >>> 24)] ^ (tt >>> 24)); out[j++] = (byte) (Si[(t0 >>> 16) & 0xFF] ^ (tt >>> 16)); out[j++] = (byte) (Si[(t3 >>> 8) & 0xFF] ^ (tt >>> 8)); out[j++] = (byte) (Si[t2 & 0xFF] ^ tt); tt = Kdr[2]; out[j++] = (byte) (Si[(t2 >>> 24)] ^ (tt >>> 24)); out[j++] = (byte) (Si[(t1 >>> 16) & 0xFF] ^ (tt >>> 16)); out[j++] = (byte) (Si[(t0 >>> 8) & 0xFF] ^ (tt >>> 8)); out[j++] = (byte) (Si[t3 & 0xFF] ^ tt); tt = Kdr[3]; out[j++] = (byte) (Si[(t3 >>> 24)] ^ (tt >>> 24)); out[j++] = (byte) (Si[(t2 >>> 16) & 0xFF] ^ (tt >>> 16)); out[j++] = (byte) (Si[(t1 >>> 8) & 0xFF] ^ (tt >>> 8)); out[j++] = (byte) (Si[t0 & 0xFF] ^ tt); if (Configuration.DEBUG) log.fine("PT=" + Util.toString(out, j - 16, 16)); }
static { long time = System.currentTimeMillis(); int ROOT = 0x11B; int i, j = 0; // S-box, inverse S-box, T-boxes, U-boxes int s, s2, s3, i2, i4, i8, i9, ib, id, ie, t; char c; for (i = 0; i < 256; i++) { 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 int r = 1; rcon[0] = 1; for (i = 1; i < 30; i++) { r <<= 1; if (r >= 0x100) r ^= ROOT; rcon[i] = (byte) r; } time = System.currentTimeMillis() - time; if (Configuration.DEBUG) { log.fine("Static Data"); log.fine("S[]:"); StringBuilder sb; for (i = 0; i < 16; i++) { sb = new StringBuilder(); for (j = 0; j < 16; j++) sb.append("0x").append(Util.toString(S[i * 16 + j])).append(", "); log.fine(sb.toString()); } log.fine("Si[]:"); for (i = 0; i < 16; i++) { sb = new StringBuilder(); for (j = 0; j < 16; j++) sb.append("0x").append(Util.toString(Si[i * 16 + j])).append(", "); log.fine(sb.toString()); } log.fine("T1[]:"); for (i = 0; i < 64; i++) { sb = new StringBuilder(); for (j = 0; j < 4; j++) sb.append("0x").append(Util.toString(T1[i * 4 + j])).append(", "); log.fine(sb.toString()); } log.fine("T2[]:"); for (i = 0; i < 64; i++) { sb = new StringBuilder(); for (j = 0; j < 4; j++) sb.append("0x").append(Util.toString(T2[i * 4 + j])).append(", "); log.fine(sb.toString()); } log.fine("T3[]:"); for (i = 0; i < 64; i++) { sb = new StringBuilder(); for (j = 0; j < 4; j++) sb.append("0x").append(Util.toString(T3[i * 4 + j])).append(", "); log.fine(sb.toString()); } log.fine("T4[]:"); for (i = 0; i < 64; i++) { sb = new StringBuilder(); for (j = 0; j < 4; j++) sb.append("0x").append(Util.toString(T4[i * 4 + j])).append(", "); log.fine(sb.toString()); } log.fine("T5[]:"); for (i = 0; i < 64; i++) { sb = new StringBuilder(); for (j = 0; j < 4; j++) sb.append("0x").append(Util.toString(T5[i * 4 + j])).append(", "); log.fine(sb.toString()); } log.fine("T6[]:"); for (i = 0; i < 64; i++) { sb = new StringBuilder(); for (j = 0; j < 4; j++) sb.append("0x").append(Util.toString(T6[i * 4 + j])).append(", "); log.fine(sb.toString()); } log.fine("T7[]:"); for (i = 0; i < 64; i++) { sb = new StringBuilder(); for (j = 0; j < 4; j++) sb.append("0x").append(Util.toString(T7[i * 4 + j])).append(", "); log.fine(sb.toString()); } log.fine("T8[]:"); for (i = 0; i < 64; i++) { sb = new StringBuilder(); for (j = 0; j < 4; j++) sb.append("0x").append(Util.toString(T8[i * 4 + j])).append(", "); log.fine(sb.toString()); } log.fine("U1[]:"); for (i = 0; i < 64; i++) { sb = new StringBuilder(); for (j = 0; j < 4; j++) sb.append("0x").append(Util.toString(U1[i * 4 + j])).append(", "); log.fine(sb.toString()); } log.fine("U2[]:"); for (i = 0; i < 64; i++) { sb = new StringBuilder(); for (j = 0; j < 4; j++) sb.append("0x").append(Util.toString(U2[i * 4 + j])).append(", "); log.fine(sb.toString()); } log.fine("U3[]:"); for (i = 0; i < 64; i++) { sb = new StringBuilder(); for (j = 0; j < 4; j++) sb.append("0x").append(Util.toString(U3[i * 4 + j])).append(", "); log.fine(sb.toString()); } log.fine("U4[]:"); for (i = 0; i < 64; i++) { sb = new StringBuilder(); for (j = 0; j < 4; j++) sb.append("0x").append(Util.toString(U4[i * 4 + j])).append(", "); log.fine(sb.toString()); } log.fine("rcon[]:"); for (i = 0; i < 5; i++) { sb = new StringBuilder(); for (j = 0; j < 6; j++) sb.append("0x").append(Util.toString(rcon[i * 6 + j])).append(", "); log.fine(sb.toString()); } log.fine("Total initialization time: " + time + " ms."); } }