1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44:
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50:
51:
64: public final class Rijndael
65: extends BaseCipher
66: {
67: private static final Logger log = Configuration.DEBUG ?
68: Logger.getLogger(Rijndael.class.getName()) : null;
69: private static final int DEFAULT_BLOCK_SIZE = 16;
70: private static final int DEFAULT_KEY_SIZE = 16;
71: private static final String SS =
72: "\u637C\u777B\uF26B\u6FC5\u3001\u672B\uFED7\uAB76"
73: + "\uCA82\uC97D\uFA59\u47F0\uADD4\uA2AF\u9CA4\u72C0"
74: + "\uB7FD\u9326\u363F\uF7CC\u34A5\uE5F1\u71D8\u3115"
75: + "\u04C7\u23C3\u1896\u059A\u0712\u80E2\uEB27\uB275"
76: + "\u0983\u2C1A\u1B6E\u5AA0\u523B\uD6B3\u29E3\u2F84"
77: + "\u53D1\u00ED\u20FC\uB15B\u6ACB\uBE39\u4A4C\u58CF"
78: + "\uD0EF\uAAFB\u434D\u3385\u45F9\u027F\u503C\u9FA8"
79: + "\u51A3\u408F\u929D\u38F5\uBCB6\uDA21\u10FF\uF3D2"
80: + "\uCD0C\u13EC\u5F97\u4417\uC4A7\u7E3D\u645D\u1973"
81: + "\u6081\u4FDC\u222A\u9088\u46EE\uB814\uDE5E\u0BDB"
82: + "\uE032\u3A0A\u4906\u245C\uC2D3\uAC62\u9195\uE479"
83: + "\uE7C8\u376D\u8DD5\u4EA9\u6C56\uF4EA\u657A\uAE08"
84: + "\uBA78\u252E\u1CA6\uB4C6\uE8DD\u741F\u4BBD\u8B8A"
85: + "\u703E\uB566\u4803\uF60E\u6135\u57B9\u86C1\u1D9E"
86: + "\uE1F8\u9811\u69D9\u8E94\u9B1E\u87E9\uCE55\u28DF"
87: + "\u8CA1\u890D\uBFE6\u4268\u4199\u2D0F\uB054\uBB16";
88: private static final byte[] S = new byte[256];
89: private static final byte[] Si = new byte[256];
90: private static final int[] T1 = new int[256];
91: private static final int[] T2 = new int[256];
92: private static final int[] T3 = new int[256];
93: private static final int[] T4 = new int[256];
94: private static final int[] T5 = new int[256];
95: private static final int[] T6 = new int[256];
96: private static final int[] T7 = new int[256];
97: private static final int[] T8 = new int[256];
98: private static final int[] U1 = new int[256];
99: private static final int[] U2 = new int[256];
100: private static final int[] U3 = new int[256];
101: private static final int[] U4 = new int[256];
102: private static final byte[] rcon = new byte[30];
103: private static final int[][][] shifts = new int[][][] {
104: { { 0, 0 }, { 1, 3 }, { 2, 2 }, { 3, 1 } },
105: { { 0, 0 }, { 1, 5 }, { 2, 4 }, { 3, 3 } },
106: { { 0, 0 }, { 1, 7 }, { 3, 5 }, { 4, 4 } } };
107:
112: private static final byte[] KAT_KEY = Util.toBytesFromString(
113: "0000000000000000000000010000000000000000000000000000000000000000");
114: private static final byte[] KAT_CT = Util.toBytesFromString(
115: "E44429474D6FC3084EB2A6B8B46AF754");
116:
117: private static Boolean valid;
118:
119: static
120: {
121: long time = System.currentTimeMillis();
122: int ROOT = 0x11B;
123: int i, j = 0;
124:
125: int s, s2, s3, i2, i4, i8, i9, ib, id, ie, t;
126: char c;
127: for (i = 0; i < 256; i++)
128: {
129: c = SS.charAt(i >>> 1);
130: S[i] = (byte)(((i & 1) == 0) ? c >>> 8 : c & 0xFF);
131: s = S[i] & 0xFF;
132: Si[s] = (byte) i;
133: s2 = s << 1;
134: if (s2 >= 0x100)
135: s2 ^= ROOT;
136: s3 = s2 ^ s;
137: i2 = i << 1;
138: if (i2 >= 0x100)
139: i2 ^= ROOT;
140: i4 = i2 << 1;
141: if (i4 >= 0x100)
142: i4 ^= ROOT;
143: i8 = i4 << 1;
144: if (i8 >= 0x100)
145: i8 ^= ROOT;
146: i9 = i8 ^ i;
147: ib = i9 ^ i2;
148: id = i9 ^ i4;
149: ie = i8 ^ i4 ^ i2;
150: T1[i] = t = (s2 << 24) | (s << 16) | (s << 8) | s3;
151: T2[i] = (t >>> 8) | (t << 24);
152: T3[i] = (t >>> 16) | (t << 16);
153: T4[i] = (t >>> 24) | (t << 8);
154: T5[s] = U1[i] = t = (ie << 24) | (i9 << 16) | (id << 8) | ib;
155: T6[s] = U2[i] = (t >>> 8) | (t << 24);
156: T7[s] = U3[i] = (t >>> 16) | (t << 16);
157: T8[s] = U4[i] = (t >>> 24) | (t << 8);
158: }
159:
160: int r = 1;
161: rcon[0] = 1;
162: for (i = 1; i < 30; i++)
163: {
164: r <<= 1;
165: if (r >= 0x100)
166: r ^= ROOT;
167: rcon[i] = (byte) r;
168: }
169: time = System.currentTimeMillis() - time;
170: if (Configuration.DEBUG)
171: {
172: log.fine("Static Data");
173: log.fine("S[]:");
174: StringBuilder sb;
175: for (i = 0; i < 16; i++)
176: {
177: sb = new StringBuilder();
178: for (j = 0; j < 16; j++)
179: sb.append("0x").append(Util.toString(S[i * 16 + j])).append(", ");
180: log.fine(sb.toString());
181: }
182: log.fine("Si[]:");
183: for (i = 0; i < 16; i++)
184: {
185: sb = new StringBuilder();
186: for (j = 0; j < 16; j++)
187: sb.append("0x").append(Util.toString(Si[i * 16 + j])).append(", ");
188: log.fine(sb.toString());
189: }
190:
191: log.fine("T1[]:");
192: for (i = 0; i < 64; i++)
193: {
194: sb = new StringBuilder();
195: for (j = 0; j < 4; j++)
196: sb.append("0x").append(Util.toString(T1[i * 4 + j])).append(", ");
197: log.fine(sb.toString());
198: }
199: log.fine("T2[]:");
200: for (i = 0; i < 64; i++)
201: {
202: sb = new StringBuilder();
203: for (j = 0; j < 4; j++)
204: sb.append("0x").append(Util.toString(T2[i * 4 + j])).append(", ");
205: log.fine(sb.toString());
206: }
207: log.fine("T3[]:");
208: for (i = 0; i < 64; i++)
209: {
210: sb = new StringBuilder();
211: for (j = 0; j < 4; j++)
212: sb.append("0x").append(Util.toString(T3[i * 4 + j])).append(", ");
213: log.fine(sb.toString());
214: }
215: log.fine("T4[]:");
216: for (i = 0; i < 64; i++)
217: {
218: sb = new StringBuilder();
219: for (j = 0; j < 4; j++)
220: sb.append("0x").append(Util.toString(T4[i * 4 + j])).append(", ");
221: log.fine(sb.toString());
222: }
223: log.fine("T5[]:");
224: for (i = 0; i < 64; i++)
225: {
226: sb = new StringBuilder();
227: for (j = 0; j < 4; j++)
228: sb.append("0x").append(Util.toString(T5[i * 4 + j])).append(", ");
229: log.fine(sb.toString());
230: }
231: log.fine("T6[]:");
232: for (i = 0; i < 64; i++)
233: {
234: sb = new StringBuilder();
235: for (j = 0; j < 4; j++)
236: sb.append("0x").append(Util.toString(T6[i * 4 + j])).append(", ");
237: log.fine(sb.toString());
238: }
239: log.fine("T7[]:");
240: for (i = 0; i < 64; i++)
241: {
242: sb = new StringBuilder();
243: for (j = 0; j < 4; j++)
244: sb.append("0x").append(Util.toString(T7[i * 4 + j])).append(", ");
245: log.fine(sb.toString());
246: }
247: log.fine("T8[]:");
248: for (i = 0; i < 64; i++)
249: {
250: sb = new StringBuilder();
251: for (j = 0; j < 4; j++)
252: sb.append("0x").append(Util.toString(T8[i * 4 + j])).append(", ");
253: log.fine(sb.toString());
254: }
255:
256: log.fine("U1[]:");
257: for (i = 0; i < 64; i++)
258: {
259: sb = new StringBuilder();
260: for (j = 0; j < 4; j++)
261: sb.append("0x").append(Util.toString(U1[i * 4 + j])).append(", ");
262: log.fine(sb.toString());
263: }
264: log.fine("U2[]:");
265: for (i = 0; i < 64; i++)
266: {
267: sb = new StringBuilder();
268: for (j = 0; j < 4; j++)
269: sb.append("0x").append(Util.toString(U2[i * 4 + j])).append(", ");
270: log.fine(sb.toString());
271: }
272: log.fine("U3[]:");
273: for (i = 0; i < 64; i++)
274: {
275: sb = new StringBuilder();
276: for (j = 0; j < 4; j++)
277: sb.append("0x").append(Util.toString(U3[i * 4 + j])).append(", ");
278: log.fine(sb.toString());
279: }
280: log.fine("U4[]:");
281: for (i = 0; i < 64; i++)
282: {
283: sb = new StringBuilder();
284: for (j = 0; j < 4; j++)
285: sb.append("0x").append(Util.toString(U4[i * 4 + j])).append(", ");
286: log.fine(sb.toString());
287: }
288:
289: log.fine("rcon[]:");
290: for (i = 0; i < 5; i++)
291: {
292: sb = new StringBuilder();
293: for (j = 0; j < 6; j++)
294: sb.append("0x").append(Util.toString(rcon[i * 6 + j])).append(", ");
295: log.fine(sb.toString());
296: }
297: log.fine("Total initialization time: " + time + " ms.");
298: }
299: }
300:
301:
302: public Rijndael()
303: {
304: super(Registry.RIJNDAEL_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE);
305: }
306:
307:
314: public static int getRounds(int ks, int bs)
315: {
316: switch (ks)
317: {
318: case 16:
319: return bs == 16 ? 10 : (bs == 24 ? 12 : 14);
320: case 24:
321: return bs != 32 ? 12 : 14;
322: default:
323: return 14;
324: }
325: }
326:
327: private static void rijndaelEncrypt(byte[] in, int inOffset, byte[] out,
328: int outOffset, Object sessionKey, int bs)
329: {
330: Object[] sKey = (Object[]) sessionKey;
331: int[][] Ke = (int[][]) sKey[0];
332: int BC = bs / 4;
333: int ROUNDS = Ke.length - 1;
334: int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2);
335: int s1 = shifts[SC][1][0];
336: int s2 = shifts[SC][2][0];
337: int s3 = shifts[SC][3][0];
338: int[] a = new int[BC];
339: int[] t = new int[BC];
340: int i, tt;
341: for (i = 0; i < BC; i++)
342: t[i] = (in[inOffset++] << 24
343: | (in[inOffset++] & 0xFF) << 16
344: | (in[inOffset++] & 0xFF) << 8
345: | (in[inOffset++] & 0xFF) ) ^ Ke[0][i];
346: for (int r = 1; r < ROUNDS; r++)
347: {
348: for (i = 0; i < BC; i++)
349: a[i] = (T1[(t[ i ] >>> 24) ]
350: ^ T2[(t[(i + s1) % BC] >>> 16) & 0xFF]
351: ^ T3[(t[(i + s2) % BC] >>> 8) & 0xFF]
352: ^ T4[ t[(i + s3) % BC] & 0xFF]) ^ Ke[r][i];
353: System.arraycopy(a, 0, t, 0, BC);
354: if (Configuration.DEBUG)
355: log.fine("CT" + r + "=" + Util.toString(t));
356: }
357: for (i = 0; i < BC; i++)
358: {
359: tt = Ke[ROUNDS][i];
360: out[outOffset++] = (byte)(S[(t[ i ] >>> 24) ] ^ (tt >>> 24));
361: out[outOffset++] = (byte)(S[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ (tt >>> 16));
362: out[outOffset++] = (byte)(S[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ (tt >>> 8));
363: out[outOffset++] = (byte)(S[ t[(i + s3) % BC] & 0xFF] ^ tt );
364: }
365: if (Configuration.DEBUG)
366: log.fine("CT=" + Util.toString(out, outOffset - bs, bs));
367: }
368:
369: private static void rijndaelDecrypt(byte[] in, int inOffset, byte[] out,
370: int outOffset, Object sessionKey, int bs)
371: {
372: Object[] sKey = (Object[]) sessionKey;
373: int[][] Kd = (int[][]) sKey[1];
374: int BC = bs / 4;
375: int ROUNDS = Kd.length - 1;
376: int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2);
377: int s1 = shifts[SC][1][1];
378: int s2 = shifts[SC][2][1];
379: int s3 = shifts[SC][3][1];
380: int[] a = new int[BC];
381: int[] t = new int[BC];
382: int i, tt;
383: for (i = 0; i < BC; i++)
384: t[i] = (in[inOffset++] << 24
385: | (in[inOffset++] & 0xFF) << 16
386: | (in[inOffset++] & 0xFF) << 8
387: | (in[inOffset++] & 0xFF) ) ^ Kd[0][i];
388: for (int r = 1; r < ROUNDS; r++)
389: {
390: for (i = 0; i < BC; i++)
391: a[i] = (T5[(t[ i ] >>> 24) ]
392: ^ T6[(t[(i + s1) % BC] >>> 16) & 0xFF]
393: ^ T7[(t[(i + s2) % BC] >>> 8) & 0xFF]
394: ^ T8[ t[(i + s3) % BC] & 0xFF]) ^ Kd[r][i];
395: System.arraycopy(a, 0, t, 0, BC);
396: if (Configuration.DEBUG)
397: log.fine("PT" + r + "=" + Util.toString(t));
398: }
399: for (i = 0; i < BC; i++)
400: {
401: tt = Kd[ROUNDS][i];
402: out[outOffset++] = (byte)(Si[(t[ i ] >>> 24) ] ^ (tt >>> 24));
403: out[outOffset++] = (byte)(Si[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ (tt >>> 16));
404: out[outOffset++] = (byte)(Si[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ (tt >>> 8));
405: out[outOffset++] = (byte)(Si[ t[(i + s3) % BC] & 0xFF] ^ tt );
406: }
407: if (Configuration.DEBUG)
408: log.fine("PT=" + Util.toString(out, outOffset - bs, bs));
409: }
410:
411: private static void aesEncrypt(byte[] in, int i, byte[] out, int j, Object key)
412: {
413: int[][] Ke = (int[][])((Object[]) key)[0];
414: int ROUNDS = Ke.length - 1;
415: int[] Ker = Ke[0];
416:
417: int t0 = (in[i++] << 24
418: | (in[i++] & 0xFF) << 16
419: | (in[i++] & 0xFF) << 8
420: | (in[i++] & 0xFF) ) ^ Ker[0];
421: int t1 = (in[i++] << 24
422: | (in[i++] & 0xFF) << 16
423: | (in[i++] & 0xFF) << 8
424: | (in[i++] & 0xFF) ) ^ Ker[1];
425: int t2 = (in[i++] << 24
426: | (in[i++] & 0xFF) << 16
427: | (in[i++] & 0xFF) << 8
428: | (in[i++] & 0xFF) ) ^ Ker[2];
429: int t3 = (in[i++] << 24
430: | (in[i++] & 0xFF) << 16
431: | (in[i++] & 0xFF) << 8
432: | (in[i++] & 0xFF) ) ^ Ker[3];
433: int a0, a1, a2, a3;
434: for (int r = 1; r < ROUNDS; r++)
435: {
436: Ker = Ke[r];
437: a0 = (T1[(t0 >>> 24) ]
438: ^ T2[(t1 >>> 16) & 0xFF]
439: ^ T3[(t2 >>> 8) & 0xFF]
440: ^ T4[ t3 & 0xFF]) ^ Ker[0];
441: a1 = (T1[(t1 >>> 24) ]
442: ^ T2[(t2 >>> 16) & 0xFF]
443: ^ T3[(t3 >>> 8) & 0xFF]
444: ^ T4[ t0 & 0xFF]) ^ Ker[1];
445: a2 = (T1[(t2 >>> 24) ]
446: ^ T2[(t3 >>> 16) & 0xFF]
447: ^ T3[(t0 >>> 8) & 0xFF]
448: ^ T4[ t1 & 0xFF]) ^ Ker[2];
449: a3 = (T1[(t3 >>> 24) ]
450: ^ T2[(t0 >>> 16) & 0xFF]
451: ^ T3[(t1 >>> 8) & 0xFF]
452: ^ T4[ t2 & 0xFF]) ^ Ker[3];
453: t0 = a0;
454: t1 = a1;
455: t2 = a2;
456: t3 = a3;
457: if (Configuration.DEBUG)
458: log.fine("CT" + r + "=" + Util.toString(t0) + Util.toString(t1)
459: + Util.toString(t2) + Util.toString(t3));
460: }
461:
462: Ker = Ke[ROUNDS];
463: int tt = Ker[0];
464: out[j++] = (byte)(S[(t0 >>> 24) ] ^ (tt >>> 24));
465: out[j++] = (byte)(S[(t1 >>> 16) & 0xFF] ^ (tt >>> 16));
466: out[j++] = (byte)(S[(t2 >>> 8) & 0xFF] ^ (tt >>> 8));
467: out[j++] = (byte)(S[ t3 & 0xFF] ^ tt );
468: tt = Ker[1];
469: out[j++] = (byte)(S[(t1 >>> 24) ] ^ (tt >>> 24));
470: out[j++] = (byte)(S[(t2 >>> 16) & 0xFF] ^ (tt >>> 16));
471: out[j++] = (byte)(S[(t3 >>> 8) & 0xFF] ^ (tt >>> 8));
472: out[j++] = (byte)(S[ t0 & 0xFF] ^ tt );
473: tt = Ker[2];
474: out[j++] = (byte)(S[(t2 >>> 24) ] ^ (tt >>> 24));
475: out[j++] = (byte)(S[(t3 >>> 16) & 0xFF] ^ (tt >>> 16));
476: out[j++] = (byte)(S[(t0 >>> 8) & 0xFF] ^ (tt >>> 8));
477: out[j++] = (byte)(S[ t1 & 0xFF] ^ tt );
478: tt = Ker[3];
479: out[j++] = (byte)(S[(t3 >>> 24) ] ^ (tt >>> 24));
480: out[j++] = (byte)(S[(t0 >>> 16) & 0xFF] ^ (tt >>> 16));
481: out[j++] = (byte)(S[(t1 >>> 8) & 0xFF] ^ (tt >>> 8));
482: out[j++] = (byte)(S[ t2 & 0xFF] ^ tt );
483: if (Configuration.DEBUG)
484: log.fine("CT=" + Util.toString(out, j - 16, 16));
485: }
486:
487: private static void aesDecrypt(byte[] in, int i, byte[] out, int j, Object key)
488: {
489: int[][] Kd = (int[][])((Object[]) key)[1];
490: int ROUNDS = Kd.length - 1;
491: int[] Kdr = Kd[0];
492:
493: int t0 = (in[i++] << 24
494: | (in[i++] & 0xFF) << 16
495: | (in[i++] & 0xFF) << 8
496: | (in[i++] & 0xFF) ) ^ Kdr[0];
497: int t1 = (in[i++] << 24
498: | (in[i++] & 0xFF) << 16
499: | (in[i++] & 0xFF) << 8
500: | (in[i++] & 0xFF) ) ^ Kdr[1];
501: int t2 = (in[i++] << 24
502: | (in[i++] & 0xFF) << 16
503: | (in[i++] & 0xFF) << 8
504: | (in[i++] & 0xFF) ) ^ Kdr[2];
505: int t3 = (in[i++] << 24
506: | (in[i++] & 0xFF) << 16
507: | (in[i++] & 0xFF) << 8
508: | (in[i++] & 0xFF) ) ^ Kdr[3];
509:
510: int a0, a1, a2, a3;
511: for (int r = 1; r < ROUNDS; r++)
512: {
513: Kdr = Kd[r];
514: a0 = (T5[(t0 >>> 24) ]
515: ^ T6[(t3 >>> 16) & 0xFF]
516: ^ T7[(t2 >>> 8) & 0xFF]
517: ^ T8[ t1 & 0xFF]) ^ Kdr[0];
518: a1 = (T5[(t1 >>> 24) ]
519: ^ T6[(t0 >>> 16) & 0xFF]
520: ^ T7[(t3 >>> 8) & 0xFF]
521: ^ T8[ t2 & 0xFF]) ^ Kdr[1];
522: a2 = (T5[(t2 >>> 24) ]
523: ^ T6[(t1 >>> 16) & 0xFF]
524: ^ T7[(t0 >>> 8) & 0xFF]
525: ^ T8[ t3 & 0xFF]) ^ Kdr[2];
526: a3 = (T5[(t3 >>> 24) ]
527: ^ T6[(t2 >>> 16) & 0xFF]
528: ^ T7[(t1 >>> 8) & 0xFF]
529: ^ T8[ t0 & 0xFF]) ^ Kdr[3];
530: t0 = a0;
531: t1 = a1;
532: t2 = a2;
533: t3 = a3;
534: if (Configuration.DEBUG)
535: log.fine("PT" + r + "=" + Util.toString(t0) + Util.toString(t1)
536: + Util.toString(t2) + Util.toString(t3));
537: }
538:
539: Kdr = Kd[ROUNDS];
540: int tt = Kdr[0];
541: out[j++] = (byte)(Si[(t0 >>> 24) ] ^ (tt >>> 24));
542: out[j++] = (byte)(Si[(t3 >>> 16) & 0xFF] ^ (tt >>> 16));
543: out[j++] = (byte)(Si[(t2 >>> 8) & 0xFF] ^ (tt >>> 8));
544: out[j++] = (byte)(Si[ t1 & 0xFF] ^ tt );
545: tt = Kdr[1];
546: out[j++] = (byte)(Si[(t1 >>> 24) ] ^ (tt >>> 24));
547: out[j++] = (byte)(Si[(t0 >>> 16) & 0xFF] ^ (tt >>> 16));
548: out[j++] = (byte)(Si[(t3 >>> 8) & 0xFF] ^ (tt >>> 8));
549: out[j++] = (byte)(Si[ t2 & 0xFF] ^ tt );
550: tt = Kdr[2];
551: out[j++] = (byte)(Si[(t2 >>> 24) ] ^ (tt >>> 24));
552: out[j++] = (byte)(Si[(t1 >>> 16) & 0xFF] ^ (tt >>> 16));
553: out[j++] = (byte)(Si[(t0 >>> 8) & 0xFF] ^ (tt >>> 8));
554: out[j++] = (byte)(Si[ t3 & 0xFF] ^ tt );
555: tt = Kdr[3];
556: out[j++] = (byte)(Si[(t3 >>> 24) ] ^ (tt >>> 24));
557: out[j++] = (byte)(Si[(t2 >>> 16) & 0xFF] ^ (tt >>> 16));
558: out[j++] = (byte)(Si[(t1 >>> 8) & 0xFF] ^ (tt >>> 8));
559: out[j++] = (byte)(Si[ t0 & 0xFF] ^ tt );
560: if (Configuration.DEBUG)
561: log.fine("PT=" + Util.toString(out, j - 16, 16));
562: }
563:
564: public Object clone()
565: {
566: Rijndael result = new Rijndael();
567: result.currentBlockSize = this.currentBlockSize;
568:
569: return result;
570: }
571:
572: public Iterator blockSizes()
573: {
574: ArrayList al = new ArrayList();
575: al.add(Integer.valueOf(128 / 8));
576: al.add(Integer.valueOf(192 / 8));
577: al.add(Integer.valueOf(256 / 8));
578:
579: return Collections.unmodifiableList(al).iterator();
580: }
581:
582: public Iterator keySizes()
583: {
584: ArrayList al = new ArrayList();
585: al.add(Integer.valueOf(128 / 8));
586: al.add(Integer.valueOf(192 / 8));
587: al.add(Integer.valueOf(256 / 8));
588:
589: return Collections.unmodifiableList(al).iterator();
590: }
591:
592:
602: public Object makeKey(byte[] k, int bs) throws InvalidKeyException
603: {
604: if (k == null)
605: throw new InvalidKeyException("Empty key");
606: if (! (k.length == 16 || k.length == 24 || k.length == 32))
607: throw new InvalidKeyException("Incorrect key length");
608: if (! (bs == 16 || bs == 24 || bs == 32))
609: throw new IllegalArgumentException();
610: int ROUNDS = getRounds(k.length, bs);
611: int BC = bs / 4;
612: int[][] Ke = new int[ROUNDS + 1][BC];
613: int[][] Kd = new int[ROUNDS + 1][BC];
614: int ROUND_KEY_COUNT = (ROUNDS + 1) * BC;
615: int KC = k.length / 4;
616: int[] tk = new int[KC];
617: int i, j;
618:
619: for (i = 0, j = 0; i < KC;)
620: tk[i++] = k[j++] << 24
621: | (k[j++] & 0xFF) << 16
622: | (k[j++] & 0xFF) << 8
623: | (k[j++] & 0xFF);
624:
625: int t = 0;
626: for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++)
627: {
628: Ke[t / BC][t % BC] = tk[j];
629: Kd[ROUNDS - (t / BC)][t % BC] = tk[j];
630: }
631: int tt, rconpointer = 0;
632: while (t < ROUND_KEY_COUNT)
633: {
634:
635: tt = tk[KC - 1];
636: tk[0] ^= (S[(tt >>> 16) & 0xFF] & 0xFF) << 24
637: ^ (S[(tt >>> 8) & 0xFF] & 0xFF) << 16
638: ^ (S[ tt & 0xFF] & 0xFF) << 8
639: ^ (S[(tt >>> 24) ] & 0xFF) ^ rcon[rconpointer++] << 24;
640: if (KC != 8)
641: for (i = 1, j = 0; i < KC;)
642: tk[i++] ^= tk[j++];
643: else
644: {
645: for (i = 1, j = 0; i < KC / 2;)
646: tk[i++] ^= tk[j++];
647: tt = tk[KC / 2 - 1];
648: tk[KC / 2] ^= (S[ tt & 0xFF] & 0xFF)
649: ^ (S[(tt >>> 8) & 0xFF] & 0xFF) << 8
650: ^ (S[(tt >>> 16) & 0xFF] & 0xFF) << 16
651: ^ S[(tt >>> 24) & 0xFF] << 24;
652: for (j = KC / 2, i = j + 1; i < KC;)
653: tk[i++] ^= tk[j++];
654: }
655:
656: for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++)
657: {
658: Ke[t / BC][t % BC] = tk[j];
659: Kd[ROUNDS - (t / BC)][t % BC] = tk[j];
660: }
661: }
662: for (int r = 1; r < ROUNDS; r++)
663: for (j = 0; j < BC; j++)
664: {
665: tt = Kd[r][j];
666: Kd[r][j] = U1[(tt >>> 24) ]
667: ^ U2[(tt >>> 16) & 0xFF]
668: ^ U3[(tt >>> 8) & 0xFF]
669: ^ U4[ tt & 0xFF];
670: }
671: return new Object[] { Ke, Kd };
672: }
673:
674: public void encrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
675: {
676: if (! (bs == 16 || bs == 24 || bs == 32))
677: throw new IllegalArgumentException();
678: if (bs == DEFAULT_BLOCK_SIZE)
679: aesEncrypt(in, i, out, j, k);
680: else
681: rijndaelEncrypt(in, i, out, j, k, bs);
682: }
683:
684: public void decrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
685: {
686: if (! (bs == 16 || bs == 24 || bs == 32))
687: throw new IllegalArgumentException();
688: if (bs == DEFAULT_BLOCK_SIZE)
689: aesDecrypt(in, i, out, j, k);
690: else
691: rijndaelDecrypt(in, i, out, j, k, bs);
692: }
693:
694: public boolean selfTest()
695: {
696: if (valid == null)
697: {
698: boolean result = super.selfTest();
699: if (result)
700: result = testKat(KAT_KEY, KAT_CT);
701: valid = Boolean.valueOf(result);
702: }
703: return valid.booleanValue();
704: }
705: }