• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package ch.ethz.ssh2.crypto.cipher;
2 
3 /*
4  This file is based on the 3DES implementation from the Bouncy Castle Crypto package.
5  Their licence file states the following:
6 
7  Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle
8  (http://www.bouncycastle.org)
9 
10  Permission is hereby granted, free of charge, to any person obtaining a copy
11  of this software and associated documentation files (the "Software"), to deal
12  in the Software without restriction, including without limitation the rights
13  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14  copies of the Software, and to permit persons to whom the Software is
15  furnished to do so, subject to the following conditions:
16 
17  The above copyright notice and this permission notice shall be included in
18  all copies or substantial portions of the Software.
19 
20  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26  THE SOFTWARE.
27  */
28 
29 /**
30  * DES.
31  *
32  * @author See comments in the source file
33  * @version 2.50, 03/15/10
34  *
35  */
36 public class DES implements BlockCipher
37 {
38 	private int[] workingKey = null;
39 
40 	/**
41 	 * standard constructor.
42 	 */
DES()43 	public DES()
44 	{
45 	}
46 
47 	/**
48 	 * initialise a DES cipher.
49 	 *
50 	 * @param encrypting
51 	 *            whether or not we are for encryption.
52 	 * @param key
53 	 *            the parameters required to set up the cipher.
54 	 * @exception IllegalArgumentException
55 	 *                if the params argument is inappropriate.
56 	 */
init(boolean encrypting, byte[] key)57 	public void init(boolean encrypting, byte[] key)
58 	{
59 		this.workingKey = generateWorkingKey(encrypting, key, 0);
60 	}
61 
getAlgorithmName()62 	public String getAlgorithmName()
63 	{
64 		return "DES";
65 	}
66 
getBlockSize()67 	public int getBlockSize()
68 	{
69 		return 8;
70 	}
71 
transformBlock(byte[] in, int inOff, byte[] out, int outOff)72 	public void transformBlock(byte[] in, int inOff, byte[] out, int outOff)
73 	{
74 		if (workingKey == null)
75 		{
76 			throw new IllegalStateException("DES engine not initialised!");
77 		}
78 
79 		desFunc(workingKey, in, inOff, out, outOff);
80 	}
81 
reset()82 	public void reset()
83 	{
84 	}
85 
86 	/**
87 	 * what follows is mainly taken from "Applied Cryptography", by Bruce
88 	 * Schneier, however it also bears great resemblance to Richard
89 	 * Outerbridge's D3DES...
90 	 */
91 
92 	static short[] Df_Key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32,
93 			0x10, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67 };
94 
95 	static short[] bytebit = { 0200, 0100, 040, 020, 010, 04, 02, 01 };
96 
97 	static int[] bigbyte = { 0x800000, 0x400000, 0x200000, 0x100000, 0x80000, 0x40000, 0x20000, 0x10000, 0x8000,
98 			0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 };
99 
100 	/*
101 	 * Use the key schedule specified in the Standard (ANSI X3.92-1981).
102 	 */
103 
104 	static byte[] pc1 = { 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2,
105 			59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12,
106 			4, 27, 19, 11, 3 };
107 
108 	static byte[] totrot = { 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 };
109 
110 	static byte[] pc2 = { 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40,
111 			51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
112 
113 	static int[] SP1 = { 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004,
114 			0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004,
115 			0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004,
116 			0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404,
117 			0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400,
118 			0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404,
119 			0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004,
120 			0x00010400, 0x00000000, 0x01010004 };
121 
122 	static int[] SP2 = { 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020,
123 			0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020,
124 			0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020,
125 			0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020,
126 			0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020,
127 			0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020,
128 			0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000,
129 			0x80100020, 0x80108020, 0x00108000 };
130 
131 	static int[] SP3 = { 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208,
132 			0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208,
133 			0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208,
134 			0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000,
135 			0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208,
136 			0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208,
137 			0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208,
138 			0x00000008, 0x08020008, 0x00020200 };
139 
140 	static int[] SP4 = { 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001,
141 			0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001,
142 			0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081,
143 			0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001,
144 			0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081,
145 			0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000,
146 			0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080,
147 			0x00800000, 0x00002000, 0x00802080 };
148 
149 	static int[] SP5 = { 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000,
150 			0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000,
151 			0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000,
152 			0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100,
153 			0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000,
154 			0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100,
155 			0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000,
156 			0x40080000, 0x02080100, 0x40000100 };
157 
158 	static int[] SP6 = { 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010,
159 			0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010,
160 			0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010,
161 			0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010,
162 			0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000,
163 			0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010,
164 			0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000,
165 			0x20000000, 0x00400010, 0x20004010 };
166 
167 	static int[] SP7 = { 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802,
168 			0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802,
169 			0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000,
170 			0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800,
171 			0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800,
172 			0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000,
173 			0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002,
174 			0x04000800, 0x00000800, 0x00200002 };
175 
176 	static int[] SP8 = { 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040,
177 			0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040,
178 			0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040,
179 			0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000,
180 			0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040,
181 			0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040,
182 			0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040,
183 			0x00040040, 0x10000000, 0x10041000 };
184 
185 	/**
186 	 * generate an integer based working key based on our secret key and what we
187 	 * processing we are planning to do.
188 	 *
189 	 * Acknowledgements for this routine go to James Gillogly & Phil Karn.
190 	 * (whoever, and wherever they are!).
191 	 */
generateWorkingKey(boolean encrypting, byte[] key, int off)192 	protected int[] generateWorkingKey(boolean encrypting, byte[] key, int off)
193 	{
194 		int[] newKey = new int[32];
195 		boolean[] pc1m = new boolean[56], pcr = new boolean[56];
196 
197 		for (int j = 0; j < 56; j++)
198 		{
199 			int l = pc1[j];
200 
201 			pc1m[j] = ((key[off + (l >>> 3)] & bytebit[l & 07]) != 0);
202 		}
203 
204 		for (int i = 0; i < 16; i++)
205 		{
206 			int l, m, n;
207 
208 			if (encrypting)
209 			{
210 				m = i << 1;
211 			}
212 			else
213 			{
214 				m = (15 - i) << 1;
215 			}
216 
217 			n = m + 1;
218 			newKey[m] = newKey[n] = 0;
219 
220 			for (int j = 0; j < 28; j++)
221 			{
222 				l = j + totrot[i];
223 				if (l < 28)
224 				{
225 					pcr[j] = pc1m[l];
226 				}
227 				else
228 				{
229 					pcr[j] = pc1m[l - 28];
230 				}
231 			}
232 
233 			for (int j = 28; j < 56; j++)
234 			{
235 				l = j + totrot[i];
236 				if (l < 56)
237 				{
238 					pcr[j] = pc1m[l];
239 				}
240 				else
241 				{
242 					pcr[j] = pc1m[l - 28];
243 				}
244 			}
245 
246 			for (int j = 0; j < 24; j++)
247 			{
248 				if (pcr[pc2[j]])
249 				{
250 					newKey[m] |= bigbyte[j];
251 				}
252 
253 				if (pcr[pc2[j + 24]])
254 				{
255 					newKey[n] |= bigbyte[j];
256 				}
257 			}
258 		}
259 
260 		//
261 		// store the processed key
262 		//
263 		for (int i = 0; i != 32; i += 2)
264 		{
265 			int i1, i2;
266 
267 			i1 = newKey[i];
268 			i2 = newKey[i + 1];
269 
270 			newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10) | ((i2 & 0x00fc0000) >>> 10)
271 					| ((i2 & 0x00000fc0) >>> 6);
272 
273 			newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16) | ((i2 & 0x0003f000) >>> 4)
274 					| (i2 & 0x0000003f);
275 		}
276 
277 		return newKey;
278 	}
279 
280 	/**
281 	 * the DES engine.
282 	 */
desFunc(int[] wKey, byte[] in, int inOff, byte[] out, int outOff)283 	protected void desFunc(int[] wKey, byte[] in, int inOff, byte[] out, int outOff)
284 	{
285 		int work, right, left;
286 
287 		left = (in[inOff + 0] & 0xff) << 24;
288 		left |= (in[inOff + 1] & 0xff) << 16;
289 		left |= (in[inOff + 2] & 0xff) << 8;
290 		left |= (in[inOff + 3] & 0xff);
291 
292 		right = (in[inOff + 4] & 0xff) << 24;
293 		right |= (in[inOff + 5] & 0xff) << 16;
294 		right |= (in[inOff + 6] & 0xff) << 8;
295 		right |= (in[inOff + 7] & 0xff);
296 
297 		work = ((left >>> 4) ^ right) & 0x0f0f0f0f;
298 		right ^= work;
299 		left ^= (work << 4);
300 		work = ((left >>> 16) ^ right) & 0x0000ffff;
301 		right ^= work;
302 		left ^= (work << 16);
303 		work = ((right >>> 2) ^ left) & 0x33333333;
304 		left ^= work;
305 		right ^= (work << 2);
306 		work = ((right >>> 8) ^ left) & 0x00ff00ff;
307 		left ^= work;
308 		right ^= (work << 8);
309 		right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff;
310 		work = (left ^ right) & 0xaaaaaaaa;
311 		left ^= work;
312 		right ^= work;
313 		left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff;
314 
315 		for (int round = 0; round < 8; round++)
316 		{
317 			int fval;
318 
319 			work = (right << 28) | (right >>> 4);
320 			work ^= wKey[round * 4 + 0];
321 			fval = SP7[work & 0x3f];
322 			fval |= SP5[(work >>> 8) & 0x3f];
323 			fval |= SP3[(work >>> 16) & 0x3f];
324 			fval |= SP1[(work >>> 24) & 0x3f];
325 			work = right ^ wKey[round * 4 + 1];
326 			fval |= SP8[work & 0x3f];
327 			fval |= SP6[(work >>> 8) & 0x3f];
328 			fval |= SP4[(work >>> 16) & 0x3f];
329 			fval |= SP2[(work >>> 24) & 0x3f];
330 			left ^= fval;
331 			work = (left << 28) | (left >>> 4);
332 			work ^= wKey[round * 4 + 2];
333 			fval = SP7[work & 0x3f];
334 			fval |= SP5[(work >>> 8) & 0x3f];
335 			fval |= SP3[(work >>> 16) & 0x3f];
336 			fval |= SP1[(work >>> 24) & 0x3f];
337 			work = left ^ wKey[round * 4 + 3];
338 			fval |= SP8[work & 0x3f];
339 			fval |= SP6[(work >>> 8) & 0x3f];
340 			fval |= SP4[(work >>> 16) & 0x3f];
341 			fval |= SP2[(work >>> 24) & 0x3f];
342 			right ^= fval;
343 		}
344 
345 		right = (right << 31) | (right >>> 1);
346 		work = (left ^ right) & 0xaaaaaaaa;
347 		left ^= work;
348 		right ^= work;
349 		left = (left << 31) | (left >>> 1);
350 		work = ((left >>> 8) ^ right) & 0x00ff00ff;
351 		right ^= work;
352 		left ^= (work << 8);
353 		work = ((left >>> 2) ^ right) & 0x33333333;
354 		right ^= work;
355 		left ^= (work << 2);
356 		work = ((right >>> 16) ^ left) & 0x0000ffff;
357 		left ^= work;
358 		right ^= (work << 16);
359 		work = ((right >>> 4) ^ left) & 0x0f0f0f0f;
360 		left ^= work;
361 		right ^= (work << 4);
362 
363 		out[outOff + 0] = (byte) ((right >>> 24) & 0xff);
364 		out[outOff + 1] = (byte) ((right >>> 16) & 0xff);
365 		out[outOff + 2] = (byte) ((right >>> 8) & 0xff);
366 		out[outOff + 3] = (byte) (right & 0xff);
367 		out[outOff + 4] = (byte) ((left >>> 24) & 0xff);
368 		out[outOff + 5] = (byte) ((left >>> 16) & 0xff);
369 		out[outOff + 6] = (byte) ((left >>> 8) & 0xff);
370 		out[outOff + 7] = (byte) (left & 0xff);
371 	}
372 }
373