001: /*******************************************************************************
002: * Class: : DESEngine
003: * Author : mbrinkley
004: * Creation : Nov 11, 2003 2:59:23 PM
005: * $Header: /cvsroot/jtds/jtds/src/main/net/sourceforge/jtds/util/DESEngine.java,v 1.3 2004/09/16 20:40:51 matt_brinkley Exp $
006: *
007: * Version: $Id: DESEngine.java,v 1.3 2004/09/16 20:40:51 matt_brinkley Exp $
008: ******************************************************************************/package net.sourceforge.jtds.util;
009:
010: /*
011: import org.bouncycastle.crypto.BlockCipher;
012: import org.bouncycastle.crypto.CipherParameters;
013: import org.bouncycastle.crypto.DataLengthException;
014: import org.bouncycastle.crypto.params.KeyParameter;
015: */
016:
017: /**
018: * a class that provides a basic DES engine.
019: * Modified by Matt Brinkley (mdb) ... mainly just removed depends on external classes.
020: *
021: * @version $Id: DESEngine.java,v 1.3 2004/09/16 20:40:51 matt_brinkley Exp $
022: */
023: public class DESEngine
024: // implements BlockCipher //mdb
025: {
026: protected static final int BLOCK_SIZE = 8;
027:
028: private int[] workingKey = null;
029:
030: /**
031: * standard constructor.
032: */
033: public DESEngine() {
034: }
035:
036: /**
037: * mdb: convenient constructor
038: */
039: public DESEngine(boolean encrypting, byte[] key) {
040: init(encrypting, key);
041: }
042:
043: /**
044: * initialise a DES cipher.
045: *
046: * @param encrypting whether or not we are for encryption.
047: * @param key the parameters required to set up the cipher.
048: * @exception IllegalArgumentException if the params argument is
049: * inappropriate.
050: */
051: public void init(boolean encrypting, byte[] key) //mdb: changed parameter from CipherParameters to byte[]
052: {
053: workingKey = generateWorkingKey(encrypting, key);
054:
055: //mdb: original:
056: /*
057: if (params instanceof KeyParameter)
058: {
059: workingKey = generateWorkingKey(encrypting,
060: ((KeyParameter)params).getKey());
061:
062: return;
063: }
064: throw new IllegalArgumentException("invalid parameter passed to DES init - " + params.getClass().getName());
065: */
066: }
067:
068: public String getAlgorithmName() {
069: return "DES";
070: }
071:
072: public int getBlockSize() {
073: return BLOCK_SIZE;
074: }
075:
076: public int processBlock(byte[] in, int inOff, byte[] out, int outOff) {
077: if (workingKey == null) {
078: throw new IllegalStateException(
079: "DES engine not initialised");
080: }
081:
082: if ((inOff + BLOCK_SIZE) > in.length) {
083: //mdb: used to be DataLengthException
084: throw new IllegalArgumentException("input buffer too short");
085: }
086:
087: if ((outOff + BLOCK_SIZE) > out.length) {
088: //mdb: used to be DataLengthException
089: throw new IllegalArgumentException(
090: "output buffer too short");
091: }
092:
093: desFunc(workingKey, in, inOff, out, outOff);
094:
095: return BLOCK_SIZE;
096: }
097:
098: public void reset() {
099: }
100:
101: /**
102: * what follows is mainly taken from "Applied Cryptography", by
103: * Bruce Schneier, however it also bears great resemblance to Richard
104: * Outerbridge's D3DES...
105: */
106:
107: static short[] Df_Key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd,
108: 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x89,
109: 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67 };
110:
111: static short[] bytebit = { 0200, 0100, 040, 020, 010, 04, 02, 01 };
112:
113: static int[] bigbyte = { 0x800000, 0x400000, 0x200000, 0x100000,
114: 0x80000, 0x40000, 0x20000, 0x10000, 0x8000, 0x4000, 0x2000,
115: 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10,
116: 0x8, 0x4, 0x2, 0x1 };
117:
118: /*
119: * Use the key schedule specified in the Standard (ANSI X3.92-1981).
120: */
121:
122: static byte[] pc1 = { 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33,
123: 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43,
124: 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
125: 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
126:
127: static byte[] totrot = { 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21,
128: 23, 25, 27, 28 };
129:
130: static byte[] pc2 = { 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
131: 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, 51, 30, 36,
132: 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45,
133: 41, 49, 35, 28, 31 };
134:
135: static int[] SP1 = { 0x01010400, 0x00000000, 0x00010000,
136: 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000,
137: 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404,
138: 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400,
139: 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000,
140: 0x01000404, 0x00010004, 0x01000004, 0x01000004, 0x00010004,
141: 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000,
142: 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000,
143: 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400,
144: 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404,
145: 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004,
146: 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400,
147: 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000,
148: 0x01010004 };
149:
150: static int[] SP2 = { 0x80108020, 0x80008000, 0x00008000,
151: 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020,
152: 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000,
153: 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020,
154: 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020,
155: 0x80100000, 0x00100020, 0x80000020, 0x00000000, 0x00108000,
156: 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000,
157: 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000,
158: 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020,
159: 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000,
160: 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020,
161: 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000,
162: 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020,
163: 0x00108000 };
164:
165: static int[] SP3 = { 0x00000208, 0x08020200, 0x00000000,
166: 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200,
167: 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208,
168: 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008,
169: 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008,
170: 0x00020208, 0x08000208, 0x00020200, 0x00020000, 0x08000208,
171: 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200,
172: 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200,
173: 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208,
174: 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008,
175: 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008,
176: 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208,
177: 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008,
178: 0x00020200 };
179:
180: static int[] SP4 = { 0x00802001, 0x00002081, 0x00002081,
181: 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001,
182: 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081,
183: 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000,
184: 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001,
185: 0x00002080, 0x00800081, 0x00000001, 0x00002080, 0x00800080,
186: 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080,
187: 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000,
188: 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081,
189: 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080,
190: 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001,
191: 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080,
192: 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000,
193: 0x00802080 };
194:
195: static int[] SP5 = { 0x00000100, 0x02080100, 0x02080000,
196: 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000,
197: 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100,
198: 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000,
199: 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100,
200: 0x02000100, 0x42080000, 0x40000100, 0x00000000, 0x42000000,
201: 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000,
202: 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000,
203: 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000,
204: 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000,
205: 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000,
206: 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100,
207: 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100,
208: 0x40000100 };
209:
210: static int[] SP6 = { 0x20000010, 0x20400000, 0x00004000,
211: 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000,
212: 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010,
213: 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010,
214: 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010,
215: 0x20400010, 0x20400010, 0x00000000, 0x00404010, 0x20404000,
216: 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000,
217: 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000,
218: 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000,
219: 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000,
220: 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010,
221: 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010,
222: 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010,
223: 0x20004010 };
224:
225: static int[] SP7 = { 0x00200000, 0x04200002, 0x04000802,
226: 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800,
227: 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002,
228: 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802,
229: 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800,
230: 0x00200002, 0x04200000, 0x00000800, 0x00000802, 0x04200802,
231: 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000,
232: 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002,
233: 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800,
234: 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800,
235: 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800,
236: 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802,
237: 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800,
238: 0x00200002 };
239:
240: static int[] SP8 = { 0x10001040, 0x00001000, 0x00040000,
241: 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000,
242: 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000,
243: 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040,
244: 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040,
245: 0x10041000, 0x00001040, 0x00000000, 0x00000000, 0x10040040,
246: 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040,
247: 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040,
248: 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040,
249: 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040,
250: 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000,
251: 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000,
252: 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000,
253: 0x10041000 };
254:
255: /**
256: * generate an integer based working key based on our secret key
257: * and what we processing we are planning to do.
258: *
259: * Acknowledgements for this routine go to James Gillogly & Phil Karn.
260: * (whoever, and wherever they are!).
261: */
262: protected int[] generateWorkingKey(boolean encrypting, byte[] key) {
263: int[] newKey = new int[32];
264: boolean[] pc1m = new boolean[56], pcr = new boolean[56];
265:
266: for (int j = 0; j < 56; j++) {
267: int l = pc1[j];
268:
269: pc1m[j] = ((key[l >>> 3] & bytebit[l & 07]) != 0);
270: }
271:
272: for (int i = 0; i < 16; i++) {
273: int l, m, n;
274:
275: if (encrypting) {
276: m = i << 1;
277: } else {
278: m = (15 - i) << 1;
279: }
280:
281: n = m + 1;
282: newKey[m] = newKey[n] = 0;
283:
284: for (int j = 0; j < 28; j++) {
285: l = j + totrot[i];
286: if (l < 28) {
287: pcr[j] = pc1m[l];
288: } else {
289: pcr[j] = pc1m[l - 28];
290: }
291: }
292:
293: for (int j = 28; j < 56; j++) {
294: l = j + totrot[i];
295: if (l < 56) {
296: pcr[j] = pc1m[l];
297: } else {
298: pcr[j] = pc1m[l - 28];
299: }
300: }
301:
302: for (int j = 0; j < 24; j++) {
303: if (pcr[pc2[j]]) {
304: newKey[m] |= bigbyte[j];
305: }
306:
307: if (pcr[pc2[j + 24]]) {
308: newKey[n] |= bigbyte[j];
309: }
310: }
311: }
312:
313: //
314: // store the processed key
315: //
316: for (int i = 0; i != 32; i += 2) {
317: int i1, i2;
318:
319: i1 = newKey[i];
320: i2 = newKey[i + 1];
321:
322: newKey[i] = ((i1 & 0x00fc0000) << 6)
323: | ((i1 & 0x00000fc0) << 10)
324: | ((i2 & 0x00fc0000) >>> 10)
325: | ((i2 & 0x00000fc0) >>> 6);
326:
327: newKey[i + 1] = ((i1 & 0x0003f000) << 12)
328: | ((i1 & 0x0000003f) << 16)
329: | ((i2 & 0x0003f000) >>> 4) | (i2 & 0x0000003f);
330: }
331:
332: return newKey;
333: }
334:
335: /**
336: * the DES engine.
337: */
338: protected void desFunc(int[] wKey, byte[] in, int inOff,
339: byte[] out, int outOff) {
340: int work, right, left;
341:
342: left = (in[inOff + 0] & 0xff) << 24;
343: left |= (in[inOff + 1] & 0xff) << 16;
344: left |= (in[inOff + 2] & 0xff) << 8;
345: left |= (in[inOff + 3] & 0xff);
346:
347: right = (in[inOff + 4] & 0xff) << 24;
348: right |= (in[inOff + 5] & 0xff) << 16;
349: right |= (in[inOff + 6] & 0xff) << 8;
350: right |= (in[inOff + 7] & 0xff);
351:
352: work = ((left >>> 4) ^ right) & 0x0f0f0f0f;
353: right ^= work;
354: left ^= (work << 4);
355: work = ((left >>> 16) ^ right) & 0x0000ffff;
356: right ^= work;
357: left ^= (work << 16);
358: work = ((right >>> 2) ^ left) & 0x33333333;
359: left ^= work;
360: right ^= (work << 2);
361: work = ((right >>> 8) ^ left) & 0x00ff00ff;
362: left ^= work;
363: right ^= (work << 8);
364: right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff;
365: work = (left ^ right) & 0xaaaaaaaa;
366: left ^= work;
367: right ^= work;
368: left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff;
369:
370: for (int round = 0; round < 8; round++) {
371: int fval;
372:
373: work = (right << 28) | (right >>> 4);
374: work ^= wKey[round * 4 + 0];
375: fval = SP7[work & 0x3f];
376: fval |= SP5[(work >>> 8) & 0x3f];
377: fval |= SP3[(work >>> 16) & 0x3f];
378: fval |= SP1[(work >>> 24) & 0x3f];
379: work = right ^ wKey[round * 4 + 1];
380: fval |= SP8[work & 0x3f];
381: fval |= SP6[(work >>> 8) & 0x3f];
382: fval |= SP4[(work >>> 16) & 0x3f];
383: fval |= SP2[(work >>> 24) & 0x3f];
384: left ^= fval;
385: work = (left << 28) | (left >>> 4);
386: work ^= wKey[round * 4 + 2];
387: fval = SP7[work & 0x3f];
388: fval |= SP5[(work >>> 8) & 0x3f];
389: fval |= SP3[(work >>> 16) & 0x3f];
390: fval |= SP1[(work >>> 24) & 0x3f];
391: work = left ^ wKey[round * 4 + 3];
392: fval |= SP8[work & 0x3f];
393: fval |= SP6[(work >>> 8) & 0x3f];
394: fval |= SP4[(work >>> 16) & 0x3f];
395: fval |= SP2[(work >>> 24) & 0x3f];
396: right ^= fval;
397: }
398:
399: right = (right << 31) | (right >>> 1);
400: work = (left ^ right) & 0xaaaaaaaa;
401: left ^= work;
402: right ^= work;
403: left = (left << 31) | (left >>> 1);
404: work = ((left >>> 8) ^ right) & 0x00ff00ff;
405: right ^= work;
406: left ^= (work << 8);
407: work = ((left >>> 2) ^ right) & 0x33333333;
408: right ^= work;
409: left ^= (work << 2);
410: work = ((right >>> 16) ^ left) & 0x0000ffff;
411: left ^= work;
412: right ^= (work << 16);
413: work = ((right >>> 4) ^ left) & 0x0f0f0f0f;
414: left ^= work;
415: right ^= (work << 4);
416:
417: out[outOff + 0] = (byte) ((right >>> 24) & 0xff);
418: out[outOff + 1] = (byte) ((right >>> 16) & 0xff);
419: out[outOff + 2] = (byte) ((right >>> 8) & 0xff);
420: out[outOff + 3] = (byte) (right & 0xff);
421: out[outOff + 4] = (byte) ((left >>> 24) & 0xff);
422: out[outOff + 5] = (byte) ((left >>> 16) & 0xff);
423: out[outOff + 6] = (byte) ((left >>> 8) & 0xff);
424: out[outOff + 7] = (byte) (left & 0xff);
425: }
426: }
|