001: /* Copyright 2003 Quadcap Software. All rights reserved.
002: *
003: * This software is distributed under the Quadcap Free Software License.
004: * This software may be used or modified for any purpose, personal or
005: * commercial. Open Source redistributions are permitted. Commercial
006: * redistribution of larger works derived from, or works which bundle
007: * this software requires a "Commercial Redistribution License"; see
008: * http://www.quadcap.com/purchase.
009: *
010: * Redistributions qualify as "Open Source" under one of the following terms:
011: *
012: * Redistributions are made at no charge beyond the reasonable cost of
013: * materials and delivery.
014: *
015: * Redistributions are accompanied by a copy of the Source Code or by an
016: * irrevocable offer to provide a copy of the Source Code for up to three
017: * years at the cost of materials and delivery. Such redistributions
018: * must allow further use, modification, and redistribution of the Source
019: * Code under substantially the same terms as this license.
020: *
021: * Redistributions of source code must retain the copyright notices as they
022: * appear in each source code file, these license terms, and the
023: * disclaimer/limitation of liability set forth as paragraph 6 below.
024: *
025: * Redistributions in binary form must reproduce this Copyright Notice,
026: * these license terms, and the disclaimer/limitation of liability set
027: * forth as paragraph 6 below, in the documentation and/or other materials
028: * provided with the distribution.
029: *
030: * The Software is provided on an "AS IS" basis. No warranty is
031: * provided that the Software is free of defects, or fit for a
032: * particular purpose.
033: *
034: * Limitation of Liability. Quadcap Software shall not be liable
035: * for any damages suffered by the Licensee or any third party resulting
036: * from use of the Software.
037: */
038:
039: package com.quadcap.crypto;
040:
041: /*
042: * Public domain SHA implementation.
043: *
044: **/
045:
046: import java.util.Random;
047:
048: import java.nio.ByteBuffer;
049: import java.nio.IntBuffer;
050:
051: import com.quadcap.util.Debug;
052: import com.quadcap.util.text.Text;
053:
054: /* $Id: Rijndael.java,v 1.3 2004/05/16 15:05:10 stan Exp $
055: *
056: * This file is in the public domain.
057: */
058: // package cryptix.provider.cipher;
059: /**
060: * Rijndael --pronounced Reindaal-- is a symmetric cipher with a 128-bit
061: * block size and variable key-size (128-, 192- and 256-bit).
062: * <p>
063: * Rijndael was designed by <a href="mailto:rijmen@esat.kuleuven.ac.be">Vincent
064: * Rijmen</a> and <a href="mailto:daemen.j@protonworld.com">Joan Daemen</a>.
065: * <p>
066: * @version $Revision: 1.3 $
067: * @author Raif S. Naffah
068: * @author Paulo S. L. M. Barreto (pbarreto@cryptix.org)
069: * @author Jeroen C. van Gelderen (gelderen@cryptix.org)
070: * @author Edwin Woudt (edwin@cryptix.org)
071: * @since Cryptix 3.1.3/3.2.0
072: */
073: public class Rijndael extends AbstractSymmetricKey implements
074: SymmetricKey {
075: byte[] keyBytes = null;
076:
077: /**
078: * Default constructor
079: */
080: public Rijndael() {
081: }
082:
083: /**
084: * Initialize key from serialized representation
085: */
086: public void init(String s) throws Exception {
087: String[] v = Text.extractN(s, "*:*");
088: byte[] k = v[1].getBytes();
089: init(k);
090: }
091:
092: /**
093: * Initialize from key bytes
094: */
095: final void init(byte[] k) {
096: try {
097: this .coreInit(k, false);
098: Rijndael decryptor = new Rijndael();
099: decryptor.coreInit(k, true);
100: dkey = new DecryptionKey(decryptor);
101: } catch (Exception e) {
102: Debug.print(e);
103: throw new RuntimeException(e.toString());
104: }
105: }
106:
107: /**
108: * Initialize: Create a random key
109: */
110: public void init(Random r) {
111: byte[] b = new byte[KEYSIZE];
112: r.nextBytes(b);
113: init(b);
114: }
115:
116: /**
117: * Return the serialized form of the key
118: */
119: public String toString() {
120: return "Rijndael:" + new String(keyBytes);
121: }
122:
123: /**
124: * Encrypt a buffer (must be multiple of 8 bytes)
125: */
126: public void encrypt(ByteBuffer m, ByteBuffer c) {
127: while (m.position() < m.limit()) {
128: blockEncrypt(m, c);
129: }
130: }
131:
132: /**
133: * Decrypt a buffer (must be a multiple of 8 bytes)
134: */
135: public void decrypt(ByteBuffer c, ByteBuffer m) {
136: while (c.position() < c.limit()) {
137: blockDecrypt(c, m);
138: }
139: }
140:
141: static final int KEYSIZE = 16; // default, that is.
142:
143: private boolean ROUNDS_12, ROUNDS_14;
144:
145: /** True if in decrypt mode */
146: private boolean decrypt;
147:
148: /** Subkeys */
149: private int[] K;
150:
151: /** (ROUNDS-1) * 4 */
152: private int limit;
153:
154: protected void coreInit(byte[] userKey, boolean decrypt)
155: throws Exception {
156: this .keyBytes = userKey;
157:
158: int len = userKey.length;
159: if (len != 16 && len != 24 && len != 32) {
160: throw new Exception("Invalid user key length");
161: }
162:
163: this .decrypt = decrypt;
164: this .K = makeKey(userKey, decrypt);
165: if (decrypt)
166: invertKey(this .K);
167:
168: ROUNDS_12 = (len >= 24);
169: ROUNDS_14 = (len == 32);
170:
171: this .limit = getRounds(len) * 4;
172: }
173:
174: public int getBlockSize() {
175: return BLOCK_SIZE;
176: }
177:
178: private static final int BLOCK_SIZE = 16; // block size in bytes
179:
180: private static final String SS = "\u637C\u777B\uF26B\u6FC5\u3001\u672B\uFED7\uAB76"
181: + "\uCA82\uC97D\uFA59\u47F0\uADD4\uA2AF\u9CA4\u72C0"
182: + "\uB7FD\u9326\u363F\uF7CC\u34A5\uE5F1\u71D8\u3115"
183: + "\u04C7\u23C3\u1896\u059A\u0712\u80E2\uEB27\uB275"
184: + "\u0983\u2C1A\u1B6E\u5AA0\u523B\uD6B3\u29E3\u2F84"
185: + "\u53D1\u00ED\u20FC\uB15B\u6ACB\uBE39\u4A4C\u58CF"
186: + "\uD0EF\uAAFB\u434D\u3385\u45F9\u027F\u503C\u9FA8"
187: + "\u51A3\u408F\u929D\u38F5\uBCB6\uDA21\u10FF\uF3D2"
188: + "\uCD0C\u13EC\u5F97\u4417\uC4A7\u7E3D\u645D\u1973"
189: + "\u6081\u4FDC\u222A\u9088\u46EE\uB814\uDE5E\u0BDB"
190: + "\uE032\u3A0A\u4906\u245C\uC2D3\uAC62\u9195\uE479"
191: + "\uE7C8\u376D\u8DD5\u4EA9\u6C56\uF4EA\u657A\uAE08"
192: + "\uBA78\u252E\u1CA6\uB4C6\uE8DD\u741F\u4BBD\u8B8A"
193: + "\u703E\uB566\u4803\uF60E\u6135\u57B9\u86C1\u1D9E"
194: + "\uE1F8\u9811\u69D9\u8E94\u9B1E\u87E9\uCE55\u28DF"
195: + "\u8CA1\u890D\uBFE6\u4268\u4199\u2D0F\uB054\uBB16";
196:
197: private static final byte[] S = new byte[256], Si = new byte[256];
198:
199: private static final int[] T1 = new int[256], T2 = new int[256],
200: T3 = new int[256], T4 = new int[256], T5 = new int[256],
201: T6 = new int[256], T7 = new int[256], T8 = new int[256];
202:
203: private static final int[] U1 = new int[256], U2 = new int[256],
204: U3 = new int[256], U4 = new int[256];
205:
206: private static final byte[] rcon = new byte[30];
207:
208: // Static code - to intialise S-boxes and T-boxes
209: //.......................................................................
210:
211: static {
212: int ROOT = 0x11B;
213: int i, j = 0;
214:
215: for (i = 0; i < 256; i++) {
216: int s, s2, s3, i2, i4, i8, i9, ib, id, ie, t;
217: char c = SS.charAt(i >>> 1);
218: S[i] = (byte) (((i & 1) == 0) ? c >>> 8 : c & 0xFF);
219: s = S[i] & 0xFF;
220: Si[s] = (byte) i;
221: s2 = s << 1;
222: if (s2 >= 0x100) {
223: s2 ^= ROOT;
224: }
225: s3 = s2 ^ s;
226: i2 = i << 1;
227: if (i2 >= 0x100) {
228: i2 ^= ROOT;
229: }
230: i4 = i2 << 1;
231: if (i4 >= 0x100) {
232: i4 ^= ROOT;
233: }
234: i8 = i4 << 1;
235: if (i8 >= 0x100) {
236: i8 ^= ROOT;
237: }
238: i9 = i8 ^ i;
239: ib = i9 ^ i2;
240: id = i9 ^ i4;
241: ie = i8 ^ i4 ^ i2;
242:
243: T1[i] = t = (s2 << 24) | (s << 16) | (s << 8) | s3;
244: T2[i] = (t >>> 8) | (t << 24);
245: T3[i] = (t >>> 16) | (t << 16);
246: T4[i] = (t >>> 24) | (t << 8);
247:
248: T5[s] = U1[i] = t = (ie << 24) | (i9 << 16) | (id << 8)
249: | ib;
250: T6[s] = U2[i] = (t >>> 8) | (t << 24);
251: T7[s] = U3[i] = (t >>> 16) | (t << 16);
252: T8[s] = U4[i] = (t >>> 24) | (t << 8);
253: }
254: //
255: // round constants
256: //
257: int r = 1;
258: rcon[0] = 1;
259: for (i = 1; i < 30; i++) {
260: r <<= 1;
261: if (r >= 0x100) {
262: r ^= ROOT;
263: }
264: rcon[i] = (byte) r;
265: }
266:
267: }
268:
269: //...........................................................................
270:
271: /**
272: * Encrypt exactly one block of plaintext.
273: */
274: private void blockEncrypt(ByteBuffer in, ByteBuffer out) {
275: // plaintext to ints + key
276: int keyOffset = 0;
277: int t0 = ((in.get()) << 24 | (in.get() & 0xFF) << 16
278: | (in.get() & 0xFF) << 8 | (in.get() & 0xFF))
279: ^ K[keyOffset++];
280: int t1 = ((in.get()) << 24 | (in.get() & 0xFF) << 16
281: | (in.get() & 0xFF) << 8 | (in.get() & 0xFF))
282: ^ K[keyOffset++];
283: int t2 = ((in.get()) << 24 | (in.get() & 0xFF) << 16
284: | (in.get() & 0xFF) << 8 | (in.get() & 0xFF))
285: ^ K[keyOffset++];
286: int t3 = ((in.get()) << 24 | (in.get() & 0xFF) << 16
287: | (in.get() & 0xFF) << 8 | (in.get() & 0xFF))
288: ^ K[keyOffset++];
289:
290: // apply round transforms
291: while (keyOffset < limit) {
292: int a0, a1, a2;
293: a0 = T1[(t0 >>> 24)] ^ T2[(t1 >>> 16) & 0xFF]
294: ^ T3[(t2 >>> 8) & 0xFF] ^ T4[(t3) & 0xFF]
295: ^ K[keyOffset++];
296: a1 = T1[(t1 >>> 24)] ^ T2[(t2 >>> 16) & 0xFF]
297: ^ T3[(t3 >>> 8) & 0xFF] ^ T4[(t0) & 0xFF]
298: ^ K[keyOffset++];
299: a2 = T1[(t2 >>> 24)] ^ T2[(t3 >>> 16) & 0xFF]
300: ^ T3[(t0 >>> 8) & 0xFF] ^ T4[(t1) & 0xFF]
301: ^ K[keyOffset++];
302: t3 = T1[(t3 >>> 24)] ^ T2[(t0 >>> 16) & 0xFF]
303: ^ T3[(t1 >>> 8) & 0xFF] ^ T4[(t2) & 0xFF]
304: ^ K[keyOffset++];
305: t0 = a0;
306: t1 = a1;
307: t2 = a2;
308: }
309:
310: // last round is special
311: int tt = K[keyOffset++];
312: out.put((byte) (S[(t0 >>> 24)] ^ (tt >>> 24)));
313: out.put((byte) (S[(t1 >>> 16) & 0xFF] ^ (tt >>> 16)));
314: out.put((byte) (S[(t2 >>> 8) & 0xFF] ^ (tt >>> 8)));
315: out.put((byte) (S[(t3) & 0xFF] ^ (tt)));
316: tt = K[keyOffset++];
317: out.put((byte) (S[(t1 >>> 24)] ^ (tt >>> 24)));
318: out.put((byte) (S[(t2 >>> 16) & 0xFF] ^ (tt >>> 16)));
319: out.put((byte) (S[(t3 >>> 8) & 0xFF] ^ (tt >>> 8)));
320: out.put((byte) (S[(t0) & 0xFF] ^ (tt)));
321: tt = K[keyOffset++];
322: out.put((byte) (S[(t2 >>> 24)] ^ (tt >>> 24)));
323: out.put((byte) (S[(t3 >>> 16) & 0xFF] ^ (tt >>> 16)));
324: out.put((byte) (S[(t0 >>> 8) & 0xFF] ^ (tt >>> 8)));
325: out.put((byte) (S[(t1) & 0xFF] ^ (tt)));
326: tt = K[keyOffset++];
327: out.put((byte) (S[(t3 >>> 24)] ^ (tt >>> 24)));
328: out.put((byte) (S[(t0 >>> 16) & 0xFF] ^ (tt >>> 16)));
329: out.put((byte) (S[(t1 >>> 8) & 0xFF] ^ (tt >>> 8)));
330: out.put((byte) (S[(t2) & 0xFF] ^ (tt)));
331: }
332:
333: /**
334: * Decrypt exactly one block of plaintext.
335: */
336: private void blockDecrypt(ByteBuffer in, ByteBuffer out) {
337: int keyOffset = 8;
338: int t0, t1, t2, t3, a0, a1, a2;
339:
340: t0 = ((in.get()) << 24 | (in.get() & 0xFF) << 16
341: | (in.get() & 0xFF) << 8 | (in.get() & 0xFF))
342: ^ K[4];
343: t1 = ((in.get()) << 24 | (in.get() & 0xFF) << 16
344: | (in.get() & 0xFF) << 8 | (in.get() & 0xFF))
345: ^ K[5];
346: t2 = ((in.get()) << 24 | (in.get() & 0xFF) << 16
347: | (in.get() & 0xFF) << 8 | (in.get() & 0xFF))
348: ^ K[6];
349: t3 = ((in.get()) << 24 | (in.get() & 0xFF) << 16
350: | (in.get() & 0xFF) << 8 | (in.get() & 0xFF))
351: ^ K[7];
352:
353: if (ROUNDS_12) {
354: a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
355: ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF]
356: ^ K[keyOffset++];
357: a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF]
358: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF]
359: ^ K[keyOffset++];
360: a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF]
361: ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
362: ^ K[keyOffset++];
363: t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF]
364: ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF]
365: ^ K[keyOffset++];
366: t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
367: ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF]
368: ^ K[keyOffset++];
369: t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF]
370: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF]
371: ^ K[keyOffset++];
372: t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF]
373: ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
374: ^ K[keyOffset++];
375: t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF]
376: ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF]
377: ^ K[keyOffset++];
378:
379: if (ROUNDS_14) {
380: a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
381: ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF]
382: ^ K[keyOffset++];
383: a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF]
384: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF]
385: ^ K[keyOffset++];
386: a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF]
387: ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
388: ^ K[keyOffset++];
389: t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF]
390: ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF]
391: ^ K[keyOffset++];
392: t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
393: ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF]
394: ^ K[keyOffset++];
395: t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF]
396: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF]
397: ^ K[keyOffset++];
398: t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF]
399: ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
400: ^ K[keyOffset++];
401: t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF]
402: ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF]
403: ^ K[keyOffset++];
404: }
405: }
406: a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
407: ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF]
408: ^ K[keyOffset++];
409: a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF]
410: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF]
411: ^ K[keyOffset++];
412: a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF]
413: ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
414: ^ K[keyOffset++];
415: t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF]
416: ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF]
417: ^ K[keyOffset++];
418: t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
419: ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF]
420: ^ K[keyOffset++];
421: t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF]
422: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF]
423: ^ K[keyOffset++];
424: t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF]
425: ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
426: ^ K[keyOffset++];
427: t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF]
428: ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF]
429: ^ K[keyOffset++];
430: a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
431: ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF]
432: ^ K[keyOffset++];
433: a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF]
434: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF]
435: ^ K[keyOffset++];
436: a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF]
437: ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
438: ^ K[keyOffset++];
439: t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF]
440: ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF]
441: ^ K[keyOffset++];
442: t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
443: ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF]
444: ^ K[keyOffset++];
445: t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF]
446: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF]
447: ^ K[keyOffset++];
448: t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF]
449: ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
450: ^ K[keyOffset++];
451: t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF]
452: ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF]
453: ^ K[keyOffset++];
454: a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
455: ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF]
456: ^ K[keyOffset++];
457: a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF]
458: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF]
459: ^ K[keyOffset++];
460: a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF]
461: ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
462: ^ K[keyOffset++];
463: t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF]
464: ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF]
465: ^ K[keyOffset++];
466: t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
467: ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF]
468: ^ K[keyOffset++];
469: t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF]
470: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF]
471: ^ K[keyOffset++];
472: t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF]
473: ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
474: ^ K[keyOffset++];
475: t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF]
476: ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF]
477: ^ K[keyOffset++];
478: a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
479: ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF]
480: ^ K[keyOffset++];
481: a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF]
482: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF]
483: ^ K[keyOffset++];
484: a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF]
485: ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
486: ^ K[keyOffset++];
487: t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF]
488: ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF]
489: ^ K[keyOffset++];
490: t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
491: ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF]
492: ^ K[keyOffset++];
493: t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF]
494: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF]
495: ^ K[keyOffset++];
496: t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF]
497: ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
498: ^ K[keyOffset++];
499: t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF]
500: ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF]
501: ^ K[keyOffset++];
502: a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
503: ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF]
504: ^ K[keyOffset++];
505: a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF]
506: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF]
507: ^ K[keyOffset++];
508: a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF]
509: ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
510: ^ K[keyOffset++];
511: t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF]
512: ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF]
513: ^ K[keyOffset++];
514:
515: t1 = K[0];
516: out.put((byte) (Si[(a0 >>> 24)] ^ (t1 >>> 24)));
517: out.put((byte) (Si[(t3 >>> 16) & 0xFF] ^ (t1 >>> 16)));
518: out.put((byte) (Si[(a2 >>> 8) & 0xFF] ^ (t1 >>> 8)));
519: out.put((byte) (Si[(a1) & 0xFF] ^ (t1)));
520: t1 = K[1];
521: out.put((byte) (Si[(a1 >>> 24)] ^ (t1 >>> 24)));
522: out.put((byte) (Si[(a0 >>> 16) & 0xFF] ^ (t1 >>> 16)));
523: out.put((byte) (Si[(t3 >>> 8) & 0xFF] ^ (t1 >>> 8)));
524: out.put((byte) (Si[(a2) & 0xFF] ^ (t1)));
525: t1 = K[2];
526: out.put((byte) (Si[(a2 >>> 24)] ^ (t1 >>> 24)));
527: out.put((byte) (Si[(a1 >>> 16) & 0xFF] ^ (t1 >>> 16)));
528: out.put((byte) (Si[(a0 >>> 8) & 0xFF] ^ (t1 >>> 8)));
529: out.put((byte) (Si[(t3) & 0xFF] ^ (t1)));
530: t1 = K[3];
531: out.put((byte) (Si[(t3 >>> 24)] ^ (t1 >>> 24)));
532: out.put((byte) (Si[(a2 >>> 16) & 0xFF] ^ (t1 >>> 16)));
533: out.put((byte) (Si[(a1 >>> 8) & 0xFF] ^ (t1 >>> 8)));
534: out.put((byte) (Si[(a0) & 0xFF] ^ (t1)));
535: }
536:
537: /**
538: * Expand a user-supplied key material into a session key.
539: *
540: * @param key The 128/192/256-bit user-key to use.
541: * @exception InvalidKeyException If the key is invalid.
542: */
543: private static int[] makeKey(byte[] keyBytes, boolean decrypt)
544: throws Exception {
545: int ROUNDS = getRounds(keyBytes.length);
546: int ROUND_KEY_COUNT = (ROUNDS + 1) * 4;
547:
548: int[] Ki = new int[ROUND_KEY_COUNT];
549:
550: int KC = keyBytes.length / 4; // keylen in 32-bit elements
551: int[] tk = new int[KC];
552:
553: int i, j;
554:
555: // copy user material bytes into temporary ints
556: for (i = 0, j = 0; i < KC;)
557: tk[i++] = (keyBytes[j++]) << 24
558: | (keyBytes[j++] & 0xFF) << 16
559: | (keyBytes[j++] & 0xFF) << 8
560: | (keyBytes[j++] & 0xFF);
561:
562: // copy values into round key arrays
563: int t = 0;
564: for (; t < KC; t++)
565: Ki[t] = tk[t];
566:
567: int tt, rconpointer = 0;
568: while (t < ROUND_KEY_COUNT) {
569: // extrapolate using phi (the round key evolution function)
570: tt = tk[KC - 1];
571: tk[0] ^= (S[(tt >>> 16) & 0xFF]) << 24
572: ^ (S[(tt >>> 8) & 0xFF] & 0xFF) << 16
573: ^ (S[(tt) & 0xFF] & 0xFF) << 8
574: ^ (S[(tt >>> 24)] & 0xFF)
575: ^ (rcon[rconpointer++]) << 24;
576: if (KC != 8)
577: for (i = 1, j = 0; i < KC;)
578: tk[i++] ^= tk[j++];
579: else {
580: for (i = 1, j = 0; i < KC / 2;)
581: tk[i++] ^= tk[j++];
582: tt = tk[KC / 2 - 1];
583: tk[KC / 2] ^= (S[(tt) & 0xFF] & 0xFF)
584: ^ (S[(tt >>> 8) & 0xFF] & 0xFF) << 8
585: ^ (S[(tt >>> 16) & 0xFF] & 0xFF) << 16
586: ^ (S[(tt >>> 24)]) << 24;
587: for (j = KC / 2, i = j + 1; i < KC;)
588: tk[i++] ^= tk[j++];
589: }
590:
591: // copy values into round key arrays
592: for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++)
593: Ki[t] = tk[j];
594: }
595:
596: return Ki;
597: }
598:
599: private static void invertKey(int[] K) {
600:
601: for (int i = 0; i < K.length / 2 - 4; i += 4) {
602: int jj0 = K[i + 0];
603: int jj1 = K[i + 1];
604: int jj2 = K[i + 2];
605: int jj3 = K[i + 3];
606: K[i + 0] = K[K.length - i - 4 + 0];
607: K[i + 1] = K[K.length - i - 4 + 1];
608: K[i + 2] = K[K.length - i - 4 + 2];
609: K[i + 3] = K[K.length - i - 4 + 3];
610: K[K.length - i - 4 + 0] = jj0;
611: K[K.length - i - 4 + 1] = jj1;
612: K[K.length - i - 4 + 2] = jj2;
613: K[K.length - i - 4 + 3] = jj3;
614: }
615:
616: for (int r = 4; r < K.length - 4; r++) {
617: int tt = K[r];
618: K[r] = U1[(tt >>> 24) & 0xFF] ^ U2[(tt >>> 16) & 0xFF]
619: ^ U3[(tt >>> 8) & 0xFF] ^ U4[tt & 0xFF];
620: }
621:
622: int j0 = K[K.length - 4];
623: int j1 = K[K.length - 3];
624: int j2 = K[K.length - 2];
625: int j3 = K[K.length - 1];
626: for (int i = K.length - 1; i > 3; i--)
627: K[i] = K[i - 4];
628: K[0] = j0;
629: K[1] = j1;
630: K[2] = j2;
631: K[3] = j3;
632: }
633:
634: /**
635: * Return The number of rounds for a given Rijndael keysize.
636: *
637: * @param keySize The size of the user key material in bytes.
638: * MUST be one of (16, 24, 32).
639: * @return The number of rounds.
640: */
641: private final static int getRounds(int keySize) {
642: return (keySize >> 2) + 6;
643: }
644: }
|