001: /* $Id: MARS.java,v 1.1 2004/01/19 02:03:50 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: * MARS is an AES candidate submitted by IBM.
018: * <p>
019: * MARS was designed by Carolynn Burwick, Don Coppersmith, Edward D'Avignon,
020: * Rosario Gennaro, Shai Halevi, Charanjit Jutla, Stephen M. Matyas Jr.,
021: * Luke O'Connor, Mohammad Peyravian, David Safford, and Nevenko Zunic.
022: * <p>
023: * Please note that this is the 'amended' 2nd round version.
024: *
025: * @version $Revision: 1.1 $
026: * @author Jeroen C. van Gelderen (gelderen@cryptix.org)
027: * @author Raif S. Naffah
028: */
029: public final class MARS extends BlockCipher {
030:
031: // Constants
032: //...........................................................................
033:
034: static final int BLOCK_SIZE = 16, // bytes in a data-block
035: ROUNDS = 32; // rounds of a MARS cipher
036:
037: /** MARS S-box */
038: private static final int[] S = { 0x09D0C479, 0x28C8FFE0,
039: 0x84AA6C39, 0x9DAD7287, 0x7DFF9BE3, 0xD4268361, 0xC96DA1D4,
040: 0x7974CC93, 0x85D0582E, 0x2A4B5705, 0x1CA16A62, 0xC3BD279D,
041: 0x0F1F25E5, 0x5160372F, 0xC695C1FB, 0x4D7FF1E4, 0xAE5F6BF4,
042: 0x0D72EE46, 0xFF23DE8A, 0xB1CF8E83, 0xF14902E2, 0x3E981E42,
043: 0x8BF53EB6, 0x7F4BF8AC, 0x83631F83, 0x25970205, 0x76AFE784,
044: 0x3A7931D4, 0x4F846450, 0x5C64C3F6, 0x210A5F18, 0xC6986A26,
045: 0x28F4E826, 0x3A60A81C, 0xD340A664, 0x7EA820C4, 0x526687C5,
046: 0x7EDDD12B, 0x32A11D1D, 0x9C9EF086, 0x80F6E831, 0xAB6F04AD,
047: 0x56FB9B53, 0x8B2E095C, 0xB68556AE, 0xD2250B0D, 0x294A7721,
048: 0xE21FB253, 0xAE136749, 0xE82AAE86, 0x93365104, 0x99404A66,
049: 0x78A784DC, 0xB69BA84B, 0x04046793, 0x23DB5C1E, 0x46CAE1D6,
050: 0x2FE28134, 0x5A223942, 0x1863CD5B, 0xC190C6E3, 0x07DFB846,
051: 0x6EB88816, 0x2D0DCC4A, 0xA4CCAE59, 0x3798670D, 0xCBFA9493,
052: 0x4F481D45, 0xEAFC8CA8, 0xDB1129D6, 0xB0449E20, 0x0F5407FB,
053: 0x6167D9A8, 0xD1F45763, 0x4DAA96C3, 0x3BEC5958, 0xABABA014,
054: 0xB6CCD201, 0x38D6279F, 0x02682215, 0x8F376CD5, 0x092C237E,
055: 0xBFC56593, 0x32889D2C, 0x854B3E95, 0x05BB9B43, 0x7DCD5DCD,
056: 0xA02E926C, 0xFAE527E5, 0x36A1C330, 0x3412E1AE, 0xF257F462,
057: 0x3C4F1D71, 0x30A2E809, 0x68E5F551, 0x9C61BA44, 0x5DED0AB8,
058: 0x75CE09C8, 0x9654F93E, 0x698C0CCA, 0x243CB3E4, 0x2B062B97,
059: 0x0F3B8D9E, 0x00E050DF, 0xFC5D6166, 0xE35F9288, 0xC079550D,
060: 0x0591AEE8, 0x8E531E74, 0x75FE3578, 0x2F6D829A, 0xF60B21AE,
061: 0x95E8EB8D, 0x6699486B, 0x901D7D9B, 0xFD6D6E31, 0x1090ACEF,
062: 0xE0670DD8, 0xDAB2E692, 0xCD6D4365, 0xE5393514, 0x3AF345F0,
063: 0x6241FC4D, 0x460DA3A3, 0x7BCF3729, 0x8BF1D1E0, 0x14AAC070,
064: 0x1587ED55, 0x3AFD7D3E, 0xD2F29E01, 0x29A9D1F6, 0xEFB10C53,
065: 0xCF3B870F, 0xB414935C, 0x664465ED, 0x024ACAC7, 0x59A744C1,
066: 0x1D2936A7, 0xDC580AA6, 0xCF574CA8, 0x040A7A10, 0x6CD81807,
067: 0x8A98BE4C, 0xACCEA063, 0xC33E92B5, 0xD1E0E03D, 0xB322517E,
068: 0x2092BD13, 0x386B2C4A, 0x52E8DD58, 0x58656DFB, 0x50820371,
069: 0x41811896, 0xE337EF7E, 0xD39FB119, 0xC97F0DF6, 0x68FEA01B,
070: 0xA150A6E5, 0x55258962, 0xEB6FF41B, 0xD7C9CD7A, 0xA619CD9E,
071: 0xBCF09576, 0x2672C073, 0xF003FB3C, 0x4AB7A50B, 0x1484126A,
072: 0x487BA9B1, 0xA64FC9C6, 0xF6957D49, 0x38B06A75, 0xDD805FCD,
073: 0x63D094CF, 0xF51C999E, 0x1AA4D343, 0xB8495294, 0xCE9F8E99,
074: 0xBFFCD770, 0xC7C275CC, 0x378453A7, 0x7B21BE33, 0x397F41BD,
075: 0x4E94D131, 0x92CC1F98, 0x5915EA51, 0x99F861B7, 0xC9980A88,
076: 0x1D74FD5F, 0xB0A495F8, 0x614DEED0, 0xB5778EEA, 0x5941792D,
077: 0xFA90C1F8, 0x33F824B4, 0xC4965372, 0x3FF6D550, 0x4CA5FEC0,
078: 0x8630E964, 0x5B3FBBD6, 0x7DA26A48, 0xB203231A, 0x04297514,
079: 0x2D639306, 0x2EB13149, 0x16A45272, 0x532459A0, 0x8E5F4872,
080: 0xF966C7D9, 0x07128DC0, 0x0D44DB62, 0xAFC8D52D, 0x06316131,
081: 0xD838E7CE, 0x1BC41D00, 0x3A2E8C0F, 0xEA83837E, 0xB984737D,
082: 0x13BA4891, 0xC4F8B949, 0xA6D6ACB3, 0xA215CDCE, 0x8359838B,
083: 0x6BD1AA31, 0xF579DD52, 0x21B93F93, 0xF5176781, 0x187DFDDE,
084: 0xE94AEB76, 0x2B38FD54, 0x431DE1DA, 0xAB394825, 0x9AD3048F,
085: 0xDFEA32AA, 0x659473E3, 0x623F7863, 0xF3346C59, 0xAB3AB685,
086: 0x3346A90B, 0x6B56443E, 0xC6DE01F8, 0x8D421FC0, 0x9B0ED10C,
087: 0x88F1A1E9, 0x54C1F029, 0x7DEAD57B, 0x8D7BA426, 0x4CF5178A,
088: 0x551A7CCA, 0x1A9A5F08, 0xFCD651B9, 0x25605182, 0xE11FC6C3,
089: 0xB6FD9676, 0x337B3027, 0xB7C8EB14, 0x9E5FD030, 0x6B57E354,
090: 0xAD913CF7, 0x7E16688D, 0x58872A69, 0x2C2FC7DF, 0xE389CCC6,
091: 0x30738DF1, 0x0824A734, 0xE1797A8B, 0xA4A8D57B, 0x5B5D193B,
092: 0xC8A8309B, 0x73F9A978, 0x73398D32, 0x0F59573E, 0xE9DF2B03,
093: 0xE8A5B6C8, 0x848D0704, 0x98DF93C2, 0x720A1DC3, 0x684F259A,
094: 0x943BA848, 0xA6370152, 0x863B5EA3, 0xD17B978B, 0x6D9B58EF,
095: 0x0A700DD4, 0xA73D36BF, 0x8E6A0829, 0x8695BC14, 0xE35B3447,
096: 0x933AC568, 0x8894B022, 0x2F511C27, 0xDDFBCC3C, 0x006662B6,
097: 0x117C83FE, 0x4E12B414, 0xC2BCA766, 0x3A2FEC10, 0xF4562420,
098: 0x55792E2A, 0x46F5D857, 0xCEDA25CE, 0xC3601D3B, 0x6C00AB46,
099: 0xEFAC9C28, 0xB3C35047, 0x611DFEE3, 0x257C3207, 0xFDD58482,
100: 0x3B14D84F, 0x23BECB64, 0xA075F3A3, 0x088F8EAD, 0x07ADF158,
101: 0x7796943C, 0xFACABF3D, 0xC09730CD, 0xF7679969, 0xDA44E9ED,
102: 0x2C854C12, 0x35935FA3, 0x2F057D9F, 0x690624F8, 0x1CB0BAFD,
103: 0x7B0DBDC6, 0x810F23BB, 0xFA929A1A, 0x6D969A17, 0x6742979B,
104: 0x74AC7D05, 0x010E65C4, 0x86A3D963, 0xF907B5A0, 0xD0042BD3,
105: 0x158D7D03, 0x287A8255, 0xBBA8366F, 0x096EDC33, 0x21916A7B,
106: 0x77B56B86, 0x951622F9, 0xA6C5E650, 0x8CEA17D1, 0xCD8C62BC,
107: 0xA3D63433, 0x358A68FD, 0x0F9B9D3C, 0xD6AA295B, 0xFE33384A,
108: 0xC000738E, 0xCD67EB2F, 0xE2EB6DC2, 0x97338B02, 0x06C9F246,
109: 0x419CF1AD, 0x2B83C045, 0x3723F18A, 0xCB5B3089, 0x160BEAD7,
110: 0x5D494656, 0x35F8A74B, 0x1E4E6C9E, 0x000399BD, 0x67466880,
111: 0xB4174831, 0xACF423B2, 0xCA815AB3, 0x5A6395E7, 0x302A67C5,
112: 0x8BDB446B, 0x108F8FA4, 0x10223EDA, 0x92B8B48B, 0x7F38D0EE,
113: 0xAB2701D4, 0x0262D415, 0xAF224A30, 0xB3D88ABA, 0xF8B2C3AF,
114: 0xDAF7EF70, 0xCC97D3B7, 0xE9614B6C, 0x2BAEBFF4, 0x70F687CF,
115: 0x386C9156, 0xCE092EE5, 0x01E87DA6, 0x6CE91E6A, 0xBB7BCC84,
116: 0xC7922C20, 0x9D3B71FD, 0x060E41C6, 0xD7590F15, 0x4E03BB47,
117: 0x183C198E, 0x63EEB240, 0x2DDBF49A, 0x6D5CBA54, 0x923750AF,
118: 0xF9E14236, 0x7838162B, 0x59726C72, 0x81B66760, 0xBB2926C1,
119: 0x48A0CE0D, 0xA6C0496D, 0xAD43507B, 0x718D496A, 0x9DF057AF,
120: 0x44B1BDE6, 0x054356DC, 0xDE7CED35, 0xD51A138B, 0x62088CC9,
121: 0x35830311, 0xC96EFCA2, 0x686F86EC, 0x8E77CB68, 0x63E1D6B8,
122: 0xC80F9778, 0x79C491FD, 0x1B4C67F2, 0x72698D7D, 0x5E368C31,
123: 0xF7D95E2E, 0xA1D3493F, 0xDCD9433E, 0x896F1552, 0x4BC4CA7A,
124: 0xA6D1BAF4, 0xA5A96DCC, 0x0BEF8B46, 0xA169FDA7, 0x74DF40B7,
125: 0x4E208804, 0x9A756607, 0x038E87C8, 0x20211E44, 0x8B7AD4BF,
126: 0xC6403F35, 0x1848E36D, 0x80BDB038, 0x1E62891C, 0x643D2107,
127: 0xBF04D6F8, 0x21092C8C, 0xF644F389, 0x0778404E, 0x7B78ADB8,
128: 0xA2C52D53, 0x42157ABE, 0xA2253E2E, 0x7BF3F4AE, 0x80F594F9,
129: 0x953194E7, 0x77EB92ED, 0xB3816930, 0xDA8D9336, 0xBF447469,
130: 0xF26D9483, 0xEE6FAED5, 0x71371235, 0xDE425F73, 0xB4E59F43,
131: 0x7DBE2D4E, 0x2D37B185, 0x49DC9A63, 0x98C39D98, 0x1301C9A2,
132: 0x389B1BBF, 0x0C18588D, 0xA421C1BA, 0x7AA3865C, 0x71E08558,
133: 0x3C5CFCAA, 0x7D239CA4, 0x0297D9DD, 0xD7DC2830, 0x4B37802B,
134: 0x7428AB54, 0xAEEE0347, 0x4B3FBB85, 0x692F2F08, 0x134E578E,
135: 0x36D9E0BF, 0xAE8B5FCF, 0xEDB93ECF, 0x2B27248E, 0x170EB1EF,
136: 0x7DC57FD6, 0x1E760F16, 0xB1136601, 0x864E1B9B, 0xD7EA7319,
137: 0x3AB871BD, 0xCFA4D76F, 0xE31BD782, 0x0DBEB469, 0xABB96061,
138: 0x5370F85D, 0xFFB07E37, 0xDA30D0FB, 0xEBC977B6, 0x0B98B40F,
139: 0x3A4D0FE6, 0xDF4FC26B, 0x159CF22A, 0xC298D6E2, 0x2B78EF6A,
140: 0x61A94AC0, 0xAB561187, 0x14EEA0F0, 0xDF0D4164, 0x19AF70EE };
141:
142: // Instance variables
143: //...........................................................................
144:
145: /** Encrypt (false) or decrypt mode (true) */
146: private boolean decrypt;
147:
148: /** Subkeys (40). */
149: private final int[] K = new int[40];
150:
151: // Constructor
152: //...........................................................................
153:
154: public MARS() {
155: super (BLOCK_SIZE);
156: }
157:
158: // BlockCipher abstract method implementation
159: //...........................................................................
160:
161: protected void coreInit(Key key, boolean decrypt)
162: throws InvalidKeyException {
163: if (key == null)
164: throw new InvalidKeyException("key: key is null");
165:
166: if (!key.getFormat().equalsIgnoreCase("RAW"))
167: throw new InvalidKeyException(
168: "key: wrong format, RAW needed");
169:
170: byte[] userkey = key.getEncoded();
171: if (userkey == null)
172: throw new InvalidKeyException("RAW bytes missing");
173:
174: int len = userkey.length;
175: if (len != 16 && len != 24 && len != 32)
176: throw new InvalidKeyException("Invalid user key length");
177:
178: generateSubKeys(userkey);
179: this .decrypt = decrypt;
180: }
181:
182: protected void coreCrypt(byte[] in, int inOffset, byte[] out,
183: int outOffset) {
184: if (decrypt)
185: blockDecrypt(in, inOffset, out, outOffset);
186: else
187: blockEncrypt(in, inOffset, out, outOffset);
188: }
189:
190: // Helper methods
191: //...........................................................................
192:
193: /** Expand a session key into 40 MARS subkeys in int[] this.K . */
194: private final void generateSubKeys(byte[] key) {
195: int keyLen = key.length;
196: int n = keyLen / 4;
197:
198: int[] K = this .K;
199: int[] T = new int[15]; // (3)
200: int[] B = { 0xa4a8d57b, 0x5b5d193b, 0xc8a8309b, 0x73f9a978 }; // (4,5,6)
201:
202: int i;
203: for (i = 0; i < keyLen; i++)
204: T[i / 4] |= (key[i] & 0xFF) << (i * 8);
205:
206: T[i / 4] = i / 4;
207:
208: int j, ii;
209: for (j = 0; j < 4; j++) {
210: // Do linear transformation
211: for (i = 0; i < 15; i++)
212: T[i] ^= rotl(T[(i + 8) % 15] ^ T[(i + 13) % 15], 3)
213: ^ (4 * i + j);
214:
215: // Do four rounds of stirring
216: for (ii = 0; ii < 4; ii++)
217: for (i = 0; i < 15; i++)
218: T[i] = rotl(T[i] + S[T[(i + 14) % 15] & 0x1FF], 9);
219:
220: // Store next 10 key words into K[]
221: for (i = 0; i < 10; i++)
222: K[10 * j + i] = T[(4 * i) % 15];
223: }
224:
225: // Modify multiplication key-words
226: int m, p, r, w;
227: for (i = 5; i <= 35; i += 2) {
228: j = K[i] & 0x3;
229: w = K[i] | 0x3;
230:
231: m = maskFrom(w);
232: r = K[i - 1] & 0x1F;
233: p = rotl(B[j], r);
234:
235: K[i] = w ^ (p & m);
236: }
237: }
238:
239: /**
240: * Generate a bit-mask M from x.
241: *
242: * Bit M{i}=1 iff x{i} belongs to a sequence of 10 consecutive 0's
243: * or 1's in x, and also 2 <= i <= 30 and x{i-1} = w{i} = w{i+1}.
244: *
245: * Code taken from the MARS implementation in C/C++ by
246: * Dr. B. R. Gladman (brian.gladman@btinternet.com).
247: *
248: * This is used during key expansion.
249: */
250: private static int maskFrom(int x) {
251: int m;
252:
253: // Set m{bn} = 1 if x{bn} == x{bn+1} for 0 <= bn <= 30.
254: // That is, set a bit in m if the corresponding bit and the
255: // next higher bit in x are equal in value (set m{31} = 0).
256: m = (~x ^ (x >>> 1)) & 0x7fffffff;
257:
258: // Sequences of 9 '1' bits in m now correspond to sequences
259: // of 10 '0's or 10 '1' bits in x. Shift and 'and' bits in
260: // m to find sequences of 9 or more '1' bits. As a result
261: // bits in m are set if they are at the bottom of sequences
262: // of 10 adjacent '0's or 10 adjacent '1's in x.
263: m &= (m >>> 1) & (m >>> 2);
264: m &= (m >>> 3) & (m >>> 6);
265:
266: // We need the internal bits in each continuous sequence of
267: // matching bits (that is the bits less the two endpoints).
268: // We thus propagate each set bit into the 8 internal bits
269: // that it represents, starting 1 left and finsihing 8 left
270: // of its position.
271: m <<= 1;
272: m |= (m << 1);
273: m |= (m << 2);
274: m |= (m << 4);
275:
276: return m & 0xfffffffc;
277: }
278:
279: /** Rotate left an int by the specified amount. */
280: private static int rotl(int arg, int amount) {
281: return (arg << amount) | (arg >>> (32 - amount));
282: }
283:
284: /** Encrypt exactly one block of plaintext. */
285: private final void blockEncrypt(byte[] in, int inOffset,
286: byte[] out, int outOffset) {
287: int D0 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
288: | (in[inOffset++] & 0xFF) << 16
289: | (in[inOffset++] & 0xFF) << 24;
290: int D1 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
291: | (in[inOffset++] & 0xFF) << 16
292: | (in[inOffset++] & 0xFF) << 24;
293: int D2 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
294: | (in[inOffset++] & 0xFF) << 16
295: | (in[inOffset++] & 0xFF) << 24;
296: int D3 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
297: | (in[inOffset++] & 0xFF) << 16
298: | (in[inOffset] & 0xFF) << 24;
299:
300: // 1. key addition // (1)
301: D0 += K[0];
302: D1 += K[1];
303: D2 += K[2];
304: D3 += K[3];
305:
306: // 2. forward mixing
307: int i, t;
308: for (i = 0; i < 8; i++) // (5)
309: {
310: D1 ^= S[D0 & 0xFF]; // (7)
311: D1 += S[256 + ((D0 >>> 8) & 0xFF)]; // (8)
312: D2 += S[(D0 >>> 16) & 0xFF]; // (9)
313: D3 ^= S[256 + ((D0 >>> 24) & 0xFF)]; // (10)
314: D0 = D0 >>> 24 | D0 << 8; // (12)
315:
316: switch (i) {
317: case 0:
318: case 4:
319: D0 += D3;
320: break; // (15)
321: case 1:
322: case 5:
323: D0 += D1;
324: break; // (17)
325: }
326:
327: t = D0;
328: D0 = D1;
329: D1 = D2;
330: D2 = D3;
331: D3 = t; // (19)
332: } // (20)
333:
334: // 3. Keyed transformation
335: int[] ia;
336: for (i = 0; i < 16; i++) // (22)
337: {
338: ia = E(D0, K[2 * i + 4], K[2 * i + 5]); // (23)
339: D0 = D0 << 13 | D0 >>> 19; // (24)
340: D2 += ia[1]; // (25)
341: if (i < 8) {
342: D1 += ia[0]; // (27)
343: D3 ^= ia[2]; // (28)
344: } else {
345: D3 += ia[0]; // (30)
346: D1 ^= ia[2]; // (31)
347: }
348: t = D0;
349: D0 = D1;
350: D1 = D2;
351: D2 = D3;
352: D3 = t; // (34)
353: } // (35)
354:
355: // 4. Backward mixing
356: for (i = 0; i < 8; i++) // (37)
357: {
358: switch (i) {
359: case 2:
360: case 6:
361: D0 -= D3;
362: break; // (40)
363: case 3:
364: case 7:
365: D0 -= D1;
366: break; // (42)
367: }
368: D1 ^= S[256 + (D0 & 0xFF)]; // (44)
369: D2 -= S[(D0 >>> 24) & 0xFF]; // (45)
370: D3 -= S[256 + ((D0 >>> 16) & 0xFF)]; // (46)
371: D3 ^= S[(D0 >>> 8) & 0xFF]; // (47)
372: D0 = D0 << 24 | D0 >>> 8; // (49)
373: t = D0;
374: D0 = D1;
375: D1 = D2;
376: D2 = D3;
377: D3 = t; // (51)
378: } // (52)
379:
380: D0 -= K[36];
381: D1 -= K[37];
382: D2 -= K[38];
383: D3 -= K[39];
384:
385: out[outOffset++] = (byte) (D0);
386: out[outOffset++] = (byte) (D0 >>> 8);
387: out[outOffset++] = (byte) (D0 >>> 16);
388: out[outOffset++] = (byte) (D0 >>> 24);
389:
390: out[outOffset++] = (byte) (D1);
391: out[outOffset++] = (byte) (D1 >>> 8);
392: out[outOffset++] = (byte) (D1 >>> 16);
393: out[outOffset++] = (byte) (D1 >>> 24);
394:
395: out[outOffset++] = (byte) (D2);
396: out[outOffset++] = (byte) (D2 >>> 8);
397: out[outOffset++] = (byte) (D2 >>> 16);
398: out[outOffset++] = (byte) (D2 >>> 24);
399:
400: out[outOffset++] = (byte) (D3);
401: out[outOffset++] = (byte) (D3 >>> 8);
402: out[outOffset++] = (byte) (D3 >>> 16);
403: out[outOffset] = (byte) (D3 >>> 24);
404: }
405:
406: /** Decrypt exactly one block of ciphertext. */
407: private final void blockDecrypt(byte[] in, int inOffset,
408: byte[] out, int outOffset) {
409: int D0 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
410: | (in[inOffset++] & 0xFF) << 16
411: | (in[inOffset++] & 0xFF) << 24;
412: int D1 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
413: | (in[inOffset++] & 0xFF) << 16
414: | (in[inOffset++] & 0xFF) << 24;
415: int D2 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
416: | (in[inOffset++] & 0xFF) << 16
417: | (in[inOffset++] & 0xFF) << 24;
418: int D3 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
419: | (in[inOffset++] & 0xFF) << 16
420: | (in[inOffset] & 0xFF) << 24;
421:
422: // 1. key addition
423: D0 += K[36];
424: D1 += K[37];
425: D2 += K[38];
426: D3 += K[39];
427:
428: // 2. forward mixing // (1)
429: int i, t;
430: for (i = 7; i >= 0; i--) // (5)
431: {
432: t = D3;
433: D3 = D2;
434: D2 = D1;
435: D1 = D0;
436: D0 = t; // (7)
437: D0 = D0 >>> 24 | D0 << 8; // (9)
438: D3 ^= S[(D0 >>> 8) & 0xFF]; // (11)
439: D3 += S[256 + ((D0 >>> 16) & 0xFF)]; // (12)
440: D2 += S[(D0 >>> 24) & 0xFF]; // (13)
441: D1 ^= S[256 + (D0 & 0xFF)]; // (14)
442: switch (i) {
443: case 2:
444: case 6:
445: D0 += D3;
446: break; // (17)
447: case 3:
448: case 7:
449: D0 += D1;
450: break; // (19)
451: }
452: } // (20)
453:
454: // 3. Keyed transformation
455: int[] ia;
456: for (i = 15; i >= 0; i--) // (22)
457: {
458: t = D3;
459: D3 = D2;
460: D2 = D1;
461: D1 = D0;
462: D0 = t; // (24)
463: D0 = D0 >>> 13 | D0 << 19; // (25)
464: ia = E(D0, K[2 * i + 4], K[2 * i + 5]); // (26)
465: D2 -= ia[1]; // (27)
466: if (i < 8) {
467: D1 -= ia[0]; // (29)
468: D3 ^= ia[2]; // (30)
469: } else {
470: D3 -= ia[0]; // (32)
471: D1 ^= ia[2]; // (33)
472: }
473: } // (35)
474:
475: // 4. Backward mixing
476: for (i = 7; i >= 0; i--) // (37)
477: {
478: t = D3;
479: D3 = D2;
480: D2 = D1;
481: D1 = D0;
482: D0 = t; // (39)
483: switch (i) {
484: case 0:
485: case 4:
486: D0 -= D3;
487: break; // (42)
488: case 1:
489: case 5:
490: D0 -= D1;
491: break; // (44)
492: }
493: D0 = D0 << 24 | D0 >>> 8; // (46)
494: D3 ^= S[256 + ((D0 >>> 24) & 0xFF)]; // (48)
495: D2 -= S[(D0 >>> 16) & 0xFF]; // (49)
496: D1 -= S[256 + ((D0 >>> 8) & 0xFF)]; // (50)
497: D1 ^= S[D0 & 0xFF]; // (51)
498: } // (52)
499:
500: D0 -= K[0];
501: D1 -= K[1];
502: D2 -= K[2];
503: D3 -= K[3];
504:
505: out[outOffset++] = (byte) (D0);
506: out[outOffset++] = (byte) (D0 >>> 8);
507: out[outOffset++] = (byte) (D0 >>> 16);
508: out[outOffset++] = (byte) (D0 >>> 24);
509:
510: out[outOffset++] = (byte) (D1);
511: out[outOffset++] = (byte) (D1 >>> 8);
512: out[outOffset++] = (byte) (D1 >>> 16);
513: out[outOffset++] = (byte) (D1 >>> 24);
514:
515: out[outOffset++] = (byte) (D2);
516: out[outOffset++] = (byte) (D2 >>> 8);
517: out[outOffset++] = (byte) (D2 >>> 16);
518: out[outOffset++] = (byte) (D2 >>> 24);
519:
520: out[outOffset++] = (byte) (D3);
521: out[outOffset++] = (byte) (D3 >>> 8);
522: out[outOffset++] = (byte) (D3 >>> 16);
523: out[outOffset] = (byte) (D3 >>> 24);
524: }
525:
526: private static int[] E(int in, int key1, int key2) {
527: int M = in + key1; // (2)
528: int R = (in << 13 | in >>> 19) * key2; // (3)
529: int i = M & 0x1FF; // (4)
530: int L = S[i]; // (5)
531: R = R << 5 | R >>> 27; // (6)
532: int r = R & 0x1F; // (7)
533: M = M << r | M >>> (32 - r); // (8)
534: L ^= R; // (9)
535: R = R << 5 | R >>> 27; // (10)
536: L ^= R; // (11)
537: r = R & 0x1F; // (12)
538: L = L << r | L >>> (32 - r); // (13)
539: return new int[] { L, M, R }; // (14)
540: }
541: }
|