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