1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44:
45: import ;
46: import ;
47: import ;
48: import ;
49:
50:
67: public class DES
68: extends BaseCipher
69: {
70:
71: public static final int BLOCK_SIZE = 8;
72:
73: public static final int KEY_SIZE = 8;
74:
75: private static final int[] SP1 = new int[] {
76: 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404,
77: 0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400,
78: 0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400,
79: 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404,
80: 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404,
81: 0x00010404, 0x01000000, 0x00010000, 0x01010404, 0x00000004, 0x01010000,
82: 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000,
83: 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404,
84: 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404,
85: 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000,
86: 0x00010004, 0x00010400, 0x00000000, 0x01010004 };
87: private static final int[] SP2 = new int[] {
88: 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020,
89: 0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000,
90: 0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020,
91: 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000,
92: 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000,
93: 0x80100000, 0x00008020, 0x00000000, 0x00108020, 0x80100020, 0x00100000,
94: 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000,
95: 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000,
96: 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020,
97: 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020,
98: 0x80000000, 0x80100020, 0x80108020, 0x00108000 };
99: private static final int[] SP3 = new int[] {
100: 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000,
101: 0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000,
102: 0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008,
103: 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208,
104: 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208,
105: 0x00000200, 0x08000000, 0x08020200, 0x08000000, 0x00020008, 0x00000208,
106: 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008,
107: 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008,
108: 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208,
109: 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000,
110: 0x00020208, 0x00000008, 0x08020008, 0x00020200 };
111: private static final int[] SP4 = new int[] {
112: 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081,
113: 0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081,
114: 0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000,
115: 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080,
116: 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080,
117: 0x00802081, 0x00000081, 0x00800080, 0x00800001, 0x00802000, 0x00802081,
118: 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080,
119: 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080,
120: 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001,
121: 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001,
122: 0x00000080, 0x00800000, 0x00002000, 0x00802080 };
123: private static final int[] SP5 = new int[] {
124: 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100,
125: 0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100,
126: 0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000,
127: 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100,
128: 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000,
129: 0x42000000, 0x00080100, 0x00080000, 0x42000100, 0x00000100, 0x02000000,
130: 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000,
131: 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000,
132: 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000,
133: 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000,
134: 0x00000000, 0x40080000, 0x02080100, 0x40000100 };
135: private static final int[] SP6 = new int[] {
136: 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010,
137: 0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010,
138: 0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010,
139: 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010,
140: 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000,
141: 0x20404000, 0x20000000, 0x20004000, 0x00000010, 0x20400010, 0x00404000,
142: 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000,
143: 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000,
144: 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000,
145: 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000,
146: 0x20404000, 0x20000000, 0x00400010, 0x20004010 };
147: private static final int[] SP7 = new int[] {
148: 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802,
149: 0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002,
150: 0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802,
151: 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002,
152: 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002,
153: 0x04000000, 0x00200800, 0x04000000, 0x00200800, 0x00200000, 0x04000802,
154: 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000,
155: 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800,
156: 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000,
157: 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800,
158: 0x04000002, 0x04000800, 0x00000800, 0x00200002 };
159: private static final int[] SP8 = new int[] {
160: 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040,
161: 0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000,
162: 0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040,
163: 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000,
164: 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000,
165: 0x00041040, 0x00040000, 0x00041040, 0x00040000, 0x10041000, 0x00001000,
166: 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040,
167: 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040,
168: 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000,
169: 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040,
170: 0x00001040, 0x00040040, 0x10000000, 0x10041000 };
171:
175: private static final byte[] PARITY = {
176: 8, 1, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 2, 8,
177: 0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 3,
178: 0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0,
179: 8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8,
180: 0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0,
181: 8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8,
182: 8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8,
183: 0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0,
184: 0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0,
185: 8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8,
186: 8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8,
187: 0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0,
188: 8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8,
189: 0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0,
190: 4, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0,
191: 8, 5, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 6, 8 };
192:
193: private static final byte[] ROTARS = {
194: 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 };
195: private static final byte[] PC1 = {
196: 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1,
197: 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 62, 54, 46, 38,
198: 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36,
199: 28, 20, 12, 4, 27, 19, 11, 3 };
200: private static final byte[] PC2 = {
201: 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3,
202: 25, 7, 15, 6, 26, 19, 12, 1, 40, 51, 30, 36, 46, 54, 29, 39,
203: 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
204:
209: public static final byte[][] WEAK_KEYS = {
210: Util.toBytesFromString("0101010101010101"),
211: Util.toBytesFromString("01010101FEFEFEFE"),
212: Util.toBytesFromString("FEFEFEFE01010101"),
213: Util.toBytesFromString("FEFEFEFEFEFEFEFE") };
214:
221: public static final byte[][] SEMIWEAK_KEYS = {
222: Util.toBytesFromString("01FE01FE01FE01FE"),
223: Util.toBytesFromString("FE01FE01FE01FE01"),
224: Util.toBytesFromString("1FE01FE00EF10EF1"),
225: Util.toBytesFromString("E01FE01FF10EF10E"),
226: Util.toBytesFromString("01E001E001F101F1"),
227: Util.toBytesFromString("E001E001F101F101"),
228: Util.toBytesFromString("1FFE1FFE0EFE0EFE"),
229: Util.toBytesFromString("FE1FFE1FFE0EFE0E"),
230: Util.toBytesFromString("011F011F010E010E"),
231: Util.toBytesFromString("1F011F010E010E01"),
232: Util.toBytesFromString("E0FEE0FEF1FEF1FE"),
233: Util.toBytesFromString("FEE0FEE0FEF1FEF1") };
234:
235: public static final byte[][] POSSIBLE_WEAK_KEYS = {
236: Util.toBytesFromString("1F1F01010E0E0101"),
237: Util.toBytesFromString("011F1F01010E0E01"),
238: Util.toBytesFromString("1F01011F0E01010E"),
239: Util.toBytesFromString("01011F1F01010E0E"),
240: Util.toBytesFromString("E0E00101F1F10101"),
241: Util.toBytesFromString("FEFE0101FEFE0101"),
242: Util.toBytesFromString("FEE01F01FEF10E01"),
243: Util.toBytesFromString("E0FE1F01F1FE0E01"),
244: Util.toBytesFromString("FEE0011FFEF1010E"),
245: Util.toBytesFromString("E0FE011FF1FE010E"),
246: Util.toBytesFromString("E0E01F1FF1F10E0E"),
247: Util.toBytesFromString("FEFE1F1FFEFE0E0E"),
248: Util.toBytesFromString("1F1F01010E0E0101"),
249: Util.toBytesFromString("011F1F01010E0E01"),
250: Util.toBytesFromString("1F01011F0E01010E"),
251: Util.toBytesFromString("01011F1F01010E0E"),
252: Util.toBytesFromString("01E0E00101F1F101"),
253: Util.toBytesFromString("1FFEE0010EFEF001"),
254: Util.toBytesFromString("1FE0FE010EF1FE01"),
255: Util.toBytesFromString("01FEFE0101FEFE01"),
256: Util.toBytesFromString("1FE0E01F0EF1F10E"),
257: Util.toBytesFromString("01FEE01F01FEF10E"),
258: Util.toBytesFromString("01E0FE1F01F1FE0E"),
259: Util.toBytesFromString("1FFEFE1F0EFEFE0E"),
260:
261: Util.toBytesFromString("E00101E0F10101F1"),
262: Util.toBytesFromString("FE1F01E0FE0E0EF1"),
263: Util.toBytesFromString("FE011FE0FE010EF1"),
264: Util.toBytesFromString("E01F1FE0F10E0EF1"),
265: Util.toBytesFromString("FE0101FEFE0101FE"),
266: Util.toBytesFromString("E01F01FEF10E01FE"),
267: Util.toBytesFromString("E0011FFEF1010EFE"),
268: Util.toBytesFromString("FE1F1FFEFE0E0EFE"),
269: Util.toBytesFromString("1FFE01E00EFE01F1"),
270: Util.toBytesFromString("01FE1FE001FE0EF1"),
271: Util.toBytesFromString("1FE001FE0EF101FE"),
272: Util.toBytesFromString("01E01FFE01F10EFE"),
273: Util.toBytesFromString("0101E0E00101F1F1"),
274: Util.toBytesFromString("1F1FE0E00E0EF1F1"),
275: Util.toBytesFromString("1F01FEE00E01FEF1"),
276: Util.toBytesFromString("011FFEE0010EFEF1"),
277: Util.toBytesFromString("1F01E0FE0E01F1FE"),
278: Util.toBytesFromString("011FE0FE010EF1FE"),
279: Util.toBytesFromString("0101FEFE0001FEFE"),
280: Util.toBytesFromString("1F1FFEFE0E0EFEFE"),
281: Util.toBytesFromString("FEFEE0E0FEFEF1F1"),
282: Util.toBytesFromString("E0FEFEE0F1FEFEF1"),
283: Util.toBytesFromString("FEE0E0FEFEF1F1FE"),
284: Util.toBytesFromString("E0E0FEFEF1F1FEFE") };
285:
286:
287: public DES()
288: {
289: super(Registry.DES_CIPHER, BLOCK_SIZE, KEY_SIZE);
290: }
291:
292:
300: public static void adjustParity(byte[] kb, int offset)
301: {
302: for (int i = offset; i < offset + KEY_SIZE; i++)
303: kb[i] ^= (PARITY[kb[i] & 0xff] == 8) ? 1 : 0;
304: }
305:
306:
315: public static boolean isParityAdjusted(byte[] kb, int offset)
316: {
317: int w = 0x88888888;
318: int n = PARITY[kb[offset + 0] & 0xff];
319: n <<= 4;
320: n |= PARITY[kb[offset + 1] & 0xff];
321: n <<= 4;
322: n |= PARITY[kb[offset + 2] & 0xff];
323: n <<= 4;
324: n |= PARITY[kb[offset + 3] & 0xff];
325: n <<= 4;
326: n |= PARITY[kb[offset + 4] & 0xff];
327: n <<= 4;
328: n |= PARITY[kb[offset + 5] & 0xff];
329: n <<= 4;
330: n |= PARITY[kb[offset + 6] & 0xff];
331: n <<= 4;
332: n |= PARITY[kb[offset + 7] & 0xff];
333: return (n & w) == 0;
334: }
335:
336:
342: public static boolean isWeak(byte[] kb)
343: {
344: for (int i = 0; i < WEAK_KEYS.length; i++)
345: if (Arrays.equals(WEAK_KEYS[i], kb))
346: return true;
347: return false;
348: }
349:
350:
356: public static boolean isSemiWeak(byte[] kb)
357: {
358: for (int i = 0; i < SEMIWEAK_KEYS.length; i++)
359: if (Arrays.equals(SEMIWEAK_KEYS[i], kb))
360: return true;
361: return false;
362: }
363:
364:
371: public static boolean isPossibleWeak(byte[] kb)
372: {
373: for (int i = 0; i < POSSIBLE_WEAK_KEYS.length; i++)
374: if (Arrays.equals(POSSIBLE_WEAK_KEYS[i], kb))
375: return true;
376: return false;
377: }
378:
379:
389: private static void desFunc(byte[] in, int i, byte[] out, int o, int[] key)
390: {
391: int right, left, work;
392:
393: left = (in[i++] & 0xff) << 24
394: | (in[i++] & 0xff) << 16
395: | (in[i++] & 0xff) << 8
396: | in[i++] & 0xff;
397: right = (in[i++] & 0xff) << 24
398: | (in[i++] & 0xff) << 16
399: | (in[i++] & 0xff) << 8
400: | in[i ] & 0xff;
401:
402: work = ((left >>> 4) ^ right) & 0x0F0F0F0F;
403: left ^= work << 4;
404: right ^= work;
405:
406: work = ((left >>> 16) ^ right) & 0x0000FFFF;
407: left ^= work << 16;
408: right ^= work;
409:
410: work = ((right >>> 2) ^ left) & 0x33333333;
411: right ^= work << 2;
412: left ^= work;
413:
414: work = ((right >>> 8) ^ left) & 0x00FF00FF;
415: right ^= work << 8;
416: left ^= work;
417:
418: right = ((right << 1) | ((right >>> 31) & 1)) & 0xFFFFFFFF;
419: work = (left ^ right) & 0xAAAAAAAA;
420: left ^= work;
421: right ^= work;
422: left = ((left << 1) | ((left >>> 31) & 1)) & 0xFFFFFFFF;
423:
424: int k = 0, t;
425: for (int round = 0; round < 8; round++)
426: {
427: work = right >>> 4 | right << 28;
428: work ^= key[k++];
429: t = SP7[work & 0x3F];
430: work >>>= 8;
431: t |= SP5[work & 0x3F];
432: work >>>= 8;
433: t |= SP3[work & 0x3F];
434: work >>>= 8;
435: t |= SP1[work & 0x3F];
436: work = right ^ key[k++];
437: t |= SP8[work & 0x3F];
438: work >>>= 8;
439: t |= SP6[work & 0x3F];
440: work >>>= 8;
441: t |= SP4[work & 0x3F];
442: work >>>= 8;
443: t |= SP2[work & 0x3F];
444: left ^= t;
445:
446: work = left >>> 4 | left << 28;
447: work ^= key[k++];
448: t = SP7[work & 0x3F];
449: work >>>= 8;
450: t |= SP5[work & 0x3F];
451: work >>>= 8;
452: t |= SP3[work & 0x3F];
453: work >>>= 8;
454: t |= SP1[work & 0x3F];
455: work = left ^ key[k++];
456: t |= SP8[work & 0x3F];
457: work >>>= 8;
458: t |= SP6[work & 0x3F];
459: work >>>= 8;
460: t |= SP4[work & 0x3F];
461: work >>>= 8;
462: t |= SP2[work & 0x3F];
463: right ^= t;
464: }
465:
466: right = (right << 31) | (right >>> 1);
467: work = (left ^ right) & 0xAAAAAAAA;
468: left ^= work;
469: right ^= work;
470: left = (left << 31) | (left >>> 1);
471:
472: work = ((left >>> 8) ^ right) & 0x00FF00FF;
473: left ^= work << 8;
474: right ^= work;
475:
476: work = ((left >>> 2) ^ right) & 0x33333333;
477: left ^= work << 2;
478: right ^= work;
479:
480: work = ((right >>> 16) ^ left) & 0x0000FFFF;
481: right ^= work << 16;
482: left ^= work;
483:
484: work = ((right >>> 4) ^ left) & 0x0F0F0F0F;
485: right ^= work << 4;
486: left ^= work;
487:
488: out[o++] = (byte)(right >>> 24);
489: out[o++] = (byte)(right >>> 16);
490: out[o++] = (byte)(right >>> 8);
491: out[o++] = (byte) right;
492: out[o++] = (byte)(left >>> 24);
493: out[o++] = (byte)(left >>> 16);
494: out[o++] = (byte)(left >>> 8);
495: out[o ] = (byte) left;
496: }
497:
498: public Object clone()
499: {
500: return new DES();
501: }
502:
503: public Iterator blockSizes()
504: {
505: return Collections.singleton(Integer.valueOf(BLOCK_SIZE)).iterator();
506: }
507:
508: public Iterator keySizes()
509: {
510: return Collections.singleton(Integer.valueOf(KEY_SIZE)).iterator();
511: }
512:
513: public Object makeKey(byte[] kb, int bs) throws InvalidKeyException
514: {
515: if (kb == null || kb.length != KEY_SIZE)
516: throw new InvalidKeyException("DES keys must be 8 bytes long");
517:
518: if (Properties.checkForWeakKeys()
519: && (isWeak(kb) || isSemiWeak(kb) || isPossibleWeak(kb)))
520: throw new WeakKeyException();
521:
522: int i, j, l, m, n;
523: long pc1m = 0, pcr = 0;
524:
525: for (i = 0; i < 56; i++)
526: {
527: l = PC1[i];
528: pc1m |= ((kb[l >>> 3] & (0x80 >>> (l & 7))) != 0) ? (1L << (55 - i))
529: : 0;
530: }
531: Context ctx = new Context();
532:
533: for (i = 0; i < 16; i++)
534: {
535: pcr = 0;
536: m = i << 1;
537: n = m + 1;
538: for (j = 0; j < 28; j++)
539: {
540: l = j + ROTARS[i];
541: if (l < 28)
542: pcr |= ((pc1m & 1L << (55 - l)) != 0) ? (1L << (55 - j)) : 0;
543: else
544: pcr |= ((pc1m & 1L << (55 - (l - 28))) != 0) ? (1L << (55 - j))
545: : 0;
546: }
547: for (j = 28; j < 56; j++)
548: {
549: l = j + ROTARS[i];
550: if (l < 56)
551: pcr |= ((pc1m & 1L << (55 - l)) != 0) ? (1L << (55 - j)) : 0;
552: else
553: pcr |= ((pc1m & 1L << (55 - (l - 28))) != 0) ? (1L << (55 - j))
554: : 0;
555: }
556: for (j = 0; j < 24; j++)
557: {
558: if ((pcr & 1L << (55 - PC2[j])) != 0)
559: ctx.ek[m] |= 1 << (23 - j);
560: if ((pcr & 1L << (55 - PC2[j + 24])) != 0)
561: ctx.ek[n] |= 1 << (23 - j);
562: }
563: }
564:
565: for (i = 0; i < Context.EXPANDED_KEY_SIZE; i += 2)
566: {
567: ctx.dk[30 - i] = ctx.ek[i];
568: ctx.dk[31 - i] = ctx.ek[i + 1];
569: }
570:
571: for (i = 0; i < 32; i += 2)
572: {
573: int x, y;
574: x = ctx.ek[i];
575: y = ctx.ek[i + 1];
576: ctx.ek[i ] = ((x & 0x00FC0000) << 6)
577: | ((x & 0x00000FC0) << 10)
578: | ((y & 0x00FC0000) >>> 10)
579: | ((y & 0x00000FC0) >>> 6);
580: ctx.ek[i + 1] = ((x & 0x0003F000) << 12)
581: | ((x & 0x0000003F) << 16)
582: | ((y & 0x0003F000) >>> 4)
583: | (y & 0x0000003F);
584: x = ctx.dk[i];
585: y = ctx.dk[i + 1];
586: ctx.dk[i ] = ((x & 0x00FC0000) << 6)
587: | ((x & 0x00000FC0) << 10)
588: | ((y & 0x00FC0000) >>> 10)
589: | ((y & 0x00000FC0) >>> 6);
590: ctx.dk[i + 1] = ((x & 0x0003F000) << 12)
591: | ((x & 0x0000003F) << 16)
592: | ((y & 0x0003F000) >>> 4)
593: | (y & 0x0000003F);
594: }
595: return ctx;
596: }
597:
598: public void encrypt(byte[] in, int i, byte[] out, int o, Object K, int bs)
599: {
600: desFunc(in, i, out, o, ((Context) K).ek);
601: }
602:
603: public void decrypt(byte[] in, int i, byte[] out, int o, Object K, int bs)
604: {
605: desFunc(in, i, out, o, ((Context) K).dk);
606: }
607:
608:
612: final class Context
613: {
614: private static final int EXPANDED_KEY_SIZE = 32;
615:
616:
617: int[] ek;
618:
619:
620: int[] dk;
621:
622:
623: Context()
624: {
625: ek = new int[EXPANDED_KEY_SIZE];
626: dk = new int[EXPANDED_KEY_SIZE];
627: }
628:
629: byte[] getEncryptionKeyBytes()
630: {
631: return toByteArray(ek);
632: }
633:
634: byte[] getDecryptionKeyBytes()
635: {
636: return toByteArray(dk);
637: }
638:
639: byte[] toByteArray(int[] k)
640: {
641: byte[] result = new byte[4 * k.length];
642: for (int i = 0, j = 0; i < k.length; i++)
643: {
644: result[j++] = (byte)(k[i] >>> 24);
645: result[j++] = (byte)(k[i] >>> 16);
646: result[j++] = (byte)(k[i] >>> 8);
647: result[j++] = (byte) k[i];
648: }
649: return result;
650: }
651: }
652: }