001: /* $Id: Rijndael.java,v 1.1 2004/01/19 02:03:51 rgrimm Exp $
002: *
003: * Copyright (C) 1995-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: * Rijndael --pronounced Reindaal-- is a symmetric cipher with a 128-bit
018: * block size and variable key-size (128-, 192- and 256-bit).
019: * <p>
020: * Rijndael was designed by <a href="mailto:rijmen@esat.kuleuven.ac.be">Vincent
021: * Rijmen</a> and <a href="mailto:daemen.j@protonworld.com">Joan Daemen</a>.
022: * <p>
023: * @version $Revision: 1.1 $
024: * @author Raif S. Naffah
025: * @author Paulo S. L. M. Barreto (pbarreto@cryptix.org)
026: * @author Jeroen C. van Gelderen (gelderen@cryptix.org)
027: */
028: public final class Rijndael extends BlockCipher {
029:
030: private boolean ROUNDS_12, ROUNDS_14;
031:
032: /** True if in decrypt mode */
033: private boolean decrypt;
034:
035: /** Subkeys */
036: private int[] K;
037:
038: /** (ROUNDS-1) * 4 */
039: private int limit;
040:
041: public Rijndael() {
042: super (BLOCK_SIZE);
043: }
044:
045: protected void coreInit(Key key, boolean decrypt)
046: throws InvalidKeyException {
047: if (key == null)
048: throw new InvalidKeyException("Key missing");
049:
050: if (!key.getFormat().equalsIgnoreCase("RAW"))
051: throw new InvalidKeyException(
052: "Wrong format: RAW bytes needed");
053:
054: byte[] userkey = key.getEncoded();
055: if (userkey == null)
056: throw new InvalidKeyException("RAW bytes missing");
057:
058: int len = userkey.length;
059: if (len != 16 && len != 24 && len != 32)
060: throw new InvalidKeyException("Invalid user key length");
061:
062: this .decrypt = decrypt;
063:
064: this .K = makeKey(userkey, decrypt);
065: if (decrypt)
066: invertKey(this .K);
067:
068: ROUNDS_12 = (len >= 24);
069: ROUNDS_14 = (len == 32);
070:
071: this .limit = getRounds(len) * 4;
072: }
073:
074: protected void coreCrypt(byte[] in, int inOffset, byte[] out,
075: int outOffset) {
076: if (decrypt)
077: blockDecrypt(in, inOffset, out, outOffset);
078: else
079: blockEncrypt(in, inOffset, out, outOffset);
080: }
081:
082: // Constants and variables
083: //...........................................................................
084:
085: private static final int BLOCK_SIZE = 16; // block size in bytes
086:
087: private static final String SS = "\u637C\u777B\uF26B\u6FC5\u3001\u672B\uFED7\uAB76"
088: + "\uCA82\uC97D\uFA59\u47F0\uADD4\uA2AF\u9CA4\u72C0"
089: + "\uB7FD\u9326\u363F\uF7CC\u34A5\uE5F1\u71D8\u3115"
090: + "\u04C7\u23C3\u1896\u059A\u0712\u80E2\uEB27\uB275"
091: + "\u0983\u2C1A\u1B6E\u5AA0\u523B\uD6B3\u29E3\u2F84"
092: + "\u53D1\u00ED\u20FC\uB15B\u6ACB\uBE39\u4A4C\u58CF"
093: + "\uD0EF\uAAFB\u434D\u3385\u45F9\u027F\u503C\u9FA8"
094: + "\u51A3\u408F\u929D\u38F5\uBCB6\uDA21\u10FF\uF3D2"
095: + "\uCD0C\u13EC\u5F97\u4417\uC4A7\u7E3D\u645D\u1973"
096: + "\u6081\u4FDC\u222A\u9088\u46EE\uB814\uDE5E\u0BDB"
097: + "\uE032\u3A0A\u4906\u245C\uC2D3\uAC62\u9195\uE479"
098: + "\uE7C8\u376D\u8DD5\u4EA9\u6C56\uF4EA\u657A\uAE08"
099: + "\uBA78\u252E\u1CA6\uB4C6\uE8DD\u741F\u4BBD\u8B8A"
100: + "\u703E\uB566\u4803\uF60E\u6135\u57B9\u86C1\u1D9E"
101: + "\uE1F8\u9811\u69D9\u8E94\u9B1E\u87E9\uCE55\u28DF"
102: + "\u8CA1\u890D\uBFE6\u4268\u4199\u2D0F\uB054\uBB16";
103:
104: private static final byte[] S = new byte[256], Si = new byte[256];
105:
106: private static final int[] T1 = new int[256], T2 = new int[256],
107: T3 = new int[256], T4 = new int[256], T5 = new int[256],
108: T6 = new int[256], T7 = new int[256], T8 = new int[256];
109:
110: private static final int[] U1 = new int[256], U2 = new int[256],
111: U3 = new int[256], U4 = new int[256];
112:
113: private static final byte[] rcon = new byte[30];
114:
115: // Static code - to intialise S-boxes and T-boxes
116: //...........................................................................
117:
118: static {
119: int ROOT = 0x11B;
120: int i, j = 0;
121:
122: for (i = 0; i < 256; i++) {
123: int s, s2, s3, i2, i4, i8, i9, ib, id, ie, t;
124: char c = SS.charAt(i >>> 1);
125: S[i] = (byte) (((i & 1) == 0) ? c >>> 8 : c & 0xFF);
126: s = S[i] & 0xFF;
127: Si[s] = (byte) i;
128: s2 = s << 1;
129: if (s2 >= 0x100) {
130: s2 ^= ROOT;
131: }
132: s3 = s2 ^ s;
133: i2 = i << 1;
134: if (i2 >= 0x100) {
135: i2 ^= ROOT;
136: }
137: i4 = i2 << 1;
138: if (i4 >= 0x100) {
139: i4 ^= ROOT;
140: }
141: i8 = i4 << 1;
142: if (i8 >= 0x100) {
143: i8 ^= ROOT;
144: }
145: i9 = i8 ^ i;
146: ib = i9 ^ i2;
147: id = i9 ^ i4;
148: ie = i8 ^ i4 ^ i2;
149:
150: T1[i] = t = (s2 << 24) | (s << 16) | (s << 8) | s3;
151: T2[i] = (t >>> 8) | (t << 24);
152: T3[i] = (t >>> 16) | (t << 16);
153: T4[i] = (t >>> 24) | (t << 8);
154:
155: T5[s] = U1[i] = t = (ie << 24) | (i9 << 16) | (id << 8)
156: | ib;
157: T6[s] = U2[i] = (t >>> 8) | (t << 24);
158: T7[s] = U3[i] = (t >>> 16) | (t << 16);
159: T8[s] = U4[i] = (t >>> 24) | (t << 8);
160: }
161: //
162: // round constants
163: //
164: int r = 1;
165: rcon[0] = 1;
166: for (i = 1; i < 30; i++) {
167: r <<= 1;
168: if (r >= 0x100) {
169: r ^= ROOT;
170: }
171: rcon[i] = (byte) r;
172: }
173:
174: }
175:
176: //...........................................................................
177:
178: /**
179: * Encrypt exactly one block of plaintext.
180: */
181: private void blockEncrypt(byte[] in, int inOffset, byte[] out,
182: int outOffset) {
183: // plaintext to ints + key
184: int keyOffset = 0;
185: int t0 = ((in[inOffset++]) << 24
186: | (in[inOffset++] & 0xFF) << 16
187: | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF))
188: ^ K[keyOffset++];
189: int t1 = ((in[inOffset++]) << 24
190: | (in[inOffset++] & 0xFF) << 16
191: | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF))
192: ^ K[keyOffset++];
193: int t2 = ((in[inOffset++]) << 24
194: | (in[inOffset++] & 0xFF) << 16
195: | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF))
196: ^ K[keyOffset++];
197: int t3 = ((in[inOffset++]) << 24
198: | (in[inOffset++] & 0xFF) << 16
199: | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF))
200: ^ K[keyOffset++];
201:
202: // apply round transforms
203: while (keyOffset < limit) {
204: int a0, a1, a2;
205: a0 = T1[(t0 >>> 24)] ^ T2[(t1 >>> 16) & 0xFF]
206: ^ T3[(t2 >>> 8) & 0xFF] ^ T4[(t3) & 0xFF]
207: ^ K[keyOffset++];
208: a1 = T1[(t1 >>> 24)] ^ T2[(t2 >>> 16) & 0xFF]
209: ^ T3[(t3 >>> 8) & 0xFF] ^ T4[(t0) & 0xFF]
210: ^ K[keyOffset++];
211: a2 = T1[(t2 >>> 24)] ^ T2[(t3 >>> 16) & 0xFF]
212: ^ T3[(t0 >>> 8) & 0xFF] ^ T4[(t1) & 0xFF]
213: ^ K[keyOffset++];
214: t3 = T1[(t3 >>> 24)] ^ T2[(t0 >>> 16) & 0xFF]
215: ^ T3[(t1 >>> 8) & 0xFF] ^ T4[(t2) & 0xFF]
216: ^ K[keyOffset++];
217: t0 = a0;
218: t1 = a1;
219: t2 = a2;
220: }
221:
222: // last round is special
223: int tt = K[keyOffset++];
224: out[outOffset++] = (byte) (S[(t0 >>> 24)] ^ (tt >>> 24));
225: out[outOffset++] = (byte) (S[(t1 >>> 16) & 0xFF] ^ (tt >>> 16));
226: out[outOffset++] = (byte) (S[(t2 >>> 8) & 0xFF] ^ (tt >>> 8));
227: out[outOffset++] = (byte) (S[(t3) & 0xFF] ^ (tt));
228: tt = K[keyOffset++];
229: out[outOffset++] = (byte) (S[(t1 >>> 24)] ^ (tt >>> 24));
230: out[outOffset++] = (byte) (S[(t2 >>> 16) & 0xFF] ^ (tt >>> 16));
231: out[outOffset++] = (byte) (S[(t3 >>> 8) & 0xFF] ^ (tt >>> 8));
232: out[outOffset++] = (byte) (S[(t0) & 0xFF] ^ (tt));
233: tt = K[keyOffset++];
234: out[outOffset++] = (byte) (S[(t2 >>> 24)] ^ (tt >>> 24));
235: out[outOffset++] = (byte) (S[(t3 >>> 16) & 0xFF] ^ (tt >>> 16));
236: out[outOffset++] = (byte) (S[(t0 >>> 8) & 0xFF] ^ (tt >>> 8));
237: out[outOffset++] = (byte) (S[(t1) & 0xFF] ^ (tt));
238: tt = K[keyOffset++];
239: out[outOffset++] = (byte) (S[(t3 >>> 24)] ^ (tt >>> 24));
240: out[outOffset++] = (byte) (S[(t0 >>> 16) & 0xFF] ^ (tt >>> 16));
241: out[outOffset++] = (byte) (S[(t1 >>> 8) & 0xFF] ^ (tt >>> 8));
242: out[outOffset] = (byte) (S[(t2) & 0xFF] ^ (tt));
243: }
244:
245: /**
246: * Decrypt exactly one block of plaintext.
247: */
248: private void blockDecrypt(byte[] in, int inOffset, byte[] out,
249: int outOffset) {
250:
251: int keyOffset = 8;
252: int t0, t1, t2, t3, a0, a1, a2;
253:
254: t0 = ((in[inOffset++]) << 24 | (in[inOffset++] & 0xFF) << 16
255: | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF))
256: ^ K[4];
257: t1 = ((in[inOffset++]) << 24 | (in[inOffset++] & 0xFF) << 16
258: | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF))
259: ^ K[5];
260: t2 = ((in[inOffset++]) << 24 | (in[inOffset++] & 0xFF) << 16
261: | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF))
262: ^ K[6];
263: t3 = ((in[inOffset++]) << 24 | (in[inOffset++] & 0xFF) << 16
264: | (in[inOffset++] & 0xFF) << 8 | (in[inOffset] & 0xFF))
265: ^ K[7];
266:
267: if (ROUNDS_12) {
268: a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
269: ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF]
270: ^ K[keyOffset++];
271: a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF]
272: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF]
273: ^ K[keyOffset++];
274: a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF]
275: ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
276: ^ K[keyOffset++];
277: t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF]
278: ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF]
279: ^ K[keyOffset++];
280: t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
281: ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF]
282: ^ K[keyOffset++];
283: t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF]
284: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF]
285: ^ K[keyOffset++];
286: t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF]
287: ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
288: ^ K[keyOffset++];
289: t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF]
290: ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF]
291: ^ K[keyOffset++];
292:
293: if (ROUNDS_14) {
294: a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
295: ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF]
296: ^ K[keyOffset++];
297: a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF]
298: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF]
299: ^ K[keyOffset++];
300: a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF]
301: ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
302: ^ K[keyOffset++];
303: t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF]
304: ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF]
305: ^ K[keyOffset++];
306: t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
307: ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF]
308: ^ K[keyOffset++];
309: t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF]
310: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF]
311: ^ K[keyOffset++];
312: t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF]
313: ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
314: ^ K[keyOffset++];
315: t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF]
316: ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF]
317: ^ K[keyOffset++];
318: }
319: }
320: a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
321: ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF]
322: ^ K[keyOffset++];
323: a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF]
324: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF]
325: ^ K[keyOffset++];
326: a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF]
327: ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
328: ^ K[keyOffset++];
329: t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF]
330: ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF]
331: ^ K[keyOffset++];
332: t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
333: ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF]
334: ^ K[keyOffset++];
335: t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF]
336: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF]
337: ^ K[keyOffset++];
338: t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF]
339: ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
340: ^ K[keyOffset++];
341: t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF]
342: ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF]
343: ^ K[keyOffset++];
344: a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
345: ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF]
346: ^ K[keyOffset++];
347: a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF]
348: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF]
349: ^ K[keyOffset++];
350: a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF]
351: ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
352: ^ K[keyOffset++];
353: t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF]
354: ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF]
355: ^ K[keyOffset++];
356: t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
357: ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF]
358: ^ K[keyOffset++];
359: t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF]
360: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF]
361: ^ K[keyOffset++];
362: t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF]
363: ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
364: ^ K[keyOffset++];
365: t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF]
366: ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF]
367: ^ K[keyOffset++];
368: a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
369: ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF]
370: ^ K[keyOffset++];
371: a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF]
372: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF]
373: ^ K[keyOffset++];
374: a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF]
375: ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
376: ^ K[keyOffset++];
377: t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF]
378: ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF]
379: ^ K[keyOffset++];
380: t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
381: ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF]
382: ^ K[keyOffset++];
383: t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF]
384: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF]
385: ^ K[keyOffset++];
386: t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF]
387: ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
388: ^ K[keyOffset++];
389: t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF]
390: ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF]
391: ^ K[keyOffset++];
392: a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
393: ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF]
394: ^ K[keyOffset++];
395: a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF]
396: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF]
397: ^ K[keyOffset++];
398: a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF]
399: ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
400: ^ K[keyOffset++];
401: t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF]
402: ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF]
403: ^ K[keyOffset++];
404: t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
405: ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF]
406: ^ K[keyOffset++];
407: t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF]
408: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF]
409: ^ K[keyOffset++];
410: t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF]
411: ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
412: ^ K[keyOffset++];
413: t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF]
414: ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF]
415: ^ K[keyOffset++];
416: a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF]
417: ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF]
418: ^ K[keyOffset++];
419: a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF]
420: ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF]
421: ^ K[keyOffset++];
422: a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF]
423: ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF]
424: ^ K[keyOffset++];
425: t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF]
426: ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF]
427: ^ K[keyOffset++];
428:
429: t1 = K[0];
430: out[outOffset++] = (byte) (Si[(a0 >>> 24)] ^ (t1 >>> 24));
431: out[outOffset++] = (byte) (Si[(t3 >>> 16) & 0xFF] ^ (t1 >>> 16));
432: out[outOffset++] = (byte) (Si[(a2 >>> 8) & 0xFF] ^ (t1 >>> 8));
433: out[outOffset++] = (byte) (Si[(a1) & 0xFF] ^ (t1));
434: t1 = K[1];
435: out[outOffset++] = (byte) (Si[(a1 >>> 24)] ^ (t1 >>> 24));
436: out[outOffset++] = (byte) (Si[(a0 >>> 16) & 0xFF] ^ (t1 >>> 16));
437: out[outOffset++] = (byte) (Si[(t3 >>> 8) & 0xFF] ^ (t1 >>> 8));
438: out[outOffset++] = (byte) (Si[(a2) & 0xFF] ^ (t1));
439: t1 = K[2];
440: out[outOffset++] = (byte) (Si[(a2 >>> 24)] ^ (t1 >>> 24));
441: out[outOffset++] = (byte) (Si[(a1 >>> 16) & 0xFF] ^ (t1 >>> 16));
442: out[outOffset++] = (byte) (Si[(a0 >>> 8) & 0xFF] ^ (t1 >>> 8));
443: out[outOffset++] = (byte) (Si[(t3) & 0xFF] ^ (t1));
444: t1 = K[3];
445: out[outOffset++] = (byte) (Si[(t3 >>> 24)] ^ (t1 >>> 24));
446: out[outOffset++] = (byte) (Si[(a2 >>> 16) & 0xFF] ^ (t1 >>> 16));
447: out[outOffset++] = (byte) (Si[(a1 >>> 8) & 0xFF] ^ (t1 >>> 8));
448: out[outOffset] = (byte) (Si[(a0) & 0xFF] ^ (t1));
449: }
450:
451: /**
452: * Expand a user-supplied key material into a session key.
453: *
454: * @param key The 128/192/256-bit user-key to use.
455: * @exception InvalidKeyException If the key is invalid.
456: */
457: private static int[] makeKey(byte[] keyBytes, boolean decrypt)
458: throws InvalidKeyException {
459: int ROUNDS = getRounds(keyBytes.length);
460: int ROUND_KEY_COUNT = (ROUNDS + 1) * 4;
461:
462: int[] K = new int[ROUND_KEY_COUNT];
463:
464: int KC = keyBytes.length / 4; // keylen in 32-bit elements
465: int[] tk = new int[KC];
466:
467: int i, j;
468:
469: // copy user material bytes into temporary ints
470: for (i = 0, j = 0; i < KC;)
471: tk[i++] = (keyBytes[j++]) << 24
472: | (keyBytes[j++] & 0xFF) << 16
473: | (keyBytes[j++] & 0xFF) << 8
474: | (keyBytes[j++] & 0xFF);
475:
476: // copy values into round key arrays
477: int t = 0;
478: for (; t < KC; t++)
479: K[t] = tk[t];
480:
481: int tt, rconpointer = 0;
482: while (t < ROUND_KEY_COUNT) {
483: // extrapolate using phi (the round key evolution function)
484: tt = tk[KC - 1];
485: tk[0] ^= (S[(tt >>> 16) & 0xFF]) << 24
486: ^ (S[(tt >>> 8) & 0xFF] & 0xFF) << 16
487: ^ (S[(tt) & 0xFF] & 0xFF) << 8
488: ^ (S[(tt >>> 24)] & 0xFF)
489: ^ (rcon[rconpointer++]) << 24;
490: if (KC != 8)
491: for (i = 1, j = 0; i < KC;)
492: tk[i++] ^= tk[j++];
493: else {
494: for (i = 1, j = 0; i < KC / 2;)
495: tk[i++] ^= tk[j++];
496: tt = tk[KC / 2 - 1];
497: tk[KC / 2] ^= (S[(tt) & 0xFF] & 0xFF)
498: ^ (S[(tt >>> 8) & 0xFF] & 0xFF) << 8
499: ^ (S[(tt >>> 16) & 0xFF] & 0xFF) << 16
500: ^ (S[(tt >>> 24)]) << 24;
501: for (j = KC / 2, i = j + 1; i < KC;)
502: tk[i++] ^= tk[j++];
503: }
504:
505: // copy values into round key arrays
506: for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++)
507: K[t] = tk[j];
508: }
509:
510: return K;
511: }
512:
513: private static void invertKey(int[] K) {
514:
515: for (int i = 0; i < K.length / 2 - 4; i += 4) {
516: int jj0 = K[i + 0];
517: int jj1 = K[i + 1];
518: int jj2 = K[i + 2];
519: int jj3 = K[i + 3];
520: K[i + 0] = K[K.length - i - 4 + 0];
521: K[i + 1] = K[K.length - i - 4 + 1];
522: K[i + 2] = K[K.length - i - 4 + 2];
523: K[i + 3] = K[K.length - i - 4 + 3];
524: K[K.length - i - 4 + 0] = jj0;
525: K[K.length - i - 4 + 1] = jj1;
526: K[K.length - i - 4 + 2] = jj2;
527: K[K.length - i - 4 + 3] = jj3;
528: }
529:
530: for (int r = 4; r < K.length - 4; r++) {
531: int tt = K[r];
532: K[r] = U1[(tt >>> 24) & 0xFF] ^ U2[(tt >>> 16) & 0xFF]
533: ^ U3[(tt >>> 8) & 0xFF] ^ U4[tt & 0xFF];
534: }
535:
536: int j0 = K[K.length - 4];
537: int j1 = K[K.length - 3];
538: int j2 = K[K.length - 2];
539: int j3 = K[K.length - 1];
540: for (int i = K.length - 1; i > 3; i--)
541: K[i] = K[i - 4];
542: K[0] = j0;
543: K[1] = j1;
544: K[2] = j2;
545: K[3] = j3;
546: }
547:
548: /**
549: * Return The number of rounds for a given Rijndael keysize.
550: *
551: * @param keySize The size of the user key material in bytes.
552: * MUST be one of (16, 24, 32).
553: * @return The number of rounds.
554: */
555: private static int getRounds(int keySize) {
556: return (keySize >> 2) + 6;
557: }
558: }
|