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:
69: public final class Twofish
70: extends BaseCipher
71: {
72: private static final Logger log = Configuration.DEBUG ?
73: Logger.getLogger(Twofish.class.getName()) : null;
74: private static final int DEFAULT_BLOCK_SIZE = 16;
75: private static final int DEFAULT_KEY_SIZE = 16;
76: private static final int MAX_ROUNDS = 16;
77: private static final int ROUNDS = MAX_ROUNDS;
78:
79: private static final int INPUT_WHITEN = 0;
80: private static final int OUTPUT_WHITEN = INPUT_WHITEN + DEFAULT_BLOCK_SIZE / 4;
81: private static final int ROUND_SUBKEYS = OUTPUT_WHITEN + DEFAULT_BLOCK_SIZE / 4;
82: private static final int SK_STEP = 0x02020202;
83: private static final int SK_BUMP = 0x01010101;
84: private static final int SK_ROTL = 9;
85: private static final String[] Pm = new String[] {
86:
87: "\uA967\uB3E8\u04FD\uA376\u9A92\u8078\uE4DD\uD138"
88: + "\u0DC6\u3598\u18F7\uEC6C\u4375\u3726\uFA13\u9448"
89: + "\uF2D0\u8B30\u8454\uDF23\u195B\u3D59\uF3AE\uA282"
90: + "\u6301\u832E\uD951\u9B7C\uA6EB\uA5BE\u160C\uE361"
91: + "\uC08C\u3AF5\u732C\u250B\uBB4E\u896B\u536A\uB4F1"
92: + "\uE1E6\uBD45\uE2F4\uB666\uCC95\u0356\uD41C\u1ED7"
93: + "\uFBC3\u8EB5\uE9CF\uBFBA\uEA77\u39AF\u33C9\u6271"
94: + "\u8179\u09AD\u24CD\uF9D8\uE5C5\uB94D\u4408\u86E7"
95: + "\uA11D\uAAED\u0670\uB2D2\u417B\uA011\u31C2\u2790"
96: + "\u20F6\u60FF\u965C\uB1AB\u9E9C\u521B\u5F93\u0AEF"
97: + "\u9185\u49EE\u2D4F\u8F3B\u4787\u6D46\uD63E\u6964"
98: + "\u2ACE\uCB2F\uFC97\u057A\uAC7F\uD51A\u4B0E\uA75A"
99: + "\u2814\u3F29\u883C\u4C02\uB8DA\uB017\u551F\u8A7D"
100: + "\u57C7\u8D74\uB7C4\u9F72\u7E15\u2212\u5807\u9934"
101: + "\u6E50\uDE68\u65BC\uDBF8\uC8A8\u2B40\uDCFE\u32A4"
102: + "\uCA10\u21F0\uD35D\u0F00\u6F9D\u3642\u4A5E\uC1E0",
103:
104: "\u75F3\uC6F4\uDB7B\uFBC8\u4AD3\uE66B\u457D\uE84B"
105: + "\uD632\uD8FD\u3771\uF1E1\u300F\uF81B\u87FA\u063F"
106: + "\u5EBA\uAE5B\u8A00\uBC9D\u6DC1\uB10E\u805D\uD2D5"
107: + "\uA084\u0714\uB590\u2CA3\uB273\u4C54\u9274\u3651"
108: + "\u38B0\uBD5A\uFC60\u6296\u6C42\uF710\u7C28\u278C"
109: + "\u1395\u9CC7\u2446\u3B70\uCAE3\u85CB\u11D0\u93B8"
110: + "\uA683\u20FF\u9F77\uC3CC\u036F\u08BF\u40E7\u2BE2"
111: + "\u790C\uAA82\u413A\uEAB9\uE49A\uA497\u7EDA\u7A17"
112: + "\u6694\uA11D\u3DF0\uDEB3\u0B72\uA71C\uEFD1\u533E"
113: + "\u8F33\u265F\uEC76\u2A49\u8188\uEE21\uC41A\uEBD9"
114: + "\uC539\u99CD\uAD31\u8B01\u1823\uDD1F\u4E2D\uF948"
115: + "\u4FF2\u658E\u785C\u5819\u8DE5\u9857\u677F\u0564"
116: + "\uAF63\uB6FE\uF5B7\u3CA5\uCEE9\u6844\uE04D\u4369"
117: + "\u292E\uAC15\u59A8\u0A9E\u6E47\uDF34\u356A\uCFDC"
118: + "\u22C9\uC09B\u89D4\uEDAB\u12A2\u0D52\uBB02\u2FA9"
119: + "\uD761\u1EB4\u5004\uF6C2\u1625\u8656\u5509\uBE91" };
120:
121: private static final byte[][] P = new byte[2][256];
122:
127: private static final int P_00 = 1;
128: private static final int P_01 = 0;
129: private static final int P_02 = 0;
130: private static final int P_03 = P_01 ^ 1;
131: private static final int P_04 = 1;
132: private static final int P_10 = 0;
133: private static final int P_11 = 0;
134: private static final int P_12 = 1;
135: private static final int P_13 = P_11 ^ 1;
136: private static final int P_14 = 0;
137: private static final int P_20 = 1;
138: private static final int P_21 = 1;
139: private static final int P_22 = 0;
140: private static final int P_23 = P_21 ^ 1;
141: private static final int P_24 = 0;
142: private static final int P_30 = 0;
143: private static final int P_31 = 1;
144: private static final int P_32 = 1;
145: private static final int P_33 = P_31 ^ 1;
146: private static final int P_34 = 1;
147:
148: private static final int GF256_FDBK_2 = 0x169 / 2;
149: private static final int GF256_FDBK_4 = 0x169 / 4;
150:
151: private static final int[][] MDS = new int[4][256];
152: private static final int RS_GF_FDBK = 0x14D;
153:
159: private static final byte[] KAT_KEY = Util.toBytesFromString(
160: "0000000000000000000000000000000000000000000002000000000000000000");
161: private static final byte[] KAT_CT =
162: Util.toBytesFromString("F51410475B33FBD3DB2117B5C17C82D4");
163:
164: private static Boolean valid;
165: static
166: {
167: long time = System.currentTimeMillis();
168:
169: int i;
170: char c;
171: for (i = 0; i < 256; i++)
172: {
173: c = Pm[0].charAt(i >>> 1);
174: P[0][i] = (byte)((i & 1) == 0 ? c >>> 8 : c);
175: c = Pm[1].charAt(i >>> 1);
176: P[1][i] = (byte)((i & 1) == 0 ? c >>> 8 : c);
177: }
178:
179: int[] m1 = new int[2];
180: int[] mX = new int[2];
181: int[] mY = new int[2];
182: int j;
183: for (i = 0; i < 256; i++)
184: {
185: j = P[0][i] & 0xFF;
186: m1[0] = j;
187: mX[0] = Mx_X(j) & 0xFF;
188: mY[0] = Mx_Y(j) & 0xFF;
189: j = P[1][i] & 0xFF;
190: m1[1] = j;
191: mX[1] = Mx_X(j) & 0xFF;
192: mY[1] = Mx_Y(j) & 0xFF;
193: MDS[0][i] = m1[P_00] << 0
194: | mX[P_00] << 8
195: | mY[P_00] << 16
196: | mY[P_00] << 24;
197: MDS[1][i] = mY[P_10] << 0
198: | mY[P_10] << 8
199: | mX[P_10] << 16
200: | m1[P_10] << 24;
201: MDS[2][i] = mX[P_20] << 0
202: | mY[P_20] << 8
203: | m1[P_20] << 16
204: | mY[P_20] << 24;
205: MDS[3][i] = mX[P_30] << 0
206: | m1[P_30] << 8
207: | mY[P_30] << 16
208: | mX[P_30] << 24;
209: }
210: time = System.currentTimeMillis() - time;
211: if (Configuration.DEBUG)
212: {
213: log.fine("Static Data");
214: log.fine("MDS[0][]:");
215: StringBuilder sb;
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(MDS[0][i * 4 + j])).append(", ");
221: log.fine(sb.toString());
222: }
223: log.fine("MDS[1][]:");
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(MDS[1][i * 4 + j])).append(", ");
229: log.fine(sb.toString());
230: }
231: log.fine("MDS[2][]:");
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(MDS[2][i * 4 + j])).append(", ");
237: log.fine(sb.toString());
238: }
239: log.fine("MDS[3][]:");
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(MDS[3][i * 4 + j])).append(", ");
245: log.fine(sb.toString());
246: }
247: log.fine("Total initialization time: " + time + " ms.");
248: }
249: }
250:
251: private static final int LFSR1(int x)
252: {
253: return (x >> 1) ^ ((x & 0x01) != 0 ? GF256_FDBK_2 : 0);
254: }
255:
256: private static final int LFSR2(int x)
257: {
258: return (x >> 2)
259: ^ ((x & 0x02) != 0 ? GF256_FDBK_2 : 0)
260: ^ ((x & 0x01) != 0 ? GF256_FDBK_4 : 0);
261: }
262:
263: private static final int Mx_X(int x)
264: {
265: return x ^ LFSR2(x);
266: }
267:
268: private static final int Mx_Y(int x)
269: {
270: return x ^ LFSR1(x) ^ LFSR2(x);
271: }
272:
273:
274: public Twofish()
275: {
276: super(Registry.TWOFISH_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE);
277: }
278:
279: private static final int b0(int x)
280: {
281: return x & 0xFF;
282: }
283:
284: private static final int b1(int x)
285: {
286: return (x >>> 8) & 0xFF;
287: }
288:
289: private static final int b2(int x)
290: {
291: return (x >>> 16) & 0xFF;
292: }
293:
294: private static final int b3(int x)
295: {
296: return (x >>> 24) & 0xFF;
297: }
298:
299:
307: private static final int RS_MDS_Encode(int k0, int k1)
308: {
309: int r = k1;
310: int i;
311: for (i = 0; i < 4; i++)
312: r = RS_rem(r);
313: r ^= k0;
314: for (i = 0; i < 4; i++)
315: r = RS_rem(r);
316: return r;
317: }
318:
319:
326: private static final int RS_rem(int x)
327: {
328: int b = (x >>> 24) & 0xFF;
329: int g2 = ((b << 1) ^ ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xFF;
330: int g3 = (b >>> 1) ^ ((b & 0x01) != 0 ? (RS_GF_FDBK >>> 1) : 0) ^ g2;
331: int result = (x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b;
332: return result;
333: }
334:
335: private static final int F32(int k64Cnt, int x, int[] k32)
336: {
337: int b0 = b0(x);
338: int b1 = b1(x);
339: int b2 = b2(x);
340: int b3 = b3(x);
341: int k0 = k32[0];
342: int k1 = k32[1];
343: int k2 = k32[2];
344: int k3 = k32[3];
345: int result = 0;
346: switch (k64Cnt & 3)
347: {
348: case 1:
349: result = MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)]
350: ^ MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)]
351: ^ MDS[2][(P[P_21][b2] & 0xFF) ^ b2(k0)]
352: ^ MDS[3][(P[P_31][b3] & 0xFF) ^ b3(k0)];
353: break;
354: case 0:
355: b0 = (P[P_04][b0] & 0xFF) ^ b0(k3);
356: b1 = (P[P_14][b1] & 0xFF) ^ b1(k3);
357: b2 = (P[P_24][b2] & 0xFF) ^ b2(k3);
358: b3 = (P[P_34][b3] & 0xFF) ^ b3(k3);
359: case 3:
360: b0 = (P[P_03][b0] & 0xFF) ^ b0(k2);
361: b1 = (P[P_13][b1] & 0xFF) ^ b1(k2);
362: b2 = (P[P_23][b2] & 0xFF) ^ b2(k2);
363: b3 = (P[P_33][b3] & 0xFF) ^ b3(k2);
364: case 2:
365: result = MDS[0][(P[P_01][(P[P_02][b0] & 0xFF) ^ b0(k1)] & 0xFF) ^ b0(k0)]
366: ^ MDS[1][(P[P_11][(P[P_12][b1] & 0xFF) ^ b1(k1)] & 0xFF) ^ b1(k0)]
367: ^ MDS[2][(P[P_21][(P[P_22][b2] & 0xFF) ^ b2(k1)] & 0xFF) ^ b2(k0)]
368: ^ MDS[3][(P[P_31][(P[P_32][b3] & 0xFF) ^ b3(k1)] & 0xFF) ^ b3(k0)];
369: break;
370: }
371: return result;
372: }
373:
374: private static final int Fe32(int[] sBox, int x, int R)
375: {
376: return sBox[ 2 * _b(x, R ) ]
377: ^ sBox[ 2 * _b(x, R + 1) + 1]
378: ^ sBox[0x200 + 2 * _b(x, R + 2) ]
379: ^ sBox[0x200 + 2 * _b(x, R + 3) + 1];
380: }
381:
382: private static final int _b(int x, int N)
383: {
384: switch (N % 4)
385: {
386: case 0:
387: return x & 0xFF;
388: case 1:
389: return (x >>> 8) & 0xFF;
390: case 2:
391: return (x >>> 16) & 0xFF;
392: default:
393: return x >>> 24;
394: }
395: }
396:
397: public Object clone()
398: {
399: Twofish result = new Twofish();
400: result.currentBlockSize = this.currentBlockSize;
401: return result;
402: }
403:
404: public Iterator blockSizes()
405: {
406: ArrayList al = new ArrayList();
407: al.add(Integer.valueOf(DEFAULT_BLOCK_SIZE));
408: return Collections.unmodifiableList(al).iterator();
409: }
410:
411: public Iterator keySizes()
412: {
413: ArrayList al = new ArrayList();
414: al.add(Integer.valueOf(8));
415: al.add(Integer.valueOf(16));
416: al.add(Integer.valueOf(24));
417: al.add(Integer.valueOf(32));
418: return Collections.unmodifiableList(al).iterator();
419: }
420:
421:
431: public Object makeKey(byte[] k, int bs) throws InvalidKeyException
432: {
433: if (bs != DEFAULT_BLOCK_SIZE)
434: throw new IllegalArgumentException();
435: if (k == null)
436: throw new InvalidKeyException("Empty key");
437: int length = k.length;
438: if (! (length == 8 || length == 16 || length == 24 || length == 32))
439: throw new InvalidKeyException("Incorrect key length");
440: int k64Cnt = length / 8;
441: int subkeyCnt = ROUND_SUBKEYS + 2 * ROUNDS;
442: int[] k32e = new int[4];
443: int[] k32o = new int[4];
444: int[] sBoxKey = new int[4];
445:
446:
447: int i, j, offset = 0;
448: for (i = 0, j = k64Cnt - 1; i < 4 && offset < length; i++, j--)
449: {
450: k32e[i] = (k[offset++] & 0xFF)
451: | (k[offset++] & 0xFF) << 8
452: | (k[offset++] & 0xFF) << 16
453: | (k[offset++] & 0xFF) << 24;
454: k32o[i] = (k[offset++] & 0xFF)
455: | (k[offset++] & 0xFF) << 8
456: | (k[offset++] & 0xFF) << 16
457: | (k[offset++] & 0xFF) << 24;
458: sBoxKey[j] = RS_MDS_Encode(k32e[i], k32o[i]);
459: }
460:
461:
462: int q, A, B;
463: int[] subKeys = new int[subkeyCnt];
464: for (i = q = 0; i < subkeyCnt / 2; i++, q += SK_STEP)
465: {
466: A = F32(k64Cnt, q, k32e);
467: B = F32(k64Cnt, q + SK_BUMP, k32o);
468: B = B << 8 | B >>> 24;
469: A += B;
470: subKeys[2 * i] = A;
471: A += B;
472: subKeys[2 * i + 1] = A << SK_ROTL | A >>> (32 - SK_ROTL);
473: }
474:
475: int k0 = sBoxKey[0];
476: int k1 = sBoxKey[1];
477: int k2 = sBoxKey[2];
478: int k3 = sBoxKey[3];
479: int b0, b1, b2, b3;
480: int[] sBox = new int[4 * 256];
481: for (i = 0; i < 256; i++)
482: {
483: b0 = b1 = b2 = b3 = i;
484: switch (k64Cnt & 3)
485: {
486: case 1:
487: sBox[ 2 * i ] = MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)];
488: sBox[ 2 * i + 1] = MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)];
489: sBox[0x200 + 2 * i ] = MDS[2][(P[P_21][b2] & 0xFF) ^ b2(k0)];
490: sBox[0x200 + 2 * i + 1] = MDS[3][(P[P_31][b3] & 0xFF) ^ b3(k0)];
491: break;
492: case 0:
493: b0 = (P[P_04][b0] & 0xFF) ^ b0(k3);
494: b1 = (P[P_14][b1] & 0xFF) ^ b1(k3);
495: b2 = (P[P_24][b2] & 0xFF) ^ b2(k3);
496: b3 = (P[P_34][b3] & 0xFF) ^ b3(k3);
497: case 3:
498: b0 = (P[P_03][b0] & 0xFF) ^ b0(k2);
499: b1 = (P[P_13][b1] & 0xFF) ^ b1(k2);
500: b2 = (P[P_23][b2] & 0xFF) ^ b2(k2);
501: b3 = (P[P_33][b3] & 0xFF) ^ b3(k2);
502: case 2:
503: sBox[ 2 * i ] = MDS[0][(P[P_01][(P[P_02][b0] & 0xFF)
504: ^ b0(k1)] & 0xFF) ^ b0(k0)];
505: sBox[ 2 * i + 1] = MDS[1][(P[P_11][(P[P_12][b1] & 0xFF)
506: ^ b1(k1)] & 0xFF) ^ b1(k0)];
507: sBox[0x200 + 2 * i ] = MDS[2][(P[P_21][(P[P_22][b2] & 0xFF)
508: ^ b2(k1)] & 0xFF) ^ b2(k0)];
509: sBox[0x200 + 2 * i + 1] = MDS[3][(P[P_31][(P[P_32][b3] & 0xFF)
510: ^ b3(k1)] & 0xFF) ^ b3(k0)];
511: }
512: }
513: if (Configuration.DEBUG)
514: {
515: StringBuilder sb;
516: log.fine("S-box[]:");
517: for (i = 0; i < 64; i++)
518: {
519: sb = new StringBuilder();
520: for (j = 0; j < 4; j++)
521: sb.append("0x").append(Util.toString(sBox[i * 4 + j])).append(", ");
522: log.fine(sb.toString());
523: }
524: log.fine("");
525: for (i = 0; i < 64; i++)
526: {
527: sb = new StringBuilder();
528: for (j = 0; j < 4; j++)
529: sb.append("0x").append(Util.toString(sBox[256 + i * 4 + j])).append(", ");
530: log.fine(sb.toString());
531: }
532: log.fine("");
533: for (i = 0; i < 64; i++)
534: {
535: sb = new StringBuilder();
536: for (j = 0; j < 4; j++)
537: sb.append("0x").append(Util.toString(sBox[512 + i * 4 + j])).append(", ");
538: log.fine(sb.toString());
539: }
540: log.fine("");
541: for (i = 0; i < 64; i++)
542: {
543: sb = new StringBuilder();
544: for (j = 0; j < 4; j++)
545: sb.append("0x").append(Util.toString(sBox[768 + i * 4 + j])).append(", ");
546: log.fine(sb.toString());
547: }
548: log.fine("User (odd, even) keys --> S-Box keys:");
549: for (i = 0; i < k64Cnt; i++)
550: log.fine("0x" + Util.toString(k32o[i])
551: + " 0x" + Util.toString(k32e[i])
552: + " --> 0x" + Util.toString(sBoxKey[k64Cnt - 1 - i]));
553: log.fine("Round keys:");
554: for (i = 0; i < ROUND_SUBKEYS + 2 * ROUNDS; i += 2)
555: log.fine("0x" + Util.toString(subKeys[i])
556: + " 0x" + Util.toString(subKeys[i + 1]));
557: }
558: return new Object[] { sBox, subKeys };
559: }
560:
561: public void encrypt(byte[] in, int inOffset, byte[] out, int outOffset,
562: Object sessionKey, int bs)
563: {
564: if (bs != DEFAULT_BLOCK_SIZE)
565: throw new IllegalArgumentException();
566: Object[] sk = (Object[]) sessionKey;
567: int[] sBox = (int[]) sk[0];
568: int[] sKey = (int[]) sk[1];
569: if (Configuration.DEBUG)
570: log.fine("PT=" + Util.toString(in, inOffset, bs));
571: int x0 = (in[inOffset++] & 0xFF)
572: | (in[inOffset++] & 0xFF) << 8
573: | (in[inOffset++] & 0xFF) << 16
574: | (in[inOffset++] & 0xFF) << 24;
575: int x1 = (in[inOffset++] & 0xFF)
576: | (in[inOffset++] & 0xFF) << 8
577: | (in[inOffset++] & 0xFF) << 16
578: | (in[inOffset++] & 0xFF) << 24;
579: int x2 = (in[inOffset++] & 0xFF)
580: | (in[inOffset++] & 0xFF) << 8
581: | (in[inOffset++] & 0xFF) << 16
582: | (in[inOffset++] & 0xFF) << 24;
583: int x3 = (in[inOffset++] & 0xFF)
584: | (in[inOffset++] & 0xFF) << 8
585: | (in[inOffset++] & 0xFF) << 16
586: | (in[inOffset++] & 0xFF) << 24;
587: x0 ^= sKey[INPUT_WHITEN];
588: x1 ^= sKey[INPUT_WHITEN + 1];
589: x2 ^= sKey[INPUT_WHITEN + 2];
590: x3 ^= sKey[INPUT_WHITEN + 3];
591: if (Configuration.DEBUG)
592: log.fine("PTw=" + Util.toString(x0) + Util.toString(x1)
593: + Util.toString(x2) + Util.toString(x3));
594: int t0, t1;
595: int k = ROUND_SUBKEYS;
596: for (int R = 0; R < ROUNDS; R += 2)
597: {
598: t0 = Fe32(sBox, x0, 0);
599: t1 = Fe32(sBox, x1, 3);
600: x2 ^= t0 + t1 + sKey[k++];
601: x2 = x2 >>> 1 | x2 << 31;
602: x3 = x3 << 1 | x3 >>> 31;
603: x3 ^= t0 + 2 * t1 + sKey[k++];
604: if (Configuration.DEBUG)
605: log.fine("CT" + (R) + "=" + Util.toString(x0) + Util.toString(x1)
606: + Util.toString(x2) + Util.toString(x3));
607: t0 = Fe32(sBox, x2, 0);
608: t1 = Fe32(sBox, x3, 3);
609: x0 ^= t0 + t1 + sKey[k++];
610: x0 = x0 >>> 1 | x0 << 31;
611: x1 = x1 << 1 | x1 >>> 31;
612: x1 ^= t0 + 2 * t1 + sKey[k++];
613: if (Configuration.DEBUG)
614: log.fine("CT" + (R + 1) + "=" + Util.toString(x0) + Util.toString(x1)
615: + Util.toString(x2) + Util.toString(x3));
616: }
617: x2 ^= sKey[OUTPUT_WHITEN];
618: x3 ^= sKey[OUTPUT_WHITEN + 1];
619: x0 ^= sKey[OUTPUT_WHITEN + 2];
620: x1 ^= sKey[OUTPUT_WHITEN + 3];
621: if (Configuration.DEBUG)
622: log.fine("CTw=" + Util.toString(x0) + Util.toString(x1)
623: + Util.toString(x2) + Util.toString(x3));
624: out[outOffset++] = (byte) x2;
625: out[outOffset++] = (byte)(x2 >>> 8);
626: out[outOffset++] = (byte)(x2 >>> 16);
627: out[outOffset++] = (byte)(x2 >>> 24);
628: out[outOffset++] = (byte) x3;
629: out[outOffset++] = (byte)(x3 >>> 8);
630: out[outOffset++] = (byte)(x3 >>> 16);
631: out[outOffset++] = (byte)(x3 >>> 24);
632: out[outOffset++] = (byte) x0;
633: out[outOffset++] = (byte)(x0 >>> 8);
634: out[outOffset++] = (byte)(x0 >>> 16);
635: out[outOffset++] = (byte)(x0 >>> 24);
636: out[outOffset++] = (byte) x1;
637: out[outOffset++] = (byte)(x1 >>> 8);
638: out[outOffset++] = (byte)(x1 >>> 16);
639: out[outOffset ] = (byte)(x1 >>> 24);
640: if (Configuration.DEBUG)
641: log.fine("CT=" + Util.toString(out, outOffset - 15, 16) + "\n");
642: }
643:
644: public void decrypt(byte[] in, int inOffset, byte[] out, int outOffset,
645: Object sessionKey, int bs)
646: {
647: if (bs != DEFAULT_BLOCK_SIZE)
648: throw new IllegalArgumentException();
649: Object[] sk = (Object[]) sessionKey;
650: int[] sBox = (int[]) sk[0];
651: int[] sKey = (int[]) sk[1];
652: if (Configuration.DEBUG)
653: log.fine("CT=" + Util.toString(in, inOffset, bs));
654: int x2 = (in[inOffset++] & 0xFF)
655: | (in[inOffset++] & 0xFF) << 8
656: | (in[inOffset++] & 0xFF) << 16
657: | (in[inOffset++] & 0xFF) << 24;
658: int x3 = (in[inOffset++] & 0xFF)
659: | (in[inOffset++] & 0xFF) << 8
660: | (in[inOffset++] & 0xFF) << 16
661: | (in[inOffset++] & 0xFF) << 24;
662: int x0 = (in[inOffset++] & 0xFF)
663: | (in[inOffset++] & 0xFF) << 8
664: | (in[inOffset++] & 0xFF) << 16
665: | (in[inOffset++] & 0xFF) << 24;
666: int x1 = (in[inOffset++] & 0xFF)
667: | (in[inOffset++] & 0xFF) << 8
668: | (in[inOffset++] & 0xFF) << 16
669: | (in[inOffset++] & 0xFF) << 24;
670: x2 ^= sKey[OUTPUT_WHITEN];
671: x3 ^= sKey[OUTPUT_WHITEN + 1];
672: x0 ^= sKey[OUTPUT_WHITEN + 2];
673: x1 ^= sKey[OUTPUT_WHITEN + 3];
674: if (Configuration.DEBUG)
675: log.fine("CTw=" + Util.toString(x2) + Util.toString(x3)
676: + Util.toString(x0) + Util.toString(x1));
677: int k = ROUND_SUBKEYS + 2 * ROUNDS - 1;
678: int t0, t1;
679: for (int R = 0; R < ROUNDS; R += 2)
680: {
681: t0 = Fe32(sBox, x2, 0);
682: t1 = Fe32(sBox, x3, 3);
683: x1 ^= t0 + 2 * t1 + sKey[k--];
684: x1 = x1 >>> 1 | x1 << 31;
685: x0 = x0 << 1 | x0 >>> 31;
686: x0 ^= t0 + t1 + sKey[k--];
687: if (Configuration.DEBUG)
688: log.fine("PT" + (ROUNDS - R) + "=" + Util.toString(x2)
689: + Util.toString(x3) + Util.toString(x0) + Util.toString(x1));
690: t0 = Fe32(sBox, x0, 0);
691: t1 = Fe32(sBox, x1, 3);
692: x3 ^= t0 + 2 * t1 + sKey[k--];
693: x3 = x3 >>> 1 | x3 << 31;
694: x2 = x2 << 1 | x2 >>> 31;
695: x2 ^= t0 + t1 + sKey[k--];
696: if (Configuration.DEBUG)
697: log.fine("PT" + (ROUNDS - R - 1) + "=" + Util.toString(x2)
698: + Util.toString(x3) + Util.toString(x0) + Util.toString(x1));
699: }
700: x0 ^= sKey[INPUT_WHITEN];
701: x1 ^= sKey[INPUT_WHITEN + 1];
702: x2 ^= sKey[INPUT_WHITEN + 2];
703: x3 ^= sKey[INPUT_WHITEN + 3];
704: if (Configuration.DEBUG)
705: log.fine("PTw=" + Util.toString(x2) + Util.toString(x3)
706: + Util.toString(x0) + Util.toString(x1));
707: out[outOffset++] = (byte) x0;
708: out[outOffset++] = (byte)(x0 >>> 8);
709: out[outOffset++] = (byte)(x0 >>> 16);
710: out[outOffset++] = (byte)(x0 >>> 24);
711: out[outOffset++] = (byte) x1;
712: out[outOffset++] = (byte)(x1 >>> 8);
713: out[outOffset++] = (byte)(x1 >>> 16);
714: out[outOffset++] = (byte)(x1 >>> 24);
715: out[outOffset++] = (byte) x2;
716: out[outOffset++] = (byte)(x2 >>> 8);
717: out[outOffset++] = (byte)(x2 >>> 16);
718: out[outOffset++] = (byte)(x2 >>> 24);
719: out[outOffset++] = (byte) x3;
720: out[outOffset++] = (byte)(x3 >>> 8);
721: out[outOffset++] = (byte)(x3 >>> 16);
722: out[outOffset ] = (byte)(x3 >>> 24);
723: if (Configuration.DEBUG)
724: log.fine("PT=" + Util.toString(out, outOffset - 15, 16) + "\n");
725: }
726:
727: public boolean selfTest()
728: {
729: if (valid == null)
730: {
731: boolean result = super.selfTest();
732: if (result)
733: result = testKat(KAT_KEY, KAT_CT);
734: valid = Boolean.valueOf(result);
735: }
736: return valid.booleanValue();
737: }
738: }