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