001: /* $Id: Twofish.java,v 1.1 2004/01/19 02:03:52 rgrimm Exp $
002: *
003: * Copyright (C) 1997-2000 The Cryptix Foundation Limited.
004: * All rights reserved.
005: *
006: * Use, modification, copying and distribution of this software is subject
007: * the terms and conditions of the Cryptix General Licence. You should have
008: * received a copy of the Cryptix General Licence along with this library;
009: * if not, you can download a copy from http://www.cryptix.org/ .
010: */
011: package cryptix.jce.provider.cipher;
012:
013: import java.security.InvalidKeyException;
014: import java.security.Key;
015:
016: /**
017: * Twofish is an AES candidate algorithm. It is a balanced 128-bit Feistel
018: * cipher, consisting of 16 rounds. In each round, a 64-bit S-box value is
019: * computed from 64 bits of the block, and this value is xored into the other
020: * half of the block. The two half-blocks are then exchanged, and the next
021: * round begins. Before the first round, all input bits are xored with key-
022: * dependent "whitening" subkeys, and after the final round the output bits
023: * are xored with other key-dependent whitening subkeys; these subkeys are
024: * not used anywhere else in the algorithm.<p>
025: *
026: * Twofish was submitted by Bruce Schneier, Doug Whiting, John Kelsey, Chris
027: * Hall and David Wagner.<p>
028: *
029: * Reference:<ol>
030: * <li>TWOFISH2.C -- Optimized C API calls for TWOFISH AES submission,
031: * Version 1.00, April 1998, by Doug Whiting.</ol><p>
032: *
033: * @version $Revision: 1.1 $
034: * @author Raif S. Naffah
035: * @author Jeroen C. van Gelderen (gelderen@cryptix.org)
036: */
037: public final class Twofish extends BlockCipher {
038:
039: // Constants
040: //...........................................................................
041:
042: private static final int BLOCK_SIZE = 16, // bytes in a data-block
043: ROUNDS = 16;
044:
045: private static final int TOTAL_SUBKEYS = 4 + 4 + 2 * ROUNDS;
046:
047: private static final int SK_BUMP = 0x01010101, SK_ROTL = 9;
048:
049: /** Fixed 8x8 permutation S-boxes */
050: private static final byte[][] P = new byte[][] {
051: { // p0
052: (byte) 0xA9, (byte) 0x67, (byte) 0xB3, (byte) 0xE8,
053: (byte) 0x04, (byte) 0xFD, (byte) 0xA3, (byte) 0x76,
054: (byte) 0x9A, (byte) 0x92, (byte) 0x80, (byte) 0x78,
055: (byte) 0xE4, (byte) 0xDD, (byte) 0xD1, (byte) 0x38,
056: (byte) 0x0D, (byte) 0xC6, (byte) 0x35, (byte) 0x98,
057: (byte) 0x18, (byte) 0xF7, (byte) 0xEC, (byte) 0x6C,
058: (byte) 0x43, (byte) 0x75, (byte) 0x37, (byte) 0x26,
059: (byte) 0xFA, (byte) 0x13, (byte) 0x94, (byte) 0x48,
060: (byte) 0xF2, (byte) 0xD0, (byte) 0x8B, (byte) 0x30,
061: (byte) 0x84, (byte) 0x54, (byte) 0xDF, (byte) 0x23,
062: (byte) 0x19, (byte) 0x5B, (byte) 0x3D, (byte) 0x59,
063: (byte) 0xF3, (byte) 0xAE, (byte) 0xA2, (byte) 0x82,
064: (byte) 0x63, (byte) 0x01, (byte) 0x83, (byte) 0x2E,
065: (byte) 0xD9, (byte) 0x51, (byte) 0x9B, (byte) 0x7C,
066: (byte) 0xA6, (byte) 0xEB, (byte) 0xA5, (byte) 0xBE,
067: (byte) 0x16, (byte) 0x0C, (byte) 0xE3, (byte) 0x61,
068: (byte) 0xC0, (byte) 0x8C, (byte) 0x3A, (byte) 0xF5,
069: (byte) 0x73, (byte) 0x2C, (byte) 0x25, (byte) 0x0B,
070: (byte) 0xBB, (byte) 0x4E, (byte) 0x89, (byte) 0x6B,
071: (byte) 0x53, (byte) 0x6A, (byte) 0xB4, (byte) 0xF1,
072: (byte) 0xE1, (byte) 0xE6, (byte) 0xBD, (byte) 0x45,
073: (byte) 0xE2, (byte) 0xF4, (byte) 0xB6, (byte) 0x66,
074: (byte) 0xCC, (byte) 0x95, (byte) 0x03, (byte) 0x56,
075: (byte) 0xD4, (byte) 0x1C, (byte) 0x1E, (byte) 0xD7,
076: (byte) 0xFB, (byte) 0xC3, (byte) 0x8E, (byte) 0xB5,
077: (byte) 0xE9, (byte) 0xCF, (byte) 0xBF, (byte) 0xBA,
078: (byte) 0xEA, (byte) 0x77, (byte) 0x39, (byte) 0xAF,
079: (byte) 0x33, (byte) 0xC9, (byte) 0x62, (byte) 0x71,
080: (byte) 0x81, (byte) 0x79, (byte) 0x09, (byte) 0xAD,
081: (byte) 0x24, (byte) 0xCD, (byte) 0xF9, (byte) 0xD8,
082: (byte) 0xE5, (byte) 0xC5, (byte) 0xB9, (byte) 0x4D,
083: (byte) 0x44, (byte) 0x08, (byte) 0x86, (byte) 0xE7,
084: (byte) 0xA1, (byte) 0x1D, (byte) 0xAA, (byte) 0xED,
085: (byte) 0x06, (byte) 0x70, (byte) 0xB2, (byte) 0xD2,
086: (byte) 0x41, (byte) 0x7B, (byte) 0xA0, (byte) 0x11,
087: (byte) 0x31, (byte) 0xC2, (byte) 0x27, (byte) 0x90,
088: (byte) 0x20, (byte) 0xF6, (byte) 0x60, (byte) 0xFF,
089: (byte) 0x96, (byte) 0x5C, (byte) 0xB1, (byte) 0xAB,
090: (byte) 0x9E, (byte) 0x9C, (byte) 0x52, (byte) 0x1B,
091: (byte) 0x5F, (byte) 0x93, (byte) 0x0A, (byte) 0xEF,
092: (byte) 0x91, (byte) 0x85, (byte) 0x49, (byte) 0xEE,
093: (byte) 0x2D, (byte) 0x4F, (byte) 0x8F, (byte) 0x3B,
094: (byte) 0x47, (byte) 0x87, (byte) 0x6D, (byte) 0x46,
095: (byte) 0xD6, (byte) 0x3E, (byte) 0x69, (byte) 0x64,
096: (byte) 0x2A, (byte) 0xCE, (byte) 0xCB, (byte) 0x2F,
097: (byte) 0xFC, (byte) 0x97, (byte) 0x05, (byte) 0x7A,
098: (byte) 0xAC, (byte) 0x7F, (byte) 0xD5, (byte) 0x1A,
099: (byte) 0x4B, (byte) 0x0E, (byte) 0xA7, (byte) 0x5A,
100: (byte) 0x28, (byte) 0x14, (byte) 0x3F, (byte) 0x29,
101: (byte) 0x88, (byte) 0x3C, (byte) 0x4C, (byte) 0x02,
102: (byte) 0xB8, (byte) 0xDA, (byte) 0xB0, (byte) 0x17,
103: (byte) 0x55, (byte) 0x1F, (byte) 0x8A, (byte) 0x7D,
104: (byte) 0x57, (byte) 0xC7, (byte) 0x8D, (byte) 0x74,
105: (byte) 0xB7, (byte) 0xC4, (byte) 0x9F, (byte) 0x72,
106: (byte) 0x7E, (byte) 0x15, (byte) 0x22, (byte) 0x12,
107: (byte) 0x58, (byte) 0x07, (byte) 0x99, (byte) 0x34,
108: (byte) 0x6E, (byte) 0x50, (byte) 0xDE, (byte) 0x68,
109: (byte) 0x65, (byte) 0xBC, (byte) 0xDB, (byte) 0xF8,
110: (byte) 0xC8, (byte) 0xA8, (byte) 0x2B, (byte) 0x40,
111: (byte) 0xDC, (byte) 0xFE, (byte) 0x32, (byte) 0xA4,
112: (byte) 0xCA, (byte) 0x10, (byte) 0x21, (byte) 0xF0,
113: (byte) 0xD3, (byte) 0x5D, (byte) 0x0F, (byte) 0x00,
114: (byte) 0x6F, (byte) 0x9D, (byte) 0x36, (byte) 0x42,
115: (byte) 0x4A, (byte) 0x5E, (byte) 0xC1, (byte) 0xE0 },
116: { // p1
117: (byte) 0x75, (byte) 0xF3, (byte) 0xC6, (byte) 0xF4,
118: (byte) 0xDB, (byte) 0x7B, (byte) 0xFB, (byte) 0xC8,
119: (byte) 0x4A, (byte) 0xD3, (byte) 0xE6, (byte) 0x6B,
120: (byte) 0x45, (byte) 0x7D, (byte) 0xE8, (byte) 0x4B,
121: (byte) 0xD6, (byte) 0x32, (byte) 0xD8, (byte) 0xFD,
122: (byte) 0x37, (byte) 0x71, (byte) 0xF1, (byte) 0xE1,
123: (byte) 0x30, (byte) 0x0F, (byte) 0xF8, (byte) 0x1B,
124: (byte) 0x87, (byte) 0xFA, (byte) 0x06, (byte) 0x3F,
125: (byte) 0x5E, (byte) 0xBA, (byte) 0xAE, (byte) 0x5B,
126: (byte) 0x8A, (byte) 0x00, (byte) 0xBC, (byte) 0x9D,
127: (byte) 0x6D, (byte) 0xC1, (byte) 0xB1, (byte) 0x0E,
128: (byte) 0x80, (byte) 0x5D, (byte) 0xD2, (byte) 0xD5,
129: (byte) 0xA0, (byte) 0x84, (byte) 0x07, (byte) 0x14,
130: (byte) 0xB5, (byte) 0x90, (byte) 0x2C, (byte) 0xA3,
131: (byte) 0xB2, (byte) 0x73, (byte) 0x4C, (byte) 0x54,
132: (byte) 0x92, (byte) 0x74, (byte) 0x36, (byte) 0x51,
133: (byte) 0x38, (byte) 0xB0, (byte) 0xBD, (byte) 0x5A,
134: (byte) 0xFC, (byte) 0x60, (byte) 0x62, (byte) 0x96,
135: (byte) 0x6C, (byte) 0x42, (byte) 0xF7, (byte) 0x10,
136: (byte) 0x7C, (byte) 0x28, (byte) 0x27, (byte) 0x8C,
137: (byte) 0x13, (byte) 0x95, (byte) 0x9C, (byte) 0xC7,
138: (byte) 0x24, (byte) 0x46, (byte) 0x3B, (byte) 0x70,
139: (byte) 0xCA, (byte) 0xE3, (byte) 0x85, (byte) 0xCB,
140: (byte) 0x11, (byte) 0xD0, (byte) 0x93, (byte) 0xB8,
141: (byte) 0xA6, (byte) 0x83, (byte) 0x20, (byte) 0xFF,
142: (byte) 0x9F, (byte) 0x77, (byte) 0xC3, (byte) 0xCC,
143: (byte) 0x03, (byte) 0x6F, (byte) 0x08, (byte) 0xBF,
144: (byte) 0x40, (byte) 0xE7, (byte) 0x2B, (byte) 0xE2,
145: (byte) 0x79, (byte) 0x0C, (byte) 0xAA, (byte) 0x82,
146: (byte) 0x41, (byte) 0x3A, (byte) 0xEA, (byte) 0xB9,
147: (byte) 0xE4, (byte) 0x9A, (byte) 0xA4, (byte) 0x97,
148: (byte) 0x7E, (byte) 0xDA, (byte) 0x7A, (byte) 0x17,
149: (byte) 0x66, (byte) 0x94, (byte) 0xA1, (byte) 0x1D,
150: (byte) 0x3D, (byte) 0xF0, (byte) 0xDE, (byte) 0xB3,
151: (byte) 0x0B, (byte) 0x72, (byte) 0xA7, (byte) 0x1C,
152: (byte) 0xEF, (byte) 0xD1, (byte) 0x53, (byte) 0x3E,
153: (byte) 0x8F, (byte) 0x33, (byte) 0x26, (byte) 0x5F,
154: (byte) 0xEC, (byte) 0x76, (byte) 0x2A, (byte) 0x49,
155: (byte) 0x81, (byte) 0x88, (byte) 0xEE, (byte) 0x21,
156: (byte) 0xC4, (byte) 0x1A, (byte) 0xEB, (byte) 0xD9,
157: (byte) 0xC5, (byte) 0x39, (byte) 0x99, (byte) 0xCD,
158: (byte) 0xAD, (byte) 0x31, (byte) 0x8B, (byte) 0x01,
159: (byte) 0x18, (byte) 0x23, (byte) 0xDD, (byte) 0x1F,
160: (byte) 0x4E, (byte) 0x2D, (byte) 0xF9, (byte) 0x48,
161: (byte) 0x4F, (byte) 0xF2, (byte) 0x65, (byte) 0x8E,
162: (byte) 0x78, (byte) 0x5C, (byte) 0x58, (byte) 0x19,
163: (byte) 0x8D, (byte) 0xE5, (byte) 0x98, (byte) 0x57,
164: (byte) 0x67, (byte) 0x7F, (byte) 0x05, (byte) 0x64,
165: (byte) 0xAF, (byte) 0x63, (byte) 0xB6, (byte) 0xFE,
166: (byte) 0xF5, (byte) 0xB7, (byte) 0x3C, (byte) 0xA5,
167: (byte) 0xCE, (byte) 0xE9, (byte) 0x68, (byte) 0x44,
168: (byte) 0xE0, (byte) 0x4D, (byte) 0x43, (byte) 0x69,
169: (byte) 0x29, (byte) 0x2E, (byte) 0xAC, (byte) 0x15,
170: (byte) 0x59, (byte) 0xA8, (byte) 0x0A, (byte) 0x9E,
171: (byte) 0x6E, (byte) 0x47, (byte) 0xDF, (byte) 0x34,
172: (byte) 0x35, (byte) 0x6A, (byte) 0xCF, (byte) 0xDC,
173: (byte) 0x22, (byte) 0xC9, (byte) 0xC0, (byte) 0x9B,
174: (byte) 0x89, (byte) 0xD4, (byte) 0xED, (byte) 0xAB,
175: (byte) 0x12, (byte) 0xA2, (byte) 0x0D, (byte) 0x52,
176: (byte) 0xBB, (byte) 0x02, (byte) 0x2F, (byte) 0xA9,
177: (byte) 0xD7, (byte) 0x61, (byte) 0x1E, (byte) 0xB4,
178: (byte) 0x50, (byte) 0x04, (byte) 0xF6, (byte) 0xC2,
179: (byte) 0x16, (byte) 0x25, (byte) 0x86, (byte) 0x56,
180: (byte) 0x55, (byte) 0x09, (byte) 0xBE, (byte) 0x91 } };
181:
182: /**
183: * Define the fixed p0/p1 permutations used in keyed S-box lookup.
184: * By changing the following constant definitions, the S-boxes will
185: * automatically get changed in the Twofish engine.
186: */
187: private static final int P_00 = 1, P_01 = 0, P_02 = 0,
188: P_03 = P_01 ^ 1, P_04 = 1, P_10 = 0, P_11 = 0, P_12 = 1,
189: P_13 = P_11 ^ 1, P_14 = 0, P_20 = 1, P_21 = 1, P_22 = 0,
190: P_23 = P_21 ^ 1, P_24 = 0, P_30 = 0, P_31 = 1, P_32 = 1,
191: P_33 = P_31 ^ 1, P_34 = 1;
192:
193: /** Primitive polynomial for GF(256) */
194: private static final int GF256_FDBK = 0x169,
195: GF256_FDBK_2 = 0x169 / 2, GF256_FDBK_4 = 0x169 / 4;
196:
197: /** MDS matrix */
198: private static final int[][] MDS = new int[4][256]; // blank final
199:
200: private static final int RS_GF_FDBK = 0x14D; // field generator
201:
202: // Static code - to intialise the MDS matrix
203: //...........................................................................
204:
205: static {
206: // precompute the MDS matrix
207:
208: int[] m1 = new int[2];
209: int[] mX = new int[2];
210: int[] mY = new int[2];
211: int i, j;
212: for (i = 0; i < 256; i++) {
213: j = P[0][i] & 0xFF; // compute all the matrix elements
214: m1[0] = j;
215: mX[0] = Mx_X(j) & 0xFF;
216: mY[0] = Mx_Y(j) & 0xFF;
217:
218: j = P[1][i] & 0xFF;
219: m1[1] = j;
220: mX[1] = Mx_X(j) & 0xFF;
221: mY[1] = Mx_Y(j) & 0xFF;
222:
223: MDS[0][i] = m1[P_00] << 0 | // fill matrix w/ above elements
224: mX[P_00] << 8 | mY[P_00] << 16 | mY[P_00] << 24;
225: MDS[1][i] = mY[P_10] << 0 | mY[P_10] << 8 | mX[P_10] << 16
226: | m1[P_10] << 24;
227: MDS[2][i] = mX[P_20] << 0 | mY[P_20] << 8 | m1[P_20] << 16
228: | mY[P_20] << 24;
229: MDS[3][i] = mX[P_30] << 0 | m1[P_30] << 8 | mY[P_30] << 16
230: | mX[P_30] << 24;
231: }
232: }
233:
234: private static final int LFSR1(int x) {
235: return (x >> 1) ^ ((x & 0x01) != 0 ? GF256_FDBK_2 : 0);
236: }
237:
238: private static final int LFSR2(int x) {
239: return (x >> 2) ^ ((x & 0x02) != 0 ? GF256_FDBK_2 : 0)
240: ^ ((x & 0x01) != 0 ? GF256_FDBK_4 : 0);
241: }
242:
243: private static final int Mx_1(int x) {
244: return x;
245: }
246:
247: private static final int Mx_X(int x) {
248: return x ^ LFSR2(x);
249: }
250:
251: private static final int Mx_Y(int x) {
252: return x ^ LFSR1(x) ^ LFSR2(x);
253: }
254:
255: // Instance variables
256: //...........................................................................
257:
258: /** Encrypt (false) or decrypt mode (true) */
259: private boolean decrypt;
260:
261: /** Key dependent S-box */
262: private final int[] sBox = new int[4 * 256];
263:
264: /** Subkeys */
265: private final int[] subKeys = new int[TOTAL_SUBKEYS];
266:
267: // Constructor
268: //...........................................................................
269:
270: public Twofish() {
271: super (BLOCK_SIZE);
272: }
273:
274: // BlockCipher abstract method implementation
275: //...........................................................................
276:
277: protected void coreInit(Key key, boolean decrypt)
278: throws InvalidKeyException {
279: if (key == null)
280: throw new InvalidKeyException("key: key is null");
281:
282: if (!key.getFormat().equalsIgnoreCase("RAW"))
283: throw new InvalidKeyException(
284: "key: wrong format, RAW needed");
285:
286: byte[] userkey = key.getEncoded();
287: if (userkey == null)
288: throw new InvalidKeyException("RAW bytes missing");
289:
290: int len = userkey.length;
291: if (len != 16 && len != 24 && len != 32)
292: throw new InvalidKeyException("Invalid user key length");
293:
294: this .decrypt = decrypt;
295: makeSubKeys(userkey);
296: }
297:
298: protected void coreCrypt(byte[] in, int inOffset, byte[] out,
299: int outOffset) {
300: blockCrypt(in, inOffset, out, outOffset);
301: }
302:
303: // Private methods
304: //...........................................................................
305:
306: /**
307: * Expand a user-supplied key material into a session key.
308: *
309: * @param key The 64/128/192/256-bit user-key to use.
310: * @return This cipher's round keys.
311: * @exception InvalidKeyException If the key is invalid.
312: */
313: private final void makeSubKeys(byte[] k) throws InvalidKeyException {
314: int length = k.length;
315: int k64Cnt = length / 8;
316: int[] k32e = new int[4]; // even 32-bit entities
317: int[] k32o = new int[4]; // odd 32-bit entities
318: int[] sBoxKey = new int[4];
319:
320: // split user key material into even and odd 32-bit entities and
321: // compute S-box keys using (12, 8) Reed-Solomon code over GF(256)
322: int i, j, offset = 0;
323: for (i = 0, j = k64Cnt - 1; i < 4 && offset < length; i++, j--) {
324: k32e[i] = (k[offset++] & 0xFF) | (k[offset++] & 0xFF) << 8
325: | (k[offset++] & 0xFF) << 16
326: | (k[offset++] & 0xFF) << 24;
327: k32o[i] = (k[offset++] & 0xFF) | (k[offset++] & 0xFF) << 8
328: | (k[offset++] & 0xFF) << 16
329: | (k[offset++] & 0xFF) << 24;
330: sBoxKey[j] = RS_MDS_Encode(k32e[i], k32o[i]); // reverse order
331: }
332:
333: // compute the round decryption subkeys for PHT. these same subkeys
334: // will be used in encryption but will be applied in reverse order.
335: int A, B, q = 0;
336: i = 0;
337: while (i < TOTAL_SUBKEYS) {
338: A = F32(k64Cnt, q, k32e); // A uses even key entities
339: q += SK_BUMP;
340:
341: B = F32(k64Cnt, q, k32o); // B uses odd key entities
342: q += SK_BUMP;
343:
344: B = B << 8 | B >>> 24;
345:
346: A += B;
347: subKeys[i++] = A; // combine with a PHT
348:
349: A += B;
350: subKeys[i++] = A << SK_ROTL | A >>> (32 - SK_ROTL);
351: }
352:
353: // fully expand the table for speed
354: int k0 = sBoxKey[0];
355: int k1 = sBoxKey[1];
356: int k2 = sBoxKey[2];
357: int k3 = sBoxKey[3];
358: int b0, b1, b2, b3;
359: for (i = 0; i < 256; i++) {
360: b0 = b1 = b2 = b3 = i;
361: switch (k64Cnt & 3) {
362: case 1:
363: sBox[2 * i] = MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)];
364: sBox[2 * i + 1] = MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)];
365: sBox[0x200 + 2 * i] = MDS[2][(P[P_21][b2] & 0xFF)
366: ^ b2(k0)];
367: sBox[0x200 + 2 * i + 1] = MDS[3][(P[P_31][b3] & 0xFF)
368: ^ b3(k0)];
369: break;
370: case 0: // same as 4
371: b0 = (P[P_04][b0] & 0xFF) ^ b0(k3);
372: b1 = (P[P_14][b1] & 0xFF) ^ b1(k3);
373: b2 = (P[P_24][b2] & 0xFF) ^ b2(k3);
374: b3 = (P[P_34][b3] & 0xFF) ^ b3(k3);
375: case 3:
376: b0 = (P[P_03][b0] & 0xFF) ^ b0(k2);
377: b1 = (P[P_13][b1] & 0xFF) ^ b1(k2);
378: b2 = (P[P_23][b2] & 0xFF) ^ b2(k2);
379: b3 = (P[P_33][b3] & 0xFF) ^ b3(k2);
380: case 2: // 128-bit keys
381: sBox[2 * i] = MDS[0][(P[P_01][(P[P_02][b0] & 0xFF)
382: ^ b0(k1)] & 0xFF)
383: ^ b0(k0)];
384:
385: sBox[2 * i + 1] = MDS[1][(P[P_11][(P[P_12][b1] & 0xFF)
386: ^ b1(k1)] & 0xFF)
387: ^ b1(k0)];
388:
389: sBox[0x200 + 2 * i] = MDS[2][(P[P_21][(P[P_22][b2] & 0xFF)
390: ^ b2(k1)] & 0xFF)
391: ^ b2(k0)];
392:
393: sBox[0x200 + 2 * i + 1] = MDS[3][(P[P_31][(P[P_32][b3] & 0xFF)
394: ^ b3(k1)] & 0xFF)
395: ^ b3(k0)];
396: }
397: }
398:
399: // swap input and output whitening keys when decrypting
400: if (decrypt)
401: for (i = 0; i < 4; i++) {
402: int t = subKeys[i];
403: subKeys[i] = subKeys[i + 4];
404: subKeys[i + 4] = t;
405: }
406: }
407:
408: /**
409: * Encrypt exactly one block of plaintext. Blocks may overlap.
410: *
411: * @param in The plaintext.
412: * @param inOffset Index of in from which to start considering data.
413: * @param sessionKey The session key to use for encryption.
414: * @return The ciphertext generated from a plaintext using the session key.
415: */
416: private final void blockCrypt(byte[] in, int inOffset, byte[] out,
417: int outOffset) {
418: int[] sBox = this .sBox;
419: int[] sKey = this .subKeys;
420:
421: int x0 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
422: | (in[inOffset++] & 0xFF) << 16
423: | (in[inOffset++] & 0xFF) << 24;
424: int x1 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
425: | (in[inOffset++] & 0xFF) << 16
426: | (in[inOffset++] & 0xFF) << 24;
427: int x2 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
428: | (in[inOffset++] & 0xFF) << 16
429: | (in[inOffset++] & 0xFF) << 24;
430: int x3 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
431: | (in[inOffset++] & 0xFF) << 16
432: | (in[inOffset] & 0xFF) << 24;
433:
434: x0 ^= sKey[0];
435: x1 ^= sKey[1];
436: x2 ^= sKey[2];
437: x3 ^= sKey[3];
438:
439: int k, t0, t1;
440: if (decrypt) {
441: k = 39;
442: for (int R = 0; R < ROUNDS; R += 2) {
443: t0 = Fe32(sBox, x0, 0);
444: t1 = Fe32(sBox, x1, 3);
445: x3 ^= t0 + 2 * t1 + sKey[k--];
446: x3 = x3 >>> 1 | x3 << 31;
447: x2 = x2 << 1 | x2 >>> 31;
448: x2 ^= t0 + t1 + sKey[k--];
449:
450: t0 = Fe32(sBox, x2, 0);
451: t1 = Fe32(sBox, x3, 3);
452: x1 ^= t0 + 2 * t1 + sKey[k--];
453: x1 = x1 >>> 1 | x1 << 31;
454: x0 = x0 << 1 | x0 >>> 31;
455: x0 ^= t0 + t1 + sKey[k--];
456: }
457: } else {
458: k = 8;
459: for (int R = 0; R < ROUNDS; R += 2) {
460: t0 = Fe32(sBox, x0, 0);
461: t1 = Fe32(sBox, x1, 3);
462: x2 ^= t0 + t1 + sKey[k++];
463: x2 = x2 >>> 1 | x2 << 31;
464: x3 = x3 << 1 | x3 >>> 31;
465: x3 ^= t0 + 2 * t1 + sKey[k++];
466:
467: t0 = Fe32(sBox, x2, 0);
468: t1 = Fe32(sBox, x3, 3);
469: x0 ^= t0 + t1 + sKey[k++];
470: x0 = x0 >>> 1 | x0 << 31;
471: x1 = x1 << 1 | x1 >>> 31;
472: x1 ^= t0 + 2 * t1 + sKey[k++];
473: }
474: }
475:
476: x2 ^= sKey[4];
477: x3 ^= sKey[5];
478: x0 ^= sKey[6];
479: x1 ^= sKey[7];
480:
481: out[outOffset++] = (byte) (x2);
482: out[outOffset++] = (byte) (x2 >>> 8);
483: out[outOffset++] = (byte) (x2 >>> 16);
484: out[outOffset++] = (byte) (x2 >>> 24);
485:
486: out[outOffset++] = (byte) (x3);
487: out[outOffset++] = (byte) (x3 >>> 8);
488: out[outOffset++] = (byte) (x3 >>> 16);
489: out[outOffset++] = (byte) (x3 >>> 24);
490:
491: out[outOffset++] = (byte) (x0);
492: out[outOffset++] = (byte) (x0 >>> 8);
493: out[outOffset++] = (byte) (x0 >>> 16);
494: out[outOffset++] = (byte) (x0 >>> 24);
495:
496: out[outOffset++] = (byte) (x1);
497: out[outOffset++] = (byte) (x1 >>> 8);
498: out[outOffset++] = (byte) (x1 >>> 16);
499: out[outOffset] = (byte) (x1 >>> 24);
500: }
501:
502: // own methods
503: //...........................................................................
504:
505: private static final int b0(int x) {
506: return x & 0xFF;
507: }
508:
509: private static final int b1(int x) {
510: return (x >>> 8) & 0xFF;
511: }
512:
513: private static final int b2(int x) {
514: return (x >>> 16) & 0xFF;
515: }
516:
517: private static final int b3(int x) {
518: return (x >>> 24) & 0xFF;
519: }
520:
521: /**
522: * Use (12, 8) Reed-Solomon code over GF(256) to produce a key S-box
523: * 32-bit entity from two key material 32-bit entities.
524: *
525: * @param k0 1st 32-bit entity.
526: * @param k1 2nd 32-bit entity.
527: * @return Remainder polynomial generated using RS code
528: */
529: private static final int RS_MDS_Encode(int k0, int k1) {
530: int r = k1;
531: for (int i = 0; i < 4; i++)
532: // shift 1 byte at a time
533: r = RS_rem(r);
534:
535: r ^= k0;
536: for (int i = 0; i < 4; i++)
537: r = RS_rem(r);
538:
539: return r;
540: }
541:
542: /*
543: * Reed-Solomon code parameters: (12, 8) reversible code:<p>
544: * <pre>
545: * g(x) = x**4 + (a + 1/a) x**3 + a x**2 + (a + 1/a) x + 1
546: * </pre>
547: * where a = primitive root of field generator 0x14D
548: */
549: private static final int RS_rem(int x) {
550: int b = (x >>> 24) & 0xFF;
551: int g2 = ((b << 1) ^ ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xFF;
552: int g3 = (b >>> 1) ^ ((b & 0x01) != 0 ? (RS_GF_FDBK >>> 1) : 0)
553: ^ g2;
554: int result = (x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b;
555: return result;
556: }
557:
558: private static final int F32(int k64Cnt, int x, int[] k32) {
559: int b0 = b0(x);
560: int b1 = b1(x);
561: int b2 = b2(x);
562: int b3 = b3(x);
563: int k0 = k32[0];
564: int k1 = k32[1];
565: int k2 = k32[2];
566: int k3 = k32[3];
567:
568: int result = 0;
569: switch (k64Cnt & 3) {
570: case 1:
571: result = MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)]
572: ^ MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)]
573: ^ MDS[2][(P[P_21][b2] & 0xFF) ^ b2(k0)]
574: ^ MDS[3][(P[P_31][b3] & 0xFF) ^ b3(k0)];
575: break;
576: case 0: // same as 4
577: b0 = (P[P_04][b0] & 0xFF) ^ b0(k3);
578: b1 = (P[P_14][b1] & 0xFF) ^ b1(k3);
579: b2 = (P[P_24][b2] & 0xFF) ^ b2(k3);
580: b3 = (P[P_34][b3] & 0xFF) ^ b3(k3);
581: case 3:
582: b0 = (P[P_03][b0] & 0xFF) ^ b0(k2);
583: b1 = (P[P_13][b1] & 0xFF) ^ b1(k2);
584: b2 = (P[P_23][b2] & 0xFF) ^ b2(k2);
585: b3 = (P[P_33][b3] & 0xFF) ^ b3(k2);
586: case 2: // 128-bit keys (optimize for this case)
587: result = MDS[0][(P[P_01][(P[P_02][b0] & 0xFF) ^ b0(k1)] & 0xFF)
588: ^ b0(k0)]
589: ^ MDS[1][(P[P_11][(P[P_12][b1] & 0xFF) ^ b1(k1)] & 0xFF)
590: ^ b1(k0)]
591: ^ MDS[2][(P[P_21][(P[P_22][b2] & 0xFF) ^ b2(k1)] & 0xFF)
592: ^ b2(k0)]
593: ^ MDS[3][(P[P_31][(P[P_32][b3] & 0xFF) ^ b3(k1)] & 0xFF)
594: ^ b3(k0)];
595: break;
596: }
597: return result;
598: }
599:
600: private static final int Fe32(int[] sBox, int x, int R) {
601: return sBox[2 * _b(x, R)] ^ sBox[2 * _b(x, R + 1) + 1]
602: ^ sBox[0x200 + 2 * _b(x, R + 2)]
603: ^ sBox[0x200 + 2 * _b(x, R + 3) + 1];
604: }
605:
606: private static final int _b(int x, int N) {
607: int result = 0;
608: switch (N % 4) {
609: case 0:
610: result = b0(x);
611: break;
612: case 1:
613: result = b1(x);
614: break;
615: case 2:
616: result = b2(x);
617: break;
618: case 3:
619: result = b3(x);
620: break;
621: }
622: return result;
623: }
624: }
|