001: /* $Id: Serpent.java,v 1.1 2004/01/19 02:03:51 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: * A bit-slice implementation in Java of the Serpent cipher.<p>
018: *
019: * Serpent is a 128-bit 32-round block cipher with variable key lengths,
020: * including 128-, 192- and 256-bit
021: * keys conjectured to be at least as secure as three-key triple-DES.<p>
022: *
023: * Serpent was designed by Ross Anderson, Eli Biham and Lars Knudsen as a
024: * candidate algorithm for the NIST AES Quest.<p>
025: *
026: * References:<ol>
027: * <li>Serpent: A New Block Cipher Proposal. This paper was published in the
028: * proceedings of the "Fast Software Encryption Workshop No. 5" held in
029: * Paris in March 1998. LNCS, Springer Verlag.<p>
030: * <li>Reference implementation of the standard Serpent cipher written in C
031: * by <a href="http://www.cl.cam.ac.uk/~fms/"> Frank Stajano</a>.</ol><p>
032: *
033: * @version $Revision: 1.1 $
034: * @author Jeroen C. van Gelderen (gelderen@cryptix.org)
035: * @author Raif S. Naffah
036: * @author Serpent authors (Ross Anderson, Eli Biham and Lars Knudsen)
037: */
038: public final class Serpent extends BlockCipher {
039:
040: // Constants
041: //...........................................................................
042:
043: private static final int BLOCK_SIZE = 16, // bytes in a data-block
044: ROUNDS = 32, // nbr of rounds
045: PHI = 0x9E3779B9; // (sqrt(5) - 1) * 2**31
046:
047: private boolean decrypt;
048:
049: private int[] K = new int[4 * (ROUNDS + 1)];
050:
051: // Constructor
052: //...........................................................................
053:
054: public Serpent() {
055: super (BLOCK_SIZE);
056: }
057:
058: // BlockCipher abstract method implementation
059: //...........................................................................
060:
061: protected void coreInit(Key key, boolean decrypt)
062: throws InvalidKeyException {
063: if (key == null)
064: throw new InvalidKeyException("key: key is null");
065:
066: if (!key.getFormat().equalsIgnoreCase("RAW"))
067: throw new InvalidKeyException(
068: "key: wrong format, RAW needed");
069:
070: byte[] userkey = key.getEncoded();
071: if (userkey == null)
072: throw new InvalidKeyException("RAW bytes missing");
073:
074: int len = userkey.length;
075: if (len != 16 && len != 24 && len != 32)
076: throw new InvalidKeyException("Invalid user key length");
077:
078: generateSubKeys(userkey);
079: this .decrypt = decrypt;
080: }
081:
082: protected void coreCrypt(byte[] in, int inOffset, byte[] out,
083: int outOffset) {
084: if (decrypt)
085: blockDecrypt(in, inOffset, out, outOffset);
086: else
087: blockEncrypt(in, inOffset, out, outOffset);
088: }
089:
090: /**
091: * An array of 8 (number of rounds/4) S boxes.<p>
092: *
093: * An S box is an array of 16 distinct quantities, each in the range 0-15.
094: * A value v at position p for a given S box, implies that if this S box
095: * is given on input a value p, it will return the value v.
096: *
097: * Original S box data below. We use a more compact encoding that is
098: * expanded in a static initializer.
099: *
100: * { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 }, // S0
101: * {15,12, 2, 7, 9, 0, 5,10, 1,11,14, 8, 6,13, 3, 4 }, // S1
102: * { 8, 6, 7, 9, 3,12,10,15,13, 1,14, 4, 0,11, 5, 2 }, // S2
103: * { 0,15,11, 8,12, 9, 6, 3,13, 1, 2, 4,10, 7, 5,14 }, // S3
104: * { 1,15, 8, 3,12, 0,11, 6, 2, 5, 4,10, 9,14, 7,13 }, // S4
105: * {15, 5, 2,11, 4,10, 9,12, 0, 3,14, 8,13, 6, 7, 1 }, // S5
106: * { 7, 2,12, 5, 8, 4, 6,11,14, 9, 1,15,13, 3,10, 0 }, // S6
107: * { 1,13,15, 0,14, 8, 2,11, 7, 4,12,10, 9, 3, 5, 6 } // S7
108: */
109: private static final byte[][] Sbox;
110:
111: static {
112: Sbox = new byte[8][16];
113:
114: String SBOX_INIT = "\u0038\u00f1\u00a6\u005b\u00ed\u0042\u0070\u009c"
115: + "\u00fc\u0027\u0090\u005a\u001b\u00e8\u006d\u0034"
116: + "\u0086\u0079\u003c\u00af\u00d1\u00e4\u000b\u0052"
117: + "\u000f\u00b8\u00c9\u0063\u00d1\u0024\u00a7\u005e"
118: + "\u001f\u0083\u00c0\u00b6\u0025\u004a\u009e\u007d"
119: + "\u00f5\u002b\u004a\u009c\u0003\u00e8\u00d6\u0071"
120: + "\u0072\u00c5\u0084\u006b\u00e9\u001f\u00d3\u00a0"
121: + "\u001d\u00f0\u00e8\u002b\u0074\u00ca\u0093\u0056";
122:
123: for (int i = 0; i < 8; i++)
124: for (int j = 0; j < 16;) {
125: int ci = (i * 8) + (j / 2);
126: Sbox[i][j] = (byte) (SBOX_INIT.charAt(ci) >>> 4);
127: j++;
128: Sbox[i][j] = (byte) (SBOX_INIT.charAt(ci) & 0xF);
129: j++;
130: }
131: }
132:
133: // Implementation
134: //...........................................................................
135:
136: /**
137: * Expand a user-supplied key material into a session key.
138: *
139: * @param key The user-key bytes (multiples of 4) to use.
140: */
141: private final void generateSubKeys(byte[] key) {
142: // compute prekeys w[]:
143: // (a) from user key material
144: this .K = new int[4 * (ROUNDS + 1)];
145: int[] w = this .K;
146:
147: int limit = key.length / 4;
148: int offset = key.length - 1;
149: int i, j, t;
150: for (i = 0; i < limit; i++)
151: w[i] = (key[offset--] & 0xFF) | (key[offset--] & 0xFF) << 8
152: | (key[offset--] & 0xFF) << 16
153: | (key[offset--] & 0xFF) << 24;
154:
155: if (i < 8)
156: w[i++] = 1;
157:
158: // (b) and expanding them to full 132 x 32-bit material
159: // this is a literal implementation of the Serpent paper
160: // (section 4 The Key Schedule, p.226)
161: //
162: // start by computing the first 8 values using the second
163: // lot of 8 values as an intermediary buffer
164: for (i = 8, j = 0; i < 16; i++) {
165: t = w[j] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ j++;
166: w[i] = t << 11 | t >>> 21;
167: }
168:
169: // translate the buffer by -8
170: for (i = 0, j = 8; i < 8;)
171: w[i++] = w[j++];
172:
173: limit = 4 * (ROUNDS + 1); // 132 for a 32-round Serpent
174:
175: // finish computing the remaining intermediary subkeys
176: for (; i < limit; i++) {
177: t = w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i;
178: w[i] = t << 11 | t >>> 21;
179: }
180:
181: // compute intermediary key. use the same array as prekeys
182: int x0, x1, x2, x3, y0, y1, y2, y3, z;
183: byte[] sb;
184: for (i = 0; i < ROUNDS + 1; i++) {
185: x0 = w[4 * i];
186: x1 = w[4 * i + 1];
187: x2 = w[4 * i + 2];
188: x3 = w[4 * i + 3];
189: y0 = y1 = y2 = y3 = 0;
190: sb = Sbox[(ROUNDS + 3 - i) % 8];
191: for (j = 0; j < 32; j++) {
192: z = sb[((x0 >>> j) & 0x01) | ((x1 >>> j) & 0x01) << 1
193: | ((x2 >>> j) & 0x01) << 2
194: | ((x3 >>> j) & 0x01) << 3];
195: y0 |= (z & 0x01) << j;
196: y1 |= ((z >>> 1) & 0x01) << j;
197: y2 |= ((z >>> 2) & 0x01) << j;
198: y3 |= ((z >>> 3) & 0x01) << j;
199: }
200: w[4 * i] = y0;
201: w[4 * i + 1] = y1;
202: w[4 * i + 2] = y2;
203: w[4 * i + 3] = y3;
204: }
205: }
206:
207: /**
208: * Encrypt exactly one block of plaintext.
209: *
210: * @param in The plaintext.
211: * @param inOffset Index of in from which to start considering data.
212: * @param sessionKey The session key to use for encryption.
213: * @return The ciphertext generated from a plaintext using the session key.
214: */
215: private final void blockEncrypt(byte[] in, int inOffset,
216: byte[] out, int outOffset) {
217: int x3 = (in[inOffset++] & 0xFF) << 24
218: | (in[inOffset++] & 0xFF) << 16
219: | (in[inOffset++] & 0xFF) << 8
220: | (in[inOffset++] & 0xFF);
221: int x2 = (in[inOffset++] & 0xFF) << 24
222: | (in[inOffset++] & 0xFF) << 16
223: | (in[inOffset++] & 0xFF) << 8
224: | (in[inOffset++] & 0xFF);
225: int x1 = (in[inOffset++] & 0xFF) << 24
226: | (in[inOffset++] & 0xFF) << 16
227: | (in[inOffset++] & 0xFF) << 8
228: | (in[inOffset++] & 0xFF);
229: int x0 = (in[inOffset++] & 0xFF) << 24
230: | (in[inOffset++] & 0xFF) << 16
231: | (in[inOffset++] & 0xFF) << 8
232: | (in[inOffset++] & 0xFF);
233:
234: int y0 = 0, y1 = 0, y2 = 0, y3 = 0, z;
235:
236: int t00, t01, t02, t03, t04, t05, t06, t07, t08, t09, t10;
237: int t11, t12, t13, t14, t15, t16, t17, t18, t19;
238:
239: int idxK = 0;
240:
241: for (int i = 0; i < 4; i++) {
242: x0 ^= K[idxK++];
243: x1 ^= K[idxK++];
244: x2 ^= K[idxK++];
245: x3 ^= K[idxK++];
246:
247: // S0: 3 8 15 1 10 6 5 11 14 13 4 2 7 0 9 12
248: // depth = 5,7,4,2, Total gates=18
249: t01 = x1 ^ x2;
250: t02 = x0 | x3;
251: t03 = x0 ^ x1;
252: y3 = t02 ^ t01;
253: t05 = x2 | y3;
254: t06 = x0 ^ x3;
255: t07 = x1 | x2;
256: t08 = x3 & t05;
257: t09 = t03 & t07;
258: y2 = t09 ^ t08;
259: t11 = t09 & y2;
260: t12 = x2 ^ x3;
261: t13 = t07 ^ t11;
262: t14 = x1 & t06;
263: t15 = t06 ^ t13;
264: y0 = ~t15;
265: t17 = y0 ^ t14;
266: y1 = t12 ^ t17;
267:
268: x0 = ((((y0)) << (13)) | (((y0)) >>> (32 - (13))));
269: x2 = ((((y2)) << (3)) | (((y2)) >>> (32 - (3))));
270: x1 = y1 ^ x0 ^ x2;
271: x3 = y3 ^ x2 ^ (x0) << 3;
272: x1 = ((((x1)) << (1)) | (((x1)) >>> (32 - (1))));
273: x3 = ((((x3)) << (7)) | (((x3)) >>> (32 - (7))));
274: x0 = x0 ^ x1 ^ x3;
275: x2 = x2 ^ x3 ^ (x1 << 7);
276: x0 = ((((x0)) << (5)) | (((x0)) >>> (32 - (5))));
277: x2 = ((((x2)) << (22)) | (((x2)) >>> (32 - (22))));
278: x0 ^= K[idxK++];
279: x1 ^= K[idxK++];
280: x2 ^= K[idxK++];
281: x3 ^= K[idxK++];
282:
283: // S1: 15 12 2 7 9 0 5 10 1 11 14 8 6 13 3 4
284: // depth = 10,7,3,5, Total gates=18
285: t01 = x0 | x3;
286: t02 = x2 ^ x3;
287: t03 = ~x1;
288: t04 = x0 ^ x2;
289: t05 = x0 | t03;
290: t06 = x3 & t04;
291: t07 = t01 & t02;
292: t08 = x1 | t06;
293: y2 = t02 ^ t05;
294: t10 = t07 ^ t08;
295: t11 = t01 ^ t10;
296: t12 = y2 ^ t11;
297: t13 = x1 & x3;
298: y3 = ~t10;
299: y1 = t13 ^ t12;
300: t16 = t10 | y1;
301: t17 = t05 & t16;
302: y0 = x2 ^ t17;
303:
304: x0 = ((((y0)) << (13)) | (((y0)) >>> (32 - (13))));
305: x2 = ((((y2)) << (3)) | (((y2)) >>> (32 - (3))));
306: x1 = y1 ^ x0 ^ x2;
307: x3 = y3 ^ x2 ^ (x0) << 3;
308: x1 = ((((x1)) << (1)) | (((x1)) >>> (32 - (1))));
309: x3 = ((((x3)) << (7)) | (((x3)) >>> (32 - (7))));
310: x0 = x0 ^ x1 ^ x3;
311: x2 = x2 ^ x3 ^ (x1 << 7);
312: x0 = ((((x0)) << (5)) | (((x0)) >>> (32 - (5))));
313: x2 = ((((x2)) << (22)) | (((x2)) >>> (32 - (22))));
314: x0 ^= K[idxK++];
315: x1 ^= K[idxK++];
316: x2 ^= K[idxK++];
317: x3 ^= K[idxK++];
318:
319: // S2: 8 6 7 9 3 12 10 15 13 1 14 4 0 11 5 2
320: // depth = 3,8,11,7, Total gates=16
321: t01 = x0 | x2;
322: t02 = x0 ^ x1;
323: t03 = x3 ^ t01;
324: y0 = t02 ^ t03;
325: t05 = x2 ^ y0;
326: t06 = x1 ^ t05;
327: t07 = x1 | t05;
328: t08 = t01 & t06;
329: t09 = t03 ^ t07;
330: t10 = t02 | t09;
331: y1 = t10 ^ t08;
332: t12 = x0 | x3;
333: t13 = t09 ^ y1;
334: t14 = x1 ^ t13;
335: y3 = ~t09;
336: y2 = t12 ^ t14;
337:
338: x0 = ((((y0)) << (13)) | (((y0)) >>> (32 - (13))));
339: x2 = ((((y2)) << (3)) | (((y2)) >>> (32 - (3))));
340: x1 = y1 ^ x0 ^ x2;
341: x3 = y3 ^ x2 ^ (x0) << 3;
342: x1 = ((((x1)) << (1)) | (((x1)) >>> (32 - (1))));
343: x3 = ((((x3)) << (7)) | (((x3)) >>> (32 - (7))));
344: x0 = x0 ^ x1 ^ x3;
345: x2 = x2 ^ x3 ^ (x1 << 7);
346: x0 = ((((x0)) << (5)) | (((x0)) >>> (32 - (5))));
347: x2 = ((((x2)) << (22)) | (((x2)) >>> (32 - (22))));
348: x0 ^= K[idxK++];
349: x1 ^= K[idxK++];
350: x2 ^= K[idxK++];
351: x3 ^= K[idxK++];
352:
353: // S3: 0 15 11 8 12 9 6 3 13 1 2 4 10 7 5 14
354: // depth = 8,3,5,5, Total gates=18 */
355: t01 = x0 ^ x2;
356: t02 = x0 | x3;
357: t03 = x0 & x3;
358: t04 = t01 & t02;
359: t05 = x1 | t03;
360: t06 = x0 & x1;
361: t07 = x3 ^ t04;
362: t08 = x2 | t06;
363: t09 = x1 ^ t07;
364: t10 = x3 & t05;
365: t11 = t02 ^ t10;
366: y3 = t08 ^ t09;
367: t13 = x3 | y3;
368: t14 = x0 | t07;
369: t15 = x1 & t13;
370: y2 = t08 ^ t11;
371: y0 = t14 ^ t15;
372: y1 = t05 ^ t04;
373:
374: x0 = ((((y0)) << (13)) | (((y0)) >>> (32 - (13))));
375: x2 = ((((y2)) << (3)) | (((y2)) >>> (32 - (3))));
376: x1 = y1 ^ x0 ^ x2;
377: x3 = y3 ^ x2 ^ (x0) << 3;
378: x1 = ((((x1)) << (1)) | (((x1)) >>> (32 - (1))));
379: x3 = ((((x3)) << (7)) | (((x3)) >>> (32 - (7))));
380: x0 = x0 ^ x1 ^ x3;
381: x2 = x2 ^ x3 ^ (x1 << 7);
382: x0 = ((((x0)) << (5)) | (((x0)) >>> (32 - (5))));
383: x2 = ((((x2)) << (22)) | (((x2)) >>> (32 - (22))));
384: x0 ^= K[idxK++];
385: x1 ^= K[idxK++];
386: x2 ^= K[idxK++];
387: x3 ^= K[idxK++];
388:
389: // S4: 1 15 8 3 12 0 11 6 2 5 4 10 9 14 7 13
390: // depth = 6,7,5,3, Total gates=19
391:
392: t01 = x0 | x1;
393: t02 = x1 | x2;
394: t03 = x0 ^ t02;
395: t04 = x1 ^ x3;
396: t05 = x3 | t03;
397: t06 = x3 & t01;
398: y3 = t03 ^ t06;
399: t08 = y3 & t04;
400: t09 = t04 & t05;
401: t10 = x2 ^ t06;
402: t11 = x1 & x2;
403: t12 = t04 ^ t08;
404: t13 = t11 | t03;
405: t14 = t10 ^ t09;
406: t15 = x0 & t05;
407: t16 = t11 | t12;
408: y2 = t13 ^ t08;
409: y1 = t15 ^ t16;
410: y0 = ~t14;
411:
412: x0 = ((((y0)) << (13)) | (((y0)) >>> (32 - (13))));
413: x2 = ((((y2)) << (3)) | (((y2)) >>> (32 - (3))));
414: x1 = y1 ^ x0 ^ x2;
415: x3 = y3 ^ x2 ^ (x0) << 3;
416: x1 = ((((x1)) << (1)) | (((x1)) >>> (32 - (1))));
417: x3 = ((((x3)) << (7)) | (((x3)) >>> (32 - (7))));
418: x0 = x0 ^ x1 ^ x3;
419: x2 = x2 ^ x3 ^ (x1 << 7);
420: x0 = ((((x0)) << (5)) | (((x0)) >>> (32 - (5))));
421: x2 = ((((x2)) << (22)) | (((x2)) >>> (32 - (22))));
422: x0 ^= K[idxK++];
423: x1 ^= K[idxK++];
424: x2 ^= K[idxK++];
425: x3 ^= K[idxK++];
426:
427: // S5: 15 5 2 11 4 10 9 12 0 3 14 8 13 6 7 1
428: // depth = 4,6,8,6, Total gates=17
429: t01 = x1 ^ x3;
430: t02 = x1 | x3;
431: t03 = x0 & t01;
432: t04 = x2 ^ t02;
433: t05 = t03 ^ t04;
434: y0 = ~t05;
435: t07 = x0 ^ t01;
436: t08 = x3 | y0;
437: t09 = x1 | t05;
438: t10 = x3 ^ t08;
439: t11 = x1 | t07;
440: t12 = t03 | y0;
441: t13 = t07 | t10;
442: t14 = t01 ^ t11;
443: y2 = t09 ^ t13;
444: y1 = t07 ^ t08;
445: y3 = t12 ^ t14;
446:
447: x0 = ((((y0)) << (13)) | (((y0)) >>> (32 - (13))));
448: x2 = ((((y2)) << (3)) | (((y2)) >>> (32 - (3))));
449: x1 = y1 ^ x0 ^ x2;
450: x3 = y3 ^ x2 ^ (x0) << 3;
451: x1 = ((((x1)) << (1)) | (((x1)) >>> (32 - (1))));
452: x3 = ((((x3)) << (7)) | (((x3)) >>> (32 - (7))));
453: x0 = x0 ^ x1 ^ x3;
454: x2 = x2 ^ x3 ^ (x1 << 7);
455: x0 = ((((x0)) << (5)) | (((x0)) >>> (32 - (5))));
456: x2 = ((((x2)) << (22)) | (((x2)) >>> (32 - (22))));
457: x0 ^= K[idxK++];
458: x1 ^= K[idxK++];
459: x2 ^= K[idxK++];
460: x3 ^= K[idxK++];
461:
462: // S6: 7 2 12 5 8 4 6 11 14 9 1 15 13 3 10 0
463: // depth = 8,3,6,3, Total gates=19
464: t01 = x0 & x3;
465: t02 = x1 ^ x2;
466: t03 = x0 ^ x3;
467: t04 = t01 ^ t02;
468: t05 = x1 | x2;
469: y1 = ~t04;
470: t07 = t03 & t05;
471: t08 = x1 & y1;
472: t09 = x0 | x2;
473: t10 = t07 ^ t08;
474: t11 = x1 | x3;
475: t12 = x2 ^ t11;
476: t13 = t09 ^ t10;
477: y2 = ~t13;
478: t15 = y1 & t03;
479: y3 = t12 ^ t07;
480: t17 = x0 ^ x1;
481: t18 = y2 ^ t15;
482: y0 = t17 ^ t18;
483:
484: x0 = ((((y0)) << (13)) | (((y0)) >>> (32 - (13))));
485: x2 = ((((y2)) << (3)) | (((y2)) >>> (32 - (3))));
486: x1 = y1 ^ x0 ^ x2;
487: x3 = y3 ^ x2 ^ (x0) << 3;
488: x1 = ((((x1)) << (1)) | (((x1)) >>> (32 - (1))));
489: x3 = ((((x3)) << (7)) | (((x3)) >>> (32 - (7))));
490: x0 = x0 ^ x1 ^ x3;
491: x2 = x2 ^ x3 ^ (x1 << 7);
492: x0 = ((((x0)) << (5)) | (((x0)) >>> (32 - (5))));
493: x2 = ((((x2)) << (22)) | (((x2)) >>> (32 - (22))));
494: x0 ^= K[idxK++];
495: x1 ^= K[idxK++];
496: x2 ^= K[idxK++];
497: x3 ^= K[idxK++];
498:
499: // S7: 1 13 15 0 14 8 2 11 7 4 12 10 9 3 5 6
500: // depth = 10,7,10,4, Total gates=19
501: t01 = x0 & x2;
502: t02 = ~x3;
503: t03 = x0 & t02;
504: t04 = x1 | t01;
505: t05 = x0 & x1;
506: t06 = x2 ^ t04;
507: y3 = t03 ^ t06;
508: t08 = x2 | y3;
509: t09 = x3 | t05;
510: t10 = x0 ^ t08;
511: t11 = t04 & y3;
512: y1 = t09 ^ t10;
513: t13 = x1 ^ y1;
514: t14 = t01 ^ y1;
515: t15 = x2 ^ t05;
516: t16 = t11 | t13;
517: t17 = t02 | t14;
518: y0 = t15 ^ t17;
519: y2 = x0 ^ t16;
520:
521: if (i == 3)
522: break;
523:
524: x0 = ((((y0)) << (13)) | (((y0)) >>> (32 - (13))));
525: x2 = ((((y2)) << (3)) | (((y2)) >>> (32 - (3))));
526: x1 = y1 ^ x0 ^ x2;
527: x3 = y3 ^ x2 ^ (x0) << 3;
528: x1 = ((((x1)) << (1)) | (((x1)) >>> (32 - (1))));
529: x3 = ((((x3)) << (7)) | (((x3)) >>> (32 - (7))));
530: x0 = x0 ^ x1 ^ x3;
531: x2 = x2 ^ x3 ^ (x1 << 7);
532: x0 = ((((x0)) << (5)) | (((x0)) >>> (32 - (5))));
533: x2 = ((((x2)) << (22)) | (((x2)) >>> (32 - (22))));
534: }
535:
536: y0 ^= K[idxK++];
537: y1 ^= K[idxK++];
538: y2 ^= K[idxK++];
539: y3 ^= K[idxK];
540:
541: out[outOffset++] = (byte) (y3 >>> 24);
542: out[outOffset++] = (byte) (y3 >>> 16);
543: out[outOffset++] = (byte) (y3 >>> 8);
544: out[outOffset++] = (byte) (y3);
545:
546: out[outOffset++] = (byte) (y2 >>> 24);
547: out[outOffset++] = (byte) (y2 >>> 16);
548: out[outOffset++] = (byte) (y2 >>> 8);
549: out[outOffset++] = (byte) (y2);
550:
551: out[outOffset++] = (byte) (y1 >>> 24);
552: out[outOffset++] = (byte) (y1 >>> 16);
553: out[outOffset++] = (byte) (y1 >>> 8);
554: out[outOffset++] = (byte) (y1);
555:
556: out[outOffset++] = (byte) (y0 >>> 24);
557: out[outOffset++] = (byte) (y0 >>> 16);
558: out[outOffset++] = (byte) (y0 >>> 8);
559: out[outOffset] = (byte) (y0);
560: }
561:
562: /**
563: * Decrypt exactly one block of ciphertext.
564: *
565: * @param in The ciphertext.
566: * @param inOffset Index of in from which to start considering data.
567: * @param sessionKey The session key to use for decryption.
568: * @return The plaintext generated from a ciphertext using the session key.
569: */
570: private final void blockDecrypt(byte[] in, int inOffset,
571: byte[] out, int outOffset) {
572: int x3 = (in[inOffset++] & 0xFF) << 24
573: | (in[inOffset++] & 0xFF) << 16
574: | (in[inOffset++] & 0xFF) << 8
575: | (in[inOffset++] & 0xFF);
576: int x2 = (in[inOffset++] & 0xFF) << 24
577: | (in[inOffset++] & 0xFF) << 16
578: | (in[inOffset++] & 0xFF) << 8
579: | (in[inOffset++] & 0xFF);
580: int x1 = (in[inOffset++] & 0xFF) << 24
581: | (in[inOffset++] & 0xFF) << 16
582: | (in[inOffset++] & 0xFF) << 8
583: | (in[inOffset++] & 0xFF);
584: int x0 = (in[inOffset++] & 0xFF) << 24
585: | (in[inOffset++] & 0xFF) << 16
586: | (in[inOffset++] & 0xFF) << 8
587: | (in[inOffset++] & 0xFF);
588:
589: int y0 = 0, y1 = 0, y2 = 0, y3 = 0, z;
590: int t00, t01, t02, t03, t04, t05, t06, t07, t08, t09, t10;
591: int t11, t12, t13, t14, t15, t16, t17, t18, t19;
592:
593: int idxK = 32 * 4 + 3;
594:
595: x3 ^= K[idxK--];
596: x2 ^= K[idxK--];
597: x1 ^= K[idxK--];
598: x0 ^= K[idxK--];
599:
600: for (int i = 0; i < 4; i++) {
601: // InvS7: 3 0 6 13 9 14 15 8 5 12 11 7 10 1 4 2
602: // depth = 9,7,3,3, Total gates=18
603: t01 = x0 & x1;
604: t02 = x0 | x1;
605: t03 = x2 | t01;
606: t04 = x3 & t02;
607: y3 = t03 ^ t04;
608: t06 = x1 ^ t04;
609: t07 = x3 ^ y3;
610: t08 = ~t07;
611: t09 = t06 | t08;
612: t10 = x1 ^ x3;
613: t11 = x0 | x3;
614: y1 = x0 ^ t09;
615: t13 = x2 ^ t06;
616: t14 = x2 & t11;
617: t15 = x3 | y1;
618: t16 = t01 | t10;
619: y0 = t13 ^ t15;
620: y2 = t14 ^ t16;
621:
622: y3 ^= K[idxK--];
623: y2 ^= K[idxK--];
624: y1 ^= K[idxK--];
625: y0 ^= K[idxK--];
626:
627: x2 = ((((y2)) << (32 - (22))) | (((y2)) >>> (22)));
628: x0 = ((((y0)) << (32 - (5))) | (((y0)) >>> (5)));
629: x2 = x2 ^ y3 ^ (y1 << 7);
630: x0 = x0 ^ y1 ^ y3;
631: x3 = ((((y3)) << (32 - (7))) | (((y3)) >>> (7)));
632: x1 = ((((y1)) << (32 - (1))) | (((y1)) >>> (1)));
633: x3 = x3 ^ x2 ^ (x0) << 3;
634: x1 = x1 ^ x0 ^ x2;
635: x2 = ((((x2)) << (32 - (3))) | (((x2)) >>> (3)));
636: x0 = ((((x0)) << (32 - (13))) | (((x0)) >>> (13)));
637:
638: // InvS6: 15 10 1 13 5 3 6 0 4 9 14 7 2 12 8 11
639: // depth = 5,3,8,6, Total gates=19
640: t01 = x0 ^ x2;
641: t02 = ~x2;
642: t03 = x1 & t01;
643: t04 = x1 | t02;
644: t05 = x3 | t03;
645: t06 = x1 ^ x3;
646: t07 = x0 & t04;
647: t08 = x0 | t02;
648: t09 = t07 ^ t05;
649: y1 = t06 ^ t08;
650: y0 = ~t09;
651: t12 = x1 & y0;
652: t13 = t01 & t05;
653: t14 = t01 ^ t12;
654: t15 = t07 ^ t13;
655: t16 = x3 | t02;
656: t17 = x0 ^ y1;
657: y3 = t17 ^ t15;
658: y2 = t16 ^ t14;
659:
660: y3 ^= K[idxK--];
661: y2 ^= K[idxK--];
662: y1 ^= K[idxK--];
663: y0 ^= K[idxK--];
664:
665: x2 = ((((y2)) << (32 - (22))) | (((y2)) >>> (22)));
666: x0 = ((((y0)) << (32 - (5))) | (((y0)) >>> (5)));
667: x2 = x2 ^ y3 ^ (y1 << 7);
668: x0 = x0 ^ y1 ^ y3;
669: x3 = ((((y3)) << (32 - (7))) | (((y3)) >>> (7)));
670: x1 = ((((y1)) << (32 - (1))) | (((y1)) >>> (1)));
671: x3 = x3 ^ x2 ^ (x0) << 3;
672: x1 = x1 ^ x0 ^ x2;
673: x2 = ((((x2)) << (32 - (3))) | (((x2)) >>> (3)));
674: x0 = ((((x0)) << (32 - (13))) | (((x0)) >>> (13)));
675:
676: // InvS5: 8 15 2 9 4 1 13 14 11 6 5 3 7 12 10 0
677: // depth = 4,6,9,7, Total gates=17
678: t01 = x0 & x3;
679: t02 = x2 ^ t01;
680: t03 = x0 ^ x3;
681: t04 = x1 & t02;
682: t05 = x0 & x2;
683: y0 = t03 ^ t04;
684: t07 = x0 & y0;
685: t08 = t01 ^ y0;
686: t09 = x1 | t05;
687: t10 = ~x1;
688: y1 = t08 ^ t09;
689: t12 = t10 | t07;
690: t13 = y0 | y1;
691: y3 = t02 ^ t12;
692: t15 = t02 ^ t13;
693: t16 = x1 ^ x3;
694: y2 = t16 ^ t15;
695:
696: y3 ^= K[idxK--];
697: y2 ^= K[idxK--];
698: y1 ^= K[idxK--];
699: y0 ^= K[idxK--];
700:
701: x2 = ((((y2)) << (32 - (22))) | (((y2)) >>> (22)));
702: x0 = ((((y0)) << (32 - (5))) | (((y0)) >>> (5)));
703: x2 = x2 ^ y3 ^ (y1 << 7);
704: x0 = x0 ^ y1 ^ y3;
705: x3 = ((((y3)) << (32 - (7))) | (((y3)) >>> (7)));
706: x1 = ((((y1)) << (32 - (1))) | (((y1)) >>> (1)));
707: x3 = x3 ^ x2 ^ (x0) << 3;
708: x1 = x1 ^ x0 ^ x2;
709: x2 = ((((x2)) << (32 - (3))) | (((x2)) >>> (3)));
710: x0 = ((((x0)) << (32 - (13))) | (((x0)) >>> (13)));
711:
712: // InvS4: 5 0 8 3 10 9 7 14 2 12 11 6 4 15 13 1
713: // depth = 6,4,7,3, Total gates=17
714: t01 = x1 | x3;
715: t02 = x2 | x3;
716: t03 = x0 & t01;
717: t04 = x1 ^ t02;
718: t05 = x2 ^ x3;
719: t06 = ~t03;
720: t07 = x0 & t04;
721: y1 = t05 ^ t07;
722: t09 = y1 | t06;
723: t10 = x0 ^ t07;
724: t11 = t01 ^ t09;
725: t12 = x3 ^ t04;
726: t13 = x2 | t10;
727: y3 = t03 ^ t12;
728: t15 = x0 ^ t04;
729: y2 = t11 ^ t13;
730: y0 = t15 ^ t09;
731:
732: y3 ^= K[idxK--];
733: y2 ^= K[idxK--];
734: y1 ^= K[idxK--];
735: y0 ^= K[idxK--];
736:
737: x2 = ((((y2)) << (32 - (22))) | (((y2)) >>> (22)));
738: x0 = ((((y0)) << (32 - (5))) | (((y0)) >>> (5)));
739: x2 = x2 ^ y3 ^ (y1 << 7);
740: x0 = x0 ^ y1 ^ y3;
741: x3 = ((((y3)) << (32 - (7))) | (((y3)) >>> (7)));
742: x1 = ((((y1)) << (32 - (1))) | (((y1)) >>> (1)));
743: x3 = x3 ^ x2 ^ (x0) << 3;
744: x1 = x1 ^ x0 ^ x2;
745: x2 = ((((x2)) << (32 - (3))) | (((x2)) >>> (3)));
746: x0 = ((((x0)) << (32 - (13))) | (((x0)) >>> (13)));
747:
748: // InvS3: 0 9 10 7 11 14 6 13 3 5 12 2 4 8 15 1
749: // depth = 3,6,4,4, Total gates=17
750: t01 = x2 | x3;
751: t02 = x0 | x3;
752: t03 = x2 ^ t02;
753: t04 = x1 ^ t02;
754: t05 = x0 ^ x3;
755: t06 = t04 & t03;
756: t07 = x1 & t01;
757: y2 = t05 ^ t06;
758: t09 = x0 ^ t03;
759: y0 = t07 ^ t03;
760: t11 = y0 | t05;
761: t12 = t09 & t11;
762: t13 = x0 & y2;
763: t14 = t01 ^ t05;
764: y1 = x1 ^ t12;
765: t16 = x1 | t13;
766: y3 = t14 ^ t16;
767:
768: y3 ^= K[idxK--];
769: y2 ^= K[idxK--];
770: y1 ^= K[idxK--];
771: y0 ^= K[idxK--];
772:
773: x2 = ((((y2)) << (32 - (22))) | (((y2)) >>> (22)));
774: x0 = ((((y0)) << (32 - (5))) | (((y0)) >>> (5)));
775: x2 = x2 ^ y3 ^ (y1 << 7);
776: x0 = x0 ^ y1 ^ y3;
777: x3 = ((((y3)) << (32 - (7))) | (((y3)) >>> (7)));
778: x1 = ((((y1)) << (32 - (1))) | (((y1)) >>> (1)));
779: x3 = x3 ^ x2 ^ (x0) << 3;
780: x1 = x1 ^ x0 ^ x2;
781: x2 = ((((x2)) << (32 - (3))) | (((x2)) >>> (3)));
782: x0 = ((((x0)) << (32 - (13))) | (((x0)) >>> (13)));
783:
784: // InvS2: 12 9 15 4 11 14 1 2 0 3 6 13 5 8 10 7
785: // depth = 3,6,8,3, Total gates=18
786: t01 = x0 ^ x3;
787: t02 = x2 ^ x3;
788: t03 = x0 & x2;
789: t04 = x1 | t02;
790: y0 = t01 ^ t04;
791: t06 = x0 | x2;
792: t07 = x3 | y0;
793: t08 = ~x3;
794: t09 = x1 & t06;
795: t10 = t08 | t03;
796: t11 = x1 & t07;
797: t12 = t06 & t02;
798: y3 = t09 ^ t10;
799: y1 = t12 ^ t11;
800: t15 = x2 & y3;
801: t16 = y0 ^ y1;
802: t17 = t10 ^ t15;
803: y2 = t16 ^ t17;
804:
805: y3 ^= K[idxK--];
806: y2 ^= K[idxK--];
807: y1 ^= K[idxK--];
808: y0 ^= K[idxK--];
809:
810: x2 = ((((y2)) << (32 - (22))) | (((y2)) >>> (22)));
811: x0 = ((((y0)) << (32 - (5))) | (((y0)) >>> (5)));
812: x2 = x2 ^ y3 ^ (y1 << 7);
813: x0 = x0 ^ y1 ^ y3;
814: x3 = ((((y3)) << (32 - (7))) | (((y3)) >>> (7)));
815: x1 = ((((y1)) << (32 - (1))) | (((y1)) >>> (1)));
816: x3 = x3 ^ x2 ^ (x0) << 3;
817: x1 = x1 ^ x0 ^ x2;
818: x2 = ((((x2)) << (32 - (3))) | (((x2)) >>> (3)));
819: x0 = ((((x0)) << (32 - (13))) | (((x0)) >>> (13)));
820:
821: // InvS1: 5 8 2 14 15 6 12 3 11 4 7 9 1 13 10 0
822: // depth = 7,4,5,3, Total gates=18
823: t01 = x0 ^ x1;
824: t02 = x1 | x3;
825: t03 = x0 & x2;
826: t04 = x2 ^ t02;
827: t05 = x0 | t04;
828: t06 = t01 & t05;
829: t07 = x3 | t03;
830: t08 = x1 ^ t06;
831: t09 = t07 ^ t06;
832: t10 = t04 | t03;
833: t11 = x3 & t08;
834: y2 = ~t09;
835: y1 = t10 ^ t11;
836: t14 = x0 | y2;
837: t15 = t06 ^ y1;
838: y3 = t01 ^ t04;
839: t17 = x2 ^ t15;
840: y0 = t14 ^ t17;
841:
842: y3 ^= K[idxK--];
843: y2 ^= K[idxK--];
844: y1 ^= K[idxK--];
845: y0 ^= K[idxK--];
846:
847: x2 = ((((y2)) << (32 - (22))) | (((y2)) >>> (22)));
848: x0 = ((((y0)) << (32 - (5))) | (((y0)) >>> (5)));
849: x2 = x2 ^ y3 ^ (y1 << 7);
850: x0 = x0 ^ y1 ^ y3;
851: x3 = ((((y3)) << (32 - (7))) | (((y3)) >>> (7)));
852: x1 = ((((y1)) << (32 - (1))) | (((y1)) >>> (1)));
853: x3 = x3 ^ x2 ^ (x0) << 3;
854: x1 = x1 ^ x0 ^ x2;
855: x2 = ((((x2)) << (32 - (3))) | (((x2)) >>> (3)));
856: x0 = ((((x0)) << (32 - (13))) | (((x0)) >>> (13)));
857:
858: // InvS0: 13 3 11 0 10 6 5 12 1 14 4 7 15 9 8 2
859: // depth = 8,4,3,6, Total gates=19
860: t01 = x2 ^ x3;
861: t02 = x0 | x1;
862: t03 = x1 | x2;
863: t04 = x2 & t01;
864: t05 = t02 ^ t01;
865: t06 = x0 | t04;
866: y2 = ~t05;
867: t08 = x1 ^ x3;
868: t09 = t03 & t08;
869: t10 = x3 | y2;
870: y1 = t09 ^ t06;
871: t12 = x0 | t05;
872: t13 = y1 ^ t12;
873: t14 = t03 ^ t10;
874: t15 = x0 ^ x2;
875: y3 = t14 ^ t13;
876: t17 = t05 & t13;
877: t18 = t14 | t17;
878: y0 = t15 ^ t18;
879:
880: y3 ^= K[idxK--];
881: y2 ^= K[idxK--];
882: y1 ^= K[idxK--];
883: y0 ^= K[idxK--];
884:
885: if (i == 3)
886: break;
887:
888: x2 = ((((y2)) << (32 - (22))) | (((y2)) >>> (22)));
889: x0 = ((((y0)) << (32 - (5))) | (((y0)) >>> (5)));
890: x2 = x2 ^ y3 ^ (y1 << 7);
891: x0 = x0 ^ y1 ^ y3;
892: x3 = ((((y3)) << (32 - (7))) | (((y3)) >>> (7)));
893: x1 = ((((y1)) << (32 - (1))) | (((y1)) >>> (1)));
894: x3 = x3 ^ x2 ^ (x0) << 3;
895: x1 = x1 ^ x0 ^ x2;
896: x2 = ((((x2)) << (32 - (3))) | (((x2)) >>> (3)));
897: x0 = ((((x0)) << (32 - (13))) | (((x0)) >>> (13)));
898: }
899:
900: out[outOffset++] = (byte) (y3 >>> 24);
901: out[outOffset++] = (byte) (y3 >>> 16);
902: out[outOffset++] = (byte) (y3 >>> 8);
903: out[outOffset++] = (byte) (y3);
904:
905: out[outOffset++] = (byte) (y2 >>> 24);
906: out[outOffset++] = (byte) (y2 >>> 16);
907: out[outOffset++] = (byte) (y2 >>> 8);
908: out[outOffset++] = (byte) (y2);
909:
910: out[outOffset++] = (byte) (y1 >>> 24);
911: out[outOffset++] = (byte) (y1 >>> 16);
912: out[outOffset++] = (byte) (y1 >>> 8);
913: out[outOffset++] = (byte) (y1);
914:
915: out[outOffset++] = (byte) (y0 >>> 24);
916: out[outOffset++] = (byte) (y0 >>> 16);
917: out[outOffset++] = (byte) (y0 >>> 8);
918: out[outOffset] = (byte) (y0);
919: }
920: }
|